bug 590961 - Allow generating minidumps from processes of differing CPU architecture. r=mento a=blocking-2.0
authorTed Mielczarek <ted.mielczarek@gmail.com>
Thu, 16 Dec 2010 17:56:27 -0500
changeset 59426 2020888cd34f6378fea834425c9524a9d7a47357
parent 59425 c6f86b5978e785136955204f24be6b8ed610f47c
child 59428 51795db981f2dc408a244fc75b748c94519bc765
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersmento, blocking-2
bugs590961
milestone2.0b9pre
bug 590961 - Allow generating minidumps from processes of differing CPU architecture. r=mento a=blocking-2.0
toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_client.cc
toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_server.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/Makefile.in
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/tests/minidump_generator_test.cc
toolkit/crashreporter/google-breakpad/src/client/mac/tests/minidump_generator_test_helper.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj
@@ -46,27 +46,54 @@
 		8B31029411F0D54300FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
 		8B3102E611F0D74C00FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
 		8B3102EB11F0D78000FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
 		8B31FC8211EFD2B800FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
 		8B4BDAAF12012BC5009C7060 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
 		8B4BDABE12012CEF009C7060 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
 		8B4BDAC512012D05009C7060 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
 		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+		D23F4B2E12A7E13200686C8D /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */; };
+		D23F4B3312A7E17700686C8D /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2F9A41512131EF0002747C1 /* libgtest.a */; };
+		D23F4BB112A868CB00686C8D /* minidump_generator_test_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D23F4B9A12A8688800686C8D /* minidump_generator_test_helper.cc */; };
+		D23F4BB812A868F700686C8D /* MachIPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53790ECCE635009BE4BA /* MachIPC.mm */; };
 		D244536A12426F00009BBCE0 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535112426EBB009BBCE0 /* logging.cc */; };
 		D244536B12426F00009BBCE0 /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535212426EBB009BBCE0 /* minidump.cc */; };
 		D244536C12426F00009BBCE0 /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535312426EBB009BBCE0 /* pathname_stripper.cc */; };
 		D244536D12426F00009BBCE0 /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244534F12426E98009BBCE0 /* basic_code_modules.cc */; };
 		D244540B12439BA0009BBCE0 /* memory_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244540A12439BA0009BBCE0 /* memory_unittest.cc */; };
+		D246417012BAA40E005170D0 /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */; };
+		D246417112BAA41C005170D0 /* crash_generation_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A4C6121336C7002747C1 /* crash_generation_client.cc */; };
+		D246417512BAA438005170D0 /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */; };
+		D246417612BAA43F005170D0 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */; };
+		D246417712BAA444005170D0 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
+		D246418412BAA4BA005170D0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
+		D246418812BAA4E3005170D0 /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; };
+		D246418C12BAA508005170D0 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; };
+		D246419012BAA52A005170D0 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; };
+		D246419112BAA52F005170D0 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; };
+		D246419512BAA54C005170D0 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53740ECCE635009BE4BA /* file_id.cc */; };
+		D246419612BAA55A005170D0 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537A0ECCE635009BE4BA /* macho_id.cc */; };
+		D246419C12BAA65F005170D0 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
+		D24641A012BAA67F005170D0 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; };
+		D24641AF12BAA82D005170D0 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; };
+		D24641EC12BAC6FB005170D0 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535112426EBB009BBCE0 /* logging.cc */; };
+		D24641ED12BAC6FB005170D0 /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535212426EBB009BBCE0 /* minidump.cc */; };
+		D24641EE12BAC6FB005170D0 /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535312426EBB009BBCE0 /* pathname_stripper.cc */; };
+		D24641EF12BAC6FB005170D0 /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244534F12426E98009BBCE0 /* basic_code_modules.cc */; };
 		D24BBBFD121050F000F3D417 /* breakpadUtilities.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */; };
 		D24BBD291211EDB100F3D417 /* MachIPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53790ECCE635009BE4BA /* MachIPC.mm */; };
 		D24BBD321212CACF00F3D417 /* MachIPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53790ECCE635009BE4BA /* MachIPC.mm */; };
 		D2A5DD301188633800081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
 		D2A5DD401188640400081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
 		D2A5DD411188642E00081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
+		D2C1DBE412AFC270006917BD /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535112426EBB009BBCE0 /* logging.cc */; };
+		D2C1DBE512AFC270006917BD /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535212426EBB009BBCE0 /* minidump.cc */; };
+		D2C1DBE612AFC270006917BD /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535312426EBB009BBCE0 /* pathname_stripper.cc */; };
+		D2C1DBE712AFC270006917BD /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244534F12426E98009BBCE0 /* basic_code_modules.cc */; };
 		D2F9A3D51212F87C002747C1 /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A3D41212F87C002747C1 /* exception_handler_test.cc */; };
 		D2F9A43D12131F55002747C1 /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A43C12131F55002747C1 /* gmock-all.cc */; };
 		D2F9A44012131F65002747C1 /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A43E12131F65002747C1 /* gtest_main.cc */; };
 		D2F9A44112131F65002747C1 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A43F12131F65002747C1 /* gtest-all.cc */; };
 		D2F9A44412131F84002747C1 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2F9A41512131EF0002747C1 /* libgtest.a */; };
 		D2F9A4C9121336C7002747C1 /* client_info.h in Headers */ = {isa = PBXBuildFile; fileRef = D2F9A4C4121336C7002747C1 /* client_info.h */; };
 		D2F9A4CA121336C7002747C1 /* crash_generation_client.h in Headers */ = {isa = PBXBuildFile; fileRef = D2F9A4C5121336C7002747C1 /* crash_generation_client.h */; };
 		D2F9A4CB121336C7002747C1 /* crash_generation_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A4C6121336C7002747C1 /* crash_generation_client.cc */; };
@@ -130,17 +157,16 @@
 		F93803D00F8083B7004D428B /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; };
 		F93803D10F8083B7004D428B /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; };
 		F93803D20F8083B7004D428B /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; };
 		F93803D30F8083B7004D428B /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53740ECCE635009BE4BA /* file_id.cc */; };
 		F93803D40F8083B7004D428B /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537A0ECCE635009BE4BA /* macho_id.cc */; };
 		F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; };
 		F93803D60F8083B7004D428B /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; };
 		F93803D70F8083B7004D428B /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; };
-		F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93803D90F8083D8004D428B /* minidump_generator_test.cc */; };
 		F93DE2D80F82A70E00608B94 /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */; };
 		F93DE2D90F82A73500608B94 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; };
 		F93DE2DA0F82A73500608B94 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; };
 		F93DE2DB0F82A73500608B94 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; };
 		F93DE3350F82C66B00608B94 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */; };
 		F93DE3360F82C66B00608B94 /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */; };
 		F93DE3370F82C66B00608B94 /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */; };
 		F93DE3380F82C66B00608B94 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; };
@@ -307,16 +333,30 @@
 		};
 		8B31F7BA11EF9A8700FCF3E4 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */;
 			proxyType = 2;
 			remoteGlobalIDString = D21F97D211CBA0F200239E38;
 			remoteInfo = test_assembler_unittest;
 		};
+		D23F4B2F12A7E16200686C8D /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D2F9A41412131EF0002747C1;
+			remoteInfo = gtest;
+		};
+		D23F4BB912A8694C00686C8D /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D23F4BAA12A868A500686C8D;
+			remoteInfo = minidump_generator_test_helper;
+		};
 		D2F9A44212131F80002747C1 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 			proxyType = 1;
 			remoteGlobalIDString = D2F9A41412131EF0002747C1;
 			remoteInfo = gtest;
 		};
 		D2F9A52C121383A1002747C1 /* PBXContainerItemProxy */ = {
@@ -507,16 +547,19 @@
 		8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = ../../common/mac/GTMDefines.h; sourceTree = SOURCE_ROOT; };
 		8B3101E911F0CDE300FCF3E4 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
 		8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMGarbageCollection.h; path = ../../common/mac/GTMGarbageCollection.h; sourceTree = SOURCE_ROOT; };
 		8B31027711F0D3AF00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
 		8B31027811F0D3AF00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
 		8B31FFF611F0C90500FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
 		8B4BDAA7120124EA009C7060 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = usr/lib/libcrypto.dylib; sourceTree = SDKROOT; };
 		8DC2EF5B0486A6940098B216 /* Breakpad.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Breakpad.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test.cc; path = tests/minidump_generator_test.cc; sourceTree = "<group>"; };
+		D23F4B9A12A8688800686C8D /* minidump_generator_test_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test_helper.cc; path = tests/minidump_generator_test_helper.cc; sourceTree = "<group>"; };
+		D23F4BAB12A868A500686C8D /* minidump_generator_test_helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_generator_test_helper; sourceTree = BUILT_PRODUCTS_DIR; };
 		D244534F12426E98009BBCE0 /* basic_code_modules.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = basic_code_modules.cc; path = ../../processor/basic_code_modules.cc; sourceTree = SOURCE_ROOT; };
 		D244535112426EBB009BBCE0 /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = ../../processor/logging.cc; sourceTree = SOURCE_ROOT; };
 		D244535212426EBB009BBCE0 /* minidump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump.cc; path = ../../processor/minidump.cc; sourceTree = SOURCE_ROOT; };
 		D244535312426EBB009BBCE0 /* pathname_stripper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pathname_stripper.cc; path = ../../processor/pathname_stripper.cc; sourceTree = SOURCE_ROOT; };
 		D244540A12439BA0009BBCE0 /* memory_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memory_unittest.cc; path = ../../common/memory_unittest.cc; sourceTree = SOURCE_ROOT; };
 		D2F9A3D41212F87C002747C1 /* exception_handler_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exception_handler_test.cc; path = tests/exception_handler_test.cc; sourceTree = "<group>"; };
 		D2F9A41512131EF0002747C1 /* libgtest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		D2F9A43C12131F55002747C1 /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "../../testing/src/gmock-all.cc"; sourceTree = SOURCE_ROOT; };
@@ -597,17 +640,16 @@
 		F92C56310ECD0DF1009BE4BA /* OnDemandServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OnDemandServer.h; path = Framework/OnDemandServer.h; sourceTree = "<group>"; };
 		F92C56320ECD0DF1009BE4BA /* OnDemandServer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = OnDemandServer.mm; path = Framework/OnDemandServer.mm; sourceTree = "<group>"; };
 		F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = breakpadUtilities.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = crash_report_sender.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		F92C56A20ECE04A7009BE4BA /* crash_report_sender-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "crash_report_sender-Info.plist"; path = "sender/crash_report_sender-Info.plist"; sourceTree = "<group>"; };
 		F92C56A70ECE04C5009BE4BA /* crash_report_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crash_report_sender.h; path = sender/crash_report_sender.h; sourceTree = "<group>"; };
 		F92C56A80ECE04C5009BE4BA /* crash_report_sender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = crash_report_sender.m; path = sender/crash_report_sender.m; sourceTree = "<group>"; };
 		F93803BE0F80820F004D428B /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; };
-		F93803D90F8083D8004D428B /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test.cc; path = handler/minidump_generator_test.cc; sourceTree = "<group>"; };
 		F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_file_writer_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
 		F93DE2D70F82A70E00608B94 /* 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 = SOURCE_ROOT; };
 		F93DE32C0F82C55600608B94 /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; };
 		F945849D0F280E3C009A47BF /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = sender/English.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F945859D0F78241E009A47BF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Framework/Info.plist; sourceTree = "<group>"; };
 		F95BB87C101F949F00AA053B /* crash_report.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = crash_report.xcodeproj; path = ../../tools/mac/crash_report/crash_report.xcodeproj; sourceTree = SOURCE_ROOT; };
 		F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = dump_syms.xcodeproj; path = ../../tools/mac/dump_syms/dump_syms.xcodeproj; sourceTree = SOURCE_ROOT; };
 		F95BB894101F94C000AA053B /* symupload.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = symupload.xcodeproj; path = ../../tools/mac/symupload/symupload.xcodeproj; sourceTree = SOURCE_ROOT; };
@@ -639,16 +681,25 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				F92C565C0ECD1158009BE4BA /* breakpadUtilities.dylib in Frameworks */,
 				8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		D23F4BA912A868A500686C8D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D246418412BAA4BA005170D0 /* Foundation.framework in Frameworks */,
+				D246419C12BAA65F005170D0 /* libcrypto.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		D2F9A41312131EF0002747C1 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		D2F9A53E121383A1002747C1 /* Frameworks */ = {
@@ -691,16 +742,17 @@
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F93803BC0F80820F004D428B /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				8B31029411F0D54300FCF3E4 /* Foundation.framework in Frameworks */,
 				8B4BDABE12012CEF009C7060 /* libcrypto.dylib in Frameworks */,
+				D23F4B3312A7E17700686C8D /* libgtest.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F93DE2CF0F82A67300608B94 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
@@ -749,16 +801,17 @@
 				F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */,
 				F9C44DA50EF060A8003AEBAA /* BreakpadTest.app */,
 				F9C77DDA0F7DD5CF0045F7DB /* UnitTests.octest */,
 				F93803BE0F80820F004D428B /* generator_test */,
 				F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */,
 				F93DE32C0F82C55600608B94 /* handler_test */,
 				D2F9A41512131EF0002747C1 /* libgtest.a */,
 				D2F9A546121383A1002747C1 /* crash_generation_server_test */,
+				D23F4BAB12A868A500686C8D /* minidump_generator_test_helper */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 		};
 		0867D691FE84028FC02AAC07 /* Breakpad */ = {
 			isa = PBXGroup;
 			children = (
 				D2F9A43812131F3B002747C1 /* gtest */,
@@ -810,17 +863,16 @@
 				D2F9A43C12131F55002747C1 /* gmock-all.cc */,
 			);
 			name = gtest;
 			sourceTree = "<group>";
 		};
 		F92C53590ECCE3BB009BE4BA /* handler */ = {
 			isa = PBXGroup;
 			children = (
-				F93803D90F8083D8004D428B /* minidump_generator_test.cc */,
 				F92C53670ECCE3FD009BE4BA /* breakpad_exc_server.c */,
 				F92C53680ECCE3FD009BE4BA /* breakpad_exc_server.h */,
 				F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */,
 				F92C536A0ECCE3FD009BE4BA /* breakpad_nlist_64.h */,
 				F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */,
 				F92C536C0ECCE3FD009BE4BA /* dynamic_images.h */,
 				F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */,
 				F92C536E0ECCE3FD009BE4BA /* exception_handler.h */,
@@ -1004,16 +1056,18 @@
 				F9C44DB10EF07288003AEBAA /* TestClass.mm */,
 			);
 			name = testapp;
 			sourceTree = "<group>";
 		};
 		F9C77DDF0F7DD7CF0045F7DB /* tests */ = {
 			isa = PBXGroup;
 			children = (
+				D23F4B9A12A8688800686C8D /* minidump_generator_test_helper.cc */,
+				D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */,
 				D2F9A4CE121336F7002747C1 /* crash_generation_server_test.cc */,
 				D2F9A3D41212F87C002747C1 /* exception_handler_test.cc */,
 				F9C77DE00F7DD7E30045F7DB /* SimpleStringDictionaryTest.h */,
 				F9C77DE10F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm */,
 				F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */,
 			);
 			name = tests;
 			sourceTree = "<group>";
@@ -1077,16 +1131,32 @@
 				F9C44E970EF09F4B003AEBAA /* PBXTargetDependency */,
 			);
 			name = Breakpad;
 			productInstallPath = "$(HOME)/Library/Frameworks";
 			productName = Breakpad;
 			productReference = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */;
 			productType = "com.apple.product-type.framework";
 		};
+		D23F4BAA12A868A500686C8D /* minidump_generator_test_helper */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D23F4BB012A868C400686C8D /* Build configuration list for PBXNativeTarget "minidump_generator_test_helper" */;
+			buildPhases = (
+				D23F4BA812A868A500686C8D /* Sources */,
+				D23F4BA912A868A500686C8D /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = minidump_generator_test_helper;
+			productName = minidump_generator_test_helper;
+			productReference = D23F4BAB12A868A500686C8D /* minidump_generator_test_helper */;
+			productType = "com.apple.product-type.tool";
+		};
 		D2F9A41412131EF0002747C1 /* gtest */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = D2F9A42D12131F0E002747C1 /* Build configuration list for PBXNativeTarget "gtest" */;
 			buildPhases = (
 				D2F9A41112131EF0002747C1 /* Headers */,
 				D2F9A41212131EF0002747C1 /* Sources */,
 				D2F9A41312131EF0002747C1 /* Frameworks */,
 			);
@@ -1173,16 +1243,18 @@
 			buildConfigurationList = F93803C40F80822E004D428B /* Build configuration list for PBXNativeTarget "generator_test" */;
 			buildPhases = (
 				F93803BB0F80820F004D428B /* Sources */,
 				F93803BC0F80820F004D428B /* Frameworks */,
 			);
 			buildRules = (
 			);
 			dependencies = (
+				D23F4B3012A7E16200686C8D /* PBXTargetDependency */,
+				D23F4BBA12A8694C00686C8D /* PBXTargetDependency */,
 			);
 			name = generator_test;
 			productName = generator_test;
 			productReference = F93803BE0F80820F004D428B /* generator_test */;
 			productType = "com.apple.product-type.tool";
 		};
 		F93DE2D00F82A67300608B94 /* minidump_file_writer_unittest */ = {
 			isa = PBXNativeTarget;
@@ -1306,16 +1378,17 @@
 				F9C44DA40EF060A8003AEBAA /* BreakpadTest */,
 				F94585840F782326009A47BF /* All */,
 				F9C77DD90F7DD5CF0045F7DB /* UnitTests */,
 				F93803BD0F80820F004D428B /* generator_test */,
 				F93DE2D00F82A67300608B94 /* minidump_file_writer_unittest */,
 				F93DE32B0F82C55600608B94 /* handler_test */,
 				D2F9A41412131EF0002747C1 /* gtest */,
 				D2F9A52A121383A1002747C1 /* crash_generation_server_test */,
+				D23F4BAA12A868A500686C8D /* minidump_generator_test_helper */,
 			);
 		};
 /* End PBXProject section */
 
 /* Begin PBXReferenceProxy section */
 		8B31F7A111EF9A8700FCF3E4 /* macho_dump */ = {
 			isa = PBXReferenceProxy;
 			fileType = "compiled.mach-o.executable";
@@ -1540,16 +1613,38 @@
 				F92C56630ECD1179009BE4BA /* exception_handler.cc in Sources */,
 				F92C55D10ECD0064009BE4BA /* Breakpad.mm in Sources */,
 				F92C56340ECD0DF1009BE4BA /* OnDemandServer.mm in Sources */,
 				D2F9A4CB121336C7002747C1 /* crash_generation_client.cc in Sources */,
 				D2F9A4CD121336C7002747C1 /* crash_generation_server.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		D23F4BA812A868A500686C8D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D23F4BB112A868CB00686C8D /* minidump_generator_test_helper.cc in Sources */,
+				D23F4BB812A868F700686C8D /* MachIPC.mm in Sources */,
+				D246417012BAA40E005170D0 /* exception_handler.cc in Sources */,
+				D246417112BAA41C005170D0 /* crash_generation_client.cc in Sources */,
+				D246417512BAA438005170D0 /* minidump_generator.cc in Sources */,
+				D246417612BAA43F005170D0 /* dynamic_images.cc in Sources */,
+				D246417712BAA444005170D0 /* breakpad_nlist_64.cc in Sources */,
+				D246418812BAA4E3005170D0 /* string_utilities.cc in Sources */,
+				D246418C12BAA508005170D0 /* minidump_file_writer.cc in Sources */,
+				D246419012BAA52A005170D0 /* string_conversion.cc in Sources */,
+				D246419112BAA52F005170D0 /* convert_UTF.c in Sources */,
+				D246419512BAA54C005170D0 /* file_id.cc in Sources */,
+				D246419612BAA55A005170D0 /* macho_id.cc in Sources */,
+				D24641A012BAA67F005170D0 /* macho_walker.cc in Sources */,
+				D24641AF12BAA82D005170D0 /* macho_utilities.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		D2F9A41212131EF0002747C1 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				D2F9A43D12131F55002747C1 /* gmock-all.cc in Sources */,
 				D2F9A44012131F65002747C1 /* gtest_main.cc in Sources */,
 				D2F9A44112131F65002747C1 /* gtest-all.cc in Sources */,
 			);
@@ -1570,16 +1665,20 @@
 				D2F9A535121383A1002747C1 /* minidump_file_writer.cc in Sources */,
 				D2F9A536121383A1002747C1 /* convert_UTF.c in Sources */,
 				D2F9A537121383A1002747C1 /* string_conversion.cc in Sources */,
 				D2F9A538121383A1002747C1 /* file_id.cc in Sources */,
 				D2F9A539121383A1002747C1 /* macho_id.cc in Sources */,
 				D2F9A53A121383A1002747C1 /* macho_utilities.cc in Sources */,
 				D2F9A53B121383A1002747C1 /* macho_walker.cc in Sources */,
 				D2F9A53C121383A1002747C1 /* string_utilities.cc in Sources */,
+				D24641EC12BAC6FB005170D0 /* logging.cc in Sources */,
+				D24641ED12BAC6FB005170D0 /* minidump.cc in Sources */,
+				D24641EE12BAC6FB005170D0 /* pathname_stripper.cc in Sources */,
+				D24641EF12BAC6FB005170D0 /* basic_code_modules.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F92C53510ECCE349009BE4BA /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				F92C53B80ECCE7B3009BE4BA /* Inspector.mm in Sources */,
@@ -1616,32 +1715,36 @@
 				F9C44EE90EF0A3C1003AEBAA /* GTMLogger.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F93803BB0F80820F004D428B /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				D2C1DBE412AFC270006917BD /* logging.cc in Sources */,
+				D2C1DBE512AFC270006917BD /* minidump.cc in Sources */,
+				D2C1DBE612AFC270006917BD /* pathname_stripper.cc in Sources */,
+				D2C1DBE712AFC270006917BD /* basic_code_modules.cc in Sources */,
 				D2F9A4DF12133AD9002747C1 /* crash_generation_client.cc in Sources */,
 				D2F9A4E012133AD9002747C1 /* crash_generation_server.cc in Sources */,
 				D24BBD291211EDB100F3D417 /* MachIPC.mm in Sources */,
 				D2A5DD401188640400081F03 /* breakpad_nlist_64.cc in Sources */,
 				F93803CD0F8083B7004D428B /* dynamic_images.cc in Sources */,
 				F93803CE0F8083B7004D428B /* exception_handler.cc in Sources */,
 				F93803CF0F8083B7004D428B /* minidump_generator.cc in Sources */,
 				F93803D00F8083B7004D428B /* minidump_file_writer.cc in Sources */,
 				F93803D10F8083B7004D428B /* convert_UTF.c in Sources */,
 				F93803D20F8083B7004D428B /* string_conversion.cc in Sources */,
 				F93803D30F8083B7004D428B /* file_id.cc in Sources */,
 				F93803D40F8083B7004D428B /* macho_id.cc in Sources */,
 				F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */,
 				F93803D60F8083B7004D428B /* macho_walker.cc in Sources */,
 				F93803D70F8083B7004D428B /* string_utilities.cc in Sources */,
-				F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */,
+				D23F4B2E12A7E13200686C8D /* minidump_generator_test.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F93DE2CE0F82A67300608B94 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				F93DE2D90F82A73500608B94 /* minidump_file_writer.cc in Sources */,
@@ -1728,16 +1831,26 @@
 			name = macho_dump;
 			targetProxy = 8B31051C11F1010E00FCF3E4 /* PBXContainerItemProxy */;
 		};
 		8B31051F11F1010E00FCF3E4 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			name = minidump_upload;
 			targetProxy = 8B31051E11F1010E00FCF3E4 /* PBXContainerItemProxy */;
 		};
+		D23F4B3012A7E16200686C8D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = D2F9A41412131EF0002747C1 /* gtest */;
+			targetProxy = D23F4B2F12A7E16200686C8D /* PBXContainerItemProxy */;
+		};
+		D23F4BBA12A8694C00686C8D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = D23F4BAA12A868A500686C8D /* minidump_generator_test_helper */;
+			targetProxy = D23F4BB912A8694C00686C8D /* PBXContainerItemProxy */;
+		};
 		D2F9A44312131F80002747C1 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = D2F9A41412131EF0002747C1 /* gtest */;
 			targetProxy = D2F9A44212131F80002747C1 /* PBXContainerItemProxy */;
 		};
 		D2F9A52B121383A1002747C1 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = D2F9A41412131EF0002747C1 /* gtest */;
@@ -1925,27 +2038,74 @@
 			};
 			name = Release;
 		};
 		1DEB91B208733DA50010E9CD /* Debug */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 8B31027711F0D3AF00FCF3E4 /* BreakpadDebug.xcconfig */;
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+				SDKROOT = macosx10.5;
+				"SDKROOT[arch=i386]" = macosx10.4;
+				"SDKROOT[arch=ppc]" = macosx10.4;
+				"SDKROOT[arch=x86_64]" = macosx10.6;
 			};
 			name = Debug;
 		};
 		1DEB91B308733DA50010E9CD /* Release */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 8B31027811F0D3AF00FCF3E4 /* BreakpadRelease.xcconfig */;
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
 			};
 			name = Release;
 		};
+		D23F4BAD12A868A600686C8D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = ../..;
+				INSTALL_PATH = /usr/local/bin;
+				PREBINDING = NO;
+				PRODUCT_NAME = minidump_generator_test_helper;
+			};
+			name = Debug;
+		};
+		D23F4BAE12A868A600686C8D /* Debug With Code Coverage */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/bin;
+				PREBINDING = NO;
+				PRODUCT_NAME = minidump_generator_test_helper;
+			};
+			name = "Debug With Code Coverage";
+		};
+		D23F4BAF12A868A600686C8D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/bin;
+				PREBINDING = NO;
+				PRODUCT_NAME = minidump_generator_test_helper;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
 		D2F9A41612131EF0002747C1 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				COPY_PHASE_STRIP = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				HEADER_SEARCH_PATHS = (
@@ -1982,16 +2142,17 @@
 			};
 			name = Release;
 		};
 		D2F9A543121383A1002747C1 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = "BP_LOGGING_INCLUDE=\\\"client/mac/tests/testlogging.h\\\"";
 				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
 				HEADER_SEARCH_PATHS = (
 					../..,
 					../../testing,
 					../../testing/include,
 					../../testing/gtest,
 					../../testing/gtest/include,
 				);
@@ -2089,17 +2250,25 @@
 				INFOPLIST_FILE = "sender/crash_report_sender-Info.plist";
 				PRODUCT_NAME = crash_report_sender;
 			};
 			name = Release;
 		};
 		F93803C00F808210004D428B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				HEADER_SEARCH_PATHS = ../..;
+				GCC_PREPROCESSOR_DEFINITIONS = "BP_LOGGING_INCLUDE=\\\"client/mac/tests/testlogging.h\\\"";
+				HEADER_SEARCH_PATHS = (
+					../..,
+					../../..,
+					../../testing,
+					../../testing/include,
+					../../testing/gtest,
+					../../testing/gtest/include,
+				);
 				PRODUCT_NAME = generator_test;
 			};
 			name = Debug;
 		};
 		F93803C10F808210004D428B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				HEADER_SEARCH_PATHS = ../..;
@@ -2351,16 +2520,26 @@
 			buildConfigurations = (
 				1DEB91B208733DA50010E9CD /* Debug */,
 				F93DE3B90F830E7000608B94 /* Debug With Code Coverage */,
 				1DEB91B308733DA50010E9CD /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		D23F4BB012A868C400686C8D /* Build configuration list for PBXNativeTarget "minidump_generator_test_helper" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D23F4BAD12A868A600686C8D /* Debug */,
+				D23F4BAE12A868A600686C8D /* Debug With Code Coverage */,
+				D23F4BAF12A868A600686C8D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		D2F9A42D12131F0E002747C1 /* Build configuration list for PBXNativeTarget "gtest" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				D2F9A41612131EF0002747C1 /* Debug */,
 				D2F9A41712131EF0002747C1 /* Debug With Code Coverage */,
 				D2F9A41812131EF0002747C1 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_client.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_client.cc
@@ -49,25 +49,24 @@ bool CrashGenerationClient::RequestDumpF
   message.AddDescriptor(mach_thread_self());          // 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;
   message.SetData(&info, sizeof(info));
-  
+
   const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
   kern_return_t result = sender_.SendMessage(message, kSendTimeoutMs);
   if (result != KERN_SUCCESS)
     return false;
 
   // Give the server slightly longer to reply since it has to
   // inspect this task and write the minidump.
   const mach_msg_timeout_t kReceiveTimeoutMs = 5 * 1000;
   MachReceiveMessage acknowledge_message;
   result = acknowledge_port.WaitForMessage(&acknowledge_message,
 					   kReceiveTimeoutMs);
-  
   return result == KERN_SUCCESS;
 }
 
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_server.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/crash_generation_server.h
@@ -25,16 +25,18 @@
 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (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;
 
@@ -42,19 +44,19 @@ class ClientInfo;
 enum {
   kDumpRequestMessage     = 1,
   kAcknowledgementMessage = 2,
   kQuitMessage            = 3
 };
 
 // Exception details sent by the client when requesting a dump.
 struct ExceptionInfo {
-  int exception_type;
-  int exception_code;
-  int exception_subcode;
+  int32_t exception_type;
+  int32_t exception_code;
+  int32_t exception_subcode;
 };
 
 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,
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/Makefile.in
@@ -43,21 +43,18 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= handler
 LIBRARY_NAME	= exception_handler_s
 XPI_NAME 	= crashreporter
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../../..
 
 CPPSRCS	= \
+  breakpad_nlist_64.cc \
   exception_handler.cc \
   minidump_generator.cc \
   dynamic_images.cc \
   $(NULL)
 
-ifeq (x86_64,$(TARGET_CPU))
-CPPSRCS += breakpad_nlist_64.cc
-endif
-
 # need static lib
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.cc
@@ -49,42 +49,40 @@
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 
-/* nealsid:
+/*
  * 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. However,
- * 32-bit compatibility has not been retained. 
+ * I've modified it to be compatible with 64-bit images.
 */
 
-#ifdef __LP64__
+#include "breakpad_nlist_64.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 <fcntl.h>
 #include <sys/types.h>
 #include <sys/uio.h>
+#include <TargetConditionals.h>
 #include <unistd.h>
-#include "breakpad_nlist_64.h"
-#include <TargetConditionals.h>
-#include <stdio.h>
-#include <mach/mach.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 */
@@ -103,279 +101,312 @@ struct exec {
 
 #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_64(int fd, breakpad_nlist *list, const char **symbolNames);
+__breakpad_fdnlist(int fd, nlist_type *list, const char **symbolNames,
+                   cpu_type_t cpu_type);
 
 /*
  * nlist - retreive attributes from name list (string table version)
  */
 
-int
-breakpad_nlist_64(const char *name,
-                  breakpad_nlist *list,
-                  const char **symbolNames) {
-  int fd, n;
+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;
+}
 
-  fd = open(name, O_RDONLY, 0);
-  if (fd < 0)
-    return (-1);
-  n = __breakpad_fdnlist_64(fd, list, symbolNames);
-  (void)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 */
 
-int
-__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames) {
-  register breakpad_nlist *p, *q;
-  breakpad_nlist space[BUFSIZ/sizeof (breakpad_nlist)];
+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 register char *s1, *s2;
-  register register_t n, m;
-  int maxlen, nreq;
-  off_t sa;             /* symbol address */
-  off_t ss;             /* start of strings */
-  struct exec buf;
-  unsigned  arch_offset = 0;
+  const uint32_t magic = MachBits<nlist_type>::magic;
 
-  maxlen = 500;
-  for (q = list, nreq = 0;
+  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) && *((long *)&buf) != MH_MAGIC &&
+      (N_BADMAG(buf) && *((long *)&buf) != magic &&
        NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC) &&
-      /* nealsid: The following is the big-endian ppc64 check */
+      /* The following is the big-endian ppc64 check */
       (*((long*)&buf)) != FAT_MAGIC) {
-    return (-1);
+    return -1;
   }
 
   /* Deal with fat file if necessary */
+  unsigned arch_offset = 0;
   if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC ||
-      /* nealsid: The following is the big-endian ppc64 check */
+      /* The following is the big-endian ppc64 check */
       *((unsigned int *)&buf) == FAT_MAGIC) {
+    /* Get host info */
+    host_t host = mach_host_self();
+    unsigned i = HOST_BASIC_INFO_COUNT;
     struct host_basic_info hbi;
-    struct fat_header fh;
-    struct fat_arch *fat_archs, *fap;
-    unsigned i;
-    host_t host;
-
-    /* Get our host info */
-    host = mach_host_self();
-    i = HOST_BASIC_INFO_COUNT;
     kern_return_t kr;
-    if ((kr=host_info(host, HOST_BASIC_INFO,
-                      (host_info_t)(&hbi), &i)) != KERN_SUCCESS) {
-      return (-1);
+    if ((kr = host_info(host, HOST_BASIC_INFO,
+                        (host_info_t)(&hbi), &i)) != KERN_SUCCESS) {
+      return -1;
     }
     mach_port_deallocate(mach_task_self(), host);
 
     /* Read in the fat header */
-    lseek(fd, 0, SEEK_SET);
+    struct fat_header fh;
+    if (lseek(fd, 0, SEEK_SET) == -1) {
+      return -1;
+    }
     if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) {
-      return (-1);
+      return -1;
     }
 
     /* Convert fat_narchs to host byte order */
     fh.nfat_arch = NXSwapBigIntToHost(fh.nfat_arch);
 
     /* Read in the fat archs */
-    fat_archs = (struct fat_arch *)malloc(fh.nfat_arch *
-                                          sizeof(struct fat_arch));
+    struct fat_arch *fat_archs =
+        (struct fat_arch *)malloc(fh.nfat_arch * sizeof(struct fat_arch));
     if (fat_archs == NULL) {
-      return (-1);
+      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);
+      return -1;
     }
 
     /*
      * Convert archs to host byte ordering (a constraint of
      * cpusubtype_getbestarch()
      */
-    for (i = 0; i < fh.nfat_arch; i++) {
+    for (unsigned i = 0; i < fh.nfat_arch; i++) {
       fat_archs[i].cputype =
         NXSwapBigIntToHost(fat_archs[i].cputype);
       fat_archs[i].cpusubtype =
         NXSwapBigIntToHost(fat_archs[i].cpusubtype);
       fat_archs[i].offset =
         NXSwapBigIntToHost(fat_archs[i].offset);
       fat_archs[i].size =
         NXSwapBigIntToHost(fat_archs[i].size);
       fat_archs[i].align =
         NXSwapBigIntToHost(fat_archs[i].align);
     }
 
-    fap = NULL;
-    for (i = 0; i < fh.nfat_arch; i++) {
-      /* nealsid: Although the original Apple code uses host_info */
-      /* to retrieve the CPU type, the host_info will still return */
-      /* CPU_TYPE_X86 even if running as an x86_64 binary. Given that */
-      /* this code isn't necessary on i386, I've decided to hardcode */
-      /* looking for a 64-bit binary */
-#if TARGET_CPU_X86_64
-      if (fat_archs[i].cputype == CPU_TYPE_X86_64) {
-#elif TARGET_CPU_PPC64
-      if (fat_archs[i].cputype == CPU_TYPE_POWERPC64) {
-#else
-#error undefined cpu!
-        {
-#endif
-          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 */
-      lseek(fd, arch_offset, SEEK_SET);
-      if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) {
-        return (-1);
+    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 (*((unsigned int *)&buf) == MH_MAGIC_64) {
-      struct mach_header_64 mh;
-      struct load_command *load_commands, *lcp;
-      struct symtab_command *stp;
-      long i;
+    if (!fap) {
+      free(fat_archs);
+      return -1;
+    }
+    arch_offset = fap->offset;
+    free(fat_archs);
 
-      lseek(fd, arch_offset, SEEK_SET);
-      if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) {
-        return (-1);
-      }
-      load_commands = (struct load_command *)malloc(mh.sizeofcmds);
-      if (load_commands == NULL) {
-        return (-1);
-      }
-      if (read(fd, (char *)load_commands, mh.sizeofcmds) !=
-          mh.sizeofcmds) {
-        free(load_commands);
-        return (-1);
-      }
-      stp = NULL;
-      lcp = load_commands;
-      // nealsid:iterate through all load commands, looking for
-      // LC_SYMTAB load command
-      for (i = 0; i < mh.ncmds; i++) {
-        if (lcp->cmdsize % sizeof(long) != 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(breakpad_nlist);
-      free(load_commands);
+    /* 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;
     }
-    else {
-      sa = N_SYMOFF(buf) + arch_offset;
-      ss = sa + buf.a_syms + arch_offset;
-      n = buf.a_syms;
+  }
+
+  off_t sa;  /* symbol address */
+  off_t ss;  /* start of strings */
+  register 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;
     }
 
-    lseek(fd, sa, SEEK_SET);
-
-    // 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) {
-      long savpos;
-
-      m = sizeof (space);
-      if (n < m)
-        m = n;
-      if (read(fd, (char *)space, m) != m)
+    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) !=
+        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 (long 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;
-      n -= m;
-      savpos = lseek(fd, 0, SEEK_CUR);
-      for (q = space; (m -= sizeof(breakpad_nlist)) >= 0; q++) {
-        char nambuf[BUFSIZ];
-
-        if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
-          continue;
+      }
+      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;
+  }
 
-        // seek to the location in the binary where the symbol
-        // name is stored & read it into memory
-        lseek(fd, ss+q->n_un.n_strx, SEEK_SET);
-        read(fd, nambuf, maxlen+1);
-        s2 = nambuf;
-        for (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
-          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:           ;
-        }
-      }
-      lseek(fd, savpos, SEEK_SET);
-    }
-    return (nreq);
+  if (lseek(fd, sa, SEEK_SET) == -1) {
+    return -1;
   }
 
-#endif  /* __LP64__ */
+  // 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 register_t m = sizeof (space);
+
+    if (n < m)
+      m = n;
+    if (read(fd, (char *)space, m) != m)
+      break;
+    n -= m;
+    long 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;
+}
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_nlist_64.h
@@ -28,16 +28,20 @@
 
 // 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__
 
-typedef struct nlist_64 breakpad_nlist;
+#include <mach/machine.h>
 
-int
-breakpad_nlist_64(const char *name,
-                  breakpad_nlist *list,
-                  const char **symbolNames);
+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__ */
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.cc
@@ -22,41 +22,49 @@
 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (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/mac/handler/dynamic_images.h"
+
 extern "C" { // needed to compile on Leopard
   #include <mach-o/nlist.h>
   #include <stdlib.h>
   #include <stdio.h>
 }
 
 #include "breakpad_nlist_64.h"
 #include <assert.h>
 #include <dlfcn.h>
 #include <mach/mach_vm.h>
+#include <sys/sysctl.h>
+
 #include <algorithm>
-#include "client/mac/handler/dynamic_images.h"
+#include <string>
+#include <vector>
 
 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 void* address,
+                                          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|
@@ -111,315 +119,352 @@ static mach_vm_size_t GetMemoryRegionSiz
 }
 
 #define kMaxStringLength 8192
 //==============================================================================
 // Reads a NULL-terminated string from another task.
 //
 // Warning!  This will not read any strings longer than kMaxStringLength-1
 //
-static void* ReadTaskString(task_port_t target_task,
-                            const void* address) {
+static 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;
 
-    kern_return_t kr;
-    return ReadTaskMemory(target_task, address, (size_t)size_to_read, &kr);
+    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 NULL;
+  return string();
 }
 
 //==============================================================================
-// Reads an address range from another task.  A block of memory is malloced
-// and should be freed by the caller.
-void* ReadTaskMemory(task_port_t target_task,
-                     const void* address,
-                     size_t length,
-                     kern_return_t *kr) {
-  void* result = NULL;
+// 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 =
-      reinterpret_cast<mach_vm_address_t>(address) & (-systemPageSize);
+  mach_vm_address_t page_address = address & (-systemPageSize);
 
   mach_vm_address_t last_page_address =
-      (reinterpret_cast<mach_vm_address_t>(address) + length +
-       (systemPageSize - 1)) & (-systemPageSize);
+      (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;
-
-  r = mach_vm_read(target_task,
-                   page_address,
-                   page_size,
-                   reinterpret_cast<vm_offset_t*>(&local_start),
-                   &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 (kr != NULL) {
-    *kr = r;
-  }
+  if (r != KERN_SUCCESS)
+    return r;
 
-  if (r == KERN_SUCCESS) {
-    result = malloc(length);
-    if (result != NULL) {
-      memcpy(result,
-             &local_start[(mach_vm_address_t)address - page_address],
-             length);
-    }
-    mach_vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_length);
-  }
-
-  return result;
+  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 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 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;
+  
+  const mach_header_type* header =
+      reinterpret_cast<const mach_header_type*>(&image.header_[0]);
+
+  if(header->magic != MachBits::magic) {
+    return false;
+  }
+
+  const struct load_command *cmd =
+      reinterpret_cast<const struct load_command *>(header + 1);
+
+  bool found_text_section = false;
+  bool found_dylib_id_command = false;
+  for (unsigned int i = 0; cmd && (i < header->ncmds); ++i) {
+    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 (!strcmp(seg->segname, "__TEXT")) {
+          image.vmaddr_ = seg->vmaddr;
+          image.vmsize_ = seg->vmsize;
+          image.slide_ = 0;
+
+          if (seg->fileoff == 0 && seg->filesize != 0) {
+            image.slide_ =
+                (uintptr_t)image.GetLoadAddress() - (uintptr_t)seg->vmaddr;
+          }
+          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) {
+      return true;
+    }
+
+    cmd = reinterpret_cast<const struct load_command *>
+        (reinterpret_cast<const char *>(cmd) + cmd->cmdsize);
+  }
+
+  return false;
+}
+
+//==============================================================================
 // Initializes vmaddr_, vmsize_, and slide_
 void DynamicImage::CalculateMemoryAndVersionInfo() {
-  breakpad_mach_header *header = GetMachHeader();
-
   // unless we can process the header, ensure that calls to
   // IsValid() will return false
   vmaddr_ = 0;
   vmsize_ = 0;
   slide_ = 0;
   version_ = 0;
 
-  bool foundTextSection = false;
-  bool foundDylibIDCommand = false;
-  
-#if __LP64__
-  if(header->magic != MH_MAGIC_64) {
-    return;
-  }
-#else
-  if(header->magic != MH_MAGIC) {
-    return;
-  }
-#endif
-
-#ifdef __LP64__
-  const uint32_t segmentLoadCommand = LC_SEGMENT_64;
-#else
-  const uint32_t segmentLoadCommand = LC_SEGMENT;
-#endif
-
-  const struct load_command *cmd =
-    reinterpret_cast<const struct load_command *>(header + 1);
-
-  for (unsigned int i = 0; cmd && (i < header->ncmds); ++i) {
-    if (!foundTextSection) {
-      if (cmd->cmd == segmentLoadCommand) {
-        const breakpad_mach_segment_command *seg =
-            reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
-
-        if (!strcmp(seg->segname, "__TEXT")) {
-          vmaddr_ = seg->vmaddr;
-          vmsize_ = seg->vmsize;
-          slide_ = 0;
-
-          if (seg->fileoff == 0  &&  seg->filesize != 0) {
-            slide_ = (uintptr_t)GetLoadAddress() - (uintptr_t)seg->vmaddr;
-          }
-          foundTextSection = true;
-        }
-      }
-    }
-
-    if (!foundDylibIDCommand) {
-      if (cmd->cmd == LC_ID_DYLIB) {
-        const struct dylib_command *dc =
-            reinterpret_cast<const struct dylib_command *>(cmd);
-
-        version_ = dc->dylib.current_version;
-        foundDylibIDCommand = true;
-      }
-    }
-
-    if (foundDylibIDCommand && foundTextSection) {
-      return;
-    }
-
-    cmd = reinterpret_cast<const struct load_command *>
-      (reinterpret_cast<const char *>(cmd) + cmd->cmdsize);
-  }
-
+  // The function template above does all the real work.
+  if (Is64Bit())
+    FindTextSection<MachO64>(*this);
+  else
+    FindTextSection<MachO32>(*this);
 }
 
-void DynamicImage::Print() {
-  const char *path = GetFilePath();
-  if (!path) {
-    path = "(unknown)";
-  }
-  printf("%p: %s\n", GetLoadAddress(), path);
-  breakpad_mach_header *header = GetMachHeader();
-  MachHeader(*header).Print();
-  printf("vmaddr\t\t: %p\n", reinterpret_cast<void*>(GetVMAddr()));
-  printf("vmsize\t\t: %llu\n", GetVMSize());
-  printf("slide\t\t: %td\n", GetVMAddrSlide());
+//==============================================================================
+// 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), image_list_() {
+    : task_(task),
+      cpu_type_(DetermineTaskCPUType(task)),
+      image_list_() {
   ReadImageInfoForTask();
 }
 
-void* DynamicImages::GetDyldAllImageInfosPointer() {
-  const char *imageSymbolName = "_dyld_all_image_infos";
-  const char *dyldPath = "/usr/lib/dyld";
-#ifndef __LP64__
-  struct nlist l[8];
-  memset(l, 0, sizeof(l) );
+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;
 
-  // First we lookup the address of the "_dyld_all_image_infos" struct
-  // which lives in "dyld".  This structure contains information about all
-  // of the loaded dynamic images.
-  struct nlist &list = l[0];
-  list.n_un.n_name = const_cast<char *>(imageSymbolName);
-  nlist(dyldPath,&list);
-  if(list.n_value) {
-    return reinterpret_cast<void*>(list.n_value);
+  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;
   }
 
-  return NULL;
-#else
-  struct nlist_64 l[8];
-  struct nlist_64 &list = l[0];
-
-  memset(l, 0, sizeof(l) );
-
-  const char *symbolNames[2] = { imageSymbolName, "\0" };
+  assert(list.n_value);
+  return list.n_value;
+}
 
-  int invalidEntriesCount = breakpad_nlist_64(dyldPath,&list,symbolNames);
+uint64_t DynamicImages::GetDyldAllImageInfosPointer() {
+  const char *imageSymbolName = "_dyld_all_image_infos";
+  const char *dyldPath = "/usr/lib/dyld";
 
-  if(invalidEntriesCount != 0) {
-    return NULL;
-  }
-  assert(list.n_value);
-  return reinterpret_cast<void*>(list.n_value);
-#endif
+  if (Is64Bit())
+    return LookupSymbol<MachO64>(imageSymbolName, dyldPath, cpu_type_);
+  return LookupSymbol<MachO32>(imageSymbolName, dyldPath, cpu_type_);
+}
 
-}
 //==============================================================================
 // This code was written using dyld_debug.c (from Darwin) as a guide.
+
+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;
+  typedef typename MachBits::mach_header_type mach_header_type;
+
+  // 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]);
+    images.image_list_.reserve(count);
+
+    for (int i = 0; i < count; ++i) {
+      dyld_image_info &info = infoArray[i];
+
+      // First read just the mach_header from the image in the task.
+      vector<uint8_t> mach_header_bytes;
+      if (ReadTaskMemory(images.task_,
+                         info.load_address_,
+                         sizeof(mach_header_type),
+                         mach_header_bytes) != KERN_SUCCESS)
+        continue;  // bail on this dynamic image
+
+      mach_header_type *header =
+          reinterpret_cast<mach_header_type*>(&mach_header_bytes[0]);
+
+      // 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_,
+                         info.load_address_,
+                         header_size,
+                         mach_header_bytes) != KERN_SUCCESS)
+        continue;
+
+      header = reinterpret_cast<mach_header_type*>(&mach_header_bytes[0]);
+
+      // Read the file name from the task's memory space.
+      string file_path;
+      if (info.file_path_) {
+        // 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_, info.file_path_);
+      }
+
+      // 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,
+                                   info.load_address_,
+                                   file_path,
+                                   info.file_mod_date_,
+                                   images.task_,
+                                   images.cpu_type_);
+
+      if (new_image->IsValid()) {
+        images.image_list_.push_back(DynamicImageRef(new_image));
+      } else {
+        delete new_image;
+      }
+    }
+
+    // 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() {
-  void *imageList = GetDyldAllImageInfosPointer();
+  uint64_t imageList = GetDyldAllImageInfosPointer();
 
   if (imageList) {
-    kern_return_t kr;
-    // 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.
-    dyld_all_image_infos *dyldInfo = reinterpret_cast<dyld_all_image_infos*>
-      (ReadTaskMemory(task_,
-                      reinterpret_cast<void*>(imageList),
-                      sizeof(dyld_all_image_infos), &kr));
-
-    if (dyldInfo) {
-      // number of loaded images
-      int count = dyldInfo->infoArrayCount;
-
-      // Read an array of dyld_image_info structures each containing
-      // information about a loaded image.
-      dyld_image_info *infoArray = reinterpret_cast<dyld_image_info*>
-        (ReadTaskMemory(task_,
-                        dyldInfo->infoArray,
-                        count*sizeof(dyld_image_info), &kr));
-
-      image_list_.reserve(count);
-
-      for (int i = 0; i < count; ++i) {
-        dyld_image_info &info = infoArray[i];
-
-        // First read just the mach_header from the image in the task.
-        breakpad_mach_header *header = reinterpret_cast<breakpad_mach_header*>
-          (ReadTaskMemory(task_,
-                          info.load_address_,
-                          sizeof(breakpad_mach_header), &kr));
-
-        if (!header)
-          break;   // bail on this dynamic image
-
-        // Now determine the total amount we really want to read based on the
-        // size of the load commands.  We need the header plus all of the
-        // load commands.
-        size_t header_size =
-            sizeof(breakpad_mach_header) + header->sizeofcmds;
-
-        free(header);
-
-        header = reinterpret_cast<breakpad_mach_header*>
-          (ReadTaskMemory(task_, info.load_address_, header_size, &kr));
-
-        // Read the file name from the task's memory space.
-        char *file_path = NULL;
-        if (info.file_path_) {
-          // 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 = reinterpret_cast<char*>
-            (ReadTaskString(task_, info.file_path_));
-        }
-
-        // Create an object representing this image and add it to our list.
-        DynamicImage *new_image;
-        new_image = new DynamicImage(header,
-                                     header_size,
-                                     (breakpad_mach_header*)info.load_address_,
-                                     file_path,
-                                     info.file_mod_date_,
-                                     task_);
-
-        if (new_image->IsValid()) {
-          image_list_.push_back(DynamicImageRef(new_image));
-        } else {
-          delete new_image;
-        }
-
-        if (file_path) {
-          free(file_path);
-        }
-      }
-
-      free(dyldInfo);
-      free(infoArray);
-
-      // sorts based on loading address
-      sort(image_list_.begin(), 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(image_list_.begin(),
-                                                    image_list_.end() );
-      image_list_.erase(it, image_list_.end());
-    }
+    if (Is64Bit())
+      ReadImageInfo<MachO64>(*this, imageList);
+    else
+      ReadImageInfo<MachO32>(*this, imageList);
   }
 }
 
 //==============================================================================
 DynamicImage  *DynamicImages::GetExecutableImage() {
   int executable_index = GetExecutableImageIndex();
 
   if (executable_index >= 0) {
@@ -431,17 +476,40 @@ DynamicImage  *DynamicImages::GetExecuta
 
 //==============================================================================
 // 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->GetMachHeader()->filetype == MH_EXECUTE) {
+    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, mibLen, &cpu_type, &cpuTypeSize, 0, 0);
+    return cpu_type;
+  }
+
+  return GetNativeCPUType();
+}
+
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.h
@@ -36,173 +36,168 @@
 
 #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>
 
 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_info {
-  struct mach_header        *load_address_;
-  char                      *file_path_;
-  uintptr_t                 file_mod_date_;
-} dyld_image_info;
+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_infos {
+typedef struct dyld_all_image_infos32 {
   uint32_t                      version;  // == 1 in Mac OS X 10.4
   uint32_t                      infoArrayCount;
-  const struct dyld_image_info  *infoArray;
-  void*                         notification;
+  uint32_t                      infoArray;  // const struct dyld_image_info*
+  uint32_t                      notification;
   bool                          processDetachedFromSharedRegion;
-} dyld_all_image_infos;
+} 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;
+} 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
 
-//==============================================================================
-// A simple wrapper for a mach_header
-//
-// This could be fleshed out with some more interesting methods.
-class MachHeader {
- public:
-  explicit MachHeader(const breakpad_mach_header &header) : header_(header) {}
+// Helper functions to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImage;
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image);
 
-  void Print() {
-    printf("magic\t\t: %4x\n", header_.magic);
-    printf("cputype\t\t: %d\n", header_.cputype);
-    printf("cpusubtype\t: %d\n", header_.cpusubtype);
-    printf("filetype\t: %d\n", header_.filetype);
-    printf("ncmds\t\t: %d\n", header_.ncmds);
-    printf("sizeofcmds\t: %d\n", header_.sizeofcmds);
-    printf("flags\t\t: %d\n", header_.flags);
-  }
-
-  breakpad_mach_header   header_;
-};
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image);
 
 //==============================================================================
 // Represents a single dynamically loaded mach-o image
 class DynamicImage {
  public:
-  DynamicImage(breakpad_mach_header *header, // we take ownership
-               size_t header_size,              // includes load commands
-               breakpad_mach_header *load_address,
-               char *inFilePath,
+  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)
-    : header_(header),
+               mach_port_t task,
+               cpu_type_t cpu_type)
+    : header_(header, header + header_size),
       header_size_(header_size),
       load_address_(load_address),
       vmaddr_(0),
       vmsize_(0),
       slide_(0),
       version_(0),
-      file_path_(NULL),
+      file_path_(file_path),
       file_mod_date_(image_mod_date),
-      task_(task) {
-    InitializeFilePath(inFilePath);
+      task_(task),
+      cpu_type_(cpu_type) {
     CalculateMemoryAndVersionInfo();
   }
 
-  ~DynamicImage() {
-    if (file_path_) {
-      free(file_path_);
-    }
-    free(header_);
-  }
-
-  // Returns pointer to a local copy of the mach_header plus load commands
-  breakpad_mach_header *GetMachHeader() {return header_;}
-
   // Size of mach_header plus load commands
-  size_t GetHeaderSize() const {return header_size_;}
+  size_t GetHeaderSize() const {return header_.size();}
 
   // Full path to mach-o binary
-  char *GetFilePath() {return file_path_;}
+  string GetFilePath() {return file_path_;}
 
-  uintptr_t GetModDate() const {return file_mod_date_;}
+  uint64_t GetModDate() const {return file_mod_date_;}
 
   // Actual address where the image was loaded
-  breakpad_mach_header *GetLoadAddress() const {return load_address_;}
+  uint64_t GetLoadAddress() const {return load_address_;}
 
   // Address where the image should be loaded
   mach_vm_address_t GetVMAddr() const {return vmaddr_;}
 
   // Difference between GetLoadAddress() and GetVMAddr()
   ptrdiff_t GetVMAddrSlide() const {return slide_;}
 
   // Size of the image
   mach_vm_size_t GetVMSize() const {return vmsize_;}
 
   // Task owning this loaded image
   mach_port_t GetTask() {return task_;}
 
+  // CPU type of the task
+  cpu_type_t GetCPUType() {return cpu_type_;}
+
+  // 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();
   }
 
-  // Debugging
-  void Print();
+  // Sanity checking
+  bool IsValid() {return GetVMSize() != 0;}
 
  private:
   DynamicImage(const DynamicImage &);
   DynamicImage &operator=(const DynamicImage &);
 
   friend class DynamicImages;
-
-  // Sanity checking
-  bool IsValid() {return GetVMSize() != 0;}
-
-  // Makes local copy of file path to mach-o binary
-  void InitializeFilePath(char *inFilePath) {
-    if (inFilePath) {
-      size_t path_size = 1 + strlen(inFilePath);
-      file_path_ = reinterpret_cast<char*>(malloc(path_size));
-      strlcpy(file_path_, inFilePath, path_size);
-    } else {
-      file_path_ = NULL;
-    }
-  }
+  template<typename MachBits>
+  friend bool FindTextSection(DynamicImage& image);
+  template<typename MachBits>
+  friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
 
   // Initializes vmaddr_, vmsize_, and slide_
   void CalculateMemoryAndVersionInfo();
 
-  breakpad_mach_header    *header_;        // our local copy of the header
+  const vector<uint8_t>   header_;        // our local copy of the header
   size_t                  header_size_;    // mach_header plus load commands
-  breakpad_mach_header    *load_address_;  // base address image is mapped into
+  uint64_t                load_address_;   // base address image is mapped into
   mach_vm_address_t       vmaddr_;
   mach_vm_size_t          vmsize_;
   ptrdiff_t               slide_;
   uint32_t                version_;        // Dylib version
-  char                    *file_path_;     // path dyld used to load the image
+  string                  file_path_;     // path dyld used to load the image
   uintptr_t               file_mod_date_;  // time_t of image file
 
   mach_port_t             task_;
+  cpu_type_t              cpu_type_;        // CPU type of task_
 };
 
 //==============================================================================
 // 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<().
 //
@@ -225,16 +220,21 @@ class DynamicImageRef {
   // 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 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);
 
@@ -257,49 +257,57 @@ class DynamicImages {
 
   // 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_;}
 
-  // Debugging
-  void Print() {
-    for (int i = 0; i < GetImageCount(); ++i) {
-      image_list_[i]->Print();
-    }
-  }
+  // 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);
 
-  void TestPrint() {
-    const breakpad_mach_header *header;
-    for (int i = 0; i < GetImageCount(); ++i) {
-      printf("dyld: %p: name = %s\n", _dyld_get_image_header(i),
-             _dyld_get_image_name(i) );
-
-      const void *imageHeader = _dyld_get_image_header(i);
-      header = reinterpret_cast<const breakpad_mach_header*>(imageHeader);
-
-      MachHeader(*header).Print();
-    }
+  // 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;
+#else
+#error "GetNativeCPUType not implemented for this architecture"
+#endif
   }
 
  private:
+  template<typename MachBits>
+  friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
   bool IsOurTask() {return task_ == mach_task_self();}
 
   // Initialization
   void ReadImageInfoForTask();
-  void* GetDyldAllImageInfosPointer();
+  uint64_t GetDyldAllImageInfosPointer();
 
   mach_port_t              task_;
+  cpu_type_t               cpu_type_;  // CPU type of task_
   vector<DynamicImageRef>  image_list_;
 };
 
-// Returns a malloced block containing the contents of memory at a particular
+// Fill bytes with the contents of memory at a particular
 // location in another task.
-void* ReadTaskMemory(task_port_t target_task,
-                     const void* address,
-                     size_t len,
-                     kern_return_t *kr);
+kern_return_t ReadTaskMemory(task_port_t target_task,
+                             const uint64_t address,
+                             size_t length,
+                             vector<uint8_t> &bytes);
 
 }   // namespace google_breakpad
 
 #endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc
@@ -26,17 +26,19 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (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/i386/thread_status.h>
 #include <mach/mach_vm.h>
+#include <mach/ppc/thread_status.h>
 #include <mach/vm_statistics.h>
 #include <mach-o/dyld.h>
 #include <mach-o/loader.h>
 #include <sys/sysctl.h>
 #include <sys/resource.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 
@@ -60,38 +62,42 @@ namespace google_breakpad {
 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()),
       dynamic_images_(NULL),
       memory_blocks_(&allocator_) {
   GatherSystemInformation();
 }
 
 // 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()),
       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();
 }
 
 MinidumpGenerator::~MinidumpGenerator() {
   delete dynamic_images_;
 }
@@ -249,18 +255,20 @@ size_t MinidumpGenerator::CalculateStack
                            &info_count);
 
   if (start_addr < stack_region_base) {
     // probably stack corruption, since mach_vm_region had to go
     // higher in the process address space to find a valid region.
     return 0;
   }
 
-
-  if ((stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK) {
+  if (((cpu_type_ & CPU_ARCH_ABI64) &&
+       (stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_64BIT) ||
+      (!(cpu_type_ & CPU_ARCH_ABI64) &&
+       (stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_32BIT)) {
     // The stack for thread 0 needs to extend all the way to
     // 0xc0000000 on 32 bit and 00007fff5fc00000 on 64bit.  HOWEVER,
     // for many processes, the stack is first created in one page
     // below this, and is then later extended to a much larger size by
     // creating a new VM region immediately below the initial page.
 
     // You can see this for yourself by running vmmap on a "hello,
     // world" program
@@ -300,69 +308,129 @@ bool MinidumpGenerator::WriteStackFromSt
 
       result = memory.Copy(dummy_stack, size);
   } else {
 
     if (!memory.Allocate(size))
       return false;
 
     if (dynamic_images_) {
-
-      kern_return_t kr;
-
-      void *stack_memory = ReadTaskMemory(crashing_task_,
-                                          (void*)start_addr,
-                                          size,
-                                          &kr);
-
-      if (stack_memory == NULL) {
+      vector<uint8_t> stack_memory;
+      if (ReadTaskMemory(crashing_task_,
+                         start_addr,
+                         size,
+                         stack_memory) != KERN_SUCCESS) {
         return false;
       }
 
-      result = memory.Copy(stack_memory, size);
-      free(stack_memory);
+      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;
 }
 
-#if TARGET_CPU_PPC || TARGET_CPU_PPC64
 bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
                                    MDMemoryDescriptor *stack_location) {
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
+  switch (cpu_type_) {
+    case CPU_TYPE_POWERPC:
+      return WriteStackPPC(state, stack_location);
+    case CPU_TYPE_POWERPC64:
+      return WriteStackPPC64(state, stack_location);
+    case CPU_TYPE_I386:
+      return WriteStackX86(state, stack_location);
+    case CPU_TYPE_X86_64:
+      return WriteStackX86_64(state, stack_location);
+    default:
+      return false;
+  }
+}
+
+bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
+                                     MDLocationDescriptor *register_location) {
+  switch (cpu_type_) {
+    case CPU_TYPE_POWERPC:
+      return WriteContextPPC(state, register_location);
+    case CPU_TYPE_POWERPC64:
+      return WriteContextPPC64(state, register_location);
+    case CPU_TYPE_I386:
+      return WriteContextX86(state, register_location);
+    case CPU_TYPE_X86_64:
+      return WriteContextX86_64(state, register_location);
+    default:
+      return false;
+  }
+}
+
+u_int64_t MinidumpGenerator::CurrentPCForStack(
+    breakpad_thread_state_data_t state) {
+  switch (cpu_type_) {
+    case CPU_TYPE_POWERPC:
+      return CurrentPCForStackPPC(state);
+    case CPU_TYPE_POWERPC64:
+      return CurrentPCForStackPPC64(state);
+    case CPU_TYPE_I386:
+      return CurrentPCForStackX86(state);
+    case CPU_TYPE_X86_64:
+      return CurrentPCForStackX86_64(state);
+    default:
+      assert("Unknown CPU type!");
+      return 0;
+  }
+}
+
+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);
 }
 
 u_int64_t
-MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
+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);
 }
 
-bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
-                                     MDLocationDescriptor *register_location) {
-  TypedMDRVA<MinidumpContext> context(&writer_);
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
+u_int64_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();
-  MinidumpContext *context_ptr = context.get();
+  MDRawContextPPC *context_ptr = context.get();
   context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
 
 #define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
 #define AddGPR(a) context_ptr->gpr[a] = REGISTER_FROM_THREADSTATE(machine_state, r ## a)
 
   AddReg(srr0);
   AddReg(cr);
   AddReg(xer);
@@ -397,67 +465,134 @@ bool MinidumpGenerator::WriteContext(bre
   AddGPR(24);
   AddGPR(25);
   AddGPR(26);
   AddGPR(27);
   AddGPR(28);
   AddGPR(29);
   AddGPR(30);
   AddGPR(31);
-
-#if TARGET_CPU_PPC
-  /* The mq register  is only for PPC */
   AddReg(mq);
-#endif
-
+#undef AddReg
+#undef AddGPR
 
   return true;
 }
 
-#elif TARGET_CPU_X86 || TARGET_CPU_X86_64
-
-bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
-                                   MDMemoryDescriptor *stack_location) {
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
-
-#if TARGET_CPU_X86_64
-  mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, rsp);
-#else
-  mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp);
-#endif
-  return WriteStackFromStartAddress(start_addr, stack_location);
-}
-
-u_int64_t
-MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
-
-#if TARGET_CPU_X86_64
-  return REGISTER_FROM_THREADSTATE(machine_state, rip);
-#else
-  return REGISTER_FROM_THREADSTATE(machine_state, eip);
-#endif
-}
-
-bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
-                                     MDLocationDescriptor *register_location) {
-  TypedMDRVA<MinidumpContext> context(&writer_);
-  breakpad_thread_state_t *machine_state =
-    reinterpret_cast<breakpad_thread_state_t *>(state);
+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();
-  MinidumpContext *context_ptr = context.get();
+  MDRawContextPPC64 *context_ptr = context.get();
+  context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
 
 #define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
-#if TARGET_CPU_X86
+#define AddGPR(a) context_ptr->gpr[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;
+}
+
+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 = REGISTER_FROM_THREADSTATE(machine_state, rsp);
+  return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+u_int64_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);
+}
+
+u_int64_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 = 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);
@@ -467,17 +602,36 @@ bool MinidumpGenerator::WriteContext(bre
   AddReg(ds);
   AddReg(ss);
   AddReg(es);
   AddReg(fs);
   AddReg(gs);
   AddReg(eflags);
 
   AddReg(eip);
-#else
+#undef AddReg(a)
+
+  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 = 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);
@@ -490,36 +644,56 @@ bool MinidumpGenerator::WriteContext(bre
   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<u_int32_t>(machine_state->__rflags);
+  context_ptr->eflags = static_cast<u_int32_t>(REGISTER_FROM_THREADSTATE(machine_state, rflags));
   AddReg(cs);
   AddReg(fs);
   AddReg(gs);
-#endif
 #undef AddReg(a)
 
   return true;
 }
-#endif
+
+bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
+                                       thread_state_t state,
+                                       mach_msg_type_number_t *count) {
+  thread_state_flavor_t flavor;
+  switch (cpu_type_) {
+    case CPU_TYPE_POWERPC:
+      flavor = PPC_THREAD_STATE;
+      break;
+    case CPU_TYPE_POWERPC64:
+      flavor = PPC_THREAD_STATE64;
+      break;
+    case CPU_TYPE_I386:
+      flavor = i386_THREAD_STATE;
+      break;
+    case CPU_TYPE_X86_64:
+      flavor = x86_THREAD_STATE64;
+      break;
+    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 (thread_get_state(thread_id, BREAKPAD_MACHINE_THREAD_STATE,
-                       state, &state_count) ==
-      KERN_SUCCESS) {
+  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;
 
@@ -648,31 +822,25 @@ bool MinidumpGenerator::WriteMemoryListS
   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.
-      kern_return_t kr;
-
-      void *memory =
-        ReadTaskMemory(
-          crashing_task_,
-          reinterpret_cast<const void *>(ip_memory_d.start_of_memory_range),
-          ip_memory_d.memory.data_size,
-          &kr);
-
-      if (memory == NULL) {
+      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, ip_memory_d.memory.data_size);
-      free(memory);
+      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();
@@ -697,23 +865,20 @@ MinidumpGenerator::WriteExceptionStream(
   exception_ptr->thread_id = exception_thread_;
 
   // This naming is confusing, but it is the proper translation from
   // mach naming to minidump naming.
   exception_ptr->exception_record.exception_code = exception_type_;
   exception_ptr->exception_record.exception_flags = exception_code_;
 
   breakpad_thread_state_data_t state;
-  mach_msg_type_number_t stateCount
+  mach_msg_type_number_t state_count
       = static_cast<mach_msg_type_number_t>(sizeof(state));
 
-  if (thread_get_state(exception_thread_,
-                       BREAKPAD_MACHINE_THREAD_STATE,
-                       state,
-                       &stateCount) != KERN_SUCCESS)
+  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
@@ -728,47 +893,47 @@ bool MinidumpGenerator::WriteSystemInfoS
 
   if (!info.Allocate())
     return false;
 
   system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM;
   system_info_stream->location = info.location();
 
   // CPU Information
-  uint32_t cpu_type;
-  size_t len = sizeof(cpu_type);
-  sysctlbyname("hw.cputype", &cpu_type, &len, NULL, 0);
   uint32_t number_of_processors;
-  len = sizeof(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) {
+  switch (cpu_type_) {
     case CPU_TYPE_POWERPC:
+    case CPU_TYPE_POWERPC64:
       info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC;
       break;
     case CPU_TYPE_I386:
     case CPU_TYPE_X86_64:
-      // hw.cputype is currently always I386 even on an x86-64 system
+      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__
-      info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
       // 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__)
-      info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64;
+
 #define cpuid(op,eax,ebx,ecx,edx)      \
   asm ("cpuid         \n\t"            \
        : "=a" (eax),                   \
          "=b" (ebx),                   \
          "=c" (ecx),                   \
          "=d" (edx)                    \
        : "0" (op))
 #endif
@@ -832,29 +997,22 @@ bool MinidumpGenerator::WriteModuleStrea
                                           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;
 
-    const breakpad_mach_header *header = image->GetMachHeader();
-
-    if (!header)
-      return false;
-
-    int cpu_type = header->cputype;
-
     memset(module, 0, sizeof(MDRawModule));
 
     MDLocationDescriptor string_location;
 
-    const char* name = image->GetFilePath();
-    if (!writer_.WriteString(name, 0, &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<u_int32_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
@@ -871,22 +1029,21 @@ bool MinidumpGenerator::WriteModuleStrea
       //    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, cpu_type, name)) {
+    if (!WriteCVRecord(module, image->GetCPUType(), name.c_str())) {
       return false;
     }
   } else {
-    // we're getting module info in the crashed process
-
+    // Getting module info in the crashed process
     const breakpad_mach_header *header;
     header = (breakpad_mach_header*)_dyld_get_image_header(index);
     if (!header)
       return false;
 
 #ifdef __LP64__
     assert(header->magic == MH_MAGIC_64);
 
@@ -898,25 +1055,25 @@ bool MinidumpGenerator::WriteModuleStrea
     if(header->magic != MH_MAGIC)
       return false;
 #endif
 
     int cpu_type = header->cputype;
     unsigned long slide = _dyld_get_image_vmaddr_slide(index);
     const char* name = _dyld_get_image_name(index);
     const struct load_command *cmd =
-      reinterpret_cast<const struct load_command *>(header + 1);
+        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);
+            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;
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h
@@ -42,35 +42,18 @@
 #include "google_breakpad/common/minidump_format.h"
 
 #include "dynamic_images.h"
 
 namespace google_breakpad {
 
 using std::string;
 
-#if TARGET_CPU_X86_64 || TARGET_CPU_PPC64
-#define TOP_OF_THREAD0_STACK 0x00007fff5fbff000
-#else
-#define TOP_OF_THREAD0_STACK 0xbffff000
-#endif
-
-#if TARGET_CPU_X86_64
-typedef x86_thread_state64_t breakpad_thread_state_t;
-typedef MDRawContextAMD64 MinidumpContext;
-#elif TARGET_CPU_X86
-typedef  i386_thread_state_t breakpad_thread_state_t;
-typedef MDRawContextX86 MinidumpContext;
-#elif TARGET_CPU_PPC64
-typedef ppc_thread_state64_t breakpad_thread_state_t;
-typedef MDRawContextPPC64 MinidumpContext;
-#elif TARGET_CPU_PPC
-typedef ppc_thread_state_t breakpad_thread_state_t;
-typedef MDRawContextPPC MinidumpContext;
-#endif
+const u_int64_t TOP_OF_THREAD0_STACK_64BIT = 0x00007fff5fbff000LL;
+const u_int32_t TOP_OF_THREAD0_STACK_32BIT = 0xbffff000;
 
 // Use the REGISTER_FROM_THREADSTATE to access a register name from the
 // breakpad_thread_state_t structure.
 #if __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64
 // 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.
@@ -124,45 +107,70 @@ class MinidumpGenerator {
   bool WriteExceptionStream(MDRawDirectory *exception_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);
 
   // Helpers
   u_int64_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 WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
   bool WriteCVRecord(MDRawModule *module, int cpu_type, 
                      const char *module_path);
   bool WriteModuleStream(unsigned int index, MDRawModule *module);
+  size_t CalculateStackSize(mach_vm_address_t start_addr);
+  int  FindExecutableModule();
 
-  size_t CalculateStackSize(mach_vm_address_t start_addr);
-
-  int  FindExecutableModule();
+  // Per-CPU implementations of these methods
+  bool WriteStackPPC(breakpad_thread_state_data_t state,
+                     MDMemoryDescriptor *stack_location);
+  bool WriteContextPPC(breakpad_thread_state_data_t state,
+                       MDLocationDescriptor *register_location);
+  u_int64_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);
+  u_int64_t CurrentPCForStackPPC64(breakpad_thread_state_data_t state);
+  bool WriteStackX86(breakpad_thread_state_data_t state,
+                       MDMemoryDescriptor *stack_location);
+  bool WriteContextX86(breakpad_thread_state_data_t state,
+                       MDLocationDescriptor *register_location);
+  u_int64_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);
+  u_int64_t CurrentPCForStackX86_64(breakpad_thread_state_data_t state);
 
   // disallow copy ctor and operator=
   explicit MinidumpGenerator(const MinidumpGenerator &);
   void operator=(const MinidumpGenerator &);
 
   // Use this writer to put the data to disk
   MinidumpFileWriter writer_;
 
   // Exception information
   int exception_type_;
   int exception_code_;
   int 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_;
   
   // Information about dynamically loaded code
deleted file mode 100644
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <unistd.h>
-
-#include <pthread.h>
-#include <pwd.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "minidump_generator.h"
-#include "minidump_file_writer.h"
-
-using std::string;
-using google_breakpad::MinidumpGenerator;
-
-static bool doneWritingReport = false;
-
-static void *Reporter(void *) {
-  char buffer[PATH_MAX];
-  MinidumpGenerator md;
-
-  // Write it to the desktop
-  snprintf(buffer,
-           sizeof(buffer),
-           "/tmp/test.dmp");
-
-
-  fprintf(stdout, "Writing %s\n", buffer);
-  unlink(buffer);
-  md.Write(buffer);
-  doneWritingReport = true;
-
-  return NULL;
-}
-
-static void SleepyFunction() {
-  while (!doneWritingReport) {
-    usleep(100);
-  }
-}
-
-int main(int argc, char * const argv[]) {
-  pthread_t reporter_thread;
-
-  if (pthread_create(&reporter_thread, NULL, Reporter, NULL) == 0) {
-    pthread_detach(reporter_thread);
-  } else {
-    perror("pthread_create");
-  }
-
-  SleepyFunction();
-
-  return 0;
-}
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc
@@ -39,25 +39,43 @@
 #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/auto_tempdir.h"
+#include "client/mac/tests/spawn_child_process.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
@@ -212,12 +230,116 @@ TEST_F(CrashGenerationServerTest, testCh
   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);  
+  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,
+			       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 u_int32_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
+
 }  // namespace
--- a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc
@@ -149,35 +149,35 @@ TEST_F(ExceptionHandlerTest, DumpChildPr
   // 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[0]);
+    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[1], &data, 1);
+    read(fds[0], &data, 1);
     exit(0);
   }
   // In the parent process.
   ASSERT_NE(-1, pid);
-  close(fds[1]);
+  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);
@@ -194,17 +194,17 @@ TEST_F(ExceptionHandlerTest, DumpChildPr
   // 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;
-  (void)write(fds[0], &data, 1);
+  (void)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));
 }
 
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/minidump_generator_test.cc
@@ -0,0 +1,319 @@
+// 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/auto_tempdir.h"
+#include "client/mac/tests/spawn_child_process.h"
+#include "common/mac/MachIPC.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;
+  (void)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 u_int32_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)
+
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/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;
+}
--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
@@ -834,17 +834,17 @@ bool MinidumpContext::CheckAgainstSystem
     case MD_CONTEXT_ARM:
       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
         return_value = true;
       break;
   }
 
   BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
                                     HexString(context_cpu_type) <<
-                                    " wrong for MinidumpSysmtemInfo CPU " <<
+                                    " wrong for MinidumpSystemInfo CPU " <<
                                     HexString(system_info_cpu_type);
 
   return return_value;
 }
 
 
 void MinidumpContext::Print() {
   if (!valid_) {