diff --git a/thirdparty/google-breakpad/r318/bin/macx/dump_syms b/thirdparty/google-breakpad/r318/bin/macx/dump_syms new file mode 100644 index 00000000..bc667697 Binary files /dev/null and b/thirdparty/google-breakpad/r318/bin/macx/dump_syms differ diff --git a/thirdparty/google-breakpad/r318/bin/win32/dump_syms.exe b/thirdparty/google-breakpad/r318/bin/win32/dump_syms.exe new file mode 100644 index 00000000..79e1b7f7 Binary files /dev/null and b/thirdparty/google-breakpad/r318/bin/win32/dump_syms.exe differ diff --git a/thirdparty/google-breakpad/r318/breakpad.pro b/thirdparty/google-breakpad/r318/breakpad.pro new file mode 100644 index 00000000..8e1810a6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/breakpad.pro @@ -0,0 +1,315 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Fri Mar 13 16:41:05 2009 +###################################################################### + +TEMPLATE = lib +CONFIG += staticlib debug_and_release + +BUILD_DIR = build +CONFIG(debug, debug|release) { + BUILD_DIR = $$BUILD_DIR/debug + mac: TARGET = $$join(TARGET,,,_debug) + win32: TARGET = $$join(TARGET,,d) +} +CONFIG(release, debug|release) { + BUILD_DIR = $$BUILD_DIR/release + CONFIG += warn_off +} + +BREAKPAD_DIR = "$$[UNIBOARD_DIR]/thirdparty/google-breakpad/r318" +headersHandlerMac.path = "$$BREAKPAD_DIR/include/google_breakpad/client/mac/handler" +headersHandlerMac.files = "src/client/mac/handler/*.h" + +headersHandlerWin.path = "$$BREAKPAD_DIR/include/google_breakpad/client/windows/handler" +headersHandlerWin.files = "src/client/windows/handler/*.h" + +headersClient.path = "$$BREAKPAD_DIR/include/google_breakpad/client" +headersClient.files = "src/client/*.h" + +headersClientCommonWin.path = "$$BREAKPAD_DIR/include/google_breakpad/client/windows/common" +headersClientCommonWin.files = "src/client/windows/common/*.h" + +headersClientCrashGenerationWin.path = "$$BREAKPAD_DIR/include/google_breakpad/client/windows/crash_generation" +headersClientCrashGenerationWin.files = "src/client/windows/crash_generation/*.h" + +headersClientSenderWin.path = "$$BREAKPAD_DIR/include/google_breakpad/client/windows/sender" +headersClientSenderWin.files = "src/client/windows/sender/*.h" + +headersCommon.path = "$$BREAKPAD_DIR/include/google_breakpad/common" +headersCommon.files = "src/common/*.h" + +headersCommonWin.path = "$$BREAKPAD_DIR/include/google_breakpad/common/windows" +headersCommonWin.files = "src/common/windows/*.h" + +headersGbCommon.path = "$$BREAKPAD_DIR/include/google_breakpad/google_breakpad/common" +headersGbCommon.files = "src/google_breakpad/common/*.h" + +headersGbProcessor.path = "$$BREAKPAD_DIR/include/google_breakpad/google_breakpad/processor" +headersGbProcessor.files = "src/google_breakpad/processor/*.h" + +headersProcessor.path = "$$BREAKPAD_DIR/include/google_breakpad/processor" +headersProcessor.files = "src/processor/*.h" + +INSTALLS += "headersHandlerMac" "headersHandlerWin" "headersClient" "headersClientCommonWin" "headersCommonWin"\ + "headersClientCrashGenerationWin" "headersClientSenderWin" "headersCommon" "headersGbCommon" "headersGbProcessor" "headersProcessor" + +INCLUDEPATH += src \ + src/client \ + src/google_breakpad/common \ + src/common \ + src/processor \ + src/google_breakpad/processor + +# Input +HEADERS += src/client/minidump_file_writer-inl.h \ + src/client/minidump_file_writer.h \ + src/common/convert_UTF.h \ + src/common/md5.h \ + src/common/string_conversion.h \ + src/processor/address_map-inl.h \ + src/processor/address_map.h \ + src/processor/basic_code_module.h \ + src/processor/basic_code_modules.h \ + src/processor/contained_range_map-inl.h \ + src/processor/contained_range_map.h \ + src/processor/linked_ptr.h \ + src/processor/logging.h \ + src/processor/pathname_stripper.h \ + src/processor/postfix_evaluator-inl.h \ + src/processor/postfix_evaluator.h \ + src/processor/range_map-inl.h \ + src/processor/range_map.h \ + src/processor/scoped_ptr.h \ + src/processor/simple_symbol_supplier.h \ + src/processor/stack_frame_info.h \ + src/processor/stackwalker_amd64.h \ + src/processor/stackwalker_ppc.h \ + src/processor/stackwalker_sparc.h \ + src/processor/stackwalker_x86.h \ + src/google_breakpad/common/breakpad_types.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_size.h \ + src/google_breakpad/processor/basic_source_line_resolver.h \ + src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/minidump.h \ + src/google_breakpad/processor/minidump_processor.h \ + src/google_breakpad/processor/process_state.h \ + src/google_breakpad/processor/source_line_resolver_interface.h \ + src/google_breakpad/processor/stack_frame.h \ + src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/processor/stackwalker.h \ + src/google_breakpad/processor/symbol_supplier.h \ + src/google_breakpad/processor/system_info.h + + +win32 { + + DESTDIR = "lib/win32" + OBJECTS_DIR = $$BUILD_DIR/objects + MOC_DIR = $$BUILD_DIR/moc + RCC_DIR = $$BUILD_DIR/rcc + UI_DIR = $$BUILD_DIR/ui + + INCLUDEPATH += "C:\Program Files\Microsoft Visual Studio 9.0\DIA SDK\include" + + HEADERS += src/common/windows/guid_string.h \ + src/common/windows/http_upload.h \ + src/common/windows/pdb_source_line_writer.h \ + src/common/windows/string_utils-inl.h \ + src/client/windows/common/auto_critical_section.h \ + src/client/windows/common/ipc_protocol.h \ + src/client/windows/crash_generation/client_info.h \ + src/client/windows/crash_generation/crash_generation_client.h \ + src/client/windows/crash_generation/crash_generation_server.h \ + src/client/windows/crash_generation/minidump_generator.h \ + src/client/windows/handler/exception_handler.h \ + src/client/windows/sender/crash_report_sender.h \ + src/tools/windows/converter/ms_symbol_server_converter.h \ + src/client/windows/tests/crash_generation_app/abstract_class.h \ + src/client/windows/tests/crash_generation_app/crash_generation_app.h \ + src/client/windows/tests/crash_generation_app/precompile.h \ + src/client/windows/tests/crash_generation_app/resource.h + + SOURCES += src/common/windows/guid_string.cc \ + src/common/windows/http_upload.cc \ + src/common/windows/pdb_source_line_writer.cc \ + src/common/windows/string_utils.cc \ + src/client/windows/crash_generation/client_info.cc \ + src/client/windows/crash_generation/crash_generation_client.cc \ + src/client/windows/crash_generation/crash_generation_server.cc \ + src/client/windows/crash_generation/minidump_generator.cc \ + src/client/windows/handler/exception_handler.cc \ + src/client/windows/sender/crash_report_sender.cc \ + src/tools/windows/dump_syms/dump_syms.cc \ + src/tools/windows/symupload/symupload.cc +} + +macx { + + DESTDIR = "lib/macx" + OBJECTS_DIR = $$BUILD_DIR + + CONFIG += x86 ppc + QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.4" + + INCLUDEPATH += src/common/mac \ + src/client/mac/handler \ + src/common/mac/dwarf + + HEADERS += src/common/mac/dump_syms.h \ + src/common/mac/file_id.h \ + src/common/mac/HTTPMultipartUpload.h \ + src/common/mac/macho_id.h \ + src/common/mac/macho_utilities.h \ + src/common/mac/macho_walker.h \ + src/common/mac/string_utilities.h \ + src/client/mac/handler/breakpad_exc_server.h \ + src/client/mac/handler/breakpad_nlist_64.h \ + src/client/mac/handler/dynamic_images.h \ + src/client/mac/handler/exception_handler.h \ + src/client/mac/handler/minidump_generator.h \ + src/client/mac/handler/protected_memory_allocator.h \ + src/common/mac/dwarf/bytereader-inl.h \ + src/common/mac/dwarf/bytereader.h \ + src/common/mac/dwarf/dwarf2enums.h \ + src/common/mac/dwarf/dwarf2reader.h \ + src/common/mac/dwarf/functioninfo.h \ + src/common/mac/dwarf/line_state_machine.h \ + src/common/mac/dwarf/types.h \ + src/common/mac/externals/google-toolbox-for-mac/GTMDefines.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMShading.h \ + src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.h \ + src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugSelectorValidation.h \ + src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.h \ + src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGarbageCollection.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPFetcher.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjectSingleton.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMProgressMonitorInputStream.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.h \ + src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.h \ + src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.h \ + src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimer.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.h \ + src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.h \ + src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/PluginID.h \ + src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/PluginID.h \ + src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/PluginID.h + + SOURCES += src/common/convert_UTF.c \ + src/common/md5.c \ + src/common/string_conversion.cc \ + src/client/minidump_file_writer.cc \ + src/client/minidump_file_writer_unittest.cc \ + src/processor/address_map_unittest.cc \ + src/processor/basic_code_modules.cc \ + src/processor/basic_source_line_resolver.cc \ + src/processor/basic_source_line_resolver_unittest.cc \ + src/processor/call_stack.cc \ + src/processor/contained_range_map_unittest.cc \ + src/processor/logging.cc \ + src/processor/minidump.cc \ + src/processor/minidump_dump.cc \ + src/processor/minidump_processor.cc \ + src/processor/minidump_processor_unittest.cc \ + src/processor/minidump_stackwalk.cc \ + src/processor/pathname_stripper.cc \ + src/processor/pathname_stripper_unittest.cc \ + src/processor/postfix_evaluator_unittest.cc \ + src/processor/process_state.cc \ + src/processor/range_map_unittest.cc \ + src/processor/simple_symbol_supplier.cc \ + src/processor/stackwalker.cc \ + src/processor/stackwalker_amd64.cc \ + src/processor/stackwalker_ppc.cc \ + src/processor/stackwalker_selftest.cc \ + src/processor/stackwalker_sparc.cc \ + src/processor/stackwalker_x86.cc \ + src/common/mac/file_id.cc \ + src/common/mac/macho_id.cc \ + src/common/mac/macho_utilities.cc \ + src/common/mac/macho_walker.cc \ + src/common/mac/string_utilities.cc \ + src/client/mac/handler/breakpad_exc_server.c \ + src/client/mac/handler/breakpad_nlist_64.cc \ + src/client/mac/handler/dynamic_images.cc \ + src/client/mac/handler/exception_handler.cc \ + src/client/mac/handler/exception_handler_test.cc \ + src/client/mac/handler/minidump_generator.cc \ + src/client/mac/handler/minidump_generator_test.cc \ + src/client/mac/handler/protected_memory_allocator.cc \ + src/common/mac/dwarf/bytereader.cc \ + src/common/mac/dwarf/dwarf2reader.cc \ + src/common/mac/dwarf/functioninfo.cc +} + diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_exc_server.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_exc_server.h new file mode 100644 index 00000000..c05f25a8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_exc_server.h @@ -0,0 +1,258 @@ +#ifndef _exc_user_ +#define _exc_user_ + +/* Module exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef exc_MSG_COUNT +#define exc_MSG_COUNT 3 +#endif /* exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__BEGIN_DECLS + + +/* Routine exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__exc_subsystem__defined +#define __Request__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + } __Request__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__exc_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__exc_subsystem__defined +#define __RequestUnion__exc_subsystem__defined +union __RequestUnion__exc_subsystem { + __Request__exception_raise_t Request_exception_raise; + __Request__exception_raise_state_t Request_exception_raise_state; + __Request__exception_raise_state_identity_t Request_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__exc_subsystem__defined +#define __Reply__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__exc_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__exc_subsystem__defined +#define __ReplyUnion__exc_subsystem__defined +union __ReplyUnion__exc_subsystem { + __Reply__exception_raise_t Reply_exception_raise; + __Reply__exception_raise_state_t Reply_exception_raise_state; + __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_exc +#define subsystem_to_name_map_exc \ + { "exception_raise", 2401 },\ + { "exception_raise_state", 2402 },\ + { "exception_raise_state_identity", 2403 } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + +#endif /* _exc_user_ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_nlist_64.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_nlist_64.h new file mode 100644 index 00000000..ee10afb9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/breakpad_nlist_64.h @@ -0,0 +1,43 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// breakpad_nlist.h +// +// This file is meant to provide a header for clients of the modified +// nlist function implemented to work on 64-bit. + +#ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ + +typedef struct nlist_64 breakpad_nlist; + +int +breakpad_nlist_64(const char *name, + breakpad_nlist *list, + const char **symbolNames); + +#endif /* CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/dynamic_images.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/dynamic_images.h new file mode 100644 index 00000000..85ba8cf9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/dynamic_images.h @@ -0,0 +1,297 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dynamic_images.h +// +// Implements most of the function of the dyld API, but allowing an +// arbitrary task to be introspected, unlike the dyld API which +// only allows operation on the current task. The current implementation +// is limited to use by 32-bit tasks. + +#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ +#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ + +#include +#include +#include +#include +#include + +namespace google_breakpad { + +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; + +//============================================================================== +// 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 { + uint32_t version; // == 1 in Mac OS X 10.4 + uint32_t infoArrayCount; + const struct dyld_image_info *infoArray; + void* notification; + bool processDetachedFromSharedRegion; +} dyld_all_image_infos; + +// 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) {} + + 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_; +}; + +//============================================================================== +// Represents a single dynamically loaded mach-o image +class DynamicImage { + public: + DynamicImage(breakpad_mach_header *header, // we take ownership + int header_size, // includes load commands + breakpad_mach_header *load_address, + char *inFilePath, + uintptr_t image_mod_date, + mach_port_t task) + : header_(header), + header_size_(header_size), + load_address_(load_address), + file_mod_date_(image_mod_date), + task_(task) { + InitializeFilePath(inFilePath); + 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 + int GetHeaderSize() const {return header_size_;} + + // Full path to mach-o binary + char *GetFilePath() {return file_path_;} + + uintptr_t GetModDate() const {return file_mod_date_;} + + // Actual address where the image was loaded + breakpad_mach_header *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_;} + + uint32_t GetVersion() {return version_;} + // For sorting + bool operator<(const DynamicImage &inInfo) { + return GetLoadAddress() < inInfo.GetLoadAddress(); + } + + // Debugging + void Print(); + + private: + 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(malloc(path_size)); + strlcpy(file_path_, inFilePath, path_size); + } else { + file_path_ = NULL; + } + } + + // Initializes vmaddr_, vmsize_, and slide_ + void CalculateMemoryAndVersionInfo(); + + breakpad_mach_header *header_; // our local copy of the header + int header_size_; // mach_header plus load commands + breakpad_mach_header *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 + uintptr_t file_mod_date_; // time_t of image file + + mach_port_t 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<(). +// +class DynamicImageRef { + public: + explicit DynamicImageRef(DynamicImage *inP) : p(inP) {} + // The copy constructor is required by STL + DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {} + + bool operator<(const DynamicImageRef &inRef) const { + return (*const_cast(this)->p) + < (*const_cast(inRef).p); + } + + bool operator==(const DynamicImageRef &inInfo) const { + return (*const_cast(this)->p).GetLoadAddress() == + (*const_cast(inInfo)).GetLoadAddress(); + } + + // Be just like DynamicImage* + DynamicImage *operator->() {return p;} + operator DynamicImage*() {return p;} + + private: + DynamicImage *p; +}; + +//============================================================================== +// An object of type DynamicImages may be created to allow introspection of +// an arbitrary task's dynamically loaded mach-o binaries. This makes the +// assumption that the current task has send rights to the target task. +class DynamicImages { + public: + explicit DynamicImages(mach_port_t task); + + ~DynamicImages() { + for (int i = 0; i < (int)image_list_.size(); ++i) { + delete image_list_[i]; + } + } + + // Returns the number of dynamically loaded mach-o images. + int GetImageCount() const {return image_list_.size();} + + // Returns an individual image. + DynamicImage *GetImage(int i) { + if (i < (int)image_list_.size()) { + return image_list_[i]; + } + return NULL; + } + + // Returns the image corresponding to the main executable. + DynamicImage *GetExecutableImage(); + int GetExecutableImageIndex(); + + // Returns the task which we're looking at. + mach_port_t GetTask() const {return task_;} + + // Debugging + void Print() { + for (int i = 0; i < (int)image_list_.size(); ++i) { + image_list_[i]->Print(); + } + } + + void TestPrint() { + const breakpad_mach_header *header; + for (int i = 0; i < (int)image_list_.size(); ++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(imageHeader); + + MachHeader(*header).Print(); + } + } + + private: + bool IsOurTask() {return task_ == mach_task_self();} + + // Initialization + void ReadImageInfoForTask(); + void* GetDyldAllImageInfosPointer(); + + mach_port_t task_; + vector image_list_; +}; + +// Returns a malloced block containing 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); + +} // namespace google_breakpad + +#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/exception_handler.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/exception_handler.h new file mode 100644 index 00000000..2a8ee1e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/exception_handler.h @@ -0,0 +1,212 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// exception_handler.h: MacOS exception handler +// This class can install a Mach exception port handler to trap most common +// programming errors. If an exception occurs, a minidump file will be +// generated which contains detailed information about the process and the +// exception. + +#ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ + +#include + +#include + +namespace google_breakpad { + +using std::string; + +struct ExceptionParameters; + +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, Breakpad + // will immediately report the exception as unhandled without writing a + // minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void *context); + + // A callback function to run after the minidump has been written. + // |minidump_id| is a unique id for the dump, so the minidump + // file is /.dmp. + // |context| is the value passed into the constructor. + // |succeeded| indicates whether a minidump file was successfully written. + // Return true if the exception was fully handled and breakpad should exit. + // Return false to allow any other exception handlers to process the + // exception. + typedef bool (*MinidumpCallback)(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded); + + // A callback function which will be called directly if an exception occurs. + // This bypasses the minidump file writing and simply gives the client + // the exception information. + typedef bool (*DirectCallback)( void *context, + int exception_type, + int exception_code, + mach_port_t thread_name); + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Minidump files will be written to dump_path, and the optional callback + // is called after writing the dump file, as described above. + // If install_handler is true, then a minidump will be written whenever + // an unhandled exception occurs. If it is false, minidumps will only + // be written when WriteMinidump is called. + ExceptionHandler(const string &dump_path, + FilterCallback filter, MinidumpCallback callback, + void *callback_context, bool install_handler); + + // A special constructor if we want to bypass minidump writing and + // simply get a callback with the exception information. + ExceptionHandler(DirectCallback callback, + void *callback_context, + bool install_handler); + + ~ExceptionHandler(); + + // Get and set the minidump path. + string dump_path() const { return dump_path_; } + void set_dump_path(const string &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const string &dump_path, MinidumpCallback callback, + void *callback_context); + + private: + // Install the mach exception handler + bool InstallHandler(); + + // Uninstall the mach exception handler (if any) + bool UninstallHandler(bool in_exception); + + // Setup the handler thread, and if |install_handler| is true, install the + // mach exception port handler + bool Setup(bool install_handler); + + // Uninstall the mach exception handler (if any) and terminate the helper + // thread + bool Teardown(); + + // Send an "empty" mach message to the exception handler. Return true on + // success, false otherwise + bool SendEmptyMachMessage(); + + // All minidump writing goes through this one routine + bool WriteMinidumpWithException(int exception_type, int exception_code, + mach_port_t thread_name); + + // When installed, this static function will be call from a newly created + // pthread with |this| as the argument + static void *WaitForMessage(void *exception_handler_class); + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); + + // Generates a new ID and stores it in next_minidump_id_, and stores the + // path of the next minidump to be written in next_minidump_path_. + void UpdateNextID(); + + // These functions will suspend/resume all threads except for the + // reporting thread + bool SuspendThreads(); + bool ResumeThreads(); + + // The destination directory for the minidump + string dump_path_; + + // The basename of the next minidump w/o extension + string next_minidump_id_; + + // The full path to the next minidump to be written, including extension + string next_minidump_path_; + + // Pointers to the UTF-8 versions of above + const char *dump_path_c_; + const char *next_minidump_id_c_; + const char *next_minidump_path_c_; + + // The callback function and pointer to be passed back after the minidump + // has been written + FilterCallback filter_; + MinidumpCallback callback_; + void *callback_context_; + + // The callback function to be passed back when we don't want a minidump + // file to be written + DirectCallback directCallback_; + + // The thread that is created for the handler + pthread_t handler_thread_; + + // The port that is waiting on an exception message to be sent, if the + // handler is installed + mach_port_t handler_port_; + + // These variables save the previous exception handler's data so that it + // can be re-installed when this handler is uninstalled + ExceptionParameters *previous_; + + // True, if we've installed the exception handler + bool installed_exception_handler_; + + // True, if we're in the process of uninstalling the exception handler and + // the thread. + bool is_in_teardown_; + + // Save the last result of the last minidump + bool last_minidump_write_result_; + + // A mutex for use when writing out a minidump that was requested on a + // thread other than the exception handler. + pthread_mutex_t minidump_write_mutex_; + + // True, if we're using the mutext to indicate when mindump writing occurs + bool use_minidump_write_mutex_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/minidump_generator.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/minidump_generator.h new file mode 100644 index 00000000..0d3424c3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/minidump_generator.h @@ -0,0 +1,157 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_generator.h: Create a minidump of the current MacOS process. + +#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ +#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ + +#include + +#include + +#include "client/minidump_file_writer.h" +#include "google_breakpad/common/minidump_format.h" +#include "common/mac/macho_utilities.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 + +// Creates a minidump file of the current process. If there is exception data, +// use SetExceptionInformation() to add this to the minidump. The minidump +// file is generated by the Write() function. +// Usage: +// MinidumpGenerator minidump(); +// minidump.Write("/tmp/minidump"); +// +class MinidumpGenerator { + public: + MinidumpGenerator(); + MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread); + + ~MinidumpGenerator(); + + // Return /.dmp + // Sets |unique_name| (if requested) to the unique name for the minidump + static string UniqueNameInDirectory(const string &dir, string *unique_name); + + // Write out the minidump into |path| + // All of the components of |path| must exist and be writable + // Return true if successful, false otherwise + bool Write(const char *path); + + // Specify some exception information, if applicable + void SetExceptionInformation(int type, int code, mach_port_t thread_name) { + exception_type_ = type; + exception_code_ = code; + exception_thread_ = thread_name; + } + + // Gather system information. This should be call at least once before using + // the MinidumpGenerator class. + static void GatherSystemInformation(); + + private: + typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *); + + // Stream writers + bool WriteThreadListStream(MDRawDirectory *thread_list_stream); + 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 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(); + + // 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_; + mach_port_t exception_thread_; + mach_port_t crashing_task_; + mach_port_t handler_thread_; + + // 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 + DynamicImages *dynamic_images_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/protected_memory_allocator.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/protected_memory_allocator.h new file mode 100644 index 00000000..ed4f51d5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/mac/handler/protected_memory_allocator.h @@ -0,0 +1,85 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// ProtectedMemoryAllocator +// +// A very simple allocator class which allows allocation, but not deallocation. +// The allocations can be made read-only with the Protect() method. +// This class is NOT useful as a general-purpose memory allocation system, +// since it does not allow deallocation. It is useful to use for a group +// of allocations which are created in the same time-frame and destroyed +// in the same time-frame. It is useful for making allocations of memory +// which will not need to change often once initialized. This memory can then +// be protected from memory smashers by calling the Protect() method. + +#ifndef PROTECTED_MEMORY_ALLOCATOR_H__ +#define PROTECTED_MEMORY_ALLOCATOR_H__ + +#include + +// +class ProtectedMemoryAllocator { + public: + ProtectedMemoryAllocator(vm_size_t pool_size); + ~ProtectedMemoryAllocator(); + + // Returns a pointer to an allocation of size n within the pool. + // Fails by returning NULL is no more space is available. + // Please note that the pointers returned from this method should not + // be freed in any way (for example by calling free() on them ). + char * Allocate(size_t n); + + // Returns the base address of the allocation pool. + char * GetBaseAddress() { return (char*)base_address_; } + + // Returns the size of the allocation pool, including allocated + // plus free space. + vm_size_t GetTotalSize() { return pool_size_; } + + // Returns the number of bytes already allocated in the pool. + vm_size_t GetAllocatedSize() { return next_alloc_offset_; } + + // Returns the number of bytes available for allocation. + vm_size_t GetFreeSize() { return pool_size_ - next_alloc_offset_; } + + // Makes the entire allocation pool read-only including, of course, + // all allocations made from the pool. + kern_return_t Protect(); + + // Makes the entire allocation pool read/write. + kern_return_t Unprotect(); + + private: + vm_size_t pool_size_; + vm_address_t base_address_; + int next_alloc_offset_; + bool valid_; +}; + +#endif // PROTECTED_MEMORY_ALLOCATOR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer-inl.h new file mode 100644 index 00000000..7c556a27 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer-inl.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_file_writer-inl.h: Minidump file writer implementation. +// +// See minidump_file_writer.h for documentation. + +#ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__ +#define CLIENT_MINIDUMP_FILE_WRITER_INL_H__ + +#include + +#include "client/minidump_file_writer.h" +#include "google_breakpad/common/minidump_size.h" + +namespace google_breakpad { + +template +inline bool TypedMDRVA::Allocate() { + allocation_state_ = SINGLE_OBJECT; + return UntypedMDRVA::Allocate(minidump_size::size()); +} + +template +inline bool TypedMDRVA::Allocate(size_t additional) { + allocation_state_ = SINGLE_OBJECT; + return UntypedMDRVA::Allocate(minidump_size::size() + additional); +} + +template +inline bool TypedMDRVA::AllocateArray(size_t count) { + assert(count); + allocation_state_ = ARRAY; + return UntypedMDRVA::Allocate(minidump_size::size() * count); +} + +template +inline bool TypedMDRVA::AllocateObjectAndArray(unsigned int count, + size_t size) { + assert(count && size); + allocation_state_ = SINGLE_OBJECT_WITH_ARRAY; + return UntypedMDRVA::Allocate(minidump_size::size() + count * size); +} + +template +inline bool TypedMDRVA::CopyIndex(unsigned int index, MDType *item) { + assert(allocation_state_ == ARRAY); + return writer_->Copy(position_ + index * minidump_size::size(), item, + minidump_size::size()); +} + +template +inline bool TypedMDRVA::CopyIndexAfterObject(unsigned int index, + const void *src, + size_t size) { + assert(allocation_state_ == SINGLE_OBJECT_WITH_ARRAY); + return writer_->Copy(position_ + minidump_size::size() + index * size, + src, size); +} + +template +inline bool TypedMDRVA::Flush() { + return writer_->Copy(position_, &data_, minidump_size::size()); +} + +} // namespace google_breakpad + +#endif // CLIENT_MINIDUMP_FILE_WRITER_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer.h new file mode 100644 index 00000000..f569a553 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/minidump_file_writer.h @@ -0,0 +1,250 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_file_writer.h: Implements file-based minidump generation. It's +// intended to be used with the Google Breakpad open source crash handling +// project. + +#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__ +#define CLIENT_MINIDUMP_FILE_WRITER_H__ + +#include + +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +class UntypedMDRVA; +template class TypedMDRVA; + +// The user of this class can Open() a file and add minidump streams, data, and +// strings using the definitions in minidump_format.h. Since this class is +// expected to be used in a situation where the current process may be +// damaged, it will not allocate heap memory. +// Sample usage: +// MinidumpFileWriter writer; +// writer.Open("/tmp/minidump.dmp"); +// TypedMDRVA header(&writer_); +// header.Allocate(); +// header->get()->signature = MD_HEADER_SIGNATURE; +// : +// writer.Close(); +class MinidumpFileWriter { +public: + // Invalid MDRVA (Minidump Relative Virtual Address) + // returned on failed allocation + static const MDRVA kInvalidMDRVA; + + MinidumpFileWriter(); + ~MinidumpFileWriter(); + + // Open |path| as the destination of the minidump data. Any existing file + // will be overwritten. + // Return true on success, or false on failure + bool Open(const char *path); + + // Close the current file + // Return true on success, or false on failure + bool Close(); + + // Copy the contents of |str| to a MDString and write it to the file. + // |str| is expected to be either UTF-16 or UTF-32 depending on the size + // of wchar_t. + // Maximum |length| of characters to copy from |str|, or specify 0 to use the + // entire NULL terminated string. Copying will stop at the first NULL. + // |location| the allocated location + // Return true on success, or false on failure + bool WriteString(const wchar_t *str, unsigned int length, + MDLocationDescriptor *location); + + // Same as above, except with |str| as a UTF-8 string + bool WriteString(const char *str, unsigned int length, + MDLocationDescriptor *location); + + // Write |size| bytes starting at |src| into the current position. + // Return true on success and set |output| to position, or false on failure + bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output); + + // Copies |size| bytes from |src| to |position| + // Return true on success, or false on failure + bool Copy(MDRVA position, const void *src, ssize_t size); + + // Return the current position for writing to the minidump + inline MDRVA position() const { return position_; } + + private: + friend class UntypedMDRVA; + + // Allocates an area of |size| bytes. + // Returns the position of the allocation, or kInvalidMDRVA if it was + // unable to allocate the bytes. + MDRVA Allocate(size_t size); + + // The file descriptor for the output file + int file_; + + // Current position in buffer + MDRVA position_; + + // Current allocated size + size_t size_; + + // Copy |length| characters from |str| to |mdstring|. These are distinct + // because the underlying MDString is a UTF-16 based string. The wchar_t + // variant may need to create a MDString that has more characters than the + // source |str|, whereas the UTF-8 variant may coalesce characters to form + // a single UTF-16 character. + bool CopyStringToMDString(const wchar_t *str, unsigned int length, + TypedMDRVA *mdstring); + bool CopyStringToMDString(const char *str, unsigned int length, + TypedMDRVA *mdstring); + + // The common templated code for writing a string + template + bool WriteStringCore(const CharType *str, unsigned int length, + MDLocationDescriptor *location); +}; + +// Represents an untyped allocated chunk +class UntypedMDRVA { + public: + explicit UntypedMDRVA(MinidumpFileWriter *writer) + : writer_(writer), + position_(writer->position()), + size_(0) {} + + // Allocates |size| bytes. Must not call more than once. + // Return true on success, or false on failure + bool Allocate(size_t size); + + // Returns the current position or kInvalidMDRVA if allocation failed + inline MDRVA position() const { return position_; } + + // Number of bytes allocated + inline size_t size() const { return size_; } + + // Return size and position + inline MDLocationDescriptor location() const { + MDLocationDescriptor location = { size_, position_ }; + return location; + } + + // Copy |size| bytes starting at |src| into the minidump at |position| + // Return true on success, or false on failure + bool Copy(MDRVA position, const void *src, size_t size); + + // Copy |size| bytes from |src| to the current position + inline bool Copy(const void *src, size_t size) { + return Copy(position_, src, size); + } + + protected: + // Writer we associate with + MinidumpFileWriter *writer_; + + // Position of the start of the data + MDRVA position_; + + // Allocated size + size_t size_; +}; + +// Represents a Minidump object chunk. Additional memory can be allocated at +// the end of the object as a: +// - single allocation +// - Array of MDType objects +// - A MDType object followed by an array +template +class TypedMDRVA : public UntypedMDRVA { + public: + // Constructs an unallocated MDRVA + explicit TypedMDRVA(MinidumpFileWriter *writer) + : UntypedMDRVA(writer), + data_(), + allocation_state_(UNALLOCATED) {} + + inline ~TypedMDRVA() { + // Ensure that the data_ object is written out + if (allocation_state_ != ARRAY) + Flush(); + } + + // Address of object data_ of MDType. This is not declared const as the + // typical usage will be to access the underlying |data_| object as to + // alter its contents. + MDType *get() { return &data_; } + + // Allocates minidump_size::size() bytes. + // Must not call more than once. + // Return true on success, or false on failure + bool Allocate(); + + // Allocates minidump_size::size() + |additional| bytes. + // Must not call more than once. + // Return true on success, or false on failure + bool Allocate(size_t additional); + + // Allocate an array of |count| elements of MDType. + // Must not call more than once. + // Return true on success, or false on failure + bool AllocateArray(size_t count); + + // Allocate an array of |count| elements of |size| after object of MDType + // Must not call more than once. + // Return true on success, or false on failure + bool AllocateObjectAndArray(unsigned int count, size_t size); + + // Copy |item| to |index| + // Must have been allocated using AllocateArray(). + // Return true on success, or false on failure + bool CopyIndex(unsigned int index, MDType *item); + + // Copy |size| bytes starting at |str| to |index| + // Must have been allocated using AllocateObjectAndArray(). + // Return true on success, or false on failure + bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size); + + // Write data_ + bool Flush(); + + private: + enum AllocationState { + UNALLOCATED = 0, + SINGLE_OBJECT, + ARRAY, + SINGLE_OBJECT_WITH_ARRAY + }; + + MDType data_; + AllocationState allocation_state_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MINIDUMP_FILE_WRITER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/auto_critical_section.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/auto_critical_section.h new file mode 100644 index 00000000..82c7b7f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/auto_critical_section.h @@ -0,0 +1,63 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ +#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ + +#include + +namespace google_breakpad { + +// Automatically enters the critical section in the constructor and leaves +// the critical section in the destructor. +class AutoCriticalSection { + public: + // Creates a new instance with the given critical section object + // and enters the critical section immediately. + explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs) { + assert(cs_); + EnterCriticalSection(cs_); + } + + // Destructor: leaves the critical section. + ~AutoCriticalSection() { + LeaveCriticalSection(cs_); + } + + private: + // Disable copy ctor and operator=. + AutoCriticalSection(const AutoCriticalSection&); + AutoCriticalSection& operator=(const AutoCriticalSection&); + + CRITICAL_SECTION* cs_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/ipc_protocol.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/ipc_protocol.h new file mode 100644 index 00000000..cba8699c --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/common/ipc_protocol.h @@ -0,0 +1,179 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ +#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ + +#include +#include +#include +#include +#include "common/windows/string_utils-inl.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Name/value pair for custom client information. +struct CustomInfoEntry { + // Maximum length for name and value for client custom info. + static const int kNameMaxLength = 64; + static const int kValueMaxLength = 64; + + CustomInfoEntry() { + // Putting name and value in initializer list makes VC++ show warning 4351. + set_name(NULL); + set_value(NULL); + } + + CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) { + set_name(name_arg); + set_value(value_arg); + } + + void set_name(const wchar_t* name_arg) { + if (!name_arg) { + name[0] = L'\0'; + return; + } + WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg); + } + + void set_value(const wchar_t* value_arg) { + if (!value_arg) { + value[0] = L'\0'; + return; + } + + WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg); + } + + void set(const wchar_t* name_arg, const wchar_t* value_arg) { + set_name(name_arg); + set_value(value_arg); + } + + wchar_t name[kNameMaxLength]; + wchar_t value[kValueMaxLength]; +}; + +// Constants for the protocol between client and the server. + +// Tags sent with each message indicating the purpose of +// the message. +enum MessageTag { + MESSAGE_TAG_NONE = 0, + MESSAGE_TAG_REGISTRATION_REQUEST = 1, + MESSAGE_TAG_REGISTRATION_RESPONSE = 2, + MESSAGE_TAG_REGISTRATION_ACK = 3 +}; + +struct CustomClientInfo { + const CustomInfoEntry* entries; + int count; +}; + +// Message structure for IPC between crash client and crash server. +struct ProtocolMessage { + ProtocolMessage() + : tag(MESSAGE_TAG_NONE), + pid(0), + dump_type(MiniDumpNormal), + thread_id(0), + exception_pointers(NULL), + assert_info(NULL), + custom_client_info(), + dump_request_handle(NULL), + dump_generated_handle(NULL), + server_alive_handle(NULL) { + } + + // Creates an instance with the given parameters. + ProtocolMessage(MessageTag arg_tag, + DWORD arg_pid, + MINIDUMP_TYPE arg_dump_type, + DWORD* arg_thread_id, + EXCEPTION_POINTERS** arg_exception_pointers, + MDRawAssertionInfo* arg_assert_info, + const CustomClientInfo& custom_info, + HANDLE arg_dump_request_handle, + HANDLE arg_dump_generated_handle, + HANDLE arg_server_alive) + : tag(arg_tag), + pid(arg_pid), + dump_type(arg_dump_type), + thread_id(arg_thread_id), + exception_pointers(arg_exception_pointers), + assert_info(arg_assert_info), + custom_client_info(custom_info), + dump_request_handle(arg_dump_request_handle), + dump_generated_handle(arg_dump_generated_handle), + server_alive_handle(arg_server_alive) { + } + + // Tag in the message. + MessageTag tag; + + // Process id. + DWORD pid; + + // Dump type requested. + MINIDUMP_TYPE dump_type; + + // Client thread id pointer. + DWORD* thread_id; + + // Exception information. + EXCEPTION_POINTERS** exception_pointers; + + // Assert information in case of an invalid parameter or + // pure call failure. + MDRawAssertionInfo* assert_info; + + // Custom client information. + CustomClientInfo custom_client_info; + + // Handle to signal the crash event. + HANDLE dump_request_handle; + + // Handle to check if server is done generating crash. + HANDLE dump_generated_handle; + + // Handle to a mutex that becomes signaled (WAIT_ABANDONED) + // if server process goes down. + HANDLE server_alive_handle; + + private: + // Disable copy ctor and operator=. + ProtocolMessage(const ProtocolMessage& msg); + ProtocolMessage& operator=(const ProtocolMessage& msg); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/client_info.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/client_info.h new file mode 100644 index 00000000..774816fb --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/client_info.h @@ -0,0 +1,170 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ + +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +class CrashGenerationServer; + +// Abstraction for a crash client process. +class ClientInfo { + public: + // Creates an instance with the given values. Gets the process + // handle for the given process id and creates necessary event + // objects. + ClientInfo(CrashGenerationServer* crash_server, + DWORD pid, + MINIDUMP_TYPE dump_type, + DWORD* thread_id, + EXCEPTION_POINTERS** ex_info, + MDRawAssertionInfo* assert_info, + const CustomClientInfo& custom_client_info); + + ~ClientInfo(); + + CrashGenerationServer* crash_server() const { return crash_server_; } + DWORD pid() const { return pid_; } + MINIDUMP_TYPE dump_type() const { return dump_type_; } + EXCEPTION_POINTERS** ex_info() const { return ex_info_; } + MDRawAssertionInfo* assert_info() const { return assert_info_; } + DWORD* thread_id() const { return thread_id_; } + HANDLE process_handle() const { return process_handle_; } + HANDLE dump_requested_handle() const { return dump_requested_handle_; } + HANDLE dump_generated_handle() const { return dump_generated_handle_; } + + HANDLE dump_request_wait_handle() const { + return dump_request_wait_handle_; + } + + void set_dump_request_wait_handle(HANDLE value) { + dump_request_wait_handle_ = value; + } + + HANDLE process_exit_wait_handle() const { + return process_exit_wait_handle_; + } + + void set_process_exit_wait_handle(HANDLE value) { + process_exit_wait_handle_ = value; + } + + // Unregister all waits for the client. + bool UnregisterWaits(); + + bool Initialize(); + bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const; + bool GetClientThreadId(DWORD* thread_id) const; + + // Reads the custom information from the client process address space. + bool PopulateCustomInfo(); + + // Returns the client custom information. + CustomClientInfo GetCustomInfo() const; + + private: + // Calcualtes the uptime for the client process, converts it to a string and + // stores it in the last entry of client custom info. + void SetProcessUptime(); + + // Crash generation server. + CrashGenerationServer* crash_server_; + + // Client process ID. + DWORD pid_; + + // Dump type requested by the client. + MINIDUMP_TYPE dump_type_; + + // Address of an EXCEPTION_POINTERS* variable in the client + // process address space that will point to an instance of + // EXCEPTION_POINTERS containing information about crash. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + EXCEPTION_POINTERS** ex_info_; + + // Address of an instance of MDRawAssertionInfo in the client + // process address space that will contain information about + // non-exception related crashes like invalid parameter assertion + // failures and pure calls. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + MDRawAssertionInfo* assert_info_; + + // Custom information about the client. + CustomClientInfo custom_client_info_; + + // Contains the custom client info entries read from the client process + // memory. This will be populated only if the method GetClientCustomInfo + // is called. + scoped_array custom_info_entries_; + + // Address of a variable in the client process address space that + // will contain the thread id of the crashing client thread. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + DWORD* thread_id_; + + // Client process handle. + HANDLE process_handle_; + + // Dump request event handle. + HANDLE dump_requested_handle_; + + // Dump generated event handle. + HANDLE dump_generated_handle_; + + // Wait handle for dump request event. + HANDLE dump_request_wait_handle_; + + // Wait handle for process exit event. + HANDLE process_exit_wait_handle_; + + // Time when the client process started. It is used to determine the uptime + // for the client process when it signals a crash. + FILETIME start_time_; + + // Disallow copy ctor and operator=. + ClientInfo(const ClientInfo& client_info); + ClientInfo& operator=(const ClientInfo& client_info); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_client.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_client.h new file mode 100644 index 00000000..81b0e6ca --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_client.h @@ -0,0 +1,159 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ + +#include +#include +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +struct CustomClientInfo; + +// Abstraction of client-side implementation of out of process +// crash generation. +// +// The process that desires to have out-of-process crash dump +// generation service can use this class in the following way: +// +// * Create an instance. +// * Call Register method so that the client tries to register +// with the server process and check the return value. If +// registration is not successful, out-of-process crash dump +// generation will not be available +// * Request dump generation by calling either of the two +// overloaded RequestDump methods - one in case of exceptions +// and the other in case of assertion failures +// +// Note that it is the responsibility of the client code of +// this class to set the unhandled exception filter with the +// system by calling the SetUnhandledExceptionFilter function +// and the client code should explicitly request dump generation. +class CrashGenerationClient { + public: + CrashGenerationClient(const wchar_t* pipe_name, + MINIDUMP_TYPE dump_type, + const CustomClientInfo* custom_info); + + ~CrashGenerationClient(); + + // Registers the client process with the crash server. + // + // Returns true if the registration is successful; false otherwise. + bool Register(); + + // Requests the crash server to generate a dump with the given + // exception information. + // + // Returns true if the dump was successful; false otherwise. Note that + // if the registration step was not performed or it was not successful, + // false will be returned. + bool RequestDump(EXCEPTION_POINTERS* ex_info); + + // Requests the crash server to generate a dump with the given + // assertion information. + // + // Returns true if the dump was successful; false otherwise. Note that + // if the registration step was not performed or it was not successful, + // false will be returned. + bool RequestDump(MDRawAssertionInfo* assert_info); + + private: + // Connects to the appropriate pipe and sets the pipe handle state. + // + // Returns the pipe handle if everything goes well; otherwise Returns NULL. + HANDLE ConnectToServer(); + + // Performs a handshake with the server over the given pipe which should be + // already connected to the server. + // + // Returns true if handshake with the server was successful; false otherwise. + bool RegisterClient(HANDLE pipe); + + // Validates the given server response. + bool ValidateResponse(const ProtocolMessage& msg) const; + + // Returns true if the registration step succeeded; false otherwise. + bool IsRegistered() const; + + // Connects to the given named pipe with given parameters. + // + // Returns true if the connection is successful; false otherwise. + HANDLE ConnectToPipe(const wchar_t* pipe_name, + DWORD pipe_access, + DWORD flags_attrs); + + // Signals the crash event and wait for the server to generate crash. + bool SignalCrashEventAndWait(); + + // Pipe name to use to talk to server. + std::wstring pipe_name_; + + // Custom client information + CustomClientInfo custom_info_; + + // Type of dump to generate. + MINIDUMP_TYPE dump_type_; + + // Event to signal in case of a crash. + HANDLE crash_event_; + + // Handle to wait on after signaling a crash for the server + // to finish generating crash dump. + HANDLE crash_generated_; + + // Handle to a mutex that will become signaled with WAIT_ABANDONED + // if the server process goes down. + HANDLE server_alive_; + + // Server process id. + DWORD server_process_id_; + + // Id of the thread that caused the crash. + DWORD thread_id_; + + // Exception pointers for an exception crash. + EXCEPTION_POINTERS* exception_pointers_; + + // Assertion info for an invalid parameter or pure call crash. + MDRawAssertionInfo assert_info_; + + // Disable copy ctor and operator=. + CrashGenerationClient(const CrashGenerationClient& crash_client); + CrashGenerationClient& operator=(const CrashGenerationClient& crash_client); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_server.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_server.h new file mode 100644 index 00000000..cacb639a --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/crash_generation_server.h @@ -0,0 +1,269 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ + +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/crash_generation/client_info.h" +#include "client/windows/crash_generation/minidump_generator.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +// Abstraction for server side implementation of out-of-process crash +// generation protocol for Windows platform only. It generates Windows +// minidump files for client processes that request dump generation. When +// the server is requested to start listening for clients (by calling the +// Start method), it creates a named pipe and waits for the clients to +// register. In response, it hands them event handles that the client can +// signal to request dump generation. When the clients request dump +// generation in this way, the server generates Windows minidump files. +class CrashGenerationServer { + public: + typedef void (*OnClientConnectedCallback)(void* context, + const ClientInfo* client_info); + + typedef void (*OnClientDumpRequestCallback)(void* context, + const ClientInfo* client_info, + const std::wstring* file_path); + + typedef void (*OnClientExitedCallback)(void* context, + const ClientInfo* client_info); + + // Creates an instance with the given parameters. + // + // Parameter pipe_name: Name of the Windows named pipe + // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass + // NULL to use default security on the pipe. By default, the pipe created + // allows Local System, Administrators and the Creator full control and + // the Everyone group read access on the pipe. + // Parameter connect_callback: Callback for a new client connection. + // Parameter connect_context: Context for client connection callback. + // Parameter crash_callback: Callback for a client crash dump request. + // Parameter crash_context: Context for client crash dump request callback. + // Parameter exit_callback: Callback for client process exit. + // Parameter exit_context: Context for client exit callback. + // Parameter generate_dumps: Whether to automatically generate dumps. + // Client code of this class might want to generate dumps explicitly in the + // crash dump request callback. In that case, false can be passed for this + // parameter. + // Parameter dump_path: Path for generating dumps; required only if true is + // passed for generateDumps parameter; NULL can be passed otherwise. + CrashGenerationServer(const std::wstring& pipe_name, + SECURITY_ATTRIBUTES* pipe_sec_attrs, + OnClientConnectedCallback connect_callback, + void* connect_context, + OnClientDumpRequestCallback dump_callback, + void* dump_context, + OnClientExitedCallback exit_callback, + void* exit_context, + bool generate_dumps, + const std::wstring* dump_path); + + ~CrashGenerationServer(); + + // Performs initialization steps needed to start listening to clients. + // + // Returns true if initialization is successful; false otherwise. + bool Start(); + + private: + // Various states the client can be in during the handshake with + // the server. + enum IPCServerState { + // Server is in error state and it cannot serve any clients. + IPC_SERVER_STATE_ERROR, + + // Server starts in this state. + IPC_SERVER_STATE_INITIAL, + + // Server has issued an async connect to the pipe and it is waiting + // for the connection to be established. + IPC_SERVER_STATE_CONNECTING, + + // Server is connected successfully. + IPC_SERVER_STATE_CONNECTED, + + // Server has issued an async read from the pipe and it is waiting for + // the read to finish. + IPC_SERVER_STATE_READING, + + // Server is done reading from the pipe. + IPC_SERVER_STATE_READ_DONE, + + // Server has issued an async write to the pipe and it is waiting for + // the write to finish. + IPC_SERVER_STATE_WRITING, + + // Server is done writing to the pipe. + IPC_SERVER_STATE_WRITE_DONE, + + // Server has issued an async read from the pipe for an ack and it + // is waiting for the read to finish. + IPC_SERVER_STATE_READING_ACK, + + // Server is done writing to the pipe and it is now ready to disconnect + // and reconnect. + IPC_SERVER_STATE_DISCONNECTING + }; + + // + // Helper methods to handle various server IPC states. + // + void HandleErrorState(); + void HandleInitialState(); + void HandleConnectingState(); + void HandleConnectedState(); + void HandleReadingState(); + void HandleReadDoneState(); + void HandleWritingState(); + void HandleWriteDoneState(); + void HandleReadingAckState(); + void HandleDisconnectingState(); + + // Prepares reply for a client from the given parameters. + bool PrepareReply(const ClientInfo& client_info, + ProtocolMessage* reply) const; + + // Duplicates various handles in the ClientInfo object for the client + // process and stores them in the given ProtocolMessage instance. If + // creating any handle fails, ProtocolMessage will contain the handles + // already created successfully, which should be closed by the caller. + bool CreateClientHandles(const ClientInfo& client_info, + ProtocolMessage* reply) const; + + // Response to the given client. Return true if all steps of + // responding to the client succeed, false otherwise. + bool RespondToClient(ClientInfo* client_info); + + // Handles a connection request from the client. + void HandleConnectionRequest(); + + // Handles a dump request from the client. + void HandleDumpRequest(const ClientInfo& client_info); + + // Callback for pipe connected event. + static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait); + + // Callback for a dump request. + static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait); + + // Callback for client process exit event. + static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait); + + // Releases resources for a client. + static DWORD WINAPI CleanupClient(void* context); + + // Cleans up for the given client. + void DoCleanup(ClientInfo* client_info); + + // Adds the given client to the list of registered clients. + bool AddClient(ClientInfo* client_info); + + // Generates dump for the given client. + bool GenerateDump(const ClientInfo& client, std::wstring* dump_path); + + // Sync object for thread-safe access to the shared list of clients. + CRITICAL_SECTION clients_sync_; + + // List of clients. + std::list clients_; + + // Pipe name. + std::wstring pipe_name_; + + // Pipe security attributes + SECURITY_ATTRIBUTES* pipe_sec_attrs_; + + // Handle to the pipe used for handshake with clients. + HANDLE pipe_; + + // Pipe wait handle. + HANDLE pipe_wait_handle_; + + // Handle to server-alive mutex. + HANDLE server_alive_handle_; + + // Callback for a successful client connection. + OnClientConnectedCallback connect_callback_; + + // Context for client connected callback. + void* connect_context_; + + // Callback for a client dump request. + OnClientDumpRequestCallback dump_callback_; + + // Context for client dump request callback. + void* dump_context_; + + // Callback for client process exit. + OnClientExitedCallback exit_callback_; + + // Context for client process exit callback. + void* exit_context_; + + // Whether to generate dumps. + bool generate_dumps_; + + // Instance of a mini dump generator. + scoped_ptr dump_generator_; + + // State of the server in performing the IPC with the client. + // Note that since we restrict the pipe to one instance, we + // only need to keep one state of the server. Otherwise, server + // would have one state per client it is talking to. + volatile IPCServerState server_state_; + + // Whether the server is shutting down. + volatile bool shutting_down_; + + // Overlapped instance for async I/O on the pipe. + OVERLAPPED overlapped_; + + // Message object used in IPC with the client. + ProtocolMessage msg_; + + // Client Info for the client that's connecting to the server. + ClientInfo* client_info_; + + // Count of clean-up work items that are currently running or are + // already queued to run. + volatile LONG cleanup_item_count_; + + // Disable copy ctor and operator=. + CrashGenerationServer(const CrashGenerationServer& crash_server); + CrashGenerationServer& operator=(const CrashGenerationServer& crash_server); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/minidump_generator.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/minidump_generator.h new file mode 100644 index 00000000..8ab6a8f6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/crash_generation/minidump_generator.h @@ -0,0 +1,121 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ + +#include +#include +#include +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Abstraction for various objects and operations needed to generate +// minidump on Windows. This abstraction is useful to hide all the gory +// details for minidump generation and provide a clean interface to +// the clients to generate minidumps. +class MinidumpGenerator { + public: + // Creates an instance with the given dump path. + explicit MinidumpGenerator(const std::wstring& dump_path); + + ~MinidumpGenerator(); + + // Writes the minidump with the given parameters. Stores the + // dump file path in the dump_path parameter if dump generation + // succeeds. + bool WriteMinidump(HANDLE process_handle, + DWORD process_id, + DWORD thread_id, + DWORD requesting_thread_id, + EXCEPTION_POINTERS* exception_pointers, + MDRawAssertionInfo* assert_info, + MINIDUMP_TYPE dump_type, + bool is_client_pointers, + std::wstring* dump_path); + + private: + // Function pointer type for MiniDumpWriteDump, which is looked up + // dynamically. + typedef BOOL (WINAPI* MiniDumpWriteDumpType)( + HANDLE hProcess, + DWORD ProcessId, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + + // Function pointer type for UuidCreate, which is looked up dynamically. + typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid); + + // Loads the appropriate DLL lazily in a thread safe way. + HMODULE GetDbghelpModule(); + + // Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump + // function lazily and in a thread-safe manner. + MiniDumpWriteDumpType GetWriteDump(); + + // Loads the appropriate DLL lazily in a thread safe way. + HMODULE GetRpcrt4Module(); + + // Loads the appropriate DLL and gets a pointer to the UuidCreate + // function lazily and in a thread-safe manner. + UuidCreateType GetCreateUuid(); + + // Returns the path for the file to write dump to. + bool GenerateDumpFilePath(std::wstring* file_path); + + // Handle to dynamically loaded DbgHelp.dll. + HMODULE dbghelp_module_; + + // Pointer to the MiniDumpWriteDump function. + MiniDumpWriteDumpType write_dump_; + + // Handle to dynamically loaded rpcrt4.dll. + HMODULE rpcrt4_module_; + + // Pointer to the UuidCreate function. + UuidCreateType create_uuid_; + + // Folder path to store dump files. + std::wstring dump_path_; + + // Critical section to sychronize action of loading modules dynamically. + CRITICAL_SECTION module_load_sync_; + + // Critical section to synchronize action of dynamically getting function + // addresses from modules. + CRITICAL_SECTION get_proc_address_sync_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/handler/exception_handler.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/handler/exception_handler.h new file mode 100644 index 00000000..2cacdc38 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/handler/exception_handler.h @@ -0,0 +1,415 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ExceptionHandler can write a minidump file when an exception occurs, +// or when WriteMinidump() is called explicitly by your program. +// +// To have the exception handler write minidumps when an uncaught exception +// (crash) occurs, you should create an instance early in the execution +// of your program, and keep it around for the entire time you want to +// have crash handling active (typically, until shutdown). +// +// If you want to write minidumps without installing the exception handler, +// you can create an ExceptionHandler with install_handler set to false, +// then call WriteMinidump. You can also use this technique if you want to +// use different minidump callbacks for different call sites. +// +// In either case, a callback function is called when a minidump is written, +// which receives the unqiue id of the minidump. The caller can use this +// id to collect and write additional application state, and to launch an +// external crash-reporting application. +// +// It is important that creation and destruction of ExceptionHandler objects +// be nested cleanly, when using install_handler = true. +// Avoid the following pattern: +// ExceptionHandler *e = new ExceptionHandler(...); +// ExceptionHandler *f = new ExceptionHandler(...); +// delete e; +// This will put the exception filter stack into an inconsistent state. + +#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ + +#include +#include +#include +#include + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/crash_generation/crash_generation_client.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +using std::vector; +using std::wstring; + +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. exinfo points to the + // exception record, if any; assertion points to assertion information, + // if any. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, Breakpad + // will immediately report the exception as unhandled without writing a + // minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void* context, EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // A callback function to run after the minidump has been written. + // minidump_id is a unique id for the dump, so the minidump + // file is \.dmp. context is the parameter supplied + // by the user as callback_context when the handler was created. exinfo + // points to the exception record, or NULL if no exception occurred. + // succeeded indicates whether a minidump file was successfully written. + // assertion points to information about an assertion if the handler was + // invoked by an assertion. + // + // If an exception occurred and the callback returns true, Breakpad will treat + // the exception as fully-handled, suppressing any other handlers from being + // notified of the exception. If the callback returns false, Breakpad will + // treat the exception as unhandled, and allow another handler to handle it. + // If there are no other handlers, Breakpad will report the exception to the + // system as unhandled, allowing a debugger or native crash dialog the + // opportunity to handle the exception. Most callback implementations + // should normally return the value of |succeeded|, or when they wish to + // not report an exception of handled, false. Callbacks will rarely want to + // return true directly (unless |succeeded| is true). + // + // For out-of-process dump generation, dump path and minidump ID will always + // be NULL. In case of out-of-process dump generation, the dump path and + // minidump id are controlled by the server process and are not communicated + // back to the crashing process. + typedef bool (*MinidumpCallback)(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded); + + // HandlerType specifies which types of handlers should be installed, if + // any. Use HANDLER_NONE for an ExceptionHandler that remains idle, + // without catching any failures on its own. This type of handler may + // still be triggered by calling WriteMinidump. Otherwise, use a + // combination of the other HANDLER_ values, or HANDLER_ALL to install + // all handlers. + enum HandlerType { + HANDLER_NONE = 0, + HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter + HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler + HANDLER_PURECALL = 1 << 2, // _set_purecall_handler + HANDLER_ALL = HANDLER_EXCEPTION | + HANDLER_INVALID_PARAMETER | + HANDLER_PURECALL + }; + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Before writing a minidump, the optional filter callback will be called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // handler_types specifies the types of handlers that should be installed. + ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types); + + // Creates a new ExcetpionHandler instance that can attempt to perform + // out-of-process dump generation if pipe_name is not NULL. If pipe_name is + // NULL, or if out-of-process dump generation registration step fails, + // in-process dump generation will be used. This also allows specifying + // the dump type to generate. + ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info); + + ~ExceptionHandler(); + + // Get and set the minidump path. + wstring dump_path() const { return dump_path_; } + void set_dump_path(const wstring &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Writes a minidump immediately, with the user-supplied exception + // information. + bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const wstring &dump_path, + MinidumpCallback callback, void* callback_context); + + // Get the thread ID of the thread requesting the dump (either the exception + // thread or any other thread that called WriteMinidump directly). This + // may be useful if you want to include additional thread state in your + // dumps. + DWORD get_requesting_thread_id() const { return requesting_thread_id_; } + + // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP. + bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; } + void set_handle_debug_exceptions(bool handle_debug_exceptions) { + handle_debug_exceptions_ = handle_debug_exceptions; + } + + // Returns whether out-of-process dump generation is used or not. + bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; } + + private: + friend class AutoExceptionHandler; + + // Initializes the instance with given values. + void Initialize(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info); + + // Function pointer type for MiniDumpWriteDump, which is looked up + // dynamically. + typedef BOOL (WINAPI *MiniDumpWriteDump_type)( + HANDLE hProcess, + DWORD dwPid, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + + // Function pointer type for UuidCreate, which is looked up dynamically. + typedef RPC_STATUS (RPC_ENTRY *UuidCreate_type)(UUID* Uuid); + + // Runs the main loop for the exception handler thread. + static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter); + + // Called on the exception thread when an unhandled exception occurs. + // Signals the exception handler thread to handle the exception. + static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); + +#if _MSC_VER >= 1400 // MSVC 2005/8 + // This function will be called by some CRT functions when they detect + // that they were passed an invalid parameter. Note that in _DEBUG builds, + // the CRT may display an assertion dialog before calling this function, + // and the function will not be called unless the assertion dialog is + // dismissed by clicking "Ignore." + static void HandleInvalidParameter(const wchar_t* expression, + const wchar_t* function, + const wchar_t* file, + unsigned int line, + uintptr_t reserved); +#endif // _MSC_VER >= 1400 + + // This function will be called by the CRT when a pure virtual + // function is called. + static void HandlePureVirtualCall(); + + // This is called on the exception thread or on another thread that + // the user wishes to produce a dump from. It calls + // WriteMinidumpWithException on the handler thread, avoiding stack + // overflows and inconsistent dumps due to writing the dump from + // the exception thread. If the dump is requested as a result of an + // exception, exinfo contains exception information, otherwise, it + // is NULL. If the dump is requested as a result of an assertion + // (such as an invalid parameter being passed to a CRT function), + // assertion contains data about the assertion, otherwise, it is NULL. + bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // This function does the actual writing of a minidump. It is called + // on the handler thread. requesting_thread_id is the ID of the thread + // that requested the dump. If the dump is requested as a result of + // an exception, exinfo contains exception information, otherwise, + // it is NULL. + bool WriteMinidumpWithException(DWORD requesting_thread_id, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // Generates a new ID and stores it in next_minidump_id_, and stores the + // path of the next minidump to be written in next_minidump_path_. + void UpdateNextID(); + + FilterCallback filter_; + MinidumpCallback callback_; + void* callback_context_; + + scoped_ptr crash_generation_client_; + + // The directory in which a minidump will be written, set by the dump_path + // argument to the constructor, or set_dump_path. + wstring dump_path_; + + // The basename of the next minidump to be written, without the extension. + wstring next_minidump_id_; + + // The full pathname of the next minidump to be written, including the file + // extension. + wstring next_minidump_path_; + + // Pointers to C-string representations of the above. These are set when + // the above wstring versions are set in order to avoid calling c_str during + // an exception, as c_str may attempt to allocate heap memory. These + // pointers are not owned by the ExceptionHandler object, but their lifetimes + // should be equivalent to the lifetimes of the associated wstring, provided + // that the wstrings are not altered. + const wchar_t* dump_path_c_; + const wchar_t* next_minidump_id_c_; + const wchar_t* next_minidump_path_c_; + + HMODULE dbghelp_module_; + MiniDumpWriteDump_type minidump_write_dump_; + MINIDUMP_TYPE dump_type_; + + HMODULE rpcrt4_module_; + UuidCreate_type uuid_create_; + + // Tracks the handler types that were installed according to the + // handler_types constructor argument. + int handler_types_; + + // When installed_handler_ is true, previous_filter_ is the unhandled + // exception filter that was set prior to installing ExceptionHandler as + // the unhandled exception filter and pointing it to |this|. NULL indicates + // that there is no previous unhandled exception filter. + LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_; + +#if _MSC_VER >= 1400 // MSVC 2005/8 + // Beginning in VC 8, the CRT provides an invalid parameter handler that will + // be called when some CRT functions are passed invalid parameters. In + // earlier CRTs, the same conditions would cause unexpected behavior or + // crashes. + _invalid_parameter_handler previous_iph_; +#endif // _MSC_VER >= 1400 + + // The CRT allows you to override the default handler for pure + // virtual function calls. + _purecall_handler previous_pch_; + + // The exception handler thread. + HANDLE handler_thread_; + + // True if the exception handler is being destroyed. + // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars. + // It has release semantics on write and acquire semantics on reads. + // See the msdn documentation. + volatile bool is_shutdown_; + + // The critical section enforcing the requirement that only one exception be + // handled by a handler at a time. + CRITICAL_SECTION handler_critical_section_; + + // Semaphores used to move exception handling between the exception thread + // and the handler thread. handler_start_semaphore_ is signalled by the + // exception thread to wake up the handler thread when an exception occurs. + // handler_finish_semaphore_ is signalled by the handler thread to wake up + // the exception thread when handling is complete. + HANDLE handler_start_semaphore_; + HANDLE handler_finish_semaphore_; + + // The next 2 fields contain data passed from the requesting thread to + // the handler thread. + + // The thread ID of the thread requesting the dump (either the exception + // thread or any other thread that called WriteMinidump directly). + DWORD requesting_thread_id_; + + // The exception info passed to the exception handler on the exception + // thread, if an exception occurred. NULL for user-requested dumps. + EXCEPTION_POINTERS* exception_info_; + + // If the handler is invoked due to an assertion, this will contain a + // pointer to the assertion information. It is NULL at other times. + MDRawAssertionInfo* assertion_; + + // The return value of the handler, passed from the handler thread back to + // the requesting thread. + bool handler_return_value_; + + // If true, the handler will intercept EXCEPTION_BREAKPOINT and + // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default) + // to not interfere with debuggers. + bool handle_debug_exceptions_; + + // A stack of ExceptionHandler objects that have installed unhandled + // exception filters. This vector is used by HandleException to determine + // which ExceptionHandler object to route an exception to. When an + // ExceptionHandler is created with install_handler true, it will append + // itself to this list. + static vector* handler_stack_; + + // The index of the ExceptionHandler in handler_stack_ that will handle the + // next exception. Note that 0 means the last entry in handler_stack_, 1 + // means the next-to-last entry, and so on. This is used by HandleException + // to support multiple stacked Breakpad handlers. + static LONG handler_stack_index_; + + // handler_stack_critical_section_ guards operations on handler_stack_ and + // handler_stack_index_. The critical section is initialized by the + // first instance of the class and destroyed by the last instance of it. + static CRITICAL_SECTION handler_stack_critical_section_; + + // The number of instances of this class. + volatile static LONG instance_count_; + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/sender/crash_report_sender.h b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/sender/crash_report_sender.h new file mode 100644 index 00000000..da1ed0af --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/client/windows/sender/crash_report_sender.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ +#define CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ + +// CrashReportSender is a "static" class which provides an API to upload +// crash reports via HTTP(S). A crash report is formatted as a multipart POST +// request, which contains a set of caller-supplied string key/value pairs, +// and a minidump file to upload. +// +// To use this library in your project, you will need to link against +// wininet.lib. + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +namespace google_breakpad { + +using std::wstring; +using std::map; + +typedef enum { + RESULT_FAILED = 0, // Failed to communicate with the server; try later. + RESULT_REJECTED, // Successfully sent the crash report, but the + // server rejected it; don't resend this report. + RESULT_SUCCEEDED, // The server accepted the crash report. + RESULT_THROTTLED // No attempt was made to send the crash report, because + // we exceeded the maximum reports per day. +} ReportResult; + +class CrashReportSender { + public: + // Initializes a CrashReportSender instance. + // If checkpoint_file is non-empty, breakpad will persist crash report + // state to this file. A checkpoint file is required for + // set_max_reports_per_day() to function properly. + explicit CrashReportSender(const wstring &checkpoint_file); + ~CrashReportSender() {} + + // Sets the maximum number of crash reports that will be sent in a 24-hour + // period. This uses the state persisted to the checkpoint file. + // The default value of -1 means that there is no limit on reports sent. + void set_max_reports_per_day(int reports) { + max_reports_per_day_ = reports; + } + + int max_reports_per_day() const { return max_reports_per_day_; } + + // Sends the specified minidump file, along with the map of + // name value pairs, as a multipart POST request to the given URL. + // Parameter names must contain only printable ASCII characters, + // and may not contain a quote (") character. + // Only HTTP(S) URLs are currently supported. The return value indicates + // the result of the operation (see above for possible results). + // If report_code is non-NULL and the report is sent successfully (that is, + // the return value is RESULT_SUCCEEDED), a code uniquely identifying the + // report will be returned in report_code. + // (Otherwise, report_code will be unchanged.) + ReportResult SendCrashReport(const wstring &url, + const map ¶meters, + const wstring &dump_file_name, + wstring *report_code); + + private: + // Reads persistent state from a checkpoint file. + void ReadCheckpoint(FILE *fd); + + // Called when a new report has been sent, to update the checkpoint state. + void ReportSent(int today); + + // Returns today's date (UTC) formatted as YYYYMMDD. + int GetCurrentDate() const; + + // Opens the checkpoint file with the specified mode. + // Returns zero on success, or an error code on failure. + int OpenCheckpointFile(const wchar_t *mode, FILE **fd); + + wstring checkpoint_file_; + int max_reports_per_day_; + // The last date on which we sent a report, expressed as YYYYMMDD. + int last_sent_date_; + // Number of reports sent on last_sent_date_ + int reports_sent_; + + // Disallow copy constructor and operator= + explicit CrashReportSender(const CrashReportSender &); + void operator=(const CrashReportSender &); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/convert_UTF.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/convert_UTF.h new file mode 100644 index 00000000..b1556de8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/convert_UTF.h @@ -0,0 +1,143 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + +Conversions between UTF32, UTF-16, and UTF-8. Header file. + +Several funtions are included here, forming a complete set of +conversions between the three formats. UTF-7 is not included +here, but is handled in a separate source file. + +Each of these routines takes pointers to input buffers and output +buffers. The input buffers are const. + +Each routine converts the text between *sourceStart and sourceEnd, +putting the result into the buffer between *targetStart and +targetEnd. Note: the end pointers are *after* the last item: e.g. +*(sourceEnd - 1) is the last item. + +The return result indicates whether the conversion was successful, +and if not, whether the problem was in the source or target buffers. +(Only the first encountered problem is indicated.) + +After the conversion, *sourceStart and *targetStart are both +updated to point to the end of last text successfully converted in +the respective buffers. + +Input parameters: +sourceStart - pointer to a pointer to the source buffer. +The contents of this are modified on return so that +it points at the next thing to be converted. +targetStart - similarly, pointer to pointer to the target buffer. +sourceEnd, targetEnd - respectively pointers to the ends of the +two buffers, for overflow checking only. + +These conversion functions take a ConversionFlags argument. When this +flag is set to strict, both irregular sequences and isolated surrogates +will cause an error. When the flag is set to lenient, both irregular +sequences and isolated surrogates are converted. + +Whether the flag is strict or lenient, all illegal sequences will cause +an error return. This includes sequences such as: , , +or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code +must check for illegal sequences. + +When the flag is set to lenient, characters over 0x10FFFF are converted +to the replacement character; otherwise (when the flag is set to strict) +they constitute an error. + +Output parameters: +The value "sourceIllegal" is returned from some routines if the input +sequence is malformed. When "sourceIllegal" is returned, the source +value will point to the illegal value that caused the problem. E.g., +in UTF-8 when a sequence is malformed, it points to the start of the +malformed sequence. + +Author: Mark E. Davis, 1994. +Rev History: Rick McGowan, fixes & updates May 2001. +Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- +The following 4 definitions are compiler-specific. +The C standard does not guarantee that wchar_t has at least +16 bits, so wchar_t is no less portable than unsigned short! +All should be unsigned values to avoid sign extension during +bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/md5.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/md5.h new file mode 100644 index 00000000..dbf4893c --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/md5.h @@ -0,0 +1,31 @@ +// Copyright 2007 Google Inc. All Rights Reserved. +// Author: liuli@google.com (Liu Li) +#ifndef COMMON_MD5_H__ +#define COMMON_MD5_H__ + +#include + +typedef uint32_t u32; +typedef uint8_t u8; + +struct MD5Context { + u32 buf[4]; + u32 bits[2]; + u8 in[64]; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void MD5Init(struct MD5Context *ctx); + +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len); + +void MD5Final(unsigned char digest[16], struct MD5Context *ctx); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_MD5_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/string_conversion.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/string_conversion.h new file mode 100644 index 00000000..d51f46bb --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/string_conversion.h @@ -0,0 +1,66 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// string_conversion.h: Conversion between different UTF-8/16/32 encodings. + +#ifndef COMMON_STRING_CONVERSION_H__ +#define COMMON_STRING_CONVERSION_H__ + +#include +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::vector; + +// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the +// conversion failed, |out| will be zero length. +void UTF8ToUTF16(const char *in, vector *out); + +// Convert at least one character (up to a maximum of |in_length|) from |in| +// to UTF-16 into |out|. Return the number of characters consumed from |in|. +// Any unused characters in |out| will be initialized to 0. No memory will +// be allocated by this routine. +int UTF8ToUTF16Char(const char *in, int in_length, u_int16_t out[2]); + +// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the +// conversion failed, |out| will be zero length. +void UTF32ToUTF16(const wchar_t *in, vector *out); + +// Convert |in| to UTF-16 into |out|. Any unused characters in |out| will be +// initialized to 0. No memory will be allocated by this routine. +void UTF32ToUTF16Char(wchar_t in, u_int16_t out[2]); + +// Convert |in| to UTF-8. If |swap| is true, swap bytes before converting. +std::string UTF16ToUTF8(const vector &in, bool swap); + +} // namespace google_breakpad + +#endif // COMMON_STRING_CONVERSION_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/guid_string.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/guid_string.h new file mode 100644 index 00000000..f8aa8a23 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/guid_string.h @@ -0,0 +1,58 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// guid_string.cc: Convert GUIDs to strings. + +#ifndef COMMON_WINDOWS_GUID_STRING_H__ +#define COMMON_WINDOWS_GUID_STRING_H__ + +#include + +#include + +namespace google_breakpad { + +using std::wstring; + +class GUIDString { + public: + // Converts guid to a string in the format recommended by RFC 4122 and + // returns the string. + static wstring GUIDToWString(GUID *guid); + + // Converts guid to a string formatted as uppercase hexadecimal, with + // no separators, and returns the string. This is the format used for + // symbol server identifiers, although identifiers have an age tacked + // on to the string. + static wstring GUIDToSymbolServerWString(GUID *guid); +}; + +} // namespace google_breakpad + +#endif // COMMON_WINDOWS_GUID_STRING_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/http_upload.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/http_upload.h new file mode 100644 index 00000000..a1ba7ae1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/http_upload.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST +// request using wininet. It currently supports requests that contain +// a set of string parameters (key/value pairs), and a file to upload. + +#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H__ +#define COMMON_WINDOWS_HTTP_UPLOAD_H__ + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +#include +#include +#include + +namespace google_breakpad { + +using std::string; +using std::wstring; +using std::map; +using std::vector; + +class HTTPUpload { + public: + // Sends the given set of parameters, along with the contents of + // upload_file, as a multipart POST request to the given URL. + // file_part_name contains the name of the file part of the request + // (i.e. it corresponds to the name= attribute on an . + // Parameter names must contain only printable ASCII characters, + // and may not contain a quote (") character. + // Only HTTP(S) URLs are currently supported. Returns true on success. + // If the request is successful and response_body is non-NULL, + // the response body will be returned in response_body. + // If response_code is non-NULL, it will be set to the HTTP response code + // received (or 0 if the request failed before getting an HTTP response). + static bool SendRequest(const wstring &url, + const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + wstring *response_body, + int *response_code); + + private: + class AutoInternetHandle; + + // Retrieves the HTTP response. If NULL is passed in for response, + // this merely checks (via the return value) that we were successfully + // able to retrieve exactly as many bytes of content in the response as + // were specified in the Content-Length header. + static bool HTTPUpload::ReadResponse(HINTERNET request, wstring* response); + + // Generates a new multipart boundary for a POST request + static wstring GenerateMultipartBoundary(); + + // Generates a HTTP request header for a multipart form submit. + static wstring GenerateRequestHeader(const wstring &boundary); + + // Given a set of parameters, an upload filename, and a file part name, + // generates a multipart request body string with these parameters + // and minidump contents. Returns true on success. + static bool GenerateRequestBody(const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + const wstring &boundary, + string *request_body); + + // Fills the supplied vector with the contents of filename. + static void GetFileContents(const wstring &filename, vector *contents); + + // Converts a UTF8 string to UTF16. + static wstring UTF8ToWide(const string &utf8); + + // Converts a UTF16 string to UTF8. + static string WideToUTF8(const wstring &wide); + + // Checks that the given list of parameters has only printable + // ASCII characters in the parameter name, and does not contain + // any quote (") characters. Returns true if so. + static bool CheckParameters(const map ¶meters); + + // No instances of this class should be created. + // Disallow all constructors, destructors, and operator=. + HTTPUpload(); + explicit HTTPUpload(const HTTPUpload &); + void operator=(const HTTPUpload &); + ~HTTPUpload(); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // COMMON_WINDOWS_HTTP_UPLOAD_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/pdb_source_line_writer.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/pdb_source_line_writer.h new file mode 100644 index 00000000..e91d0737 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/pdb_source_line_writer.h @@ -0,0 +1,163 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// PDBSourceLineWriter uses a pdb file produced by Visual C++ to output +// a line/address map for use with BasicSourceLineResolver. + +#ifndef _PDB_SOURCE_LINE_WRITER_H__ +#define _PDB_SOURCE_LINE_WRITER_H__ + +#include + +#include + +struct IDiaEnumLineNumbers; +struct IDiaSession; +struct IDiaSymbol; + +namespace google_breakpad { + +using std::wstring; + +// A structure that carries information that identifies a pdb file. +struct PDBModuleInfo { + public: + // The basename of the pdb file from which information was loaded. + wstring debug_file; + + // The pdb's identifier. For recent pdb files, the identifier consists + // of the pdb's guid, in uppercase hexadecimal form without any dashes + // or separators, followed immediately by the pdb's age, also in + // uppercase hexadecimal form. For older pdb files which have no guid, + // the identifier is the pdb's 32-bit signature value, in zero-padded + // hexadecimal form, followed immediately by the pdb's age, in lowercase + // hexadecimal form. + wstring debug_identifier; + + // A string identifying the cpu that the pdb is associated with. + // Currently, this may be "x86" or "unknown". + wstring cpu; +}; + +class PDBSourceLineWriter { + public: + enum FileFormat { + PDB_FILE, // a .pdb file containing debug symbols + EXE_FILE, // a .exe or .dll file + ANY_FILE // try PDB_FILE and then EXE_FILE + }; + + explicit PDBSourceLineWriter(); + ~PDBSourceLineWriter(); + + // Opens the given file. For executable files, the corresponding pdb + // file must be available; Open will be if it is not. + // If there is already a pdb file open, it is automatically closed. + // Returns true on success. + bool Open(const wstring &file, FileFormat format); + + // Locates the pdb file for the given executable (exe or dll) file, + // and opens it. If there is already a pdb file open, it is automatically + // closed. Returns true on success. + bool OpenExecutable(const wstring &exe_file); + + // Writes a map file from the current pdb file to the given file stream. + // Returns true on success. + bool WriteMap(FILE *map_file); + + // Closes the current pdb file and its associated resources. + void Close(); + + // Retrieves information about the module's debugging file. Returns + // true on success and false on failure. + bool GetModuleInfo(PDBModuleInfo *info); + + // Sets uses_guid to true if the opened file uses a new-style CodeView + // record with a 128-bit GUID, or false if the opened file uses an old-style + // CodeView record. When no GUID is available, a 32-bit signature should be + // used to identify the module instead. If the information cannot be + // determined, this method returns false. + bool UsesGUID(bool *uses_guid); + + private: + // Outputs the line/address pairs for each line in the enumerator. + // Returns true on success. + bool PrintLines(IDiaEnumLineNumbers *lines); + + // Outputs a function address and name, followed by its source line list. + // Returns true on success. + bool PrintFunction(IDiaSymbol *function); + + // Outputs all functions as described above. Returns true on success. + bool PrintFunctions(); + + // Outputs all of the source files in the session's pdb file. + // Returns true on success. + bool PrintSourceFiles(); + + // Outputs all of the frame information necessary to construct stack + // backtraces in the absence of frame pointers. Returns true on success. + bool PrintFrameData(); + + // Outputs a single public symbol address and name, if the symbol corresponds + // to a code address. Returns true on success. If symbol is does not + // correspond to code, returns true without outputting anything. + bool PrintCodePublicSymbol(IDiaSymbol *symbol); + + // Outputs a line identifying the PDB file that is being dumped, along with + // its uuid and age. + bool PrintPDBInfo(); + + // Returns the function name for a symbol. If possible, the name is + // undecorated. If the symbol's decorated form indicates the size of + // parameters on the stack, this information is returned in stack_param_size. + // Returns true on success. If the symbol doesn't encode parameter size + // information, stack_param_size is set to -1. + static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name, + int *stack_param_size); + + // Returns the number of bytes of stack space used for a function's + // parameters. function must have the tag SymTagFunction. In the event of + // a failure, returns 0, which is also a valid number of bytes. + static int GetFunctionStackParamSize(IDiaSymbol *function); + + // The session for the currently-open pdb file. + CComPtr session_; + + // The current output file for this WriteMap invocation. + FILE *output_; + + // Disallow copy ctor and operator= + PDBSourceLineWriter(const PDBSourceLineWriter&); + void operator=(const PDBSourceLineWriter&); +}; + +} // namespace google_breakpad + +#endif // _PDB_SOURCE_LINE_WRITER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/string_utils-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/string_utils-inl.h new file mode 100644 index 00000000..6f650812 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/common/windows/string_utils-inl.h @@ -0,0 +1,139 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// string_utils-inl.h: Safer string manipulation on Windows, supporting +// pre-MSVC8 environments. + +#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H__ +#define COMMON_WINDOWS_STRING_UTILS_INL_H__ + +#include +#include + +#include + +// The "ll" printf format size specifier corresponding to |long long| was +// intrudced in MSVC8. Earlier versions did not provide this size specifier, +// but "I64" can be used to print 64-bit types. Don't use "I64" where "ll" +// is available, in the event of oddball systems where |long long| is not +// 64 bits wide. +#if _MSC_VER >= 1400 // MSVC 2005/8 +#define WIN_STRING_FORMAT_LL "ll" +#else // MSC_VER >= 1400 +#define WIN_STRING_FORMAT_LL "I64" +#endif // MSC_VER >= 1400 + +// A nonconforming version of swprintf, without the length argument, was +// included with the CRT prior to MSVC8. Although a conforming version was +// also available via an overload, it is not reliably chosen. _snwprintf +// behaves as a standards-confirming swprintf should, so force the use of +// _snwprintf when using older CRTs. +#if _MSC_VER < 1400 // MSVC 2005/8 +#define swprintf _snwprintf +#else +// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently, +// it takes the same argument list as swprintf. +#define swprintf swprintf_s +#endif // MSC_VER < 1400 + +namespace google_breakpad { + +using std::string; +using std::wstring; + +class WindowsStringUtils { + public: + // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does + // not fail if source is longer than destination_size. The destination + // buffer is always 0-terminated. + static void safe_wcscpy(wchar_t *destination, size_t destination_size, + const wchar_t *source); + + // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot + // be passed directly, and pre-MSVC8, this will not fail if source or count + // are longer than destination_size. The destination buffer is always + // 0-terminated. + static void safe_wcsncpy(wchar_t *destination, size_t destination_size, + const wchar_t *source, size_t count); + + // Performs multi-byte to wide character conversion on C++ strings, using + // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8). Returns false on failure, + // without setting wcs. + static bool safe_mbstowcs(const string &mbs, wstring *wcs); + + // Returns the base name of a file, e.g. strips off the path. + static wstring GetBaseName(const wstring &filename); + + private: + // Disallow instantiation and other object-based operations. + WindowsStringUtils(); + WindowsStringUtils(const WindowsStringUtils&); + ~WindowsStringUtils(); + void operator=(const WindowsStringUtils&); +}; + +// static +inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination, + size_t destination_size, + const wchar_t *source) { +#if _MSC_VER >= 1400 // MSVC 2005/8 + wcscpy_s(destination, destination_size, source); +#else // _MSC_VER >= 1400 + // Pre-MSVC 2005/8 doesn't have wcscpy_s. Simulate it with wcsncpy. + // wcsncpy doesn't 0-terminate the destination buffer if the source string + // is longer than size. Ensure that the destination is 0-terminated. + wcsncpy(destination, source, destination_size); + if (destination && destination_size) + destination[destination_size - 1] = 0; +#endif // _MSC_VER >= 1400 +} + +// static +inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination, + size_t destination_size, + const wchar_t *source, + size_t count) { +#if _MSC_VER >= 1400 // MSVC 2005/8 + wcsncpy_s(destination, destination_size, source, count); +#else // _MSC_VER >= 1400 + // Pre-MSVC 2005/8 doesn't have wcsncpy_s. Simulate it with wcsncpy. + // wcsncpy doesn't 0-terminate the destination buffer if the source string + // is longer than size. Ensure that the destination is 0-terminated. + if (destination_size < count) + count = destination_size; + + wcsncpy(destination, source, count); + if (destination && count) + destination[count - 1] = 0; +#endif // _MSC_VER >= 1400 +} + +} // namespace google_breakpad + +#endif // COMMON_WINDOWS_STRING_UTILS_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/breakpad_types.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/breakpad_types.h new file mode 100644 index 00000000..926b47f2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/breakpad_types.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* breakpad_types.h: Precise-width types + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file ensures that types u_intN_t are defined for N = 8, 16, 32, and + * 64. Types of precise widths are crucial to the task of writing data + * structures on one platform and reading them on another. + * + * Author: Mark Mentovai */ + +#ifndef GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ +#define GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ + +#ifndef _WIN32 + +#include +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif /* __STDC_FORMAT_MACROS */ +#include + +#if defined(__SUNPRO_CC) || (defined(__GNUC__) && defined(__sun__)) +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; +#endif + +#else /* !_WIN32 */ + +#include + +typedef unsigned __int8 u_int8_t; +typedef unsigned __int16 u_int16_t; +typedef unsigned __int32 u_int32_t; +typedef unsigned __int64 u_int64_t; + +#endif /* !_WIN32 */ + +typedef struct { + u_int64_t high; + u_int64_t low; +} u_int128_t; + +typedef u_int64_t breakpad_time_t; + +/* Try to get PRIx64 from inttypes.h, but if it's not defined, fall back to + * llx, which is the format string for "long long" - this is a 64-bit + * integral type on many systems. */ +#ifndef PRIx64 +#define PRIx64 "llx" +#endif /* !PRIx64 */ + +#endif /* GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_amd64.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_amd64.h new file mode 100644 index 00000000..75dae7dd --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_amd64.h @@ -0,0 +1,231 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on amd64. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ + + +/* + * AMD64 support, see WINNT.H + */ + +typedef struct { + u_int16_t control_word; + u_int16_t status_word; + u_int8_t tag_word; + u_int8_t reserved1; + u_int16_t error_opcode; + u_int32_t error_offset; + u_int16_t error_selector; + u_int16_t reserved2; + u_int32_t data_offset; + u_int16_t data_selector; + u_int16_t reserved3; + u_int32_t mx_csr; + u_int32_t mx_csr_mask; + u_int128_t float_registers[8]; + u_int128_t xmm_registers[16]; + u_int8_t reserved4[96]; +} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */ + +#define MD_CONTEXT_AMD64_VR_COUNT 26 + +typedef struct { + /* + * Register parameter home addresses. + */ + u_int64_t p1_home; + u_int64_t p2_home; + u_int64_t p3_home; + u_int64_t p4_home; + u_int64_t p5_home; + u_int64_t p6_home; + + /* The next field determines the layout of the structure, and which parts + * of it are populated */ + u_int32_t context_flags; + u_int32_t mx_csr; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int16_t cs; + + /* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */ + u_int16_t ds; + u_int16_t es; + u_int16_t fs; + u_int16_t gs; + + /* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */ + u_int16_t ss; + u_int32_t eflags; + + /* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */ + u_int64_t dr0; + u_int64_t dr1; + u_int64_t dr2; + u_int64_t dr3; + u_int64_t dr6; + u_int64_t dr7; + + /* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */ + u_int64_t rax; + u_int64_t rcx; + u_int64_t rdx; + u_int64_t rbx; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int64_t rsp; + + /* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */ + u_int64_t rbp; + u_int64_t rsi; + u_int64_t rdi; + u_int64_t r8; + u_int64_t r9; + u_int64_t r10; + u_int64_t r11; + u_int64_t r12; + u_int64_t r13; + u_int64_t r14; + u_int64_t r15; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int64_t rip; + + /* The next set of registers are included with + * MD_CONTEXT_AMD64_FLOATING_POINT + */ + union { + MDXmmSaveArea32AMD64 flt_save; + struct { + u_int128_t header[2]; + u_int128_t legacy[8]; + u_int128_t xmm0; + u_int128_t xmm1; + u_int128_t xmm2; + u_int128_t xmm3; + u_int128_t xmm4; + u_int128_t xmm5; + u_int128_t xmm6; + u_int128_t xmm7; + u_int128_t xmm8; + u_int128_t xmm9; + u_int128_t xmm10; + u_int128_t xmm11; + u_int128_t xmm12; + u_int128_t xmm13; + u_int128_t xmm14; + u_int128_t xmm15; + } sse_registers; + }; + + u_int128_t vector_register[MD_CONTEXT_AMD64_VR_COUNT]; + u_int64_t vector_control; + + /* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */ + u_int64_t debug_control; + u_int64_t last_branch_to_rip; + u_int64_t last_branch_from_rip; + u_int64_t last_exception_to_rip; + u_int64_t last_exception_from_rip; + +} MDRawContextAMD64; /* CONTEXT */ + +/* For (MDRawContextAMD64).context_flags. These values indicate the type of + * context stored in the structure. The high 26 bits identify the CPU, the + * low 6 bits identify the type of context saved. */ +#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001) + /* CONTEXT_CONTROL */ +#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002) + /* CONTEXT_INTEGER */ +#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004) + /* CONTEXT_SEGMENTS */ +#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008) + /* CONTEXT_FLOATING_POINT */ +#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010) + /* CONTEXT_DEBUG_REGISTERS */ +/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it + * I think it really means CONTEXT_FLOATING_POINT. + */ + +#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \ + MD_CONTEXT_AMD64_INTEGER | \ + MD_CONTEXT_AMD64_FLOATING_POINT) + /* CONTEXT_FULL */ + +#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \ + MD_CONTEXT_AMD64_SEGMENTS | \ + MD_CONTEXT_X86_DEBUG_REGISTERS) + /* CONTEXT_ALL */ + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc.h new file mode 100644 index 00000000..038e921a --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc.h @@ -0,0 +1,163 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on ppc. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +/* + * Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X' + * mach/ppc/_types.h + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ + +#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32 + +typedef struct { + /* fpregs is a double[32] in mach/ppc/_types.h, but a u_int64_t is used + * here for precise sizing. */ + u_int64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT]; + u_int32_t fpscr_pad; + u_int32_t fpscr; /* Status/control */ +} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */ + + +#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32 + +typedef struct { + /* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h + * exposes them as four 32-bit quantities. */ + u_int128_t save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT]; + u_int128_t save_vscr; /* Status/control */ + u_int32_t save_pad5[4]; + u_int32_t save_vrvalid; /* Identifies which vector registers are saved */ + u_int32_t save_pad6[7]; +} MDVectorSaveAreaPPC; /* ppc_vector_state */ + + +#define MD_CONTEXT_PPC_GPR_COUNT 32 + +/* Use the same 32-bit alignment when accessing this structure from 64-bit code + * as is used natively in 32-bit code. #pragma pack is a MSVC extension + * supported by gcc. */ +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#pragma pack(4) +#else +#pragma pack(push, 4) +#endif + +typedef struct { + /* context_flags is not present in ppc_thread_state, but it aids + * identification of MDRawContextPPC among other raw context types, + * and it guarantees alignment when we get to float_save. */ + u_int32_t context_flags; + + u_int32_t srr0; /* Machine status save/restore: stores pc + * (instruction) */ + u_int32_t srr1; /* Machine status save/restore: stores msr + * (ps, program/machine state) */ + /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is + * used for brevity. */ + u_int32_t gpr[MD_CONTEXT_PPC_GPR_COUNT]; + u_int32_t cr; /* Condition */ + u_int32_t xer; /* Integer (fiXed-point) exception */ + u_int32_t lr; /* Link */ + u_int32_t ctr; /* Count */ + u_int32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */ + u_int32_t vrsave; /* Vector save */ + + /* float_save and vector_save aren't present in ppc_thread_state, but + * are represented in separate structures that still define a thread's + * context. */ + MDFloatingSaveAreaPPC float_save; + MDVectorSaveAreaPPC vector_save; +} MDRawContextPPC; /* Based on ppc_thread_state */ + +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#pragma pack(0) +#else +#pragma pack(pop) +#endif + +/* For (MDRawContextPPC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_PPC 0x20000000 +#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) +#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) +#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020) + +#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE +#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \ + MD_CONTEXT_PPC_FLOATING_POINT | \ + MD_CONTEXT_PPC_VECTOR) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc64.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc64.h new file mode 100644 index 00000000..a788e5d1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_ppc64.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2008, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on ppc64. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Neal Sidhwaney */ + + +/* + * Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X' + * mach/ppc/_types.h + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ + +#include "minidump_cpu_ppc.h" + +// these types are the same in ppc64 & ppc +typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64; +typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64; + +#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT + +typedef struct { + /* context_flags is not present in ppc_thread_state, but it aids + * identification of MDRawContextPPC among other raw context types, + * and it guarantees alignment when we get to float_save. */ + u_int64_t context_flags; + + u_int64_t srr0; /* Machine status save/restore: stores pc + * (instruction) */ + u_int64_t srr1; /* Machine status save/restore: stores msr + * (ps, program/machine state) */ + /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is + * used for brevity. */ + u_int64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT]; + u_int64_t cr; /* Condition */ + u_int64_t xer; /* Integer (fiXed-point) exception */ + u_int64_t lr; /* Link */ + u_int64_t ctr; /* Count */ + u_int64_t vrsave; /* Vector save */ + + /* float_save and vector_save aren't present in ppc_thread_state, but + * are represented in separate structures that still define a thread's + * context. */ + MDFloatingSaveAreaPPC float_save; + MDVectorSaveAreaPPC vector_save; +} MDRawContextPPC64; /* Based on ppc_thread_state */ + +/* For (MDRawContextPPC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_PPC 0x20000000 +#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) +#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) +#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020) + +#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE +#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \ + MD_CONTEXT_PPC_FLOATING_POINT | \ + MD_CONTEXT_PPC_VECTOR) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_sparc.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_sparc.h new file mode 100644 index 00000000..ee95b64e --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_sparc.h @@ -0,0 +1,158 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on sparc. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +/* + * SPARC support, see (solaris)sys/procfs_isa.h also + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ + +#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32 + +typedef struct { + + /* FPU floating point regs */ + u_int64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT]; + + u_int64_t filler; + u_int64_t fsr; /* FPU status register */ +} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */ + +#define MD_CONTEXT_SPARC_GPR_COUNT 32 + +typedef struct { + /* The next field determines the layout of the structure, and which parts + * of it are populated + */ + u_int32_t context_flags; + u_int32_t flag_pad; + /* + * General register access (SPARC). + * Don't confuse definitions here with definitions in . + * Registers are 32 bits for ILP32, 64 bits for LP64. + * SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit + */ + + /* 32 Integer working registers */ + + /* g_r[0-7] global registers(g0-g7) + * g_r[8-15] out registers(o0-o7) + * g_r[16-23] local registers(l0-l7) + * g_r[24-31] in registers(i0-i7) + */ + u_int64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT]; + + /* several control registers */ + + /* Processor State register(PSR) for SPARC V7/V8 + * Condition Code register (CCR) for SPARC V9 + */ + u_int64_t ccr; + + u_int64_t pc; /* Program Counter register (PC) */ + u_int64_t npc; /* Next Program Counter register (nPC) */ + u_int64_t y; /* Y register (Y) */ + + /* Address Space Identifier register (ASI) for SPARC V9 + * WIM for SPARC V7/V8 + */ + u_int64_t asi; + + /* Floating-Point Registers State register (FPRS) for SPARC V9 + * TBR for for SPARC V7/V8 + */ + u_int64_t fprs; + + /* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */ + MDFloatingSaveAreaSPARC float_save; + +} MDRawContextSPARC; /* CONTEXT_SPARC */ + +/* For (MDRawContextSPARC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_SPARC 0x10000000 +#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001) +#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002) +#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004) +#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008) + +#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \ + MD_CONTEXT_SPARC_INTEGER) + +#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \ + MD_CONTEXT_SAPARC_FLOATING_POINT | \ + MD_CONTEXT_SAPARC_EXTRA) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_x86.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_x86.h new file mode 100644 index 00000000..4dbc0e9a --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_cpu_x86.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on x86. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ + +#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80 + /* SIZE_OF_80387_REGISTERS */ + +typedef struct { + u_int32_t control_word; + u_int32_t status_word; + u_int32_t tag_word; + u_int32_t error_offset; + u_int32_t error_selector; + u_int32_t data_offset; + u_int32_t data_selector; + + /* register_area contains eight 80-bit (x87 "long double") quantities for + * floating-point registers %st0 (%mm0) through %st7 (%mm7). */ + u_int8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE]; + u_int32_t cr0_npx_state; +} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */ + + +#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512 + /* MAXIMUM_SUPPORTED_EXTENSION */ + +typedef struct { + /* The next field determines the layout of the structure, and which parts + * of it are populated */ + u_int32_t context_flags; + + /* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */ + u_int32_t dr0; + u_int32_t dr1; + u_int32_t dr2; + u_int32_t dr3; + u_int32_t dr6; + u_int32_t dr7; + + /* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */ + MDFloatingSaveAreaX86 float_save; + + /* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */ + u_int32_t gs; + u_int32_t fs; + u_int32_t es; + u_int32_t ds; + /* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */ + u_int32_t edi; + u_int32_t esi; + u_int32_t ebx; + u_int32_t edx; + u_int32_t ecx; + u_int32_t eax; + + /* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */ + u_int32_t ebp; + u_int32_t eip; + u_int32_t cs; /* WinNT.h says "must be sanitized" */ + u_int32_t eflags; /* WinNT.h says "must be sanitized" */ + u_int32_t esp; + u_int32_t ss; + + /* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS. + * It contains vector (MMX/SSE) registers. It it laid out in the + * format used by the fxsave and fsrstor instructions, so it includes + * a copy of the x87 floating-point registers as well. See FXSAVE in + * "Intel Architecture Software Developer's Manual, Volume 2." */ + u_int8_t extended_registers[ + MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE]; +} MDRawContextX86; /* CONTEXT */ + +/* For (MDRawContextX86).context_flags. These values indicate the type of + * context stored in the structure. The high 26 bits identify the CPU, the + * low 6 bits identify the type of context saved. */ +#define MD_CONTEXT_X86 0x00010000 + /* CONTEXT_i386, CONTEXT_i486: identifies CPU */ +#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001) + /* CONTEXT_CONTROL */ +#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002) + /* CONTEXT_INTEGER */ +#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004) + /* CONTEXT_SEGMENTS */ +#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008) + /* CONTEXT_FLOATING_POINT */ +#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010) + /* CONTEXT_DEBUG_REGISTERS */ +#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020) + /* CONTEXT_EXTENDED_REGISTERS */ + +#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \ + MD_CONTEXT_X86_INTEGER | \ + MD_CONTEXT_X86_SEGMENTS) + /* CONTEXT_FULL */ + +#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \ + MD_CONTEXT_X86_FLOATING_POINT | \ + MD_CONTEXT_X86_DEBUG_REGISTERS | \ + MD_CONTEXT_X86_EXTENDED_REGISTERS) + /* CONTEXT_ALL */ + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_linux.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_linux.h new file mode 100644 index 00000000..d52c7519 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_linux.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_linux.h: A definition of exception codes for + * Linux + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +/* For (MDException).exception_code. These values come from bits/signum.h. + */ +typedef enum { + MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */ + MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */ + MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGURG = 23, + /* Urgent condition on socket (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25, + /* File size limit exceeded (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */ + MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */ + MD_EXCEPTION_CODE_LIN_SIGSYS = 31 /* Bad system call */ +} MDExceptionCodeLinux; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_mac.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_mac.h new file mode 100644 index 00000000..5fba44ca --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_mac.h @@ -0,0 +1,193 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_mac.h: A definition of exception codes for Mac + * OS X + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X + * support. Based on Darwin/Mac OS X' mach/exception_types.h. This is + * what Mac OS X calls an "exception", not a "code". */ +typedef enum { + /* Exception code. The high 16 bits of exception_code contains one of + * these values. */ + MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */ + /* EXC_BAD_ACCESS */ + MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */ + /* EXC_BAD_INSTRUCTION */ + MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */ + /* EXC_ARITHMETIC */ + MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */ + /* EXC_EMULATION */ + MD_EXCEPTION_MAC_SOFTWARE = 5, + /* EXC_SOFTWARE */ + MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */ + /* EXC_BREAKPOINT */ + MD_EXCEPTION_MAC_SYSCALL = 7, + /* EXC_SYSCALL */ + MD_EXCEPTION_MAC_MACH_SYSCALL = 8, + /* EXC_MACH_SYSCALL */ + MD_EXCEPTION_MAC_RPC_ALERT = 9 + /* EXC_RPC_ALERT */ +} MDExceptionMac; + +/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X + * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and + * mach/i386/exception.h. This is what Mac OS X calls a "code". */ +typedef enum { + /* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values + * from mach/kern_return.h. */ + MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1, + /* KERN_INVALID_ADDRESS */ + MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2, + /* KERN_PROTECTION_FAILURE */ + MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8, + /* KERN_NO_ACCESS */ + MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9, + /* KERN_MEMORY_FAILURE */ + MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10, + /* KERN_MEMORY_ERROR */ + + /* With MD_EXCEPTION_SOFTWARE */ + MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */ + MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */ + MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */ + + /* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101, + /* EXC_PPC_VM_PROT_READ */ + MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102, + /* EXC_PPC_BADSPACE */ + MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103, + /* EXC_PPC_UNALIGNED */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1, + /* EXC_PPC_INVALID_SYSCALL */ + MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2, + /* EXC_PPC_UNIPL_INST */ + MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3, + /* EXC_PPC_PRIVINST */ + MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4, + /* EXC_PPC_PRIVREG */ + MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5, + /* EXC_PPC_TRACE */ + MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6, + /* EXC_PPC_PERFMON */ + + /* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1, + /* EXC_PPC_OVERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2, + /* EXC_PPC_ZERO_DIVIDE */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3, + /* EXC_FLT_INEXACT */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4, + /* EXC_PPC_FLT_ZERO_DIVIDE */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5, + /* EXC_PPC_FLT_UNDERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6, + /* EXC_PPC_FLT_OVERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7, + /* EXC_PPC_FLT_NOT_A_NUMBER */ + + /* With MD_EXCEPTION_MAC_EMULATION on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8, + /* EXC_PPC_NOEMULATION */ + MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9, + /* EXC_PPC_ALTIVECASSIST */ + + /* With MD_EXCEPTION_MAC_SOFTWARE on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */ + MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */ + + /* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt + * values below. */ + MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */ + + /* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */ + MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */ + MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */ + MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */ + MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */ + MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */ + MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */ + MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */ + MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */ + + /* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */ + MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */ + MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw + * x86 interrupt codes. Most of these are mapped to other Mach + * exceptions and codes, are handled, or should not occur in user space. + * A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */ + /* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */ + /* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */ + /* EXC_I386_NMIFLT = 2: should not occur in user space */ + /* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */ + /* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */ + /* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */ + /* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */ + /* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */ + /* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */ + /* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */ + MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10, + /* EXC_INVTSSFLT */ + MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11, + /* EXC_SEGNPFLT */ + MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12, + /* EXC_STKFLT */ + MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13, + /* EXC_GPFLT */ + /* EXC_I386_PGFLT = 14: should not occur in user space */ + /* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */ + MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17 + /* EXC_ALIGNFLT (for vector operations) */ + /* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */ + /* EXC_I386_ENDPERR = 33: should not occur */ +} MDExceptionCodeMac; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_solaris.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_solaris.h new file mode 100644 index 00000000..d48632ac --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_solaris.h @@ -0,0 +1,94 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_solaris.h: A definition of exception codes for + * Solaris + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h + */ +typedef enum { + MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */ + MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */ + MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */ + MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */ + MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */ + MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */ + MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */ + MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */ + MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */ + MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */ + MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */ + MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */ + MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */ + MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */ + MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */ + MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */ + MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */ + MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */ + MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */ + MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */ + MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */ + MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */ + MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */ + MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occured */ + MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */ + MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */ + MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */ + MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */ + MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */ + MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */ + MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */ + MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */ + MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */ + MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */ + MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */ + MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */ + MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */ + MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */ + MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */ + MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */ + MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */ + MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */ + MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */ +} MDExceptionCodeSolaris; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_win32.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_win32.h new file mode 100644 index 00000000..7fd4bc4f --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_exception_win32.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_win32.h: Definitions of exception codes for + * Win32 platform + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +/* For (MDException).exception_code. These values come from WinBase.h + * and WinNT.h (names beginning with EXCEPTION_ are in WinBase.h, + * they are STATUS_ in WinNT.h). */ +typedef enum { + MD_EXCEPTION_CODE_WIN_CONTROL_C = 0x40010005, + /* DBG_CONTROL_C */ + MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001, + /* EXCEPTION_GUARD_PAGE */ + MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002, + /* EXCEPTION_DATATYPE_MISALIGNMENT */ + MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003, + /* EXCEPTION_BREAKPOINT */ + MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004, + /* EXCEPTION_SINGLE_STEP */ + MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION = 0xc0000005, + /* EXCEPTION_ACCESS_VIOLATION */ + MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR = 0xc0000006, + /* EXCEPTION_IN_PAGE_ERROR */ + MD_EXCEPTION_CODE_WIN_INVALID_HANDLE = 0xc0000008, + /* EXCEPTION_INVALID_HANDLE */ + MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION = 0xc000001d, + /* EXCEPTION_ILLEGAL_INSTRUCTION */ + MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION = 0xc0000025, + /* EXCEPTION_NONCONTINUABLE_EXCEPTION */ + MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION = 0xc0000026, + /* EXCEPTION_INVALID_DISPOSITION */ + MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED = 0xc000008c, + /* EXCEPTION_BOUNDS_EXCEEDED */ + MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND = 0xc000008d, + /* EXCEPTION_FLT_DENORMAL_OPERAND */ + MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO = 0xc000008e, + /* EXCEPTION_FLT_DIVIDE_BY_ZERO */ + MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT = 0xc000008f, + /* EXCEPTION_FLT_INEXACT_RESULT */ + MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION = 0xc0000090, + /* EXCEPTION_FLT_INVALID_OPERATION */ + MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW = 0xc0000091, + /* EXCEPTION_FLT_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK = 0xc0000092, + /* EXCEPTION_FLT_STACK_CHECK */ + MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW = 0xc0000093, + /* EXCEPTION_FLT_UNDERFLOW */ + MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094, + /* EXCEPTION_INT_DIVIDE_BY_ZERO */ + MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095, + /* EXCEPTION_INT_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096, + /* EXCEPTION_PRIV_INSTRUCTION */ + MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd, + /* EXCEPTION_STACK_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194 + /* EXCEPTION_POSSIBLE_DEADLOCK */ +} MDExceptionCodeWin; + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_format.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_format.h new file mode 100644 index 00000000..4d9e767f --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_format.h @@ -0,0 +1,721 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +#if defined(_MSC_VER) +/* Disable "zero-sized array in struct/union" warnings when compiling in + * MSVC. DbgHelp.h does this too. */ +#pragma warning(push) +#pragma warning(disable:4200) +#endif /* _MSC_VER */ + + +/* + * guiddef.h + */ + +typedef struct { + u_int32_t data1; + u_int16_t data2; + u_int16_t data3; + u_int8_t data4[8]; +} MDGUID; /* GUID */ + + +/* + * WinNT.h + */ + +/* Non-x86 CPU identifiers found in the high 26 bits of + * (MDRawContext*).context_flags. These aren't used by Breakpad, but are + * defined here for reference, to avoid assigning values that conflict + * (although some values already conflict). */ +#define MD_CONTEXT_IA64 0x00080000 /* CONTEXT_IA64 */ +#define MD_CONTEXT_AMD64 0x00100000 /* CONTEXT_AMD64 */ +/* Additional values from winnt.h in the Windows CE 5.0 SDK: */ +#define MD_CONTEXT_SHX 0x000000c0 /* CONTEXT_SH4 (Super-H, includes SH3) */ +#define MD_CONTEXT_ARM 0x00000040 /* CONTEXT_ARM (0x40 bit set in SHx?) */ +#define MD_CONTEXT_MIPS 0x00010000 /* CONTEXT_R4000 (same value as x86?) */ +#define MD_CONTEXT_ALPHA 0x00020000 /* CONTEXT_ALPHA */ + +#define MD_CONTEXT_CPU_MASK 0xffffffc0 + + +/* This is a base type for MDRawContextX86 and MDRawContextPPC. This + * structure should never be allocated directly. The actual structure type + * can be determined by examining the context_flags field. */ +typedef struct { + u_int32_t context_flags; +} MDRawContextBase; + +#include "minidump_cpu_sparc.h" +#include "minidump_cpu_x86.h" +#include "minidump_cpu_ppc.h" +#include "minidump_cpu_ppc64.h" +#include "minidump_cpu_amd64.h" + + +/* + * WinVer.h + */ + + +typedef struct { + u_int32_t signature; + u_int32_t struct_version; + u_int32_t file_version_hi; + u_int32_t file_version_lo; + u_int32_t product_version_hi; + u_int32_t product_version_lo; + u_int32_t file_flags_mask; /* Identifies valid bits in fileFlags */ + u_int32_t file_flags; + u_int32_t file_os; + u_int32_t file_type; + u_int32_t file_subtype; + u_int32_t file_date_hi; + u_int32_t file_date_lo; +} MDVSFixedFileInfo; /* VS_FIXEDFILEINFO */ + +/* For (MDVSFixedFileInfo).signature */ +#define MD_VSFIXEDFILEINFO_SIGNATURE 0xfeef04bd + /* VS_FFI_SIGNATURE */ + +/* For (MDVSFixedFileInfo).version */ +#define MD_VSFIXEDFILEINFO_VERSION 0x00010000 + /* VS_FFI_STRUCVERSION */ + +/* For (MDVSFixedFileInfo).file_flags_mask and + * (MDVSFixedFileInfo).file_flags */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG 0x00000001 + /* VS_FF_DEBUG */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRERELEASE 0x00000002 + /* VS_FF_PRERELEASE */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PATCHED 0x00000004 + /* VS_FF_PATCHED */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRIVATEBUILD 0x00000008 + /* VS_FF_PRIVATEBUILD */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_INFOINFERRED 0x00000010 + /* VS_FF_INFOINFERRED */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_SPECIALBUILD 0x00000020 + /* VS_FF_SPECIALBUILD */ + +/* For (MDVSFixedFileInfo).file_os: high 16 bits */ +#define MD_VSFIXEDFILEINFO_FILE_OS_UNKNOWN 0 /* VOS_UNKNOWN */ +#define MD_VSFIXEDFILEINFO_FILE_OS_DOS (1 << 16) /* VOS_DOS */ +#define MD_VSFIXEDFILEINFO_FILE_OS_OS216 (2 << 16) /* VOS_OS216 */ +#define MD_VSFIXEDFILEINFO_FILE_OS_OS232 (3 << 16) /* VOS_OS232 */ +#define MD_VSFIXEDFILEINFO_FILE_OS_NT (4 << 16) /* VOS_NT */ +#define MD_VSFIXEDFILEINFO_FILE_OS_WINCE (5 << 16) /* VOS_WINCE */ +/* Low 16 bits */ +#define MD_VSFIXEDFILEINFO_FILE_OS__BASE 0 /* VOS__BASE */ +#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS16 1 /* VOS__WINDOWS16 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__PM16 2 /* VOS__PM16 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__PM32 3 /* VOS__PM32 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32 4 /* VOS__WINDOWS32 */ + +/* For (MDVSFixedFileInfo).file_type */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_UNKNOWN 0 /* VFT_UNKNOWN */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_APP 1 /* VFT_APP */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_DLL 2 /* VFT_DLL */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_DRV 3 /* VFT_DLL */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_FONT 4 /* VFT_FONT */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_VXD 5 /* VFT_VXD */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_STATIC_LIB 7 /* VFT_STATIC_LIB */ + +/* For (MDVSFixedFileInfo).file_subtype */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN 0 + /* VFT2_UNKNOWN */ +/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_DRV */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_PRINTER 1 + /* VFT2_DRV_PRINTER */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_KEYBOARD 2 + /* VFT2_DRV_KEYBOARD */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_LANGUAGE 3 + /* VFT2_DRV_LANGUAGE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_DISPLAY 4 + /* VFT2_DRV_DISPLAY */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_MOUSE 5 + /* VFT2_DRV_MOUSE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_NETWORK 6 + /* VFT2_DRV_NETWORK */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SYSTEM 7 + /* VFT2_DRV_SYSTEM */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INSTALLABLE 8 + /* VFT2_DRV_INSTALLABLE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SOUND 9 + /* VFT2_DRV_SOUND */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_COMM 10 + /* VFT2_DRV_COMM */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INPUTMETHOD 11 + /* VFT2_DRV_INPUTMETHOD */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_VERSIONED_PRINTER 12 + /* VFT2_DRV_VERSIONED_PRINTER */ +/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_FONT */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_RASTER 1 + /* VFT2_FONT_RASTER */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_VECTOR 2 + /* VFT2_FONT_VECTOR */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_TRUETYPE 3 + /* VFT2_FONT_TRUETYPE */ + + +/* + * DbgHelp.h + */ + + +/* An MDRVA is an offset into the minidump file. The beginning of the + * MDRawHeader is at offset 0. */ +typedef u_int32_t MDRVA; /* RVA */ + +typedef struct { + u_int32_t data_size; + MDRVA rva; +} MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */ + + +typedef struct { + /* The base address of the memory range on the host that produced the + * minidump. */ + u_int64_t start_of_memory_range; + + MDLocationDescriptor memory; +} MDMemoryDescriptor; /* MINIDUMP_MEMORY_DESCRIPTOR */ + + +typedef struct { + u_int32_t signature; + u_int32_t version; + u_int32_t stream_count; + MDRVA stream_directory_rva; /* A |stream_count|-sized array of + * MDRawDirectory structures. */ + u_int32_t checksum; /* Can be 0. In fact, that's all that's + * been found in minidump files. */ + u_int32_t time_date_stamp; /* time_t */ + u_int64_t flags; +} MDRawHeader; /* MINIDUMP_HEADER */ + +/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the + * low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION. Per the + * documentation, the high 16 bits are implementation-specific. */ +#define MD_HEADER_SIGNATURE 0x504d444d /* 'PMDM' */ + /* MINIDUMP_SIGNATURE */ +#define MD_HEADER_VERSION 0x0000a793 /* 42899 */ + /* MINIDUMP_VERSION */ + +/* For (MDRawHeader).flags: */ +typedef enum { + /* MD_NORMAL is the standard type of minidump. It includes full + * streams for the thread list, module list, exception, system info, + * and miscellaneous info. A memory list stream is also present, + * pointing to the same stack memory contained in the thread list, + * as well as a 256-byte region around the instruction address that + * was executing when the exception occurred. Stack memory is from + * 4 bytes below a thread's stack pointer up to the top of the + * memory region encompassing the stack. */ + MD_NORMAL = 0x00000000, + MD_WITH_DATA_SEGS = 0x00000001, + MD_WITH_FULL_MEMORY = 0x00000002, + MD_WITH_HANDLE_DATA = 0x00000004, + MD_FILTER_MEMORY = 0x00000008, + MD_SCAN_MEMORY = 0x00000010, + MD_WITH_UNLOADED_MODULES = 0x00000020, + MD_WITH_INDIRECTLY_REFERENCED_MEMORY = 0x00000040, + MD_FILTER_MODULE_PATHS = 0x00000080, + MD_WITH_PROCESS_THREAD_DATA = 0x00000100, + MD_WITH_PRIVATE_READ_WRITE_MEMORY = 0x00000200, + MD_WITHOUT_OPTIONAL_DATA = 0x00000400, + MD_WITH_FULL_MEMORY_INFO = 0x00000800, + MD_WITH_THREAD_INFO = 0x00001000, + MD_WITH_CODE_SEGS = 0x00002000 +} MDType; /* MINIDUMP_TYPE */ + + +typedef struct { + u_int32_t stream_type; + MDLocationDescriptor location; +} MDRawDirectory; /* MINIDUMP_DIRECTORY */ + +/* For (MDRawDirectory).stream_type */ +typedef enum { + MD_UNUSED_STREAM = 0, + MD_RESERVED_STREAM_0 = 1, + MD_RESERVED_STREAM_1 = 2, + MD_THREAD_LIST_STREAM = 3, /* MDRawThreadList */ + MD_MODULE_LIST_STREAM = 4, /* MDRawModuleList */ + MD_MEMORY_LIST_STREAM = 5, /* MDRawMemoryList */ + MD_EXCEPTION_STREAM = 6, /* MDRawExceptionStream */ + MD_SYSTEM_INFO_STREAM = 7, /* MDRawSystemInfo */ + MD_THREAD_EX_LIST_STREAM = 8, + MD_MEMORY_64_LIST_STREAM = 9, + MD_COMMENT_STREAM_A = 10, + MD_COMMENT_STREAM_W = 11, + MD_HANDLE_DATA_STREAM = 12, + MD_FUNCTION_TABLE_STREAM = 13, + MD_UNLOADED_MODULE_LIST_STREAM = 14, + MD_MISC_INFO_STREAM = 15, /* MDRawMiscInfo */ + MD_LAST_RESERVED_STREAM = 0x0000ffff, + + /* Breakpad extension types. 0x4767 = "Gg" */ + MD_BREAKPAD_INFO_STREAM = 0x47670001, /* MDRawBreakpadInfo */ + MD_ASSERTION_INFO_STREAM = 0x47670002 /* MDRawAssertionInfo */ +} MDStreamType; /* MINIDUMP_STREAM_TYPE */ + + +typedef struct { + u_int32_t length; /* Length of buffer in bytes (not characters), + * excluding 0-terminator */ + u_int16_t buffer[1]; /* UTF-16-encoded, 0-terminated */ +} MDString; /* MINIDUMP_STRING */ + +static const size_t MDString_minsize = offsetof(MDString, buffer[0]); + + +typedef struct { + u_int32_t thread_id; + u_int32_t suspend_count; + u_int32_t priority_class; + u_int32_t priority; + u_int64_t teb; /* Thread environment block */ + MDMemoryDescriptor stack; + MDLocationDescriptor thread_context; /* MDRawContext[CPU] */ +} MDRawThread; /* MINIDUMP_THREAD */ + + +typedef struct { + u_int32_t number_of_threads; + MDRawThread threads[1]; +} MDRawThreadList; /* MINIDUMP_THREAD_LIST */ + +static const size_t MDRawThreadList_minsize = offsetof(MDRawThreadList, + threads[0]); + + +typedef struct { + u_int64_t base_of_image; + u_int32_t size_of_image; + u_int32_t checksum; /* 0 if unknown */ + u_int32_t time_date_stamp; /* time_t */ + MDRVA module_name_rva; /* MDString, pathname or filename */ + MDVSFixedFileInfo version_info; + + /* The next field stores a CodeView record and is populated when a module's + * debug information resides in a PDB file. It identifies the PDB file. */ + MDLocationDescriptor cv_record; + + /* The next field is populated when a module's debug information resides + * in a DBG file. It identifies the DBG file. This field is effectively + * obsolete with modules built by recent toolchains. */ + MDLocationDescriptor misc_record; + + /* Alignment problem: reserved0 and reserved1 are defined by the platform + * SDK as 64-bit quantities. However, that results in a structure whose + * alignment is unpredictable on different CPUs and ABIs. If the ABI + * specifies full alignment of 64-bit quantities in structures (as ppc + * does), there will be padding between miscRecord and reserved0. If + * 64-bit quantities can be aligned on 32-bit boundaries (as on x86), + * this padding will not exist. (Note that the structure up to this point + * contains 1 64-bit member followed by 21 32-bit members.) + * As a workaround, reserved0 and reserved1 are instead defined here as + * four 32-bit quantities. This should be harmless, as there are + * currently no known uses for these fields. */ + u_int32_t reserved0[2]; + u_int32_t reserved1[2]; +} MDRawModule; /* MINIDUMP_MODULE */ + +/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to + * be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC). + * This doesn't occur on systems that don't tail-pad in this manner. Define + * this macro to be the usable size of the MDRawModule struct, and use it in + * place of sizeof(MDRawModule). */ +#define MD_MODULE_SIZE 108 + + +/* (MDRawModule).cv_record can reference MDCVInfoPDB20 or MDCVInfoPDB70. + * Ref.: http://www.debuginfo.com/articles/debuginfomatch.html + * MDCVInfoPDB70 is the expected structure type with recent toolchains. */ + +typedef struct { + u_int32_t signature; + u_int32_t offset; /* Offset to debug data (expect 0 in minidump) */ +} MDCVHeader; + +typedef struct { + MDCVHeader cv_header; + u_int32_t signature; /* time_t debug information created */ + u_int32_t age; /* revision of PDB file */ + u_int8_t pdb_file_name[1]; /* Pathname or filename of PDB file */ +} MDCVInfoPDB20; + +static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20, + pdb_file_name[0]); + +#define MD_CVINFOPDB20_SIGNATURE 0x3031424e /* cvHeader.signature = '01BN' */ + +typedef struct { + u_int32_t cv_signature; + MDGUID signature; /* GUID, identifies PDB file */ + u_int32_t age; /* Identifies incremental changes to PDB file */ + u_int8_t pdb_file_name[1]; /* Pathname or filename of PDB file, + * 0-terminated 8-bit character data (UTF-8?) */ +} MDCVInfoPDB70; + +static const size_t MDCVInfoPDB70_minsize = offsetof(MDCVInfoPDB70, + pdb_file_name[0]); + +#define MD_CVINFOPDB70_SIGNATURE 0x53445352 /* cvSignature = 'SDSR' */ + +typedef struct { + u_int32_t data1[2]; + u_int32_t data2; + u_int32_t data3; + u_int32_t data4; + u_int32_t data5[3]; + u_int8_t extra[2]; +} MDCVInfoELF; + +/* In addition to the two CodeView record formats above, used for linking + * to external pdb files, it is possible for debugging data to be carried + * directly in the CodeView record itself. These signature values will + * be found in the first 4 bytes of the CodeView record. Additional values + * not commonly experienced in the wild are given by "Microsoft Symbol and + * Type Information", http://www.x86.org/ftp/manuals/tools/sym.pdf, section + * 7.2. An in-depth description of the CodeView 4.1 format is given by + * "Undocumented Windows 2000 Secrets", Windows 2000 Debugging Support/ + * Microsoft Symbol File Internals/CodeView Subsections, + * http://www.rawol.com/features/undocumented/sbs-w2k-1-windows-2000-debugging-support.pdf + */ +#define MD_CVINFOCV41_SIGNATURE 0x3930424e /* '90BN', CodeView 4.10. */ +#define MD_CVINFOCV50_SIGNATURE 0x3131424e /* '11BN', CodeView 5.0, + * MS C7-format (/Z7). */ + +#define MD_CVINFOUNKNOWN_SIGNATURE 0xffffffff /* An unlikely value. */ + +/* (MDRawModule).miscRecord can reference MDImageDebugMisc. The Windows + * structure is actually defined in WinNT.h. This structure is effectively + * obsolete with modules built by recent toolchains. */ + +typedef struct { + u_int32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because + * this debug record type is mostly obsolete. */ + u_int32_t length; /* Length of entire MDImageDebugMisc structure */ + u_int8_t unicode; /* True if data is multibyte */ + u_int8_t reserved[3]; + u_int8_t data[1]; +} MDImageDebugMisc; /* IMAGE_DEBUG_MISC */ + +static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc, + data[0]); + + +typedef struct { + u_int32_t number_of_modules; + MDRawModule modules[1]; +} MDRawModuleList; /* MINIDUMP_MODULE_LIST */ + +static const size_t MDRawModuleList_minsize = offsetof(MDRawModuleList, + modules[0]); + + +typedef struct { + u_int32_t number_of_memory_ranges; + MDMemoryDescriptor memory_ranges[1]; +} MDRawMemoryList; /* MINIDUMP_MEMORY_LIST */ + +static const size_t MDRawMemoryList_minsize = offsetof(MDRawMemoryList, + memory_ranges[0]); + + +#define MD_EXCEPTION_MAXIMUM_PARAMETERS 15 + +typedef struct { + u_int32_t exception_code; /* Windows: MDExceptionCodeWin, + * Mac OS X: MDExceptionMac, + * Linux: MDExceptionCodeLinux. */ + u_int32_t exception_flags; /* Windows: 1 if noncontinuable, + Mac OS X: MDExceptionCodeMac. */ + u_int64_t exception_record; /* Address (in the minidump-producing host's + * memory) of another MDException, for + * nested exceptions. */ + u_int64_t exception_address; /* The address that caused the exception. + * Mac OS X: exception subcode (which is + * typically the address). */ + u_int32_t number_parameters; /* Number of valid elements in + * exception_information. */ + u_int32_t __align; + u_int64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS]; +} MDException; /* MINIDUMP_EXCEPTION */ + +#include "minidump_exception_win32.h" +#include "minidump_exception_mac.h" +#include "minidump_exception_linux.h" +#include "minidump_exception_solaris.h" + +typedef struct { + u_int32_t thread_id; /* Thread in which the exception + * occurred. Corresponds to + * (MDRawThread).thread_id. */ + u_int32_t __align; + MDException exception_record; + MDLocationDescriptor thread_context; /* MDRawContext[CPU] */ +} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */ + + +typedef union { + struct { + u_int32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ + u_int32_t version_information; /* cpuid 1: eax */ + u_int32_t feature_information; /* cpuid 1: edx */ + u_int32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ + } x86_cpu_info; + struct { + u_int64_t processor_features[2]; + } other_cpu_info; +} MDCPUInformation; /* CPU_INFORMATION */ + + +typedef struct { + /* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO + * structure as returned by GetSystemInfo */ + u_int16_t processor_architecture; + u_int16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */ + u_int16_t processor_revision; /* x86: 0xMMSS, where MM=model, + * SS=stepping */ + + u_int8_t number_of_processors; + u_int8_t product_type; /* Windows: VER_NT_* from WinNT.h */ + + /* The next 5 fields are from the OSVERSIONINFO structure as returned + * by GetVersionEx */ + u_int32_t major_version; + u_int32_t minor_version; + u_int32_t build_number; + u_int32_t platform_id; + MDRVA csd_version_rva; /* MDString further identifying the + * host OS. + * Windows: name of the installed OS + * service pack. + * Mac OS X: the Apple OS build number + * (sw_vers -buildVersion). + * Linux: uname -srvmo */ + + u_int16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */ + u_int16_t reserved2; + + MDCPUInformation cpu; +} MDRawSystemInfo; /* MINIDUMP_SYSTEM_INFO */ + +/* For (MDRawSystemInfo).processor_architecture: */ +typedef enum { + MD_CPU_ARCHITECTURE_X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ + MD_CPU_ARCHITECTURE_MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ + MD_CPU_ARCHITECTURE_ALPHA = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ + MD_CPU_ARCHITECTURE_PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ + MD_CPU_ARCHITECTURE_SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX + * (Super-H) */ + MD_CPU_ARCHITECTURE_ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ + MD_CPU_ARCHITECTURE_IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ + MD_CPU_ARCHITECTURE_ALPHA64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ + MD_CPU_ARCHITECTURE_MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL + * (Microsoft Intermediate Language) */ + MD_CPU_ARCHITECTURE_AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ + MD_CPU_ARCHITECTURE_X86_WIN64 = 10, + /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ + MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */ + MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ +} MDCPUArchitecture; + +/* For (MDRawSystemInfo).platform_id: */ +typedef enum { + MD_OS_WIN32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ + MD_OS_WIN32_WINDOWS = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ + MD_OS_WIN32_NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ + MD_OS_WIN32_CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH + * (Windows CE, Windows Mobile, "Handheld") */ + + /* The following values are Breakpad-defined. */ + MD_OS_UNIX = 0x8000, /* Generic Unix-ish */ + MD_OS_MAC_OS_X = 0x8101, /* Mac OS X/Darwin */ + MD_OS_LINUX = 0x8201, /* Linux */ + MD_OS_SOLARIS = 0x8202 /* Solaris */ +} MDOSPlatform; + + +typedef struct { + u_int32_t size_of_info; /* Length of entire MDRawMiscInfo structure. */ + u_int32_t flags1; + + /* The next field is only valid if flags1 contains + * MD_MISCINFO_FLAGS1_PROCESS_ID. */ + u_int32_t process_id; + + /* The next 3 fields are only valid if flags1 contains + * MD_MISCINFO_FLAGS1_PROCESS_TIMES. */ + u_int32_t process_create_time; /* time_t process started */ + u_int32_t process_user_time; /* seconds of user CPU time */ + u_int32_t process_kernel_time; /* seconds of kernel CPU time */ + + /* The following fields are not present in MINIDUMP_MISC_INFO but are + * in MINIDUMP_MISC_INFO_2. When this struct is populated, these values + * may not be set. Use flags1 or sizeOfInfo to determine whether these + * values are present. These are only valid when flags1 contains + * MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO. */ + u_int32_t processor_max_mhz; + u_int32_t processor_current_mhz; + u_int32_t processor_mhz_limit; + u_int32_t processor_max_idle_state; + u_int32_t processor_current_idle_state; +} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO2 */ + +#define MD_MISCINFO_SIZE 24 +#define MD_MISCINFO2_SIZE 44 + +/* For (MDRawMiscInfo).flags1. These values indicate which fields in the + * MDRawMiscInfoStructure are valid. */ +typedef enum { + MD_MISCINFO_FLAGS1_PROCESS_ID = 0x00000001, + /* MINIDUMP_MISC1_PROCESS_ID */ + MD_MISCINFO_FLAGS1_PROCESS_TIMES = 0x00000002, + /* MINIDUMP_MISC1_PROCESS_TIMES */ + MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO = 0x00000004 + /* MINIDUMP_MISC1_PROCESSOR_POWER_INFO */ +} MDMiscInfoFlags1; + + +/* + * Breakpad extension types + */ + + +typedef struct { + /* validity is a bitmask with values from MDBreakpadInfoValidity, indicating + * which of the other fields in the structure are valid. */ + u_int32_t validity; + + /* Thread ID of the handler thread. dump_thread_id should correspond to + * the thread_id of an MDRawThread in the minidump's MDRawThreadList if + * a dedicated thread in that list was used to produce the minidump. If + * the MDRawThreadList does not contain a dedicated thread used to produce + * the minidump, this field should be set to 0 and the validity field + * must not contain MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID. */ + u_int32_t dump_thread_id; + + /* Thread ID of the thread that requested the minidump be produced. As + * with dump_thread_id, requesting_thread_id should correspond to the + * thread_id of an MDRawThread in the minidump's MDRawThreadList. For + * minidumps produced as a result of an exception, requesting_thread_id + * will be the same as the MDRawExceptionStream's thread_id field. For + * minidumps produced "manually" at the program's request, + * requesting_thread_id will indicate which thread caused the dump to be + * written. If the minidump was produced at the request of something + * other than a thread in the MDRawThreadList, this field should be set + * to 0 and the validity field must not contain + * MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID. */ + u_int32_t requesting_thread_id; +} MDRawBreakpadInfo; + +/* For (MDRawBreakpadInfo).validity: */ +typedef enum { + /* When set, the dump_thread_id field is valid. */ + MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID = 1 << 0, + + /* When set, the requesting_thread_id field is valid. */ + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID = 1 << 1 +} MDBreakpadInfoValidity; + +typedef struct { + /* expression, function, and file are 0-terminated UTF-16 strings. They + * may be truncated if necessary, but should always be 0-terminated when + * written to a file. + * Fixed-length strings are used because MiniDumpWriteDump doesn't offer + * a way for user streams to point to arbitrary RVAs for strings. */ + u_int16_t expression[128]; /* Assertion that failed... */ + u_int16_t function[128]; /* ...within this function... */ + u_int16_t file[128]; /* ...in this file... */ + u_int32_t line; /* ...at this line. */ + u_int32_t type; +} MDRawAssertionInfo; + +/* For (MDRawAssertionInfo).type: */ +typedef enum { + MD_ASSERTION_INFO_TYPE_UNKNOWN = 0, + + /* Used for assertions that would be raised by the MSVC CRT but are + * directed to an invalid parameter handler instead. */ + MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER, + + /* Used for assertions that would be raised by the MSVC CRT but are + * directed to a pure virtual call handler instead. */ + MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL +} MDAssertionInfoData; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ */ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_size.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_size.h new file mode 100644 index 00000000..918544b6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/common/minidump_size.h @@ -0,0 +1,107 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// minidump_size.h: Provides a C++ template for programmatic access to +// the sizes of various types defined in minidump_format.h. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ + +#include + +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +template +class minidump_size { + public: + static size_t size() { return sizeof(T); } +}; + +// Explicit specializations for variable-length types. The size returned +// for these should be the size for an object without its variable-length +// section. + +template<> +class minidump_size { + public: + static size_t size() { return MDString_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawThreadList_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDCVInfoPDB20_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDCVInfoPDB70_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDImageDebugMisc_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawModuleList_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawMemoryList_minsize; } +}; + +// Explicit specialization for MDRawModule, for which sizeof may include +// tail-padding on some architectures but not others. + +template<> +class minidump_size { + public: + static size_t size() { return MD_MODULE_SIZE; } +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/basic_source_line_resolver.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/basic_source_line_resolver.h new file mode 100644 index 00000000..38759579 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/basic_source_line_resolver.h @@ -0,0 +1,114 @@ +// 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. + +// BasicSourceLineResolver implements SourceLineResolverInterface, using +// address map files produced by a compatible writer, e.g. PDBSourceLineWriter. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ + +// TODO: Platforms that have no hash_map can use map, at the likely cost of +// performance. +#ifdef __SUNPRO_CC +#define BSLR_NO_HASH_MAP +#endif // __SUNPRO_CC + +#ifdef BSLR_NO_HASH_MAP +#include +#else // BSLR_NO_HASH_MAP +#include +#endif // BSLR_NO_HASH_MAP + +#include "google_breakpad/processor/source_line_resolver_interface.h" + +namespace google_breakpad { + +using std::string; +#ifdef BSLR_NO_HASH_MAP +using std::map; +#else // BSLR_NO_HASH_MAP +using __gnu_cxx::hash_map; +#endif // BSLR_NO_HASH_MAP + +class BasicSourceLineResolver : public SourceLineResolverInterface { + public: + BasicSourceLineResolver(); + virtual ~BasicSourceLineResolver(); + + // SourceLineResolverInterface methods, see source_line_resolver_interface.h + // for more details. + + // Adds a module to this resolver, returning true on success. + // The given map_file is read into memory, and its symbols will be + // retained until the BasicSourceLineResolver is destroyed. + virtual bool LoadModule(const string &module_name, const string &map_file); + + // Exactly the same as above, except the given map_buffer is used + // for symbols. + virtual bool LoadModuleUsingMapBuffer(const string &module_name, + const string &map_buffer); + + + virtual bool HasModule(const string &module_name) const; + + virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const; + + private: + template class MemAddrMap; + struct Line; + struct Function; + struct PublicSymbol; + struct File; +#ifdef BSLR_NO_HASH_MAP + struct CompareString { + bool operator()(const string &s1, const string &s2) const; + }; +#else // BSLR_NO_HASH_MAP + struct HashString { + size_t operator()(const string &s) const; + }; +#endif // BSLR_NO_HASH_MAP + class Module; + + // All of the modules we've loaded +#ifdef BSLR_NO_HASH_MAP + typedef map ModuleMap; +#else // BSLR_NO_HASH_MAP + typedef hash_map ModuleMap; +#endif // BSLR_NO_HASH_MAP + ModuleMap *modules_; + + // Disallow unwanted copy ctor and assignment operator + BasicSourceLineResolver(const BasicSourceLineResolver&); + void operator=(const BasicSourceLineResolver&); +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/call_stack.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/call_stack.h new file mode 100644 index 00000000..21f595e7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/call_stack.h @@ -0,0 +1,77 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// call_stack.h: A call stack comprised of stack frames. +// +// This class manages a vector of stack frames. It is used instead of +// exposing the vector directly to allow the CallStack to own StackFrame +// pointers without having to publicly export the linked_ptr class. A +// CallStack must be composed of pointers instead of objects to allow for +// CPU-specific StackFrame subclasses. +// +// By convention, the stack frame at index 0 is the innermost callee frame, +// and the frame at the highest index in a call stack is the outermost +// caller. CallStack only allows stacks to be built by pushing frames, +// beginning with the innermost callee frame. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ + +#include + +namespace google_breakpad { + +using std::vector; + +struct StackFrame; +template class linked_ptr; + +class CallStack { + public: + CallStack() { Clear(); } + ~CallStack(); + + // Resets the CallStack to its initial empty state + void Clear(); + + const vector* frames() const { return &frames_; } + + private: + // Stackwalker is responsible for building the frames_ vector. + friend class Stackwalker; + + // Storage for pushed frames. + vector frames_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_module.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_module.h new file mode 100644 index 00000000..38ee956e --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_module.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// code_module.h: Carries information about code modules that are loaded +// into a process. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +class CodeModule { + public: + virtual ~CodeModule() {} + + // The base address of this code module as it was loaded by the process. + // (u_int64_t)-1 on error. + virtual u_int64_t base_address() const = 0; + + // The size of the code module. 0 on error. + virtual u_int64_t size() const = 0; + + // The path or file name that the code module was loaded from. Empty on + // error. + virtual string code_file() const = 0; + + // An identifying string used to discriminate between multiple versions and + // builds of the same code module. This may contain a uuid, timestamp, + // version number, or any combination of this or other information, in an + // implementation-defined format. Empty on error. + virtual string code_identifier() const = 0; + + // The filename containing debugging information associated with the code + // module. If debugging information is stored in a file separate from the + // code module itself (as is the case when .pdb or .dSYM files are used), + // this will be different from code_file. If debugging information is + // stored in the code module itself (possibly prior to stripping), this + // will be the same as code_file. Empty on error. + virtual string debug_file() const = 0; + + // An identifying string similar to code_identifier, but identifies a + // specific version and build of the associated debug file. This may be + // the same as code_identifier when the debug_file and code_file are + // identical or when the same identifier is used to identify distinct + // debug and code files. + virtual string debug_identifier() const = 0; + + // A human-readable representation of the code module's version. Empty on + // error. + virtual string version() const = 0; + + // Creates a new copy of this CodeModule object, which the caller takes + // ownership of. The new CodeModule may be of a different concrete class + // than the CodeModule being copied, but will behave identically to the + // copied CodeModule as far as the CodeModule interface is concerned. + virtual const CodeModule* Copy() const = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_modules.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_modules.h new file mode 100644 index 00000000..29c55d4e --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/code_modules.h @@ -0,0 +1,98 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// code_modules.h: Contains all of the CodeModule objects that were loaded +// into a single process. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ + +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +class CodeModule; + +class CodeModules { + public: + virtual ~CodeModules() {} + + // The number of contained CodeModule objects. + virtual unsigned int module_count() const = 0; + + // Random access to modules. Returns the module whose code is present + // at the address indicated by |address|. If no module is present at this + // address, returns NULL. Ownership of the returned CodeModule is retained + // by the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleForAddress(u_int64_t address) const = 0; + + // Returns the module corresponding to the main executable. If there is + // no main executable, returns NULL. Ownership of the returned CodeModule + // is retained by the CodeModules object; pointers returned by this method + // are valid for comparison with pointers returned by the other Get + // methods. + virtual const CodeModule* GetMainModule() const = 0; + + // Sequential access to modules. A sequence number of 0 corresponds to the + // module residing lowest in memory. If the sequence number is out of + // range, returns NULL. Ownership of the returned CodeModule is retained + // by the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleAtSequence( + unsigned int sequence) const = 0; + + // Sequential access to modules. This is similar to GetModuleAtSequence, + // except no ordering requirement is enforced. A CodeModules implementation + // may return CodeModule objects from GetModuleAtIndex in any order it + // wishes, provided that the order remain the same throughout the life of + // the CodeModules object. Typically, GetModuleAtIndex would be used by + // a caller to enumerate all CodeModule objects quickly when the enumeration + // does not require any ordering. If the index argument is out of range, + // returns NULL. Ownership of the returned CodeModule is retained by + // the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleAtIndex(unsigned int index) const = 0; + + // Creates a new copy of this CodeModules object, which the caller takes + // ownership of. The new object will also contain copies of the existing + // object's child CodeModule objects. The new CodeModules object may be of + // a different concrete class than the object being copied, but will behave + // identically to the copied object as far as the CodeModules and CodeModule + // interfaces are concerned, except that the order that GetModuleAtIndex + // returns objects in may differ between a copy and the original CodeModules + // object. + virtual const CodeModules* Copy() const = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/memory_region.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/memory_region.h new file mode 100644 index 00000000..1ac3fe8d --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/memory_region.h @@ -0,0 +1,76 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// memory_region.h: Access to memory regions. +// +// A MemoryRegion provides virtual access to a range of memory. It is an +// abstraction allowing the actual source of memory to be independent of +// methods which need to access a virtual memory space. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ + + +#include "google_breakpad/common/breakpad_types.h" + + +namespace google_breakpad { + + +class MemoryRegion { + public: + virtual ~MemoryRegion() {} + + // The base address of this memory region. + virtual u_int64_t GetBase() = 0; + + // The size of this memory region. + virtual u_int32_t GetSize() = 0; + + // Access to data of various sizes within the memory region. address + // is a pointer to read, and it must lie within the memory region as + // defined by its base address and size. The location pointed to by + // value is set to the value at address. Byte-swapping is performed + // if necessary so that the value is appropriate for the running + // program. Returns true on success. Fails and returns false if address + // is out of the region's bounds (after considering the width of value), + // or for other types of errors. + virtual bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value) = 0; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump.h new file mode 100644 index 00000000..5c5dccc9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump.h @@ -0,0 +1,904 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump.h: A minidump reader. +// +// The basic structure of this module tracks the structure of the minidump +// file itself. At the top level, a minidump file is represented by a +// Minidump object. Like most other classes in this module, Minidump +// provides a Read method that initializes the object with information from +// the file. Most of the classes in this file are wrappers around the +// "raw" structures found in the minidump file itself, and defined in +// minidump_format.h. For example, each thread is represented by a +// MinidumpThread object, whose parameters are specified in an MDRawThread +// structure. A properly byte-swapped MDRawThread can be obtained from a +// MinidumpThread easily by calling its thread() method. +// +// Most of the module lazily reads only the portion of the minidump file +// necessary to fulfill the user's request. Calling Minidump::Read +// only reads the minidump's directory. The thread list is not read until +// it is needed, and even once it's read, the memory regions for each +// thread's stack aren't read until they're needed. This strategy avoids +// unnecessary file input, and allocating memory for data in which the user +// has no interest. Note that although memory allocations for a typical +// minidump file are not particularly large, it is possible for legitimate +// minidumps to be sizable. A full-memory minidump, for example, contains +// a snapshot of the entire mapped memory space. Even a normal minidump, +// with stack memory only, can be large if, for example, the dump was +// generated in response to a crash that occurred due to an infinite- +// recursion bug that caused the stack's limits to be exceeded. Finally, +// some users of this library will unfortunately find themselves in the +// position of having to process potentially-hostile minidumps that might +// attempt to cause problems by forcing the minidump processor to over- +// allocate memory. +// +// Memory management in this module is based on a strict +// you-don't-own-anything policy. The only object owned by the user is +// the top-level Minidump object, the creation and destruction of which +// must be the user's own responsibility. All other objects obtained +// through interaction with this module are ultimately owned by the +// Minidump object, and will be freed upon the Minidump object's destruction. +// Because memory regions can potentially involve large allocations, a +// FreeMemory method is provided by MinidumpMemoryRegion, allowing the user +// to release data when it is no longer needed. Use of this method is +// optional but recommended. If freed data is later required, it will +// be read back in from the minidump file again. +// +// There is one exception to this memory management policy: +// Minidump::ReadString will return a string object to the user, and the user +// is responsible for its deletion. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ + +#include + +#include +#include +#include + +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/memory_region.h" + + +namespace google_breakpad { + + +using std::map; +using std::string; +using std::vector; + + +class Minidump; +template class RangeMap; + + +// MinidumpObject is the base of all Minidump* objects except for Minidump +// itself. +class MinidumpObject { + public: + virtual ~MinidumpObject() {} + + bool valid() const { return valid_; } + + protected: + explicit MinidumpObject(Minidump* minidump); + + // Refers to the Minidump object that is the ultimate parent of this + // Some MinidumpObjects are owned by other MinidumpObjects, but at the + // root of the ownership tree is always a Minidump. The Minidump object + // is kept here for access to its seeking and reading facilities, and + // for access to data about the minidump file itself, such as whether + // it should be byte-swapped. + Minidump* minidump_; + + // MinidumpObjects are not valid when created. When a subclass populates + // its own fields, it can set valid_ to true. Accessors and mutators may + // wish to consider or alter the valid_ state as they interact with + // objects. + bool valid_; +}; + + +// This class exists primarily to provide a virtual destructor in a base +// class common to all objects that might be stored in +// Minidump::mStreamObjects. Some object types (MinidumpContext) will +// never be stored in Minidump::mStreamObjects, but are represented as +// streams and adhere to the same interface, and may be derived from +// this class. +class MinidumpStream : public MinidumpObject { + public: + virtual ~MinidumpStream() {} + + protected: + explicit MinidumpStream(Minidump* minidump); + + private: + // Populate (and validate) the MinidumpStream. minidump_ is expected + // to be positioned at the beginning of the stream, so that the next + // read from the minidump will be at the beginning of the stream. + // expected_size should be set to the stream's length as contained in + // the MDRawDirectory record or other identifying record. A class + // that implements MinidumpStream can compare expected_size to a + // known size as an integrity check. + virtual bool Read(u_int32_t expected_size) = 0; +}; + + +// MinidumpContext carries a CPU-specific MDRawContext structure, which +// contains CPU context such as register states. Each thread has its +// own context, and the exception record, if present, also has its own +// context. Note that if the exception record is present, the context it +// refers to is probably what the user wants to use for the exception +// thread, instead of that thread's own context. The exception thread's +// context (as opposed to the exception record's context) will contain +// context for the exception handler (which performs minidump generation), +// and not the context that caused the exception (which is probably what the +// user wants). +class MinidumpContext : public MinidumpStream { + public: + virtual ~MinidumpContext(); + + // Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC + // identifying the CPU type that the context was collected from. The + // returned value will identify the CPU only, and will have any other + // MD_CONTEXT_* bits masked out. Returns 0 on failure. + u_int32_t GetContextCPU() const; + + // Returns raw CPU-specific context data for the named CPU type. If the + // context data does not match the CPU type or does not exist, returns + // NULL. + const MDRawContextX86* GetContextX86() const; + const MDRawContextPPC* GetContextPPC() const; + const MDRawContextAMD64* GetContextAMD64() const; + const MDRawContextSPARC* GetContextSPARC() const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class MinidumpThread; + friend class MinidumpException; + + explicit MinidumpContext(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // Free the CPU-specific context structure. + void FreeContext(); + + // If the minidump contains a SYSTEM_INFO_STREAM, makes sure that the + // system info stream gives an appropriate CPU type matching the context + // CPU type in context_cpu_type. Returns false if the CPU type does not + // match. Returns true if the CPU type matches or if the minidump does + // not contain a system info stream. + bool CheckAgainstSystemInfo(u_int32_t context_cpu_type); + + // Store this separately because of the weirdo AMD64 context + u_int32_t context_flags_; + + // The CPU-specific context structure. + union { + MDRawContextBase* base; + MDRawContextX86* x86; + MDRawContextPPC* ppc; + MDRawContextAMD64* amd64; + // on Solaris SPARC, sparc is defined as a numeric constant, + // so variables can NOT be named as sparc + MDRawContextSPARC* ctx_sparc; + } context_; +}; + + +// MinidumpMemoryRegion does not wrap any MDRaw structure, and only contains +// a reference to an MDMemoryDescriptor. This object is intended to wrap +// portions of a minidump file that contain memory dumps. In normal +// minidumps, each MinidumpThread owns a MinidumpMemoryRegion corresponding +// to the thread's stack memory. MinidumpMemoryList also gives access to +// memory regions in its list as MinidumpMemoryRegions. This class +// adheres to MemoryRegion so that it may be used as a data provider to +// the Stackwalker family of classes. +class MinidumpMemoryRegion : public MinidumpObject, + public MemoryRegion { + public: + virtual ~MinidumpMemoryRegion(); + + static void set_max_bytes(u_int32_t max_bytes) { max_bytes_ = max_bytes; } + static u_int32_t max_bytes() { return max_bytes_; } + + // Returns a pointer to the base of the memory region. Returns the + // cached value if available, otherwise, reads the minidump file and + // caches the memory region. + const u_int8_t* GetMemory(); + + // The address of the base of the memory region. + u_int64_t GetBase(); + + // The size, in bytes, of the memory region. + u_int32_t GetSize(); + + // Frees the cached memory region, if cached. + void FreeMemory(); + + // Obtains the value of memory at the pointer specified by address. + bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class MinidumpThread; + friend class MinidumpMemoryList; + + explicit MinidumpMemoryRegion(Minidump* minidump); + + // Identify the base address and size of the memory region, and the + // location it may be found in the minidump file. + void SetDescriptor(MDMemoryDescriptor* descriptor); + + // Implementation for GetMemoryAtAddress + template bool GetMemoryAtAddressInternal(u_int64_t address, + T* value); + + // The largest memory region that will be read from a minidump. The + // default is 1MB. + static u_int32_t max_bytes_; + + // Base address and size of the memory region, and its position in the + // minidump file. + MDMemoryDescriptor* descriptor_; + + // Cached memory. + vector* memory_; +}; + + +// MinidumpThread contains information about a thread of execution, +// including a snapshot of the thread's stack and CPU context. For +// the thread that caused an exception, the context carried by +// MinidumpException is probably desired instead of the CPU context +// provided here. +class MinidumpThread : public MinidumpObject { + public: + virtual ~MinidumpThread(); + + const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; } + MinidumpMemoryRegion* GetMemory(); + MinidumpContext* GetContext(); + + // The thread ID is used to determine if a thread is the exception thread, + // so a special getter is provided to retrieve this data from the + // MDRawThread structure. Returns false if the thread ID cannot be + // determined. + bool GetThreadID(u_int32_t *thread_id) const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // These objects are managed by MinidumpThreadList. + friend class MinidumpThreadList; + + explicit MinidumpThread(Minidump* minidump); + + // This works like MinidumpStream::Read, but is driven by + // MinidumpThreadList. No size checking is done, because + // MinidumpThreadList handles that directly. + bool Read(); + + MDRawThread thread_; + MinidumpMemoryRegion* memory_; + MinidumpContext* context_; +}; + + +// MinidumpThreadList contains all of the threads (as MinidumpThreads) in +// a process. +class MinidumpThreadList : public MinidumpStream { + public: + virtual ~MinidumpThreadList(); + + static void set_max_threads(u_int32_t max_threads) { + max_threads_ = max_threads; + } + static u_int32_t max_threads() { return max_threads_; } + + unsigned int thread_count() const { return valid_ ? thread_count_ : 0; } + + // Sequential access to threads. + MinidumpThread* GetThreadAtIndex(unsigned int index) const; + + // Random access to threads. + MinidumpThread* GetThreadByID(u_int32_t thread_id); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef map IDToThreadMap; + typedef vector MinidumpThreads; + + static const u_int32_t kStreamType = MD_THREAD_LIST_STREAM; + + explicit MinidumpThreadList(Minidump* aMinidump); + + bool Read(u_int32_t aExpectedSize); + + // The largest number of threads that will be read from a minidump. The + // default is 256. + static u_int32_t max_threads_; + + // Access to threads using the thread ID as the key. + IDToThreadMap id_to_thread_map_; + + // The list of threads. + MinidumpThreads* threads_; + u_int32_t thread_count_; +}; + + +// MinidumpModule wraps MDRawModule, which contains information about loaded +// code modules. Access is provided to various data referenced indirectly +// by MDRawModule, such as the module's name and a specification for where +// to locate debugging information for the module. +class MinidumpModule : public MinidumpObject, + public CodeModule { + public: + virtual ~MinidumpModule(); + + static void set_max_cv_bytes(u_int32_t max_cv_bytes) { + max_cv_bytes_ = max_cv_bytes; + } + static u_int32_t max_cv_bytes() { return max_cv_bytes_; } + + static void set_max_misc_bytes(u_int32_t max_misc_bytes) { + max_misc_bytes_ = max_misc_bytes; + } + static u_int32_t max_misc_bytes() { return max_misc_bytes_; } + + const MDRawModule* module() const { return valid_ ? &module_ : NULL; } + + // CodeModule implementation + virtual u_int64_t base_address() const { + return valid_ ? module_.base_of_image : static_cast(-1); + } + virtual u_int64_t size() const { return valid_ ? module_.size_of_image : 0; } + virtual string code_file() const; + virtual string code_identifier() const; + virtual string debug_file() const; + virtual string debug_identifier() const; + virtual string version() const; + virtual const CodeModule* Copy() const; + + // The CodeView record, which contains information to locate the module's + // debugging information (pdb). This is returned as u_int8_t* because + // the data can be of types MDCVInfoPDB20* or MDCVInfoPDB70*, or it may be + // of a type unknown to Breakpad, in which case the raw data will still be + // returned but no byte-swapping will have been performed. Check the + // record's signature in the first four bytes to differentiate between + // the various types. Current toolchains generate modules which carry + // MDCVInfoPDB70 by default. Returns a pointer to the CodeView record on + // success, and NULL on failure. On success, the optional |size| argument + // is set to the size of the CodeView record. + const u_int8_t* GetCVRecord(u_int32_t* size); + + // The miscellaneous debug record, which is obsolete. Current toolchains + // do not generate this type of debugging information (dbg), and this + // field is not expected to be present. Returns a pointer to the debugging + // record on success, and NULL on failure. On success, the optional |size| + // argument is set to the size of the debugging record. + const MDImageDebugMisc* GetMiscRecord(u_int32_t* size); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // These objects are managed by MinidumpModuleList. + friend class MinidumpModuleList; + + explicit MinidumpModule(Minidump* minidump); + + // This works like MinidumpStream::Read, but is driven by + // MinidumpModuleList. No size checking is done, because + // MinidumpModuleList handles that directly. + bool Read(); + + // Reads indirectly-referenced data, including the module name, CodeView + // record, and miscellaneous debugging record. This is necessary to allow + // MinidumpModuleList to fully construct MinidumpModule objects without + // requiring seeks to read a contiguous set of MinidumpModule objects. + // All auxiliary data should be available when Read is called, in order to + // allow the CodeModule getters to be const methods. + bool ReadAuxiliaryData(); + + // The largest number of bytes that will be read from a minidump for a + // CodeView record or miscellaneous debugging record, respectively. The + // default for each is 1024. + static u_int32_t max_cv_bytes_; + static u_int32_t max_misc_bytes_; + + // True after a successful Read. This is different from valid_, which is + // not set true until ReadAuxiliaryData also completes successfully. + // module_valid_ is only used by ReadAuxiliaryData and the functions it + // calls to determine whether the object is ready for auxiliary data to + // be read. + bool module_valid_; + + // True if debug info was read from the module. Certain modules + // may contain debug records in formats we don't support, + // so we can just set this to false to ignore them. + bool has_debug_info_; + + MDRawModule module_; + + // Cached module name. + const string* name_; + + // Cached CodeView record - this is MDCVInfoPDB20 or (likely) + // MDCVInfoPDB70, or possibly something else entirely. Stored as a u_int8_t + // because the structure contains a variable-sized string and its exact + // size cannot be known until it is processed. + vector* cv_record_; + + // If cv_record_ is present, cv_record_signature_ contains a copy of the + // CodeView record's first four bytes, for ease of determinining the + // type of structure that cv_record_ contains. + u_int32_t cv_record_signature_; + + // Cached MDImageDebugMisc (usually not present), stored as u_int8_t + // because the structure contains a variable-sized string and its exact + // size cannot be known until it is processed. + vector* misc_record_; +}; + + +// MinidumpModuleList contains all of the loaded code modules for a process +// in the form of MinidumpModules. It maintains a map of these modules +// so that it may easily provide a code module corresponding to a specific +// address. +class MinidumpModuleList : public MinidumpStream, + public CodeModules { + public: + virtual ~MinidumpModuleList(); + + static void set_max_modules(u_int32_t max_modules) { + max_modules_ = max_modules; + } + static u_int32_t max_modules() { return max_modules_; } + + // CodeModules implementation. + virtual unsigned int module_count() const { + return valid_ ? module_count_ : 0; + } + virtual const MinidumpModule* GetModuleForAddress(u_int64_t address) const; + virtual const MinidumpModule* GetMainModule() const; + virtual const MinidumpModule* GetModuleAtSequence( + unsigned int sequence) const; + virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const; + virtual const CodeModules* Copy() const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef vector MinidumpModules; + + static const u_int32_t kStreamType = MD_MODULE_LIST_STREAM; + + explicit MinidumpModuleList(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // The largest number of modules that will be read from a minidump. The + // default is 1024. + static u_int32_t max_modules_; + + // Access to modules using addresses as the key. + RangeMap *range_map_; + + MinidumpModules *modules_; + u_int32_t module_count_; +}; + + +// MinidumpMemoryList corresponds to a minidump's MEMORY_LIST_STREAM stream, +// which references the snapshots of all of the memory regions contained +// within the minidump. For a normal minidump, this includes stack memory +// (also referenced by each MinidumpThread, in fact, the MDMemoryDescriptors +// here and in MDRawThread both point to exactly the same data in a +// minidump file, conserving space), as well as a 256-byte snapshot of memory +// surrounding the instruction pointer in the case of an exception. Other +// types of minidumps may contain significantly more memory regions. Full- +// memory minidumps contain all of a process' mapped memory. +class MinidumpMemoryList : public MinidumpStream { + public: + virtual ~MinidumpMemoryList(); + + static void set_max_regions(u_int32_t max_regions) { + max_regions_ = max_regions; + } + static u_int32_t max_regions() { return max_regions_; } + + unsigned int region_count() const { return valid_ ? region_count_ : 0; } + + // Sequential access to memory regions. + MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index); + + // Random access to memory regions. Returns the region encompassing + // the address identified by address. + MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef vector MemoryDescriptors; + typedef vector MemoryRegions; + + static const u_int32_t kStreamType = MD_MEMORY_LIST_STREAM; + + explicit MinidumpMemoryList(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // The largest number of memory regions that will be read from a minidump. + // The default is 256. + static u_int32_t max_regions_; + + // Access to memory regions using addresses as the key. + RangeMap *range_map_; + + // The list of descriptors. This is maintained separately from the list + // of regions, because MemoryRegion doesn't own its MemoryDescriptor, it + // maintains a pointer to it. descriptors_ provides the storage for this + // purpose. + MemoryDescriptors *descriptors_; + + // The list of regions. + MemoryRegions *regions_; + u_int32_t region_count_; +}; + + +// MinidumpException wraps MDRawExceptionStream, which contains information +// about the exception that caused the minidump to be generated, if the +// minidump was generated in an exception handler called as a result of +// an exception. It also provides access to a MinidumpContext object, +// which contains the CPU context for the exception thread at the time +// the exception occurred. +class MinidumpException : public MinidumpStream { + public: + virtual ~MinidumpException(); + + const MDRawExceptionStream* exception() const { + return valid_ ? &exception_ : NULL; + } + + // The thread ID is used to determine if a thread is the exception thread, + // so a special getter is provided to retrieve this data from the + // MDRawExceptionStream structure. Returns false if the thread ID cannot + // be determined. + bool GetThreadID(u_int32_t *thread_id) const; + + MinidumpContext* GetContext(); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_EXCEPTION_STREAM; + + explicit MinidumpException(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + MDRawExceptionStream exception_; + MinidumpContext* context_; +}; + + +// MinidumpSystemInfo wraps MDRawSystemInfo and provides information about +// the system on which the minidump was generated. See also MinidumpMiscInfo. +class MinidumpSystemInfo : public MinidumpStream { + public: + virtual ~MinidumpSystemInfo(); + + const MDRawSystemInfo* system_info() const { + return valid_ ? &system_info_ : NULL; + } + + // GetOS and GetCPU return textual representations of the operating system + // and CPU that produced the minidump. Unlike most other Minidump* methods, + // they return string objects, not weak pointers. Defined values for + // GetOS() are "mac", "windows", and "linux". Defined values for GetCPU + // are "x86" and "ppc". These methods return an empty string when their + // values are unknown. + string GetOS(); + string GetCPU(); + + // I don't know what CSD stands for, but this field is documented as + // returning a textual representation of the OS service pack. On other + // platforms, this provides additional information about an OS version + // level beyond major.minor.micro. Returns NULL if unknown. + const string* GetCSDVersion(); + + // If a CPU vendor string can be determined, returns a pointer to it, + // otherwise, returns NULL. CPU vendor strings can be determined from + // x86 CPUs with CPUID 0. + const string* GetCPUVendor(); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_SYSTEM_INFO_STREAM; + + explicit MinidumpSystemInfo(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + MDRawSystemInfo system_info_; + + // Textual representation of the OS service pack, for minidumps produced + // by MiniDumpWriteDump on Windows. + const string* csd_version_; + + // A string identifying the CPU vendor, if known. + const string* cpu_vendor_; +}; + + +// MinidumpMiscInfo wraps MDRawMiscInfo and provides information about +// the process that generated the minidump, and optionally additional system +// information. See also MinidumpSystemInfo. +class MinidumpMiscInfo : public MinidumpStream { + public: + const MDRawMiscInfo* misc_info() const { + return valid_ ? &misc_info_ : NULL; + } + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_MISC_INFO_STREAM; + + explicit MinidumpMiscInfo(Minidump* minidump_); + + bool Read(u_int32_t expected_size_); + + MDRawMiscInfo misc_info_; +}; + + +// MinidumpBreakpadInfo wraps MDRawBreakpadInfo, which is an optional stream in +// a minidump that provides additional information about the process state +// at the time the minidump was generated. +class MinidumpBreakpadInfo : public MinidumpStream { + public: + const MDRawBreakpadInfo* breakpad_info() const { + return valid_ ? &breakpad_info_ : NULL; + } + + // These thread IDs are used to determine if threads deserve special + // treatment, so special getters are provided to retrieve this data from + // the MDRawBreakpadInfo structure. The getters return false if the thread + // IDs cannot be determined. + bool GetDumpThreadID(u_int32_t *thread_id) const; + bool GetRequestingThreadID(u_int32_t *thread_id) const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_BREAKPAD_INFO_STREAM; + + explicit MinidumpBreakpadInfo(Minidump* minidump_); + + bool Read(u_int32_t expected_size_); + + MDRawBreakpadInfo breakpad_info_; +}; + + +// Minidump is the user's interface to a minidump file. It wraps MDRawHeader +// and provides access to the minidump's top-level stream directory. +class Minidump { + public: + // path is the pathname of a file containing the minidump. + explicit Minidump(const string& path); + + ~Minidump(); + + static void set_max_streams(u_int32_t max_streams) { + max_streams_ = max_streams; + } + static u_int32_t max_streams() { return max_streams_; } + + static void set_max_string_length(u_int32_t max_string_length) { + max_string_length_ = max_string_length; + } + static u_int32_t max_string_length() { return max_string_length_; } + + const MDRawHeader* header() const { return valid_ ? &header_ : NULL; } + + // Reads the minidump file's header and top-level stream directory. + // The minidump is expected to be positioned at the beginning of the + // header. Read() sets up the stream list and map, and validates the + // Minidump object. + bool Read(); + + // The next set of methods are stubs that call GetStream. They exist to + // force code generation of the templatized API within the module, and + // to avoid exposing an ugly API (GetStream needs to accept a garbage + // parameter). + MinidumpThreadList* GetThreadList(); + MinidumpModuleList* GetModuleList(); + MinidumpMemoryList* GetMemoryList(); + MinidumpException* GetException(); + MinidumpSystemInfo* GetSystemInfo(); + MinidumpMiscInfo* GetMiscInfo(); + MinidumpBreakpadInfo* GetBreakpadInfo(); + + // The next set of methods are provided for users who wish to access + // data in minidump files directly, while leveraging the rest of + // this class and related classes to handle the basic minidump + // structure and known stream types. + + unsigned int GetDirectoryEntryCount() const { + return valid_ ? header_.stream_count : 0; + } + const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const; + + // The next 2 methods are lower-level I/O routines. They use fd_. + + // Reads count bytes from the minidump at the current position into + // the storage area pointed to by bytes. bytes must be of sufficient + // size. After the read, the file position is advanced by count. + bool ReadBytes(void* bytes, size_t count); + + // Sets the position of the minidump file to offset. + bool SeekSet(off_t offset); + + // Returns the current position of the minidump file. + off_t Tell() { return valid_ ? lseek(fd_, 0, SEEK_CUR) : (off_t)-1; } + + // The next 2 methods are medium-level I/O routines. + + // ReadString returns a string which is owned by the caller! offset + // specifies the offset that a length-encoded string is stored at in the + // minidump file. + string* ReadString(off_t offset); + + // SeekToStreamType positions the file at the beginning of a stream + // identified by stream_type, and informs the caller of the stream's + // length by setting *stream_length. Because stream_map maps each stream + // type to only one stream in the file, this might mislead the user into + // thinking that the stream that this seeks to is the only stream with + // type stream_type. That can't happen for streams that these classes + // deal with directly, because they're only supposed to be present in the + // file singly, and that's verified when stream_map_ is built. Users who + // are looking for other stream types should be aware of this + // possibility, and consider using GetDirectoryEntryAtIndex (possibly + // with GetDirectoryEntryCount) if expecting multiple streams of the same + // type in a single minidump file. + bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length); + + bool swap() const { return valid_ ? swap_ : false; } + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // MinidumpStreamInfo is used in the MinidumpStreamMap. It lets + // the Minidump object locate interesting streams quickly, and + // provides a convenient place to stash MinidumpStream objects. + struct MinidumpStreamInfo { + MinidumpStreamInfo() : stream_index(0), stream(NULL) {} + ~MinidumpStreamInfo() { delete stream; } + + // Index into the MinidumpDirectoryEntries vector + unsigned int stream_index; + + // Pointer to the stream if cached, or NULL if not yet populated + MinidumpStream* stream; + }; + + typedef vector MinidumpDirectoryEntries; + typedef map MinidumpStreamMap; + + template T* GetStream(T** stream); + + // Opens the minidump file, or if already open, seeks to the beginning. + bool Open(); + + // The largest number of top-level streams that will be read from a minidump. + // Note that streams are only read (and only consume memory) as needed, + // when directed by the caller. The default is 128. + static u_int32_t max_streams_; + + // The maximum length of a UTF-16 string that will be read from a minidump + // in 16-bit words. The default is 1024. UTF-16 strings are converted + // to UTF-8 when stored in memory, and each UTF-16 word will be represented + // by as many as 3 bytes in UTF-8. + static unsigned int max_string_length_; + + MDRawHeader header_; + + // The list of streams. + MinidumpDirectoryEntries* directory_; + + // Access to streams using the stream type as the key. + MinidumpStreamMap* stream_map_; + + // The pathname of the minidump file to process, set in the constructor. + const string path_; + + // The file descriptor for all file I/O. Used by ReadBytes and SeekSet. + // Set based on the |path_| member by Open, which is called by Read. + int fd_; + + // swap_ is true if the minidump file should be byte-swapped. If the + // minidump was produced by a CPU that is other-endian than the CPU + // processing the minidump, this will be true. If the two CPUs are + // same-endian, this will be false. + bool swap_; + + // Validity of the Minidump structure, false immediately after + // construction or after a failed Read(); true following a successful + // Read(). + bool valid_; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump_processor.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump_processor.h new file mode 100644 index 00000000..73447f97 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/minidump_processor.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +class Minidump; +class ProcessState; +class SourceLineResolverInterface; +class SymbolSupplier; +class SystemInfo; + +class MinidumpProcessor { + public: + // Return type for Process() + enum ProcessResult { + PROCESS_OK, // the minidump was processed successfully + PROCESS_ERROR, // there was an error processing the minidump + PROCESS_INTERRUPTED // processing was interrupted by the SymbolSupplier + }; + + // Initializes this MinidumpProcessor. supplier should be an + // implementation of the SymbolSupplier abstract base class. + MinidumpProcessor(SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + ~MinidumpProcessor(); + + // Processes the minidump file and fills process_state with the result. + ProcessResult Process(const string &minidump_file, + ProcessState *process_state); + + // Populates the cpu_* fields of the |info| parameter with textual + // representations of the CPU type that the minidump in |dump| was + // produced on. Returns false if this information is not available in + // the minidump. + static bool GetCPUInfo(Minidump *dump, SystemInfo *info); + + // Populates the os_* fields of the |info| parameter with textual + // representations of the operating system that the minidump in |dump| + // was produced on. Returns false if this information is not available in + // the minidump. + static bool GetOSInfo(Minidump *dump, SystemInfo *info); + + // Returns a textual representation of the reason that a crash occurred, + // if the minidump in dump was produced as a result of a crash. Returns + // an empty string if this information cannot be determined. If address + // is non-NULL, it will be set to contain the address that caused the + // exception, if this information is available. This will be a code + // address when the crash was caused by problems such as illegal + // instructions or divisions by zero, or a data address when the crash + // was caused by a memory access violation. + static string GetCrashReason(Minidump *dump, u_int64_t *address); + + private: + SymbolSupplier *supplier_; + SourceLineResolverInterface *resolver_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/process_state.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/process_state.h new file mode 100644 index 00000000..afbbb193 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/process_state.h @@ -0,0 +1,115 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// process_state.h: A snapshot of a process, in a fully-digested state. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ + +#include +#include +#include "google_breakpad/processor/system_info.h" +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; +using std::vector; + +class CallStack; +class CodeModules; + +class ProcessState { + public: + ProcessState() : modules_(NULL) { Clear(); } + ~ProcessState(); + + // Resets the ProcessState to its default values + void Clear(); + + // Accessors. See the data declarations below. + u_int32_t time_date_stamp() const { return time_date_stamp_; } + bool crashed() const { return crashed_; } + string crash_reason() const { return crash_reason_; } + u_int64_t crash_address() const { return crash_address_; } + int requesting_thread() const { return requesting_thread_; } + const vector* threads() const { return &threads_; } + const SystemInfo* system_info() const { return &system_info_; } + const CodeModules* modules() const { return modules_; } + + private: + // MinidumpProcessor is responsible for building ProcessState objects. + friend class MinidumpProcessor; + + // The time-date stamp of the minidump (time_t format) + u_int32_t time_date_stamp_; + + // True if the process crashed, false if the dump was produced outside + // of an exception handler. + bool crashed_; + + // If the process crashed, the type of crash. OS- and possibly CPU- + // specific. For example, "EXCEPTION_ACCESS_VIOLATION" (Windows), + // "EXC_BAD_ACCESS / KERN_INVALID_ADDRESS" (Mac OS X), "SIGSEGV" + // (other Unix). + string crash_reason_; + + // If the process crashed, and if crash_reason implicates memory, + // the memory address that caused the crash. For data access errors, + // this will be the data address that caused the fault. For code errors, + // this will be the address of the instruction that caused the fault. + u_int64_t crash_address_; + + // The index of the thread that requested a dump be written in the + // threads vector. If a dump was produced as a result of a crash, this + // will point to the thread that crashed. If the dump was produced as + // by user code without crashing, and the dump contains extended Breakpad + // information, this will point to the thread that requested the dump. + // If the dump was not produced as a result of an exception and no + // extended Breakpad information is present, this field will be set to -1, + // indicating that the dump thread is not available. + int requesting_thread_; + + // Stacks for each thread (except possibly the exception handler + // thread) at the time of the crash. + vector threads_; + + // OS and CPU information. + SystemInfo system_info_; + + // The modules that were loaded into the process represented by the + // ProcessState. + const CodeModules *modules_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/source_line_resolver_interface.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/source_line_resolver_interface.h new file mode 100644 index 00000000..93ef85d2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/source_line_resolver_interface.h @@ -0,0 +1,82 @@ +// 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. + +// Abstract interface to return function/file/line info for a memory address. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +struct StackFrame; +struct StackFrameInfo; + +class SourceLineResolverInterface { + public: + typedef u_int64_t MemAddr; + + virtual ~SourceLineResolverInterface() {} + + // Adds a module to this resolver, returning true on success. + // + // module_name may be an arbitrary string. Typically, it will be the + // filename of the module, optionally with version identifiers. + // + // map_file should contain line/address mappings for this module. + virtual bool LoadModule(const string &module_name, + const string &map_file) = 0; + // Same as above, but takes the contents of a pre-read map buffer + virtual bool LoadModuleUsingMapBuffer(const string &module_name, + const string &map_buffer) = 0; + + // Returns true if a module with the given name has been loaded. + virtual bool HasModule(const string &module_name) const = 0; + + // Fills in the function_base, function_name, source_file_name, + // and source_line fields of the StackFrame. The instruction and + // module_name fields must already be filled in. Additional debugging + // information, if available, is returned. If the information is not + // available, returns NULL. A NULL return value does not indicate an + // error. The caller takes ownership of any returned StackFrameInfo + // object. + virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const = 0; + + protected: + // SourceLineResolverInterface cannot be instantiated except by subclasses + SourceLineResolverInterface() {} +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame.h new file mode 100644 index 00000000..b330f8ae --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame.h @@ -0,0 +1,84 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +class CodeModule; + +using std::string; + +struct StackFrame { + StackFrame() + : instruction(), + module(NULL), + function_name(), + function_base(), + source_file_name(), + source_line(), + source_line_base() {} + virtual ~StackFrame() {} + + // The program counter location as an absolute virtual address. For the + // innermost called frame in a stack, this will be an exact program counter + // or instruction pointer value. For all other frames, this will be within + // the instruction that caused execution to branch to a called function, + // but may not necessarily point to the exact beginning of that instruction. + u_int64_t instruction; + + // The module in which the instruction resides. + const CodeModule *module; + + // The function name, may be omitted if debug symbols are not available. + string function_name; + + // The start address of the function, may be omitted if debug symbols + // are not available. + u_int64_t function_base; + + // The source file name, may be omitted if debug symbols are not available. + string source_file_name; + + // The (1-based) source line number, may be omitted if debug symbols are + // not available. + int source_line; + + // The start address of the source line, may be omitted if debug symbols + // are not available. + u_int64_t source_line_base; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame_cpu.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame_cpu.h new file mode 100644 index 00000000..70823b9c --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stack_frame_cpu.h @@ -0,0 +1,153 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stack_frame_cpu.h: CPU-specific StackFrame extensions. +// +// These types extend the StackFrame structure to carry CPU-specific register +// state. They are defined in this header instead of stack_frame.h to +// avoid the need to include minidump_format.h when only the generic +// StackFrame type is needed. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ + +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stack_frame.h" + +namespace google_breakpad { + +struct StackFrameX86 : public StackFrame { + // ContextValidity has one entry for each relevant hardware pointer register + // (%eip and %esp) and one entry for each nonvolatile (callee-save) register. + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_EIP = 1 << 0, + CONTEXT_VALID_ESP = 1 << 1, + CONTEXT_VALID_EBP = 1 << 2, + CONTEXT_VALID_EBX = 1 << 3, + CONTEXT_VALID_ESI = 1 << 4, + CONTEXT_VALID_EDI = 1 << 5, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameX86() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextX86 context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFramePPC : public StackFrame { + // ContextValidity should eventually contain entries for the validity of + // other nonvolatile (callee-save) registers as in + // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently + // locate registers other than the ones listed here. + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_SRR0 = 1 << 0, + CONTEXT_VALID_GPR1 = 1 << 1, + CONTEXT_VALID_ALL = -1 + }; + + StackFramePPC() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextPPC context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFrameAMD64 : public StackFrame { + // ContextValidity has one entry for each relevant hardware pointer register + // (%rip and %rsp) and one entry for each nonvolatile (callee-save) register. + //FIXME: validate this list + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_RIP = 1 << 0, + CONTEXT_VALID_RSP = 1 << 1, + CONTEXT_VALID_RBP = 1 << 2, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameAMD64() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextAMD64 context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFrameSPARC : public StackFrame { + // to be confirmed + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_PC = 1 << 0, + CONTEXT_VALID_SP = 1 << 1, + CONTEXT_VALID_FP = 1 << 2, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameSPARC() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextSPARC context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stackwalker.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stackwalker.h new file mode 100644 index 00000000..c463fd80 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/stackwalker.h @@ -0,0 +1,140 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker.h: Generic stackwalker. +// +// The Stackwalker class is an abstract base class providing common generic +// methods that apply to stacks from all systems. Specific implementations +// will extend this class by providing GetContextFrame and GetCallerFrame +// methods to fill in system-specific data in a StackFrame structure. +// Stackwalker assembles these StackFrame strucutres into a CallStack. +// +// Author: Mark Mentovai + + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ + +#include + +namespace google_breakpad { + +class CallStack; +class CodeModules; +template class linked_ptr; +class MemoryRegion; +class MinidumpContext; +class SourceLineResolverInterface; +struct StackFrame; +struct StackFrameInfo; +class SymbolSupplier; +class SystemInfo; + +using std::vector; + + +class Stackwalker { + public: + virtual ~Stackwalker() {} + + // Populates the given CallStack by calling GetContextFrame and + // GetCallerFrame. The frames are further processed to fill all available + // data. Returns true if the stackwalk completed, or false if it was + // interrupted by SymbolSupplier::GetSymbolFile(). + bool Walk(CallStack *stack); + + // Returns a new concrete subclass suitable for the CPU that a stack was + // generated on, according to the CPU type indicated by the context + // argument. If no suitable concrete subclass exists, returns NULL. + static Stackwalker* StackwalkerForCPU(const SystemInfo *system_info, + MinidumpContext *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + protected: + // system_info identifies the operating system, NULL or empty if unknown. + // memory identifies a MemoryRegion that provides the stack memory + // for the stack to walk. modules, if non-NULL, is a CodeModules + // object that is used to look up which code module each stack frame is + // associated with. supplier is an optional caller-supplied SymbolSupplier + // implementation. If supplier is NULL, source line info will not be + // resolved. resolver is an instance of SourceLineResolverInterface + // (see source_line_resolver_interface.h and basic_source_line_resolver.h). + // If resolver is NULL, source line info will not be resolved. + Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + // Information about the system that produced the minidump. Subclasses + // and the SymbolSupplier may find this information useful. + const SystemInfo *system_info_; + + // The stack memory to walk. Subclasses will require this region to + // get information from the stack. + MemoryRegion *memory_; + + // A list of modules, for populating each StackFrame's module information. + // This field is optional and may be NULL. + const CodeModules *modules_; + + private: + // Obtains the context frame, the innermost called procedure in a stack + // trace. Returns NULL on failure. GetContextFrame allocates a new + // StackFrame (or StackFrame subclass), ownership of which is taken by + // the caller. + virtual StackFrame* GetContextFrame() = 0; + + // Obtains a caller frame. Each call to GetCallerFrame should return the + // frame that called the last frame returned by GetContextFrame or + // GetCallerFrame. To aid this purpose, stack contains the CallStack + // made of frames that have already been walked. GetCallerFrame should + // return NULL on failure or when there are no more caller frames (when + // the end of the stack has been reached). GetCallerFrame allocates a new + // StackFrame (or StackFrame subclass), ownership of which is taken by + // the caller. + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) = 0; + + // The optional SymbolSupplier for resolving source line info. + SymbolSupplier *supplier_; + + // The SourceLineResolver implementation + SourceLineResolverInterface *resolver_; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/symbol_supplier.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/symbol_supplier.h new file mode 100644 index 00000000..7b9d00e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/symbol_supplier.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The caller may implement the SymbolSupplier abstract base class +// to provide symbols for a given module. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ + +#include + +namespace google_breakpad { + +using std::string; +class CodeModule; +class SystemInfo; + +class SymbolSupplier { + public: + // Result type for GetSymbolFile + enum SymbolResult { + // no symbols were found, but continue processing + NOT_FOUND, + + // symbols were found, and the path has been placed in symbol_file + FOUND, + + // stops processing the minidump immediately + INTERRUPT + }; + + virtual ~SymbolSupplier() {} + + // Retrieves the symbol file for the given CodeModule, placing the + // path in symbol_file if successful. system_info contains strings + // identifying the operating system and CPU; SymbolSupplier may use + // to help locate the symbol file. system_info may be NULL or its + // fields may be empty if these values are unknown. symbol_file + // must be a pointer to a valid string + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) = 0; + // Same as above, except also places symbol data into symbol_data. + // If symbol_data is NULL, the data is not returned. + // TODO(nealsid) Once we have symbol data caching behavior implemented + // investigate making all symbol suppliers implement all methods, + // and make this pure virtual + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data) = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/system_info.h b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/system_info.h new file mode 100644 index 00000000..fdbdbfd6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/google_breakpad/processor/system_info.h @@ -0,0 +1,97 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// system_info.h: Information about the system that was running a program +// when a crash report was produced. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ + +#include + +namespace google_breakpad { + +using std::string; + +struct SystemInfo { + public: + SystemInfo() : os(), os_short(), os_version(), cpu(), cpu_info(), + cpu_count(0) {} + + // Resets the SystemInfo object to its default values. + void Clear() { + os.clear(); + os_short.clear(); + os_version.clear(); + cpu.clear(); + cpu_info.clear(); + cpu_count = 0; + } + + // A string identifying the operating system, such as "Windows NT", + // "Mac OS X", or "Linux". If the information is present in the dump but + // its value is unknown, this field will contain a numeric value. If + // the information is not present in the dump, this field will be empty. + string os; + + // A short form of the os string, using lowercase letters and no spaces, + // suitable for use in a filesystem. Possible values are "windows", + // "mac", and "linux". Empty if the information is not present in the dump + // or if the OS given by the dump is unknown. The values stored in this + // field should match those used by MinidumpSystemInfo::GetOS. + string os_short; + + // A string identifying the version of the operating system, such as + // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not + // contain this information, this field will be empty. + string os_version; + + // A string identifying the basic CPU family, such as "x86" or "ppc". + // If this information is present in the dump but its value is unknown, + // this field will contain a numeric value. If the information is not + // present in the dump, this field will be empty. The values stored in + // this field should match those used by MinidumpSystemInfo::GetCPU. + string cpu; + + // A string further identifying the specific CPU, such as + // "GenuineIntel level 6 model 13 stepping 8". If the information is not + // present in the dump, or additional identifying information is not + // defined for the CPU family, this field will be empty. + string cpu_info; + + // The number of processors in the system. Will be greater than one for + // multi-core systems. + int cpu_count; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map-inl.h new file mode 100644 index 00000000..d88b4fcc --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map-inl.h @@ -0,0 +1,92 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// address_map-inl.h: Address map implementation. +// +// See address_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_ADDRESS_MAP_INL_H__ +#define PROCESSOR_ADDRESS_MAP_INL_H__ + +#include + +#include "processor/address_map.h" +#include "processor/logging.h" + +namespace google_breakpad { + +template +bool AddressMap::Store(const AddressType &address, + const EntryType &entry) { + // Ensure that the specified address doesn't conflict with something already + // in the map. + if (map_.find(address) != map_.end()) { + BPLOG(INFO) << "Store failed, address " << HexString(address) << + " is already present"; + return false; + } + + map_.insert(MapValue(address, entry)); + return true; +} + +template +bool AddressMap::Retrieve( + const AddressType &address, + EntryType *entry, AddressType *entry_address) const { + BPLOG_IF(ERROR, !entry) << "AddressMap::Retrieve requires |entry|"; + assert(entry); + + // upper_bound gives the first element whose key is greater than address, + // but we want the first element whose key is less than or equal to address. + // Decrement the iterator to get there, but not if the upper_bound already + // points to the beginning of the map - in that case, address is lower than + // the lowest stored key, so return false. + MapConstIterator iterator = map_.upper_bound(address); + if (iterator == map_.begin()) + return false; + --iterator; + + *entry = iterator->second; + if (entry_address) + *entry_address = iterator->first; + + return true; +} + +template +void AddressMap::Clear() { + map_.clear(); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_ADDRESS_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map.h new file mode 100644 index 00000000..14139e7a --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/address_map.h @@ -0,0 +1,80 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// address_map.h: Address maps. +// +// An address map contains a set of objects keyed by address. Objects are +// retrieved from the map by returning the object with the highest key less +// than or equal to the lookup key. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_ADDRESS_MAP_H__ +#define PROCESSOR_ADDRESS_MAP_H__ + +#include + +namespace google_breakpad { + +template +class AddressMap { + public: + AddressMap() : map_() {} + + // Inserts an entry into the map. Returns false without storing the entry + // if an entry is already stored in the map at the same address as specified + // by the address argument. + bool Store(const AddressType &address, const EntryType &entry); + + // Locates the entry stored at the highest address less than or equal to + // the address argument. If there is no such range, returns false. The + // entry is returned in entry, which is a required argument. If + // entry_address is not NULL, it will be set to the address that the entry + // was stored at. + bool Retrieve(const AddressType &address, + EntryType *entry, AddressType *entry_address) const; + + // Empties the address map, restoring it to the same state as when it was + // initially created. + void Clear(); + + private: + // Convenience types. + typedef std::map AddressToEntryMap; + typedef typename AddressToEntryMap::const_iterator MapConstIterator; + typedef typename AddressToEntryMap::value_type MapValue; + + // Maps the address of each entry to an EntryType. + AddressToEntryMap map_; +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_ADDRESS_MAP_H__ + diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_module.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_module.h new file mode 100644 index 00000000..5c9f75f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_module.h @@ -0,0 +1,95 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// basic_code_module.h: Carries information about code modules that are loaded +// into a process. +// +// This is a basic concrete implementation of CodeModule. It cannot be +// instantiated directly, only based on other objects that implement +// the CodeModule interface. It exists to provide a CodeModule implementation +// a place to store information when the life of the original object (such as +// a MinidumpModule) cannot be guaranteed. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_BASIC_CODE_MODULE_H__ +#define PROCESSOR_BASIC_CODE_MODULE_H__ + +#include + +#include "google_breakpad/processor/code_module.h" + +namespace google_breakpad { + +using std::string; + +class BasicCodeModule : public CodeModule { + public: + // Creates a new BasicCodeModule given any existing CodeModule + // implementation. This is useful to make a copy of the data relevant to + // the CodeModule interface without requiring all of the resources that + // other CodeModule implementations may require. + explicit BasicCodeModule(const CodeModule *that) + : base_address_(that->base_address()), + size_(that->size()), + code_file_(that->code_file()), + code_identifier_(that->code_identifier()), + debug_file_(that->debug_file()), + debug_identifier_(that->debug_identifier()), + version_(that->version()) {} + virtual ~BasicCodeModule() {} + + // See code_module.h for descriptions of these methods and the associated + // members. + virtual u_int64_t base_address() const { return base_address_; } + virtual u_int64_t size() const { return size_; } + virtual string code_file() const { return code_file_; } + virtual string code_identifier() const { return code_identifier_; } + virtual string debug_file() const { return debug_file_; } + virtual string debug_identifier() const { return debug_identifier_; } + virtual string version() const { return version_; } + virtual const CodeModule* Copy() const { return new BasicCodeModule(this); } + + private: + u_int64_t base_address_; + u_int64_t size_; + string code_file_; + string code_identifier_; + string debug_file_; + string debug_identifier_; + string version_; + + // Disallow copy constructor and assignment operator. + BasicCodeModule(const BasicCodeModule &that); + void operator=(const BasicCodeModule &that); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_BASIC_CODE_MODULE_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_modules.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_modules.h new file mode 100644 index 00000000..df87fc49 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/basic_code_modules.h @@ -0,0 +1,85 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// basic_code_modules.h: Contains all of the CodeModule objects that +// were loaded into a single process. +// +// This is a basic concrete implementation of CodeModules. It cannot be +// instantiated directly, only based on other objects that implement +// the CodeModules interface. It exists to provide a CodeModules +// implementation a place to store information when the life of the original +// object (such as a MinidumpModuleList) cannot be guaranteed. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_BASIC_CODE_MODULES_H__ +#define PROCESSOR_BASIC_CODE_MODULES_H__ + +#include "google_breakpad/processor/code_modules.h" + +namespace google_breakpad { + +template class linked_ptr; +template class RangeMap; + +class BasicCodeModules : public CodeModules { + public: + // Creates a new BasicCodeModules object given any existing CodeModules + // implementation. This is useful to make a copy of the data relevant to + // the CodeModules and CodeModule interfaces without requiring all of the + // resources that other implementations may require. A copy will be + // made of each contained CodeModule using CodeModule::Copy. + explicit BasicCodeModules(const CodeModules *that); + + virtual ~BasicCodeModules(); + + // See code_modules.h for descriptions of these methods. + virtual unsigned int module_count() const; + virtual const CodeModule* GetModuleForAddress(u_int64_t address) const; + virtual const CodeModule* GetMainModule() const; + virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const; + virtual const CodeModule* GetModuleAtIndex(unsigned int index) const; + virtual const CodeModules* Copy() const; + + private: + // The base address of the main module. + u_int64_t main_address_; + + // The map used to contain each CodeModule, keyed by each CodeModule's + // address range. + RangeMap > *map_; + + // Disallow copy constructor and assignment operator. + BasicCodeModules(const BasicCodeModules &that); + void operator=(const BasicCodeModules &that); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_BASIC_CODE_MODULES_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map-inl.h new file mode 100644 index 00000000..5cc498df --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map-inl.h @@ -0,0 +1,197 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// contained_range_map-inl.h: Hierarchically-organized range map implementation. +// +// See contained_range_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ +#define PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ + + +#include + +#include "processor/contained_range_map.h" +#include "processor/logging.h" + + +namespace google_breakpad { + + +template +ContainedRangeMap::~ContainedRangeMap() { + // Clear frees the children pointed to by the map, and frees the map itself. + Clear(); +} + + +template +bool ContainedRangeMap::StoreRange( + const AddressType &base, const AddressType &size, const EntryType &entry) { + AddressType high = base + size - 1; + + // Check for undersize or overflow. + if (size <= 0 || high < base) { + //TODO(nealsid) We are commenting this out in order to prevent + // excessive logging. We plan to move to better logging as this + // failure happens quite often and is expected(see comment in + // basic_source_line_resolver.cc:671). + // BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+" + // << HexString(size) << ", " << HexString(high); + return false; + } + + if (!map_) + map_ = new AddressToRangeMap(); + + MapIterator iterator_base = map_->lower_bound(base); + MapIterator iterator_high = map_->lower_bound(high); + MapIterator iterator_end = map_->end(); + + if (iterator_base == iterator_high && iterator_base != iterator_end && + base >= iterator_base->second->base_) { + // The new range is entirely within an existing child range. + + // If the new range's geometry is exactly equal to an existing child + // range's, it violates the containment rules, and an attempt to store + // it must fail. iterator_base->first contains the key, which was the + // containing child's high address. + if (iterator_base->second->base_ == base && iterator_base->first == high) { + // TODO(nealsid): See the TODO above on why this is commented out. +// BPLOG(INFO) << "StoreRange failed, identical range is already " +// "present: " << HexString(base) << "+" << HexString(size); + return false; + } + + // Pass the new range on to the child to attempt to store. + return iterator_base->second->StoreRange(base, size, entry); + } + + // iterator_high might refer to an irrelevant range: one whose base address + // is higher than the new range's high address. Set contains_high to true + // only if iterator_high refers to a range that is at least partially + // within the new range. + bool contains_high = iterator_high != iterator_end && + high >= iterator_high->second->base_; + + // If the new range encompasses any existing child ranges, it must do so + // fully. Partial containment isn't allowed. + if ((iterator_base != iterator_end && base > iterator_base->second->base_) || + (contains_high && high < iterator_high->first)) { + // TODO(mmentovai): Some symbol files will trip this check frequently + // on STACK lines. Too many messages will be produced. These are more + // suitable for a DEBUG channel than an INFO channel. + // BPLOG(INFO) << "StoreRange failed, new range partially contains " + // "existing range: " << HexString(base) << "+" << + // HexString(size); + return false; + } + + // When copying and erasing contained ranges, the "end" iterator needs to + // point one past the last item of the range to copy. If contains_high is + // false, the iterator's already in the right place; the increment is safe + // because contains_high can't be true if iterator_high == iterator_end. + if (contains_high) + ++iterator_high; + + // Optimization: if the iterators are equal, no child ranges would be + // moved. Create the new child range with a NULL map to conserve space + // in leaf nodes, of which there will be many. + AddressToRangeMap *child_map = NULL; + + if (iterator_base != iterator_high) { + // The children of this range that are contained by the new range must + // be transferred over to the new range. Create the new child range map + // and copy the pointers to range maps it should contain into it. + child_map = new AddressToRangeMap(iterator_base, iterator_high); + + // Remove the copied child pointers from this range's map of children. + map_->erase(iterator_base, iterator_high); + } + + // Store the new range in the map by its high address. Any children that + // the new child range contains were formerly children of this range but + // are now this range's grandchildren. Ownership of these is transferred + // to the new child range. + map_->insert(MapValue(high, + new ContainedRangeMap(base, entry, child_map))); + return true; +} + + +template +bool ContainedRangeMap::RetrieveRange( + const AddressType &address, EntryType *entry) const { + BPLOG_IF(ERROR, !entry) << "ContainedRangeMap::RetrieveRange requires " + "|entry|"; + assert(entry); + + // If nothing was ever stored, then there's nothing to retrieve. + if (!map_) + return false; + + // Get an iterator to the child range whose high address is equal to or + // greater than the supplied address. If the supplied address is higher + // than all of the high addresses in the range, then this range does not + // contain a child at address, so return false. If the supplied address + // is lower than the base address of the child range, then it is not within + // the child range, so return false. + MapConstIterator iterator = map_->lower_bound(address); + if (iterator == map_->end() || address < iterator->second->base_) + return false; + + // The child in iterator->second contains the specified address. Find out + // if it has a more-specific descendant that also contains it. If it does, + // it will set |entry| appropriately. If not, set |entry| to the child. + if (!iterator->second->RetrieveRange(address, entry)) + *entry = iterator->second->entry_; + + return true; +} + + +template +void ContainedRangeMap::Clear() { + if (map_) { + MapConstIterator end = map_->end(); + for (MapConstIterator child = map_->begin(); child != end; ++child) + delete child->second; + + delete map_; + map_ = NULL; + } +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map.h new file mode 100644 index 00000000..f30016f3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/contained_range_map.h @@ -0,0 +1,145 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// contained_range_map.h: Hierarchically-organized range maps. +// +// A contained range map is similar to a standard range map, except it allows +// objects to be organized hierarchically. A contained range map allows +// objects to contain other objects. It is not sensitive to the order that +// objects are added to the map: larger, more general, containing objects +// may be added either before or after smaller, more specific, contained +// ones. +// +// Contained range maps guarantee that each object may only contain smaller +// objects than itself, and that a parent object may only contain child +// objects located entirely within the parent's address space. Attempts +// to introduce objects (via StoreRange) that violate these rules will fail. +// Retrieval (via RetrieveRange) always returns the most specific (smallest) +// object that contains the address being queried. Note that while it is +// not possible to insert two objects into a map that have exactly the same +// geometry (base address and size), it is possible to completely mask a +// larger object by inserting smaller objects that entirely fill the larger +// object's address space. +// +// Internally, contained range maps are implemented as a tree. Each tree +// node except for the root node describes an object in the map. Each node +// maintains its list of children in a map similar to a standard range map, +// keyed by the highest address that each child occupies. Each node's +// children occupy address ranges entirely within the node. The root node +// is the only node directly accessible to the user, and represents the +// entire address space. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_CONTAINED_RANGE_MAP_H__ +#define PROCESSOR_CONTAINED_RANGE_MAP_H__ + + +#include + + +namespace google_breakpad { + + +template +class ContainedRangeMap { + public: + // The default constructor creates a ContainedRangeMap with no geometry + // and no entry, and as such is only suitable for the root node of a + // ContainedRangeMap tree. + ContainedRangeMap() : base_(), entry_(), map_(NULL) {} + + ~ContainedRangeMap(); + + // Inserts a range into the map. If the new range is encompassed by + // an existing child range, the new range is passed into the child range's + // StoreRange method. If the new range encompasses any existing child + // ranges, those child ranges are moved to the new range, becoming + // grandchildren of this ContainedRangeMap. Returns false for a + // parameter error, or if the ContainedRangeMap hierarchy guarantees + // would be violated. + bool StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry); + + // Retrieves the most specific (smallest) descendant range encompassing + // the specified address. This method will only return entries held by + // child ranges, and not the entry contained by |this|. This is necessary + // to support a sparsely-populated root range. If no descendant range + // encompasses the address, returns false. + bool RetrieveRange(const AddressType &address, EntryType *entry) const; + + // Removes all children. Note that Clear only removes descendants, + // leaving the node on which it is called intact. Because the only + // meaningful things contained by a root node are descendants, this + // is sufficient to restore an entire ContainedRangeMap to its initial + // empty state when called on the root node. + void Clear(); + + private: + // AddressToRangeMap stores pointers. This makes reparenting simpler in + // StoreRange, because it doesn't need to copy entire objects. + typedef std::map AddressToRangeMap; + typedef typename AddressToRangeMap::const_iterator MapConstIterator; + typedef typename AddressToRangeMap::iterator MapIterator; + typedef typename AddressToRangeMap::value_type MapValue; + + // Creates a new ContainedRangeMap with the specified base address, entry, + // and initial child map, which may be NULL. This is only used internally + // by ContainedRangeMap when it creates a new child. + ContainedRangeMap(const AddressType &base, const EntryType &entry, + AddressToRangeMap *map) + : base_(base), entry_(entry), map_(map) {} + + // The base address of this range. The high address does not need to + // be stored, because it is used as the key to an object in its parent's + // map, and all ContainedRangeMaps except for the root range are contained + // within maps. The root range does not actually contain an entry, so its + // base_ field is meaningless, and the fact that it has no parent and thus + // no key is unimportant. For this reason, the base_ field should only be + // is accessed on child ContainedRangeMap objects, and never on |this|. + const AddressType base_; + + // The entry corresponding to this range. The root range does not + // actually contain an entry, so its entry_ field is meaningless. For + // this reason, the entry_ field should only be accessed on child + // ContainedRangeMap objects, and never on |this|. + const EntryType entry_; + + // The map containing child ranges, keyed by each child range's high + // address. This is a pointer to avoid allocating map structures for + // leaf nodes, where they are not needed. + AddressToRangeMap *map_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_CONTAINED_RANGE_MAP_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/linked_ptr.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/linked_ptr.h new file mode 100644 index 00000000..1a4ef7d4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/linked_ptr.h @@ -0,0 +1,193 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). + +#ifndef PROCESSOR_LINKED_PTR_H__ +#define PROCESSOR_LINKED_PTR_H__ + +namespace google_breakpad { + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) { + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true iff we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() { + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { depart(); capture(ptr); } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + // Release ownership of the pointed object and returns it. + // Sole ownership by this linked_ptr object is required. + T* release() { + bool last = link_.depart(); + T* v = value_; + value_ = NULL; + return v; + } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_LINKED_PTR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/logging.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/logging.h new file mode 100644 index 00000000..b638ff58 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/logging.h @@ -0,0 +1,153 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// logging.h: Breakpad logging +// +// Breakpad itself uses Breakpad logging with statements of the form: +// BPLOG(severity) << "message"; +// severity may be INFO, ERROR, or other values defined in this file. +// +// BPLOG is an overridable macro so that users can customize Breakpad's +// logging. Left at the default, logging messages are sent to stderr along +// with a timestamp and the source code location that produced a message. +// The streams may be changed by redefining BPLOG_*_STREAM, the logging +// behavior may be changed by redefining BPLOG_*, and the entire logging +// system may be overridden by redefining BPLOG(severity). These +// redefinitions may be passed to the preprocessor as a command-line flag +// (-D). +// +// If an additional header is required to override Breakpad logging, it can +// be specified by the BP_LOGGING_INCLUDE macro. If defined, this header +// will #include the header specified by that macro. +// +// If any initialization is needed before logging, it can be performed by +// a function called through the BPLOG_INIT macro. Each main function of +// an executable program in the Breakpad processor library calls +// BPLOG_INIT(&argc, &argv); before any logging can be performed; define +// BPLOG_INIT appropriately if initialization is required. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_LOGGING_H__ +#define PROCESSOR_LOGGING_H__ + +#include +#include + +#include "google_breakpad/common/breakpad_types.h" + +#ifdef BP_LOGGING_INCLUDE +#include BP_LOGGING_INCLUDE +#endif // BP_LOGGING_INCLUDE + +namespace google_breakpad { + +class LogStream { + public: + enum Severity { + SEVERITY_INFO, + SEVERITY_ERROR + }; + + // Begin logging a message to the stream identified by |stream|, at the + // indicated severity. The file and line parameters should be set so as to + // identify the line of source code that is producing a message. + LogStream(std::ostream &stream, Severity severity, + const char *file, int line); + + // Finish logging by printing a newline and flushing the output stream. + ~LogStream(); + + template std::ostream& operator<<(const T &t) { + return stream_ << t; + } + + private: + std::ostream &stream_; + + // Disallow copy constructor and assignment operator + explicit LogStream(const LogStream &that); + void operator=(const LogStream &that); +}; + +// This class is used to explicitly ignore values in the conditional logging +// macros. This avoids compiler warnings like "value computed is not used" +// and "statement has no effect". +class LogMessageVoidify { + public: + LogMessageVoidify() {} + + // This has to be an operator with a precedence lower than << but higher + // than ?: + void operator&(std::ostream &) {} +}; + +// Returns number formatted as a hexadecimal string, such as "0x7b". +std::string HexString(u_int32_t number); +std::string HexString(u_int64_t number); +std::string HexString(int number); + +// Returns the error code as set in the global errno variable, and sets +// error_string, a required argument, to a string describing that error +// code. +int ErrnoString(std::string *error_string); + +} // namespace google_breakpad + +#ifndef BPLOG_INIT +#define BPLOG_INIT(pargc, pargv) +#endif // BPLOG_INIT + +#ifndef BPLOG +#define BPLOG(severity) BPLOG_ ## severity +#endif // BPLOG + +#ifndef BPLOG_INFO +#ifndef BPLOG_INFO_STREAM +#define BPLOG_INFO_STREAM std::clog +#endif // BPLOG_INFO_STREAM +#define BPLOG_INFO google_breakpad::LogStream(BPLOG_INFO_STREAM, \ + google_breakpad::LogStream::SEVERITY_INFO, \ + __FILE__, __LINE__) +#endif // BPLOG_INFO + +#ifndef BPLOG_ERROR +#ifndef BPLOG_ERROR_STREAM +#define BPLOG_ERROR_STREAM std::cerr +#endif // BPLOG_ERROR_STREAM +#define BPLOG_ERROR google_breakpad::LogStream(BPLOG_ERROR_STREAM, \ + google_breakpad::LogStream::SEVERITY_ERROR, \ + __FILE__, __LINE__) +#endif // BPLOG_ERROR + +#define BPLOG_IF(severity, condition) \ + !(condition) ? (void) 0 : \ + google_breakpad::LogMessageVoidify() & BPLOG(severity) + +#endif // PROCESSOR_LOGGING_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/pathname_stripper.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/pathname_stripper.h new file mode 100644 index 00000000..17db75d6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/pathname_stripper.h @@ -0,0 +1,53 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// pathname_stripper.h: Manipulates pathnames into their component parts. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_PATHNAME_STRIPPER_H__ +#define PROCESSOR_PATHNAME_STRIPPER_H__ + +#include + +namespace google_breakpad { + +using std::string; + +class PathnameStripper { + public: + // Given path, a pathname with components separated by slashes (/) or + // backslashes (\), returns the trailing component, without any separator. + // If path ends in a separator character, returns an empty string. + static string File(const string &path); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_PATHNAME_STRIPPER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator-inl.h new file mode 100644 index 00000000..aa0851d9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator-inl.h @@ -0,0 +1,282 @@ +// 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. + +// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression +// evaluator. +// +// Documentation in postfix_evaluator.h. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ +#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ + + +#include + +#include "processor/postfix_evaluator.h" +#include "google_breakpad/processor/memory_region.h" +#include "processor/logging.h" + +namespace google_breakpad { + +using std::istringstream; +using std::ostringstream; + + +// A small class used in Evaluate to make sure to clean up the stack +// before returning failure. +class AutoStackClearer { + public: + explicit AutoStackClearer(vector *stack) : stack_(stack) {} + ~AutoStackClearer() { stack_->clear(); } + + private: + vector *stack_; +}; + + +template +bool PostfixEvaluator::Evaluate(const string &expression, + DictionaryValidityType *assigned) { + // Ensure that the stack is cleared before returning. + AutoStackClearer clearer(&stack_); + + // Tokenize, splitting on whitespace. + istringstream stream(expression); + string token; + while (stream >> token) { + // There are enough binary operations that do exactly the same thing + // (other than the specific operation, of course) that it makes sense + // to share as much code as possible. + enum BinaryOperation { + BINARY_OP_NONE = 0, + BINARY_OP_ADD, + BINARY_OP_SUBTRACT, + BINARY_OP_MULTIPLY, + BINARY_OP_DIVIDE_QUOTIENT, + BINARY_OP_DIVIDE_MODULUS + }; + + BinaryOperation operation = BINARY_OP_NONE; + if (token == "+") + operation = BINARY_OP_ADD; + else if (token == "-") + operation = BINARY_OP_SUBTRACT; + else if (token == "*") + operation = BINARY_OP_MULTIPLY; + else if (token == "/") + operation = BINARY_OP_DIVIDE_QUOTIENT; + else if (token == "%") + operation = BINARY_OP_DIVIDE_MODULUS; + + if (operation != BINARY_OP_NONE) { + // Get the operands. + ValueType operand1, operand2; + if (!PopValues(&operand1, &operand2)) { + BPLOG(ERROR) << "Could not PopValues to get two values for binary " + "operation " << token << ": " << expression; + return false; + } + + // Perform the operation. + ValueType result; + switch (operation) { + case BINARY_OP_ADD: + result = operand1 + operand2; + break; + case BINARY_OP_SUBTRACT: + result = operand1 - operand2; + break; + case BINARY_OP_MULTIPLY: + result = operand1 * operand2; + break; + case BINARY_OP_DIVIDE_QUOTIENT: + result = operand1 / operand2; + break; + case BINARY_OP_DIVIDE_MODULUS: + result = operand1 % operand2; + break; + case BINARY_OP_NONE: + // This will not happen, but compilers will want a default or + // BINARY_OP_NONE case. + BPLOG(ERROR) << "Not reached!"; + return false; + break; + } + + // Save the result. + PushValue(result); + } else if (token == "^") { + // ^ for unary dereference. Can't dereference without memory. + if (!memory_) { + BPLOG(ERROR) << "Attempt to dereference without memory: " << + expression; + return false; + } + + ValueType address; + if (!PopValue(&address)) { + BPLOG(ERROR) << "Could not PopValue to get value to derefence: " << + expression; + return false; + } + + ValueType value; + if (!memory_->GetMemoryAtAddress(address, &value)) { + BPLOG(ERROR) << "Could not dereference memory at address " << + HexString(address) << ": " << expression; + return false; + } + + PushValue(value); + } else if (token == "=") { + // = for assignment. + ValueType value; + if (!PopValue(&value)) { + BPLOG(ERROR) << "Could not PopValue to get value to assign: " << + expression; + return false; + } + + // Assignment is only meaningful when assigning into an identifier. + // The identifier must name a variable, not a constant. Variables + // begin with '$'. + string identifier; + if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { + BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " + "identifier is needed to assign " << + HexString(value) << ": " << expression; + return false; + } + if (identifier.empty() || identifier[0] != '$') { + BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << + identifier << ": " << expression; + return false; + } + + (*dictionary_)[identifier] = value; + if (assigned) + (*assigned)[identifier] = true; + } else { + // The token is not an operator, it's a literal value or an identifier. + // Push it onto the stack as-is. Use push_back instead of PushValue + // because PushValue pushes ValueType as a string, but token is already + // a string. + stack_.push_back(token); + } + } + + // If there's anything left on the stack, it indicates incomplete execution. + // This is a failure case. If the stack is empty, evalution was complete + // and successful. + BPLOG_IF(ERROR, !stack_.empty()) << "Incomplete execution: " << expression; + return stack_.empty(); +} + + +template +typename PostfixEvaluator::PopResult +PostfixEvaluator::PopValueOrIdentifier( + ValueType *value, string *identifier) { + // There needs to be at least one element on the stack to pop. + if (!stack_.size()) + return POP_RESULT_FAIL; + + string token = stack_.back(); + stack_.pop_back(); + + // First, try to treat the value as a literal. In order for this to + // succed, the entire string must be parseable as ValueType. If this + // isn't possible, it can't be a literal, so treat it as an identifier + // instead. + istringstream token_stream(token); + ValueType literal; + if (token_stream >> literal && token_stream.peek() == EOF) { + if (value) { + *value = literal; + } + return POP_RESULT_VALUE; + } else { + if (identifier) { + *identifier = token; + } + return POP_RESULT_IDENTIFIER; + } +} + + +template +bool PostfixEvaluator::PopValue(ValueType *value) { + ValueType literal; + string token; + PopResult result; + if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { + return false; + } else if (result == POP_RESULT_VALUE) { + // This is the easy case. + *value = literal; + } else { // result == POP_RESULT_IDENTIFIER + // There was an identifier at the top of the stack. Resolve it to a + // value by looking it up in the dictionary. + typename DictionaryType::const_iterator iterator = + dictionary_->find(token); + if (iterator == dictionary_->end()) { + // The identifier wasn't found in the dictionary. Don't imply any + // default value, just fail. + BPLOG(ERROR) << "Identifier " << token << " not in dictionary"; + return false; + } + + *value = iterator->second; + } + + return true; +} + + +template +bool PostfixEvaluator::PopValues(ValueType *value1, + ValueType *value2) { + return PopValue(value2) && PopValue(value1); +} + + +template +void PostfixEvaluator::PushValue(const ValueType &value) { + ostringstream token_stream; + token_stream << value; + stack_.push_back(token_stream.str()); +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator.h new file mode 100644 index 00000000..552ed159 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/postfix_evaluator.h @@ -0,0 +1,158 @@ +// 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. + +// postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator. +// +// PostfixEvaluator evaluates an expression, using the expression itself +// in postfix (reverse Polish) notation and a dictionary mapping constants +// and variables to their values. The evaluator supports standard +// arithmetic operations, assignment into variables, and when an optional +// MemoryRange is provided, dereferencing. (Any unary key-to-value operation +// may be used with a MemoryRange implementation that returns the appropriate +// values, but PostfixEvaluator was written with dereferencing in mind.) +// +// The expression language is simple. Expressions are supplied as strings, +// with operands and operators delimited by whitespace. Operands may be +// either literal values suitable for ValueType, or constants or variables, +// which reference the dictionary. The supported binary operators are + +// (addition), - (subtraction), * (multiplication), / (quotient of division), +// and % (modulus of division). The unary ^ (dereference) operator is also +// provided. These operators allow any operand to be either a literal +// value, constant, or variable. Assignment (=) of any type of operand into +// a variable is also supported. +// +// The dictionary is provided as a map with string keys. Keys beginning +// with the '$' character are treated as variables. All other keys are +// treated as constants. Any results must be assigned into variables in the +// dictionary. These variables do not need to exist prior to calling +// Evaluate, unless used in an expression prior to being assigned to. The +// internal stack state is not made available after evaluation, and any +// values remaining on the stack are treated as evidence of incomplete +// execution and cause the evaluator to indicate failure. +// +// PostfixEvaluator is intended to support evaluation of "program strings" +// obtained from MSVC frame data debugging information in pdb files as +// returned by the DIA APIs. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_POSTFIX_EVALUATOR_H__ +#define PROCESSOR_POSTFIX_EVALUATOR_H__ + + +#include +#include +#include + +namespace google_breakpad { + +using std::map; +using std::string; +using std::vector; + +class MemoryRegion; + +template +class PostfixEvaluator { + public: + typedef map DictionaryType; + typedef map DictionaryValidityType; + + // Create a PostfixEvaluator object that may be used (with Evaluate) on + // one or more expressions. PostfixEvaluator does not take ownership of + // either argument. |memory| may be NULL, in which case dereferencing + // (^) will not be supported. |dictionary| may be NULL, but evaluation + // will fail in that case unless set_dictionary is used before calling + // Evaluate. + PostfixEvaluator(DictionaryType *dictionary, MemoryRegion *memory) + : dictionary_(dictionary), memory_(memory), stack_() {} + + // Evaluate the expression. The results of execution will be stored + // in one (or more) variables in the dictionary. Returns false if any + // failures occure during execution, leaving variables in the dictionary + // in an indeterminate state. If assigned is non-NULL, any keys set in + // the dictionary as a result of evaluation will also be set to true in + // assigned, providing a way to determine if an expression modifies any + // of its input variables. + bool Evaluate(const string &expression, DictionaryValidityType *assigned); + + DictionaryType* dictionary() const { return dictionary_; } + + // Reset the dictionary. PostfixEvaluator does not take ownership. + void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; } + + private: + // Return values for PopValueOrIdentifier + enum PopResult { + POP_RESULT_FAIL = 0, + POP_RESULT_VALUE, + POP_RESULT_IDENTIFIER + }; + + // Retrieves the topmost literal value, constant, or variable from the + // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal + // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER + // if the topmost entry is a constant or variable identifier, and sets + // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such + // as when the stack is empty. + PopResult PopValueOrIdentifier(ValueType *value, string *identifier); + + // Retrieves the topmost value on the stack. If the topmost entry is + // an identifier, the dictionary is queried for the identifier's value. + // Returns false on failure, such as when the stack is empty or when + // a nonexistent identifier is named. + bool PopValue(ValueType *value); + + // Retrieves the top two values on the stack, in the style of PopValue. + // value2 is popped before value1, so that value1 corresponds to the + // entry that was pushed prior to value2. Returns false on failure. + bool PopValues(ValueType *value1, ValueType *value2); + + // Pushes a new value onto the stack. + void PushValue(const ValueType &value); + + // The dictionary mapping constant and variable identifiers (strings) to + // values. Keys beginning with '$' are treated as variable names, and + // PostfixEvaluator is free to create and modify these keys. Weak pointer. + DictionaryType *dictionary_; + + // If non-NULL, the MemoryRegion used for dereference (^) operations. + // If NULL, dereferencing is unsupported and will fail. Weak pointer. + MemoryRegion *memory_; + + // The stack contains state information as execution progresses. Values + // are pushed on to it as the expression string is read and as operations + // yield values; values are popped when used as operands to operators. + vector stack_; +}; + +} // namespace google_breakpad + + +#endif // PROCESSOR_POSTFIX_EVALUATOR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map-inl.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map-inl.h new file mode 100644 index 00000000..77bf7d20 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map-inl.h @@ -0,0 +1,210 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// range_map-inl.h: Range map implementation. +// +// See range_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_RANGE_MAP_INL_H__ +#define PROCESSOR_RANGE_MAP_INL_H__ + + +#include + +#include "processor/range_map.h" +#include "processor/logging.h" + + +namespace google_breakpad { + + +template +bool RangeMap::StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry) { + AddressType high = base + size - 1; + + // Check for undersize or overflow. + if (size <= 0 || high < base) { + // The processor will hit this case too frequently with common symbol + // files in the size == 0 case, which is more suited to a DEBUG channel. + // Filter those out since there's no DEBUG channel at the moment. + BPLOG_IF(INFO, size != 0) << "StoreRange failed, " << HexString(base) << + "+" << HexString(size) << ", " << + HexString(high); + return false; + } + + // Ensure that this range does not overlap with another one already in the + // map. + MapConstIterator iterator_base = map_.lower_bound(base); + MapConstIterator iterator_high = map_.lower_bound(high); + + if (iterator_base != iterator_high) { + // Some other range begins in the space used by this range. It may be + // contained within the space used by this range, or it may extend lower. + // Regardless, it is an error. + AddressType other_base = iterator_base->second.base(); + AddressType other_size = iterator_base->first - other_base + 1; + BPLOG(INFO) << "StoreRange failed, an existing range is contained by or " + "extends lower than the new range: new " << + HexString(base) << "+" << HexString(size) << ", existing " << + HexString(other_base) << "+" << HexString(other_size); + return false; + } + + if (iterator_high != map_.end()) { + if (iterator_high->second.base() <= high) { + // The range above this one overlaps with this one. It may fully + // contain this range, or it may begin within this range and extend + // higher. Regardless, it's an error. + AddressType other_base = iterator_high->second.base(); + AddressType other_size = iterator_high->first - other_base + 1; + BPLOG(INFO) << "StoreRange failed, an existing range contains or " + "extends higher than the new range: new " << + HexString(base) << "+" << HexString(size) << + ", existing " << + HexString(other_base) << "+" << HexString(other_size); + return false; + } + } + + // Store the range in the map by its high address, so that lower_bound can + // be used to quickly locate a range by address. + map_.insert(MapValue(high, Range(base, entry))); + return true; +} + + +template +bool RangeMap::RetrieveRange( + const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|"; + assert(entry); + + MapConstIterator iterator = map_.lower_bound(address); + if (iterator == map_.end()) + return false; + + // The map is keyed by the high address of each range, so |address| is + // guaranteed to be lower than the range's high address. If |range| is + // not directly preceded by another range, it's possible for address to + // be below the range's low address, though. When that happens, address + // references something not within any range, so return false. + if (address < iterator->second.base()) + return false; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->second.base(); + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +bool RangeMap::RetrieveNearestRange( + const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|"; + assert(entry); + + // If address is within a range, RetrieveRange can handle it. + if (RetrieveRange(address, entry, entry_base, entry_size)) + return true; + + // upper_bound gives the first element whose key is greater than address, + // but we want the first element whose key is less than or equal to address. + // Decrement the iterator to get there, but not if the upper_bound already + // points to the beginning of the map - in that case, address is lower than + // the lowest stored key, so return false. + MapConstIterator iterator = map_.upper_bound(address); + if (iterator == map_.begin()) + return false; + --iterator; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->first; + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +bool RangeMap::RetrieveRangeAtIndex( + int index, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|"; + assert(entry); + + if (index >= GetCount()) { + BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount(); + return false; + } + + // Walk through the map. Although it's ordered, it's not a vector, so it + // can't be addressed directly by index. + MapConstIterator iterator = map_.begin(); + for (int this_index = 0; this_index < index; ++this_index) + ++iterator; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->first; + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +int RangeMap::GetCount() const { + return map_.size(); +} + + +template +void RangeMap::Clear() { + map_.clear(); +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_RANGE_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map.h new file mode 100644 index 00000000..a7b67412 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/range_map.h @@ -0,0 +1,126 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// range_map.h: Range maps. +// +// A range map associates a range of addresses with a specific object. This +// is useful when certain objects of variable size are located within an +// address space. The range map makes it simple to determine which object is +// associated with a specific address, which may be any address within the +// range associated with an object. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_RANGE_MAP_H__ +#define PROCESSOR_RANGE_MAP_H__ + + +#include + + +namespace google_breakpad { + + +template +class RangeMap { + public: + RangeMap() : map_() {} + + // Inserts a range into the map. Returns false for a parameter error, + // or if the location of the range would conflict with a range already + // stored in the map. + bool StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry); + + // Locates the range encompassing the supplied address. If there is + // no such range, returns false. entry_base and entry_size, if non-NULL, + // are set to the base and size of the entry's range. + bool RetrieveRange(const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const; + + // Locates the range encompassing the supplied address, if one exists. + // If no range encompasses the supplied address, locates the nearest range + // to the supplied address that is lower than the address. Returns false + // if no range meets these criteria. entry_base and entry_size, if + // non-NULL, are set to the base and size of the entry's range. + bool RetrieveNearestRange(const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) + const; + + // Treating all ranges as a list ordered by the address spaces that they + // occupy, locates the range at the index specified by index. Returns + // false if index is larger than the number of ranges stored. entry_base + // and entry_size, if non-NULL, are set to the base and size of the entry's + // range. + // + // RetrieveRangeAtIndex is not optimized for speedy operation. + bool RetrieveRangeAtIndex(int index, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) + const; + + // Returns the number of ranges stored in the RangeMap. + int GetCount() const; + + // Empties the range map, restoring it to the state it was when it was + // initially created. + void Clear(); + + private: + class Range { + public: + Range(const AddressType &base, const EntryType &entry) + : base_(base), entry_(entry) {} + + AddressType base() const { return base_; } + EntryType entry() const { return entry_; } + + private: + // The base address of the range. The high address does not need to + // be stored, because RangeMap uses it as the key to the map. + const AddressType base_; + + // The entry corresponding to a range. + const EntryType entry_; + }; + + // Convenience types. + typedef std::map AddressToRangeMap; + typedef typename AddressToRangeMap::const_iterator MapConstIterator; + typedef typename AddressToRangeMap::value_type MapValue; + + // Maps the high address of each range to a EntryType. + AddressToRangeMap map_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_RANGE_MAP_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/scoped_ptr.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/scoped_ptr.h new file mode 100644 index 00000000..0d4f7fd3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/scoped_ptr.h @@ -0,0 +1,335 @@ +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +// *** NOTE *** +// If your scoped_ptr is a class member of class FOO pointing to a +// forward declared type BAR (as shown below), then you MUST use a non-inlined +// version of the destructor. The destructor of a scoped_ptr (called from +// FOO's destructor) must have a complete definition of BAR in order to +// destroy it. Example: +// +// -- foo.h -- +// class BAR; +// +// class FOO { +// public: +// FOO(); +// ~FOO(); // Required for sources that instantiate class FOO to compile! +// +// private: +// scoped_ptr bar_; +// }; +// +// -- foo.cc -- +// #include "foo.h" +// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. + +// scoped_ptr_malloc added by Google +// When one of these goes out of scope, instead of doing a delete or +// delete[], it calls free(). scoped_ptr_malloc is likely to see +// much more use than any other specializations. + +// release() added by Google +// Use this to conditionally transfer ownership of a heap-allocated object +// to the caller, usually on method success. + +#ifndef PROCESSOR_SCOPED_PTR_H__ +#define PROCESSOR_SCOPED_PTR_H__ + +#include // for std::ptrdiff_t +#include // for assert +#include // for free() decl + +namespace google_breakpad { + +template +class scoped_ptr { + private: + + T* ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + public: + + typedef T element_type; + + explicit scoped_ptr(T* p = 0): ptr(p) {} + + ~scoped_ptr() { + typedef char type_must_be_complete[sizeof(T)]; + delete ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete ptr; + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr should have its own object + template bool operator==(scoped_ptr const& p) const; + template bool operator!=(scoped_ptr const& p) const; +}; + +template inline +void swap(scoped_ptr& a, scoped_ptr& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr& b) { + return p != b.get(); +} + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template +class scoped_array { + private: + + T* ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + public: + + typedef T element_type; + + explicit scoped_array(T* p = 0) : ptr(p) {} + + ~scoped_array() { + typedef char type_must_be_complete[sizeof(T)]; + delete[] ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete [] ptr; + ptr = p; + } + } + + T& operator[](std::ptrdiff_t i) const { + assert(ptr != 0); + assert(i >= 0); + return ptr[i]; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_array & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_array should have its own object + template bool operator==(scoped_array const& p) const; + template bool operator!=(scoped_array const& p) const; +}; + +template inline +void swap(scoped_array& a, scoped_array& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_array& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_array& b) { + return p != b.get(); +} + + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a +// second template argument, the functor used to free the object. + +template +class scoped_ptr_malloc { + private: + + T* ptr; + + scoped_ptr_malloc(scoped_ptr_malloc const &); + scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); + + public: + + typedef T element_type; + + explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} + + ~scoped_ptr_malloc() { + typedef char type_must_be_complete[sizeof(T)]; + free_((void*) ptr); + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + free_((void*) ptr); + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr_malloc & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr_malloc should have its own object + template + bool operator==(scoped_ptr_malloc const& p) const; + template + bool operator!=(scoped_ptr_malloc const& p) const; + + static FreeProc const free_; +}; + +template +FP const scoped_ptr_malloc::free_ = FP(); + +template inline +void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr_malloc& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr_malloc& b) { + return p != b.get(); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_SCOPED_PTR_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/simple_symbol_supplier.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/simple_symbol_supplier.h new file mode 100644 index 00000000..dff6a512 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/simple_symbol_supplier.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// simple_symbol_supplier.h: A simple SymbolSupplier implementation +// +// SimpleSymbolSupplier is a straightforward implementation of SymbolSupplier +// that stores symbol files in a filesystem tree. A SimpleSymbolSupplier is +// created with one or more base directories, which are the root paths for all +// symbol files. Each symbol file contained therein has a directory entry in +// the base directory with a name identical to the corresponding debugging +// file (pdb). Within each of these directories, there are subdirectories +// named for the debugging file's identifier. For recent pdb files, this is +// a concatenation of the pdb's uuid and age, presented in hexadecimal form, +// without any dashes or separators. The uuid is in uppercase hexadecimal +// and the age is in lowercase hexadecimal. Within that subdirectory, +// SimpleSymbolSupplier expects to find the symbol file, which is named +// identically to the debug file, but with a .sym extension. If the original +// debug file had a name ending in .pdb, the .pdb extension will be replaced +// with .sym. This sample hierarchy is rooted at the "symbols" base +// directory: +// +// symbols +// symbols/test_app.pdb +// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1 +// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1/test_app.sym +// symbols/kernel32.pdb +// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542 +// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym +// +// In this case, the uuid of test_app.pdb is +// 63fe4780-728d-4937-9b9d-7bb6460cb42a and its age is 1. +// +// This scheme was chosen to be roughly analogous to the way that +// symbol files may be accessed from Microsoft Symbol Server. A hierarchy +// used for Microsoft Symbol Server storage is usable as a hierarchy for +// SimpleSymbolServer, provided that the pdb files are transformed to dumped +// format using a tool such as dump_syms, and given a .sym extension. +// +// SimpleSymbolSupplier will iterate over all root paths searching for +// a symbol file existing in that path. +// +// SimpleSymbolSupplier supports any debugging file which can be identified +// by a CodeModule object's debug_file and debug_identifier accessors. The +// expected ultimate source of these CodeModule objects are MinidumpModule +// objects; it is this class that is responsible for assigning appropriate +// values for debug_file and debug_identifier. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ +#define PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ + +#include +#include + +#include "google_breakpad/processor/symbol_supplier.h" + +namespace google_breakpad { + +using std::string; +using std::vector; + +class CodeModule; + +class SimpleSymbolSupplier : public SymbolSupplier { + public: + // Creates a new SimpleSymbolSupplier, using path as the root path where + // symbols are stored. + explicit SimpleSymbolSupplier(const string &path) : paths_(1, path) {} + + // Creates a new SimpleSymbolSupplier, using paths as a list of root + // paths where symbols may be stored. + explicit SimpleSymbolSupplier(const vector &paths) : paths_(paths) {} + + virtual ~SimpleSymbolSupplier() {} + + // Returns the path to the symbol file for the given module. See the + // description above. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data); + protected: + SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module, + const SystemInfo *system_info, + const string &root_path, + string *symbol_file); + + private: + vector paths_; +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stack_frame_info.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stack_frame_info.h new file mode 100644 index 00000000..052a9338 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stack_frame_info.h @@ -0,0 +1,126 @@ +// 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. + +// stack_frame_info.h: Holds debugging information about a stack frame. +// +// This structure is specific to Windows debugging information obtained +// from pdb files using the DIA API. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACK_FRAME_INFO_H__ +#define PROCESSOR_STACK_FRAME_INFO_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +struct StackFrameInfo { + public: + enum Validity { + VALID_NONE = 0, + VALID_PARAMETER_SIZE = 1, + VALID_ALL = -1 + }; + + StackFrameInfo() : valid(VALID_NONE), + prolog_size(0), + epilog_size(0), + parameter_size(0), + saved_register_size(0), + local_size(0), + max_stack_size(0), + allocates_base_pointer(0), + program_string() {} + + StackFrameInfo(u_int32_t set_prolog_size, + u_int32_t set_epilog_size, + u_int32_t set_parameter_size, + u_int32_t set_saved_register_size, + u_int32_t set_local_size, + u_int32_t set_max_stack_size, + int set_allocates_base_pointer, + const std::string set_program_string) + : valid(VALID_ALL), + prolog_size(set_prolog_size), + epilog_size(set_epilog_size), + parameter_size(set_parameter_size), + saved_register_size(set_saved_register_size), + local_size(set_local_size), + max_stack_size(set_max_stack_size), + allocates_base_pointer(set_allocates_base_pointer), + program_string(set_program_string) {} + + // CopyFrom makes "this" StackFrameInfo object identical to "that". + void CopyFrom(const StackFrameInfo &that) { + valid = that.valid; + prolog_size = that.prolog_size; + epilog_size = that.epilog_size; + parameter_size = that.parameter_size; + saved_register_size = that.saved_register_size; + local_size = that.local_size; + max_stack_size = that.max_stack_size; + allocates_base_pointer = that.allocates_base_pointer; + program_string = that.program_string; + } + + // Clears the StackFrameInfo object so that users will see it as though + // it contains no information. + void Clear() { + valid = VALID_NONE; + program_string.erase(); + } + + // Identifies which fields in the structure are valid. This is of + // type Validity, but it is defined as an int because it's not + // possible to OR values into an enumerated type. Users must check + // this field before using any other. + int valid; + + // These values come from IDiaFrameData. + u_int32_t prolog_size; + u_int32_t epilog_size; + u_int32_t parameter_size; + u_int32_t saved_register_size; + u_int32_t local_size; + u_int32_t max_stack_size; + + // Only one of allocates_base_pointer or program_string will be valid. + // If program_string is empty, use allocates_base_pointer. + bool allocates_base_pointer; + std::string program_string; +}; + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACK_FRAME_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_amd64.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_amd64.h new file mode 100644 index 00000000..a3e11358 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_amd64.h @@ -0,0 +1,80 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_amd64.h: amd64-specific stackwalker. +// +// Provides stack frames given amd64 register context and a memory region +// corresponding to a amd64 stack. +// +// Author: Mark Mentovai, Ted Mielczarek + + +#ifndef PROCESSOR_STACKWALKER_AMD64_H__ +#define PROCESSOR_STACKWALKER_AMD64_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerAMD64 : public Stackwalker { + public: + // context is a amd64 context object that gives access to amd64-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerAMD64(const SystemInfo *system_info, + const MDRawContextAMD64 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp, + // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp)) + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextAMD64 *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_AMD64_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_ppc.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_ppc.h new file mode 100644 index 00000000..3d312419 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_ppc.h @@ -0,0 +1,81 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_ppc.h: ppc-specific stackwalker. +// +// Provides stack frames given ppc register context and a memory region +// corresponding to a ppc stack. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACKWALKER_PPC_H__ +#define PROCESSOR_STACKWALKER_PPC_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerPPC : public Stackwalker { + public: + // context is a ppc context object that gives access to ppc-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerPPC(const SystemInfo *system_info, + const MDRawContextPPC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using ppc context (stack pointer in %r1, + // saved program counter in %srr0) and stack conventions (saved stack + // pointer at 0(%r1), return address at 8(0(%r1)). + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextPPC *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_PPC_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_sparc.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_sparc.h new file mode 100644 index 00000000..f051e5bb --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_sparc.h @@ -0,0 +1,86 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_sparc.h: sparc-specific stackwalker. +// +// Provides stack frames given sparc register context and a memory region +// corresponding to an sparc stack. +// +// Author: Michael Shang + + +#ifndef PROCESSOR_STACKWALKER_SPARC_H__ +#define PROCESSOR_STACKWALKER_SPARC_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerSPARC : public Stackwalker { + public: + // context is a sparc context object that gives access to sparc-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerSPARC(const SystemInfo *system_info, + const MDRawContextSPARC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and + // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or + // alternate conventions as guided by stack_frame_info_). + // Implementation of Stackwalker, using ppc context (stack pointer in %r1, + // saved program counter in %srr0) and stack conventions (saved stack + // pointer at 0(%r1), return address at 8(0(%r1)). + // Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and + // stack conventions (saved %sp at) + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextSPARC *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_SPARC_H__ diff --git a/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_x86.h b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_x86.h new file mode 100644 index 00000000..14b9e8b9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/include/google_breakpad/processor/stackwalker_x86.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_x86.h: x86-specific stackwalker. +// +// Provides stack frames given x86 register context and a memory region +// corresponding to an x86 stack. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACKWALKER_X86_H__ +#define PROCESSOR_STACKWALKER_X86_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + + +class StackwalkerX86 : public Stackwalker { + public: + // context is an x86 context object that gives access to x86-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerX86(const SystemInfo *system_info, + const MDRawContextX86 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and + // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or + // alternate conventions as guided by stack_frame_info_). + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextX86 *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_X86_H__ diff --git a/thirdparty/google-breakpad/r318/lib/macx/libbreakpad.a b/thirdparty/google-breakpad/r318/lib/macx/libbreakpad.a new file mode 100644 index 00000000..b8f80b2f Binary files /dev/null and b/thirdparty/google-breakpad/r318/lib/macx/libbreakpad.a differ diff --git a/thirdparty/google-breakpad/r318/lib/win32/breakpad.lib b/thirdparty/google-breakpad/r318/lib/win32/breakpad.lib new file mode 100644 index 00000000..6e6e82b3 Binary files /dev/null and b/thirdparty/google-breakpad/r318/lib/win32/breakpad.lib differ diff --git a/thirdparty/google-breakpad/r318/lib/win32/dbreakpad.lib b/thirdparty/google-breakpad/r318/lib/win32/dbreakpad.lib new file mode 100644 index 00000000..f09e1b9c Binary files /dev/null and b/thirdparty/google-breakpad/r318/lib/win32/dbreakpad.lib differ diff --git a/thirdparty/google-breakpad/r318/readme.txt b/thirdparty/google-breakpad/r318/readme.txt new file mode 100644 index 00000000..22e21517 --- /dev/null +++ b/thirdparty/google-breakpad/r318/readme.txt @@ -0,0 +1,9 @@ +To create the lib on Mac OS X: + +- qmake from r318 folder +- make install + +To create the lib on Windows: + +release.vc9.bat + diff --git a/thirdparty/google-breakpad/r318/release.vc9.bat b/thirdparty/google-breakpad/r318/release.vc9.bat new file mode 100644 index 00000000..f1d35f59 --- /dev/null +++ b/thirdparty/google-breakpad/r318/release.vc9.bat @@ -0,0 +1,17 @@ +set QT_BIN=C:\Qt\4.5.0\bin + +set VS_BIN="C:\Program Files\Microsoft Visual Studio 9.0\VC\bin" +set INNO_EXE="C:\Program Files\Inno Setup 5\iscc.exe " +set BUILD_DIR=".\build\win32\release" + +set PATH=%QT_BIN%;%PATH%; + +call %VS_BIN%\vcvars32.bat + +nmake clean + +rmdir /S /Q %BUILD_DIR% + +qmake + +nmake all diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/Makefile b/thirdparty/google-breakpad/r318/src/client/linux/handler/Makefile new file mode 100644 index 00000000..73be56d8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/Makefile @@ -0,0 +1,55 @@ +CXX=g++ +CC=gcc + +CXXFLAGS=-gstabs+ -I../../.. -Wall -D_REENTRANT +LDFLAGS=-lpthread + +OBJ_DIR=. +BIN_DIR=. + +THREAD_SRC=linux_thread.cc +SHARE_SRC=../../minidump_file_writer.cc\ + ../../../common/string_conversion.cc\ + ../../../common/linux/file_id.cc\ + minidump_generator.cc +HANDLER_SRC=exception_handler.cc\ + ../../../common/linux/guid_creator.cc +SHARE_C_SRC=../../../common/convert_UTF.c + +THREAD_TEST_SRC=linux_thread_test.cc +MINIDUMP_TEST_SRC=minidump_test.cc +EXCEPTION_TEST_SRC=exception_handler_test.cc + +THREAD_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(THREAD_SRC)) +SHARE_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(SHARE_SRC)) +HANDLER_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(HANDLER_SRC)) +SHARE_C_OBJ=$(patsubst %.c,$(OBJ_DIR)/%.o,$(SHARE_C_SRC)) md5.o +THREAD_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(THREAD_TEST_SRC))\ + $(THREAD_OBJ) +MINIDUMP_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(MINIDUMP_TEST_SRC))\ + $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) +EXCEPTION_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(EXCEPTION_TEST_SRC))\ + $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) $(HANDLER_OBJ) + +BIN=$(BIN_DIR)/minidump_test\ + $(BIN_DIR)/linux_thread_test\ + $(BIN_DIR)/exception_handler_test + +.PHONY:all clean + +all:$(BIN) + +$(BIN_DIR)/linux_thread_test:$(THREAD_TEST_OBJ) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ + +$(BIN_DIR)/minidump_test:$(MINIDUMP_TEST_OBJ) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ + +$(BIN_DIR)/exception_handler_test:$(EXCEPTION_TEST_OBJ) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ + +md5.o:../../../common/md5.c + $(CC) $(CXXFLAGS) -c $^ + +clean: + rm -f $(BIN) *.o *.dmp diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.cc new file mode 100644 index 00000000..26e09b7d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.cc @@ -0,0 +1,304 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include +#include +#include + +#include +#include +#include +#include + +#include "client/linux/handler/exception_handler.h" +#include "common/linux/guid_creator.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Signals that we are interested. +int SigTable[] = { +#if defined(SIGSEGV) + SIGSEGV, +#endif +#ifdef SIGABRT + SIGABRT, +#endif +#ifdef SIGFPE + SIGFPE, +#endif +#ifdef SIGILL + SIGILL, +#endif +#ifdef SIGBUS + SIGBUS, +#endif +}; + +std::vector *ExceptionHandler::handler_stack_ = NULL; +int ExceptionHandler::handler_stack_index_ = 0; +pthread_mutex_t ExceptionHandler::handler_stack_mutex_ = +PTHREAD_MUTEX_INITIALIZER; + +ExceptionHandler::ExceptionHandler(const string &dump_path, + FilterCallback filter, + MinidumpCallback callback, + void *callback_context, + bool install_handler) + : filter_(filter), + callback_(callback), + callback_context_(callback_context), + dump_path_(), + installed_handler_(install_handler) { + set_dump_path(dump_path); + + act_.sa_handler = HandleException; + act_.sa_flags = SA_ONSTACK; + sigemptyset(&act_.sa_mask); + // now, make sure we're blocking all the signals we are handling + // when we're handling any of them + for ( size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) { + sigaddset(&act_.sa_mask, SigTable[i]); + } + + if (install_handler) { + SetupHandler(); + pthread_mutex_lock(&handler_stack_mutex_); + if (handler_stack_ == NULL) + handler_stack_ = new std::vector; + handler_stack_->push_back(this); + pthread_mutex_unlock(&handler_stack_mutex_); + } +} + +ExceptionHandler::~ExceptionHandler() { + TeardownAllHandler(); + pthread_mutex_lock(&handler_stack_mutex_); + if (handler_stack_->back() == this) { + handler_stack_->pop_back(); + } else { + fprintf(stderr, "warning: removing Breakpad handler out of order\n"); + for (std::vector::iterator iterator = + handler_stack_->begin(); + iterator != handler_stack_->end(); + ++iterator) { + if (*iterator == this) { + handler_stack_->erase(iterator); + } + } + } + + if (handler_stack_->empty()) { + // When destroying the last ExceptionHandler that installed a handler, + // clean up the handler stack. + delete handler_stack_; + handler_stack_ = NULL; + } + pthread_mutex_unlock(&handler_stack_mutex_); +} + +bool ExceptionHandler::WriteMinidump() { + bool success = InternalWriteMinidump(0, 0, NULL); + UpdateNextID(); + return success; +} + +// static +bool ExceptionHandler::WriteMinidump(const string &dump_path, + MinidumpCallback callback, + void *callback_context) { + ExceptionHandler handler(dump_path, NULL, callback, + callback_context, false); + return handler.InternalWriteMinidump(0, 0, NULL); +} + +void ExceptionHandler::SetupHandler() { + // Signal on a different stack to avoid using the stack + // of the crashing thread. + struct sigaltstack sig_stack; + sig_stack.ss_sp = malloc(MINSIGSTKSZ); + if (sig_stack.ss_sp == NULL) + return; + sig_stack.ss_size = MINSIGSTKSZ; + sig_stack.ss_flags = 0; + + if (sigaltstack(&sig_stack, NULL) < 0) + return; + for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) + SetupHandler(SigTable[i]); +} + +void ExceptionHandler::SetupHandler(int signo) { + + // We're storing pointers to the old signal action + // structure, rather than copying the structure + // because we can't count on the sa_mask field to + // be scalar. + struct sigaction *old_act = &old_actions_[signo]; + + if (sigaction(signo, &act_, old_act) < 0) + return; +} + +void ExceptionHandler::TeardownHandler(int signo) { + TeardownHandler(signo, NULL); +} + +void ExceptionHandler::TeardownHandler(int signo, struct sigaction *final_handler) { + if (old_actions_[signo].sa_handler) { + struct sigaction *act = &old_actions_[signo]; + sigaction(signo, act, final_handler); + memset(&old_actions_[signo], 0x0, sizeof(struct sigaction)); + } +} + +void ExceptionHandler::TeardownAllHandler() { + for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) { + TeardownHandler(SigTable[i]); + } +} + +// static +void ExceptionHandler::HandleException(int signo) { + // In Linux, the context information about the signal is put on the stack of + // the signal handler frame as value parameter. For some reasons, the + // prototype of the handler doesn't declare this information as parameter, we + // will do it by hand. It is the second parameter above the signal number. + // However, if we are being called by another signal handler passing the + // signal up the chain, then we may not have this random extra parameter, + // so we may have to walk the stack to find it. We do the actual work + // on another thread, where it's a little safer, but we want the ebp + // from this frame to find it. + uintptr_t current_ebp = 0; + asm volatile ("movl %%ebp, %0" + :"=m"(current_ebp)); + + pthread_mutex_lock(&handler_stack_mutex_); + ExceptionHandler *current_handler = + handler_stack_->at(handler_stack_->size() - ++handler_stack_index_); + pthread_mutex_unlock(&handler_stack_mutex_); + + // Restore original handler. + struct sigaction old_action; + current_handler->TeardownHandler(signo, &old_action); + + struct sigcontext *sig_ctx = NULL; + if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) { + // Fully handled this exception, safe to exit. + exit(EXIT_FAILURE); + } else { + // Exception not fully handled, will call the next handler in stack to + // process it. + if (old_action.sa_handler != NULL && sig_ctx != NULL) { + + // Have our own typedef, because of the comment above w.r.t signal + // context on the stack + typedef void (*SignalHandler)(int signo, struct sigcontext); + + SignalHandler old_handler = + reinterpret_cast(old_action.sa_handler); + + sigset_t old_set; + // Use SIG_BLOCK here because we don't want to unblock a signal + // that the signal handler we're currently in needs to block + sigprocmask(SIG_BLOCK, &old_action.sa_mask, &old_set); + old_handler(signo, *sig_ctx); + sigprocmask(SIG_SETMASK, &old_set, NULL); + } + + } + + pthread_mutex_lock(&handler_stack_mutex_); + current_handler->SetupHandler(signo); + --handler_stack_index_; + // All the handlers in stack have been invoked to handle the exception, + // normally the process should be terminated and should not reach here. + // In case we got here, ask the OS to handle it to avoid endless loop, + // normally the OS will generate a core and termiate the process. This + // may be desired to debug the program. + if (handler_stack_index_ == 0) + signal(signo, SIG_DFL); + pthread_mutex_unlock(&handler_stack_mutex_); +} + +bool ExceptionHandler::InternalWriteMinidump(int signo, + uintptr_t sighandler_ebp, + struct sigcontext **sig_ctx) { + if (filter_ && !filter_(callback_context_)) + return false; + + bool success = false; + // Block all the signals we want to process when writting minidump. + // We don't want it to be interrupted. + sigset_t sig_blocked, sig_old; + bool blocked = true; + sigfillset(&sig_blocked); + for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) + sigdelset(&sig_blocked, SigTable[i]); + if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) { + blocked = false; + fprintf(stderr, "google_breakpad::ExceptionHandler::HandleException: " + "failed to block signals.\n"); + } + + success = minidump_generator_.WriteMinidumpToFile( + next_minidump_path_c_, signo, sighandler_ebp, sig_ctx); + + // Unblock the signals. + if (blocked) { + sigprocmask(SIG_SETMASK, &sig_old, NULL); + } + + if (callback_) + success = callback_(dump_path_c_, next_minidump_id_c_, + callback_context_, success); + return success; +} + +void ExceptionHandler::UpdateNextID() { + GUID guid; + char guid_str[kGUIDStringLength + 1]; + if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) { + next_minidump_id_ = guid_str; + next_minidump_id_c_ = next_minidump_id_.c_str(); + + char minidump_path[PATH_MAX]; + snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp", + dump_path_c_, + guid_str); + + next_minidump_path_ = minidump_path; + next_minidump_path_c_ = next_minidump_path_.c_str(); + } +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.h b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.h new file mode 100644 index 00000000..6ea09a11 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler.h @@ -0,0 +1,226 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ + +#include + +#include +#include +#include +#include + +#include "client/linux/handler/minidump_generator.h" + +// Context information when exception occured. +struct sigcontex; + +namespace google_breakpad { + +using std::string; + +// +// ExceptionHandler +// +// ExceptionHandler can write a minidump file when an exception occurs, +// or when WriteMinidump() is called explicitly by your program. +// +// To have the exception handler write minidumps when an uncaught exception +// (crash) occurs, you should create an instance early in the execution +// of your program, and keep it around for the entire time you want to +// have crash handling active (typically, until shutdown). +// (NOTE): There should be only be one this kind of exception handler +// object per process. +// +// If you want to write minidumps without installing the exception handler, +// you can create an ExceptionHandler with install_handler set to false, +// then call WriteMinidump. You can also use this technique if you want to +// use different minidump callbacks for different call sites. +// +// In either case, a callback function is called when a minidump is written, +// which receives the unqiue id of the minidump. The caller can use this +// id to collect and write additional application state, and to launch an +// external crash-reporting application. +// +// Caller should try to make the callbacks as crash-friendly as possible, +// it should avoid use heap memory allocation as much as possible. +// +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, + // Breakpad will immediately report the exception as unhandled without + // writing a minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void *context); + + // A callback function to run after the minidump has been written. + // minidump_id is a unique id for the dump, so the minidump + // file is \.dmp. context is the parameter supplied + // by the user as callback_context when the handler was created. succeeded + // indicates whether a minidump file was successfully written. + // + // If an exception occurred and the callback returns true, Breakpad will + // treat the exception as fully-handled, suppressing any other handlers from + // being notified of the exception. If the callback returns false, Breakpad + // will treat the exception as unhandled, and allow another handler to handle + // it. If there are no other handlers, Breakpad will report the exception to + // the system as unhandled, allowing a debugger or native crash dialog the + // opportunity to handle the exception. Most callback implementations + // should normally return the value of |succeeded|, or when they wish to + // not report an exception of handled, false. Callbacks will rarely want to + // return true directly (unless |succeeded| is true). + typedef bool (*MinidumpCallback)(const char *dump_path, + const char *minidump_id, + void *context, + bool succeeded); + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Before writing a minidump, the optional filter callback will be called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // If install_handler is true, then a minidump will be written whenever + // an unhandled exception occurs. If it is false, minidumps will only + // be written when WriteMinidump is called. + ExceptionHandler(const string &dump_path, + FilterCallback filter, MinidumpCallback callback, + void *callback_context, + bool install_handler); + ~ExceptionHandler(); + + // Get and set the minidump path. + string dump_path() const { return dump_path_; } + void set_dump_path(const string &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const string &dump_path, + MinidumpCallback callback, + void *callback_context); + + private: + // Setup crash handler. + void SetupHandler(); + // Setup signal handler for a signal. + void SetupHandler(int signo); + // Teardown the handler for a signal. + void TeardownHandler(int signo); + // Teardown the handler for a signal. + void TeardownHandler(int signo, struct sigaction *old); + // Teardown all handlers. + void TeardownAllHandler(); + + // Signal handler. + static void HandleException(int signo); + + // If called from a signal handler, sighandler_ebp is the ebp of + // that signal handler's frame, and sig_ctx is an out parameter + // that will be set to point at the sigcontext that was placed + // on the stack by the kernel. You can pass zero and NULL + // for the second and third parameters if you are not calling + // this from a signal handler. + bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp, + struct sigcontext **sig_ctx); + + // Generates a new ID and stores it in next_minidump_id, and stores the + // path of the next minidump to be written in next_minidump_path_. + void UpdateNextID(); + + private: + FilterCallback filter_; + MinidumpCallback callback_; + void *callback_context_; + + // The directory in which a minidump will be written, set by the dump_path + // argument to the constructor, or set_dump_path. + string dump_path_; + + // The basename of the next minidump to be written, without the extension + string next_minidump_id_; + + // The full pathname of the next minidump to be written, including the file + // extension + string next_minidump_path_; + + // Pointers to C-string representations of the above. These are set + // when the above are set so we can avoid calling c_str during + // an exception. + const char *dump_path_c_; + const char *next_minidump_id_c_; + const char *next_minidump_path_c_; + + // True if the ExceptionHandler installed an unhandled exception filter + // when created (with an install_handler parameter set to true). + bool installed_handler_; + + // The global exception handler stack. This is need becuase there may exist + // multiple ExceptionHandler instances in a process. Each will have itself + // registered in this stack. + static std::vector *handler_stack_; + // The index of the handler that should handle the next exception. + static int handler_stack_index_; + static pthread_mutex_t handler_stack_mutex_; + + // The minidump generator. + MinidumpGenerator minidump_generator_; + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); + + // The sigactions structure we use for each signal + struct sigaction act_; + + + // Keep the previous handlers for the signal. + // We're wasting a bit of memory here since we only change + // the handler for some signals but i want to avoid allocating + // memory in the signal handler + struct sigaction old_actions_[NSIG]; +}; + +} // namespace google_breakpad + +#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler_test.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler_test.cc new file mode 100644 index 00000000..2d94553d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/exception_handler_test.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include + +#include +#include +#include +#include + +#include "client/linux/handler/exception_handler.h" +#include "client/linux/handler/linux_thread.h" + +using namespace google_breakpad; + +// Thread use this to see if it should stop working. +static bool should_exit = false; + +static int foo2(int arg) { + // Stack variable, used for debugging stack dumps. + /*DDDebug*/printf("%s:%d\n", __FUNCTION__, __LINE__); + int c = 0xcccccccc; + fprintf(stderr, "Thread trying to crash: %x\n", getpid()); + c = *reinterpret_cast(0x5); + return c; +} + +static int foo(int arg) { + // Stack variable, used for debugging stack dumps. + int b = 0xbbbbbbbb; + b = foo2(b); + return b; +} + +static void *thread_crash(void *) { + // Stack variable, used for debugging stack dumps. + int a = 0xaaaaaaaa; + sleep(1); + a = foo(a); + printf("%x\n", a); + return NULL; +} + +static void *thread_main(void *) { + while (!should_exit) + sleep(1); + return NULL; +} + +static void CreateCrashThread() { + pthread_t h; + pthread_create(&h, NULL, thread_crash, NULL); + pthread_detach(h); +} + +// Create working threads. +static void CreateThread(int num) { + pthread_t h; + for (int i = 0; i < num; ++i) { + pthread_create(&h, NULL, thread_main, NULL); + pthread_detach(h); + } +} + +// Callback when minidump written. +static bool MinidumpCallback(const char *dump_path, + const char *minidump_id, + void *context, + bool succeeded) { + int index = reinterpret_cast(context); + printf("%d %s: %s is dumped\n", index, __FUNCTION__, minidump_id); + if (index == 0) { + should_exit = true; + return true; + } + // Don't process it. + return false; +} + +int main(int argc, char *argv[]) { + int handler_index = 0; + ExceptionHandler handler_ignore(".", NULL, MinidumpCallback, + (void*)handler_index, true); + ++handler_index; + ExceptionHandler handler_process(".", NULL, MinidumpCallback, + (void*)handler_index, true); + CreateCrashThread(); + CreateThread(10); + + while (true) + sleep(1); + should_exit = true; + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.cc new file mode 100644 index 00000000..c8ac4926 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.cc @@ -0,0 +1,411 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "client/linux/handler/linux_thread.h" + +using namespace google_breakpad; + +// This unamed namespace contains helper function. +namespace { + +// Context information for the callbacks when validating address by listing +// modules. +struct AddressValidatingContext { + uintptr_t address; + bool is_mapped; + + AddressValidatingContext() : address(0UL), is_mapped(false) { + } +}; + +// Convert from string to int. +bool LocalAtoi(char *s, int *r) { + assert(s != NULL); + assert(r != NULL); + char *endptr = NULL; + int ret = strtol(s, &endptr, 10); + if (endptr == s) + return false; + *r = ret; + return true; +} + +// Fill the proc path of a thread given its id. +void FillProcPath(int pid, char *path, int path_size) { + char pid_str[32]; + snprintf(pid_str, sizeof(pid_str), "%d", pid); + snprintf(path, path_size, "/proc/%s/", pid_str); +} + +// Read thread info from /proc/$pid/status. +bool ReadThreadInfo(int pid, ThreadInfo *info) { + assert(info != NULL); + char status_path[80]; + // Max size we want to read from status file. + static const int kStatusMaxSize = 1024; + char status_content[kStatusMaxSize]; + + FillProcPath(pid, status_path, sizeof(status_path)); + strcat(status_path, "status"); + int fd = open(status_path, O_RDONLY, 0); + if (fd < 0) + return false; + + int num_read = read(fd, status_content, kStatusMaxSize - 1); + if (num_read < 0) { + close(fd); + return false; + } + close(fd); + status_content[num_read] = '\0'; + + char *tgid_start = strstr(status_content, "Tgid:"); + if (tgid_start) + sscanf(tgid_start, "Tgid:\t%d\n", &(info->tgid)); + else + // tgid not supported by kernel?? + info->tgid = 0; + + tgid_start = strstr(status_content, "Pid:"); + if (tgid_start) { + sscanf(tgid_start, "Pid:\t%d\n" "PPid:\t%d\n", &(info->pid), + &(info->ppid)); + return true; + } + return false; +} + +// Callback invoked for each mapped module. +// It use the module's adderss range to validate the address. +bool IsAddressInModuleCallback(const ModuleInfo &module_info, + void *context) { + AddressValidatingContext *addr = + reinterpret_cast(context); + addr->is_mapped = ((addr->address >= module_info.start_addr) && + (addr->address <= module_info.start_addr + + module_info.size)); + return !addr->is_mapped; +} + +#if defined(__i386__) && !defined(NO_FRAME_POINTER) +void *GetNextFrame(void **last_ebp) { + void *sp = *last_ebp; + if ((unsigned long)sp == (unsigned long)last_ebp) + return NULL; + if ((unsigned long)sp & (sizeof(void *) - 1)) + return NULL; + if ((unsigned long)sp - (unsigned long)last_ebp > 100000) + return NULL; + return sp; +} +#else +void *GetNextFrame(void **last_ebp) { + return reinterpret_cast(last_ebp); +} +#endif + +// Suspend a thread by attaching to it. +bool SuspendThread(int pid, void *context) { + // This may fail if the thread has just died or debugged. + errno = 0; + if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 && + errno != 0) { + return false; + } + while (waitpid(pid, NULL, __WALL) < 0) { + if (errno != EINTR) { + ptrace(PTRACE_DETACH, pid, NULL, NULL); + return false; + } + } + return true; +} + +// Resume a thread by detaching from it. +bool ResumeThread(int pid, void *context) { + return ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0; +} + +// Callback to get the thread information. +// Will be called for each thread found. +bool ThreadInfoCallback(int pid, void *context) { + CallbackParam *thread_callback = + reinterpret_cast *>(context); + ThreadInfo thread_info; + if (ReadThreadInfo(pid, &thread_info) && thread_callback) { + // Invoke callback from caller. + return (thread_callback->call_back)(thread_info, thread_callback->context); + } + return false; +} + +} // namespace + +namespace google_breakpad { + +LinuxThread::LinuxThread(int pid) : pid_(pid) , threads_suspened_(false) { +} + +LinuxThread::~LinuxThread() { + if (threads_suspened_) + ResumeAllThreads(); +} + +int LinuxThread::SuspendAllThreads() { + CallbackParam callback_param(SuspendThread, NULL); + int thread_count = 0; + if ((thread_count = IterateProcSelfTask(pid_, &callback_param)) > 0) + threads_suspened_ = true; + return thread_count; +} + +void LinuxThread::ResumeAllThreads() const { + CallbackParam callback_param(ResumeThread, NULL); + IterateProcSelfTask(pid_, &callback_param); +} + +int LinuxThread::GetThreadCount() const { + return IterateProcSelfTask(pid_, NULL); +} + +int LinuxThread::ListThreads( + CallbackParam *thread_callback_param) const { + CallbackParam callback_param(ThreadInfoCallback, + thread_callback_param); + return IterateProcSelfTask(pid_, &callback_param); +} + +bool LinuxThread::GetRegisters(int pid, user_regs_struct *regs) const { + assert(regs); + return (regs != NULL && + (ptrace(PTRACE_GETREGS, pid, NULL, regs) == 0) && + errno == 0); +} + +// Get the floating-point registers of a thread. +// The caller must get the thread pid by ListThreads. +bool LinuxThread::GetFPRegisters(int pid, user_fpregs_struct *regs) const { + assert(regs); + return (regs != NULL && + (ptrace(PTRACE_GETREGS, pid, NULL, regs) ==0) && + errno == 0); +} + +bool LinuxThread::GetFPXRegisters(int pid, user_fpxregs_struct *regs) const { + assert(regs); + return (regs != NULL && + (ptrace(PTRACE_GETFPREGS, pid, NULL, regs) != 0) && + errno == 0); +} + +bool LinuxThread::GetDebugRegisters(int pid, DebugRegs *regs) const { + assert(regs); + +#define GET_DR(name, num)\ + name->dr##num = ptrace(PTRACE_PEEKUSER, pid,\ + offsetof(struct user, u_debugreg[num]), NULL) + GET_DR(regs, 0); + GET_DR(regs, 1); + GET_DR(regs, 2); + GET_DR(regs, 3); + GET_DR(regs, 4); + GET_DR(regs, 5); + GET_DR(regs, 6); + GET_DR(regs, 7); + return true; +} + +int LinuxThread::GetThreadStackDump(uintptr_t current_ebp, + uintptr_t current_esp, + void *buf, + int buf_size) const { + assert(buf); + assert(buf_size > 0); + + uintptr_t stack_bottom = GetThreadStackBottom(current_ebp); + int size = stack_bottom - current_esp; + size = buf_size > size ? size : buf_size; + if (size > 0) + memcpy(buf, reinterpret_cast(current_esp), size); + return size; +} + +// Get the stack bottom of a thread by stack walking. It works +// unless the stack has been corrupted or the frame pointer has been omited. +// This is just a temporary solution before we get better ideas about how +// this can be done. +// +// We will check each frame address by checking into module maps. +// TODO(liuli): Improve it. +uintptr_t LinuxThread::GetThreadStackBottom(uintptr_t current_ebp) const { + void **sp = reinterpret_cast(current_ebp); + void **previous_sp = sp; + while (sp && IsAddressMapped((uintptr_t)sp)) { + previous_sp = sp; + sp = reinterpret_cast(GetNextFrame(sp)); + } + return (uintptr_t)previous_sp; +} + +int LinuxThread::GetModuleCount() const { + return ListModules(NULL); +} + +int LinuxThread::ListModules( + CallbackParam *callback_param) const { + char line[512]; + const char *maps_path = "/proc/self/maps"; + + int module_count = 0; + FILE *fp = fopen(maps_path, "r"); + if (fp == NULL) + return -1; + + uintptr_t start_addr; + uintptr_t end_addr; + while (fgets(line, sizeof(line), fp) != NULL) { + if (sscanf(line, "%x-%x", &start_addr, &end_addr) == 2) { + ModuleInfo module; + memset(&module, 0, sizeof(module)); + module.start_addr = start_addr; + module.size = end_addr - start_addr; + char *name = NULL; + assert(module.size > 0); + // Only copy name if the name is a valid path name. + if ((name = strchr(line, '/')) != NULL) { + // Get rid of the last '\n' in line + char *last_return = strchr(line, '\n'); + if (last_return != NULL) + *last_return = '\0'; + // Keep a space for the ending 0. + strncpy(module.name, name, sizeof(module.name) - 1); + ++module_count; + } + if (callback_param && + !(callback_param->call_back(module, callback_param->context))) + break; + } + } + fclose(fp); + return module_count; +} + +// Parse /proc/$pid/tasks to list all the threads of the process identified by +// pid. +int LinuxThread::IterateProcSelfTask(int pid, + CallbackParam *callback_param) const { + char task_path[80]; + FillProcPath(pid, task_path, sizeof(task_path)); + strcat(task_path, "task"); + + DIR *dir = opendir(task_path); + if (dir == NULL) + return -1; + + int pid_number = 0; + // Record the last pid we've found. This is used for duplicated thread + // removal. Duplicated thread information can be found in /proc/$pid/tasks. + int last_pid = -1; + struct dirent *entry = NULL; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") && + strcmp(entry->d_name, "..")) { + int tpid = 0; + if (LocalAtoi(entry->d_name, &tpid) && + last_pid != tpid) { + last_pid = tpid; + ++pid_number; + // Invoke the callback. + if (callback_param && + !(callback_param->call_back)(tpid, callback_param->context)) + break; + } + } + } + closedir(dir); + return pid_number; +} + +// Check if the address is a valid virtual address. +// If the address is in any of the mapped modules, we take it as valid. +// Otherwise it is invalid. +bool LinuxThread::IsAddressMapped(uintptr_t address) const { + AddressValidatingContext addr; + addr.address = address; + CallbackParam callback_param(IsAddressInModuleCallback, + &addr); + ListModules(&callback_param); + return addr.is_mapped; +} + +bool LinuxThread::FindSigContext(uintptr_t sighandler_ebp, + struct sigcontext **sig_ctx) { + uintptr_t previous_ebp; + const int MAX_STACK_DEPTH = 10; + int depth_counter = 0; + + do { + // We're looking for a |struct sigcontext| as the second parameter + // to a signal handler function call. Luckily, the sigcontext + // has an ebp member which should match the ebp pointed to + // by the ebp of the signal handler frame. + previous_ebp = reinterpret_cast(GetNextFrame( + reinterpret_cast(sighandler_ebp))); + // The stack looks like this: + // | previous ebp | previous eip | first param | second param |, + // so we need to offset by 3 to get to the second parameter. + *sig_ctx = reinterpret_cast(sighandler_ebp + + 3 * sizeof(uintptr_t)); + sighandler_ebp = previous_ebp; + depth_counter++; + } while(previous_ebp != (*sig_ctx)->ebp && sighandler_ebp != 0 && + IsAddressMapped(sighandler_ebp) && depth_counter < MAX_STACK_DEPTH); + + return previous_ebp == (*sig_ctx)->ebp && previous_ebp != 0; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.h b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.h new file mode 100644 index 00000000..f738c2e0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread.h @@ -0,0 +1,204 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#ifndef CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ +#define CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ + +#include +#include + +namespace google_breakpad { + +// Max module path name length. +#define kMaxModuleNameLength 256 + +// Holding information about a thread in the process. +struct ThreadInfo { + // Id of the thread group. + int tgid; + // Id of the thread. + int pid; + // Id of the parent process. + int ppid; +}; + +// Holding infomaton about a module in the process. +struct ModuleInfo { + char name[kMaxModuleNameLength]; + uintptr_t start_addr; + int size; +}; + +// Holding debug registers. +struct DebugRegs { + int dr0; + int dr1; + int dr2; + int dr3; + int dr4; + int dr5; + int dr6; + int dr7; +}; + +// A callback to run when got a thread in the process. +// Return true will go on to the next thread while return false will stop the +// iteration. +typedef bool (*ThreadCallback)(const ThreadInfo &thread_info, void *context); + +// A callback to run when a new module is found in the process. +// Return true will go on to the next module while return false will stop the +// iteration. +typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context); + +// Holding the callback information. +template +struct CallbackParam { + // Callback function address. + CallbackFunc call_back; + // Callback context; + void *context; + + CallbackParam() : call_back(NULL), context(NULL) { + } + + CallbackParam(CallbackFunc func, void *func_context) : + call_back(func), context(func_context) { + } +}; + +/////////////////////////////////////////////////////////////////////////////// + +// +// LinuxThread +// +// Provides handy support for operation on linux threads. +// It uses ptrace to get thread registers. Since ptrace only works in a +// different process other than the one being ptraced, user of this class +// should create another process before using the class. +// +// The process should be created in the following way: +// int cloned_pid = clone(ProcessEntryFunction, stack_address, +// CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, +// (void*)&arguments); +// waitpid(cloned_pid, NULL, __WALL); +// +// If CLONE_VM is not used, GetThreadStackBottom, GetThreadStackDump +// will not work since it just use memcpy to get the stack dump. +// +class LinuxThread { + public: + // Create a LinuxThread instance to list all the threads in a process. + explicit LinuxThread(int pid); + ~LinuxThread(); + + // Stop all the threads in the process. + // Return the number of stopped threads in the process. + // Return -1 means failed to stop threads. + int SuspendAllThreads(); + + // Resume all the suspended threads. + void ResumeAllThreads() const; + + // Get the count of threads in the process. + // Return -1 means error. + int GetThreadCount() const; + + // List the threads of process. + // Whenever there is a thread found, the callback will be invoked to process + // the information. + // Return number of threads listed. + int ListThreads(CallbackParam *thread_callback_param) const; + + // Get the general purpose registers of a thread. + // The caller must get the thread pid by ListThreads. + bool GetRegisters(int pid, user_regs_struct *regs) const; + + // Get the floating-point registers of a thread. + // The caller must get the thread pid by ListThreads. + bool GetFPRegisters(int pid, user_fpregs_struct *regs) const; + + // Get all the extended floating-point registers. May not work on all + // machines. + // The caller must get the thread pid by ListThreads. + bool GetFPXRegisters(int pid, user_fpxregs_struct *regs) const; + + // Get the debug registers. + // The caller must get the thread pid by ListThreads. + bool GetDebugRegisters(int pid, DebugRegs *regs) const; + + // Get the stack memory dump. + int GetThreadStackDump(uintptr_t current_ebp, + uintptr_t current_esp, + void *buf, + int buf_size) const; + + // Get the module count of the current process. + int GetModuleCount() const; + + // Get the mapped modules in the address space. + // Whenever a module is found, the callback will be invoked to process the + // information. + // Return how may modules are found. + int ListModules(CallbackParam *callback_param) const; + + // Get the bottom of the stack from ebp. + uintptr_t GetThreadStackBottom(uintptr_t current_ebp) const; + + // Finds a sigcontext on the stack given the ebp of our signal handler. + bool FindSigContext(uintptr_t sighandler_ebp, struct sigcontext **sig_ctx); + + private: + // This callback will run when a new thread has been found. + typedef bool (*PidCallback)(int pid, void *context); + + // Read thread information from /proc/$pid/task. + // Whenever a thread has been found, and callback will be invoked with + // the pid of the thread. + // Return number of threads found. + // Return -1 means the directory doesn't exist. + int IterateProcSelfTask(int pid, + CallbackParam *callback_param) const; + + // Check if the address is a valid virtual address. + bool IsAddressMapped(uintptr_t address) const; + + private: + // The pid of the process we are listing threads. + int pid_; + + // Mark if we have suspended the threads. + bool threads_suspened_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread_test.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread_test.cc new file mode 100644 index 00000000..aeb5e64c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/linux_thread_test.cc @@ -0,0 +1,224 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include +#include +#include + +#include +#include +#include + +#include "client/linux/handler/linux_thread.h" + +using namespace google_breakpad; + +// Thread use this to see if it should stop working. +static bool should_exit = false; + +static void foo2(int *a) { + // Stack variable, used for debugging stack dumps. + int c = 0xcccccccc; + c = c; + while (!should_exit) + sleep(1); +} + +static void foo() { + // Stack variable, used for debugging stack dumps. + int a = 0xaaaaaaaa; + foo2(&a); +} + +static void *thread_main(void *) { + // Stack variable, used for debugging stack dumps. + int b = 0xbbbbbbbb; + b = b; + while (!should_exit) { + foo(); + } + return NULL; +} + +static void CreateThreads(int num) { + pthread_t handle; + for (int i = 0; i < num; i++) { + if (0 != pthread_create(&handle, NULL, thread_main, NULL)) + fprintf(stderr, "Failed to create thread.\n"); + else + pthread_detach(handle); + } +} + +static bool ProcessOneModule(const struct ModuleInfo &module_info, + void *context) { + printf("0x%x[%8d] %s\n", module_info.start_addr, module_info.size, + module_info.name); + return true; +} + +static bool ProcessOneThread(const struct ThreadInfo &thread_info, + void *context) { + printf("\n\nPID: %d, TGID: %d, PPID: %d\n", + thread_info.pid, + thread_info.tgid, + thread_info.ppid); + + struct user_regs_struct regs; + struct user_fpregs_struct fp_regs; + struct user_fpxregs_struct fpx_regs; + struct DebugRegs dbg_regs; + + LinuxThread *threads = reinterpret_cast(context); + memset(®s, 0, sizeof(regs)); + if (threads->GetRegisters(thread_info.pid, ®s)) { + printf(" gs = 0x%lx\n", regs.xgs); + printf(" fs = 0x%lx\n", regs.xfs); + printf(" es = 0x%lx\n", regs.xes); + printf(" ds = 0x%lx\n", regs.xds); + printf(" edi = 0x%lx\n", regs.edi); + printf(" esi = 0x%lx\n", regs.esi); + printf(" ebx = 0x%lx\n", regs.ebx); + printf(" edx = 0x%lx\n", regs.edx); + printf(" ecx = 0x%lx\n", regs.ecx); + printf(" eax = 0x%lx\n", regs.eax); + printf(" ebp = 0x%lx\n", regs.ebp); + printf(" eip = 0x%lx\n", regs.eip); + printf(" cs = 0x%lx\n", regs.xcs); + printf(" eflags = 0x%lx\n", regs.eflags); + printf(" esp = 0x%lx\n", regs.esp); + printf(" ss = 0x%lx\n", regs.xss); + } else { + fprintf(stderr, "ERROR: Failed to get general purpose registers\n"); + } + memset(&fp_regs, 0, sizeof(fp_regs)); + if (threads->GetFPRegisters(thread_info.pid, &fp_regs)) { + printf("\n Floating point registers:\n"); + printf(" fctl = 0x%lx\n", fp_regs.cwd); + printf(" fstat = 0x%lx\n", fp_regs.swd); + printf(" ftag = 0x%lx\n", fp_regs.twd); + printf(" fioff = 0x%lx\n", fp_regs.fip); + printf(" fiseg = 0x%lx\n", fp_regs.fcs); + printf(" fooff = 0x%lx\n", fp_regs.foo); + printf(" foseg = 0x%lx\n", fp_regs.fos); + int st_space_size = sizeof(fp_regs.st_space) / sizeof(fp_regs.st_space[0]); + printf(" st_space[%2d] = 0x", st_space_size); + for (int i = 0; i < st_space_size; ++i) + printf("%02lx", fp_regs.st_space[i]); + printf("\n"); + } else { + fprintf(stderr, "ERROR: Failed to get floating-point registers\n"); + } + memset(&fpx_regs, 0, sizeof(fpx_regs)); + if (threads->GetFPXRegisters(thread_info.pid, &fpx_regs)) { + printf("\n Extended floating point registers:\n"); + printf(" fctl = 0x%x\n", fpx_regs.cwd); + printf(" fstat = 0x%x\n", fpx_regs.swd); + printf(" ftag = 0x%x\n", fpx_regs.twd); + printf(" fioff = 0x%lx\n", fpx_regs.fip); + printf(" fiseg = 0x%lx\n", fpx_regs.fcs); + printf(" fooff = 0x%lx\n", fpx_regs.foo); + printf(" foseg = 0x%lx\n", fpx_regs.fos); + printf(" fop = 0x%x\n", fpx_regs.fop); + printf(" mxcsr = 0x%lx\n", fpx_regs.mxcsr); + int space_size = sizeof(fpx_regs.st_space) / sizeof(fpx_regs.st_space[0]); + printf(" st_space[%2d] = 0x", space_size); + for (int i = 0; i < space_size; ++i) + printf("%02lx", fpx_regs.st_space[i]); + printf("\n"); + space_size = sizeof(fpx_regs.xmm_space) / sizeof(fpx_regs.xmm_space[0]); + printf(" xmm_space[%2d] = 0x", space_size); + for (int i = 0; i < space_size; ++i) + printf("%02lx", fpx_regs.xmm_space[i]); + printf("\n"); + } + if (threads->GetDebugRegisters(thread_info.pid, &dbg_regs)) { + printf("\n Debug registers:\n"); + printf(" dr0 = 0x%x\n", dbg_regs.dr0); + printf(" dr1 = 0x%x\n", dbg_regs.dr1); + printf(" dr2 = 0x%x\n", dbg_regs.dr2); + printf(" dr3 = 0x%x\n", dbg_regs.dr3); + printf(" dr4 = 0x%x\n", dbg_regs.dr4); + printf(" dr5 = 0x%x\n", dbg_regs.dr5); + printf(" dr6 = 0x%x\n", dbg_regs.dr6); + printf(" dr7 = 0x%x\n", dbg_regs.dr7); + printf("\n"); + } + if (regs.esp != 0) { + // Print the stack content. + int size = 1024 * 2; + char *buf = new char[size]; + size = threads->GetThreadStackDump(regs.ebp, + regs.esp, + (void*)buf, size); + printf(" Stack content: = 0x"); + size /= sizeof(unsigned long); + unsigned long *p_buf = (unsigned long *)(buf); + for (int i = 0; i < size; i += 1) + printf("%.8lx ", p_buf[i]); + delete []buf; + printf("\n"); + } + return true; +} + +static int PrintAllThreads(void *argument) { + int pid = (int)argument; + + LinuxThread threads(pid); + int total_thread = threads.SuspendAllThreads(); + printf("There are %d threads in the process: %d\n", total_thread, pid); + int total_module = threads.GetModuleCount(); + printf("There are %d modules in the process: %d\n", total_module, pid); + CallbackParam module_callback(ProcessOneModule, &threads); + threads.ListModules(&module_callback); + CallbackParam thread_callback(ProcessOneThread, &threads); + threads.ListThreads(&thread_callback); + return 0; +} + +int main(int argc, char **argv) { + int pid = getpid(); + printf("Main thread is %d\n", pid); + CreateThreads(1); + // Create stack for the process. + char *stack = new char[1024 * 100]; + int cloned_pid = clone(PrintAllThreads, stack + 1024 * 100, + CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, + (void*)getpid()); + waitpid(cloned_pid, NULL, __WALL); + should_exit = true; + printf("Test finished.\n"); + + delete []stack; + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.cc new file mode 100644 index 00000000..bc4d213a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.cc @@ -0,0 +1,815 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/linux/file_id.h" +#include "client/linux/handler/linux_thread.h" +#include "client/minidump_file_writer.h" +#include "client/minidump_file_writer-inl.h" +#include "google_breakpad/common/minidump_format.h" +#include "client/linux/handler/minidump_generator.h" + +#ifndef CLONE_UNTRACED +#define CLONE_UNTRACED 0x00800000 +#endif + +// This unnamed namespace contains helper functions. +namespace { + +using namespace google_breakpad; + +// Argument for the writer function. +struct WriterArgument { + MinidumpFileWriter *minidump_writer; + + // Context for the callback. + void *version_context; + + // Pid of the thread who called WriteMinidumpToFile + int requester_pid; + + // The stack bottom of the thread which caused the dump. + // Mainly used to find the thread id of the crashed thread since signal + // handler may not be called in the thread who caused it. + uintptr_t crashed_stack_bottom; + + // Pid of the crashing thread. + int crashed_pid; + + // Signal number when crash happed. Can be 0 if this is a requested dump. + int signo; + + // The ebp of the signal handler frame. Can be zero if this + // is a requested dump. + uintptr_t sighandler_ebp; + + // Signal context when crash happed. Can be NULL if this is a requested dump. + // This is actually an out parameter, but it will be filled in at the start + // of the writer thread. + struct sigcontext *sig_ctx; + + // Used to get information about the threads. + LinuxThread *thread_lister; +}; + +// Holding context information for the callback of finding the crashing thread. +struct FindCrashThreadContext { + const LinuxThread *thread_lister; + uintptr_t crashing_stack_bottom; + int crashing_thread_pid; + + FindCrashThreadContext() : + thread_lister(NULL), + crashing_stack_bottom(0UL), + crashing_thread_pid(-1) { + } +}; + +// Callback for list threads. +// It will compare the stack bottom of the provided thread with the stack +// bottom of the crashed thread, it they are eqaul, this is thread is the one +// who crashed. +bool IsThreadCrashedCallback(const ThreadInfo &thread_info, void *context) { + FindCrashThreadContext *crashing_context = + static_cast(context); + const LinuxThread *thread_lister = crashing_context->thread_lister; + struct user_regs_struct regs; + if (thread_lister->GetRegisters(thread_info.pid, ®s)) { + uintptr_t last_ebp = regs.ebp; + uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp); + if (stack_bottom > last_ebp && + stack_bottom == crashing_context->crashing_stack_bottom) { + // Got it. Stop iteration. + crashing_context->crashing_thread_pid = thread_info.pid; + return false; + } + } + return true; +} + +// Find the crashing thread id. +// This is done based on stack bottom comparing. +int FindCrashingThread(uintptr_t crashing_stack_bottom, + int requester_pid, + const LinuxThread *thread_lister) { + FindCrashThreadContext context; + context.thread_lister = thread_lister; + context.crashing_stack_bottom = crashing_stack_bottom; + CallbackParam callback_param(IsThreadCrashedCallback, + &context); + thread_lister->ListThreads(&callback_param); + return context.crashing_thread_pid; +} + +// Write the thread stack info minidump. +bool WriteThreadStack(uintptr_t last_ebp, + uintptr_t last_esp, + const LinuxThread *thread_lister, + UntypedMDRVA *memory, + MDMemoryDescriptor *loc) { + // Maximum stack size for a thread. + uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp); + if (stack_bottom > last_esp) { + int size = stack_bottom - last_esp; + if (size > 0) { + if (!memory->Allocate(size)) + return false; + memory->Copy(reinterpret_cast(last_esp), size); + loc->start_of_memory_range = 0 | last_esp; + loc->memory = memory->location(); + } + return true; + } + return false; +} + +// Write CPU context based on signal context. +bool WriteContext(MDRawContextX86 *context, const struct sigcontext *sig_ctx, + const DebugRegs *debug_regs) { + assert(sig_ctx != NULL); + context->context_flags = MD_CONTEXT_X86_FULL; + context->gs = sig_ctx->gs; + context->fs = sig_ctx->fs; + context->es = sig_ctx->es; + context->ds = sig_ctx->ds; + context->cs = sig_ctx->cs; + context->ss = sig_ctx->ss; + context->edi = sig_ctx->edi; + context->esi = sig_ctx->esi; + context->ebp = sig_ctx->ebp; + context->esp = sig_ctx->esp; + context->ebx = sig_ctx->ebx; + context->edx = sig_ctx->edx; + context->ecx = sig_ctx->ecx; + context->eax = sig_ctx->eax; + context->eip = sig_ctx->eip; + context->eflags = sig_ctx->eflags; + if (sig_ctx->fpstate != NULL) { + context->context_flags = MD_CONTEXT_X86_FULL | + MD_CONTEXT_X86_FLOATING_POINT; + context->float_save.control_word = sig_ctx->fpstate->cw; + context->float_save.status_word = sig_ctx->fpstate->sw; + context->float_save.tag_word = sig_ctx->fpstate->tag; + context->float_save.error_offset = sig_ctx->fpstate->ipoff; + context->float_save.error_selector = sig_ctx->fpstate->cssel; + context->float_save.data_offset = sig_ctx->fpstate->dataoff; + context->float_save.data_selector = sig_ctx->fpstate->datasel; + memcpy(context->float_save.register_area, sig_ctx->fpstate->_st, + sizeof(context->float_save.register_area)); + } + + if (debug_regs != NULL) { + context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS; + context->dr0 = debug_regs->dr0; + context->dr1 = debug_regs->dr1; + context->dr2 = debug_regs->dr2; + context->dr3 = debug_regs->dr3; + context->dr6 = debug_regs->dr6; + context->dr7 = debug_regs->dr7; + } + return true; +} + +// Write CPU context based on provided registers. +bool WriteContext(MDRawContextX86 *context, + const struct user_regs_struct *regs, + const struct user_fpregs_struct *fp_regs, + const DebugRegs *dbg_regs) { + if (!context || !regs) + return false; + + context->context_flags = MD_CONTEXT_X86_FULL; + + context->cs = regs->xcs; + context->ds = regs->xds; + context->es = regs->xes; + context->fs = regs->xfs; + context->gs = regs->xgs; + context->ss = regs->xss; + context->edi = regs->edi; + context->esi = regs->esi; + context->ebx = regs->ebx; + context->edx = regs->edx; + context->ecx = regs->ecx; + context->eax = regs->eax; + context->ebp = regs->ebp; + context->eip = regs->eip; + context->esp = regs->esp; + context->eflags = regs->eflags; + + if (dbg_regs != NULL) { + context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS; + context->dr0 = dbg_regs->dr0; + context->dr1 = dbg_regs->dr1; + context->dr2 = dbg_regs->dr2; + context->dr3 = dbg_regs->dr3; + context->dr6 = dbg_regs->dr6; + context->dr7 = dbg_regs->dr7; + } + + if (fp_regs != NULL) { + context->context_flags |= MD_CONTEXT_X86_FLOATING_POINT; + context->float_save.control_word = fp_regs->cwd; + context->float_save.status_word = fp_regs->swd; + context->float_save.tag_word = fp_regs->twd; + context->float_save.error_offset = fp_regs->fip; + context->float_save.error_selector = fp_regs->fcs; + context->float_save.data_offset = fp_regs->foo; + context->float_save.data_selector = fp_regs->fos; + context->float_save.data_selector = fp_regs->fos; + + memcpy(context->float_save.register_area, fp_regs->st_space, + sizeof(context->float_save.register_area)); + } + return true; +} + +// Write information about a crashed thread. +// When a thread crash, kernel will write something on the stack for processing +// signal. This makes the current stack not reliable, and our stack walker +// won't figure out the whole call stack for this. So we write the stack at the +// time of the crash into the minidump file, not the current stack. +bool WriteCrashedThreadStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + const ThreadInfo &thread_info, + MDRawThread *thread) { + assert(writer_args->sig_ctx != NULL); + + thread->thread_id = thread_info.pid; + + UntypedMDRVA memory(minidump_writer); + if (!WriteThreadStack(writer_args->sig_ctx->ebp, + writer_args->sig_ctx->esp, + writer_args->thread_lister, + &memory, + &thread->stack)) + return false; + + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + thread->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); + return WriteContext(context.get(), writer_args->sig_ctx, NULL); +} + +// Write information about a thread. +// This function only processes thread running normally at the crash. +bool WriteThreadStream(MinidumpFileWriter *minidump_writer, + const LinuxThread *thread_lister, + const ThreadInfo &thread_info, + MDRawThread *thread) { + thread->thread_id = thread_info.pid; + + struct user_regs_struct regs; + memset(®s, 0, sizeof(regs)); + if (!thread_lister->GetRegisters(thread_info.pid, ®s)) { + perror(NULL); + return false; + } + + UntypedMDRVA memory(minidump_writer); + if (!WriteThreadStack(regs.ebp, + regs.esp, + thread_lister, + &memory, + &thread->stack)) + return false; + + struct user_fpregs_struct fp_regs; + DebugRegs dbg_regs; + memset(&fp_regs, 0, sizeof(fp_regs)); + // Get all the registers. + thread_lister->GetFPRegisters(thread_info.pid, &fp_regs); + thread_lister->GetDebugRegisters(thread_info.pid, &dbg_regs); + + // Write context + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + thread->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); + return WriteContext(context.get(), ®s, &fp_regs, &dbg_regs); +} + +bool WriteCPUInformation(MDRawSystemInfo *sys_info) { + const char *proc_cpu_path = "/proc/cpuinfo"; + char line[128]; + char vendor_id[13]; + const char vendor_id_name[] = "vendor_id"; + const size_t vendor_id_name_length = sizeof(vendor_id_name) - 1; + + struct CpuInfoEntry { + const char *info_name; + int value; + } cpu_info_table[] = { + { "processor", -1 }, + { "model", 0 }, + { "stepping", 0 }, + { "cpuid level", 0 }, + { NULL, -1 }, + }; + + memset(vendor_id, 0, sizeof(vendor_id)); + + FILE *fp = fopen(proc_cpu_path, "r"); + if (fp != NULL) { + while (fgets(line, sizeof(line), fp)) { + CpuInfoEntry *entry = &cpu_info_table[0]; + while (entry->info_name != NULL) { + if (!strncmp(line, entry->info_name, strlen(entry->info_name))) { + char *value = strchr(line, ':'); + value++; + if (value != NULL) + sscanf(value, " %d", &(entry->value)); + } + entry++; + } + + // special case for vendor_id + if (!strncmp(line, vendor_id_name, vendor_id_name_length)) { + char *value = strchr(line, ':'); + if (value == NULL) + continue; + + value++; + while (*value && isspace(*value)) + value++; + if (*value) { + size_t length = strlen(value); + // we don't want the trailing newline + if (value[length - 1] == '\n') + length--; + // ensure we have space for the value + if (length < sizeof(vendor_id)) + strncpy(vendor_id, value, length); + } + } + } + fclose(fp); + } + + // /proc/cpuinfo contains cpu id, change it into number by adding one. + cpu_info_table[0].value++; + + sys_info->number_of_processors = cpu_info_table[0].value; + sys_info->processor_level = cpu_info_table[3].value; + sys_info->processor_revision = cpu_info_table[1].value << 8 | + cpu_info_table[2].value; + + sys_info->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; + struct utsname uts; + if (uname(&uts) == 0) { + // Match i*86 and x86* as X86 architecture. + if ((strstr(uts.machine, "x86") == uts.machine) || + (strlen(uts.machine) == 4 && + uts.machine[0] == 'i' && + uts.machine[2] == '8' && + uts.machine[3] == '6')) { + sys_info->processor_architecture = MD_CPU_ARCHITECTURE_X86; + if (vendor_id[0] != '\0') + memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id, + sizeof(sys_info->cpu.x86_cpu_info.vendor_id)); + } + } + return true; +} + +bool WriteOSInformation(MinidumpFileWriter *minidump_writer, + MDRawSystemInfo *sys_info) { + sys_info->platform_id = MD_OS_LINUX; + + struct utsname uts; + if (uname(&uts) == 0) { + char os_version[512]; + size_t space_left = sizeof(os_version); + memset(os_version, 0, space_left); + const char *os_info_table[] = { + uts.sysname, + uts.release, + uts.version, + uts.machine, + "GNU/Linux", + NULL + }; + for (const char **cur_os_info = os_info_table; + *cur_os_info != NULL; + cur_os_info++) { + if (cur_os_info != os_info_table && space_left > 1) { + strcat(os_version, " "); + space_left--; + } + if (space_left > strlen(*cur_os_info)) { + strcat(os_version, *cur_os_info); + space_left -= strlen(*cur_os_info); + } else { + break; + } + } + + MDLocationDescriptor location; + if (!minidump_writer->WriteString(os_version, 0, &location)) + return false; + sys_info->csd_version_rva = location.rva; + } + return true; +} + +// Callback context for get writting thread information. +struct ThreadInfoCallbackCtx { + MinidumpFileWriter *minidump_writer; + const WriterArgument *writer_args; + TypedMDRVA *list; + int thread_index; +}; + +// Callback run for writing threads information in the process. +bool ThreadInfomationCallback(const ThreadInfo &thread_info, + void *context) { + ThreadInfoCallbackCtx *callback_context = + static_cast(context); + bool success = true; + MDRawThread thread; + memset(&thread, 0, sizeof(MDRawThread)); + if (thread_info.pid != callback_context->writer_args->crashed_pid || + callback_context->writer_args->sig_ctx == NULL) { + success = WriteThreadStream(callback_context->minidump_writer, + callback_context->writer_args->thread_lister, + thread_info, &thread); + } else { + success = WriteCrashedThreadStream(callback_context->minidump_writer, + callback_context->writer_args, + thread_info, &thread); + } + if (success) { + callback_context->list->CopyIndexAfterObject( + callback_context->thread_index++, + &thread, sizeof(MDRawThread)); + } + return success; +} + +// Stream writers +bool WriteThreadListStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + // Get the thread information. + const LinuxThread *thread_lister = writer_args->thread_lister; + int thread_count = thread_lister->GetThreadCount(); + if (thread_count < 0) + return false; + TypedMDRVA list(minidump_writer); + if (!list.AllocateObjectAndArray(thread_count, sizeof(MDRawThread))) + return false; + dir->stream_type = MD_THREAD_LIST_STREAM; + dir->location = list.location(); + list.get()->number_of_threads = thread_count; + + ThreadInfoCallbackCtx context; + context.minidump_writer = minidump_writer; + context.writer_args = writer_args; + context.list = &list; + context.thread_index = 0; + CallbackParam callback_param(ThreadInfomationCallback, + &context); + int written = thread_lister->ListThreads(&callback_param); + return written == thread_count; +} + +bool WriteCVRecord(MinidumpFileWriter *minidump_writer, + MDRawModule *module, + const char *module_path) { + TypedMDRVA cv(minidump_writer); + + // Only return the last path component of the full module path + const char *module_name = strrchr(module_path, '/'); + // Increment past the slash + if (module_name) + ++module_name; + else + module_name = ""; + + size_t module_name_length = strlen(module_name); + if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t))) + return false; + if (!cv.CopyIndexAfterObject(0, const_cast(module_name), + module_name_length)) + return false; + + module->cv_record = cv.location(); + MDCVInfoPDB70 *cv_ptr = cv.get(); + memset(cv_ptr, 0, sizeof(MDCVInfoPDB70)); + cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE; + cv_ptr->age = 0; + + // Get the module identifier + FileID file_id(module_path); + unsigned char identifier[16]; + + if (file_id.ElfFileIdentifier(identifier)) { + cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 | + (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 | + (uint32_t)identifier[3]; + cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5]; + cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7]; + cv_ptr->signature.data4[0] = identifier[8]; + cv_ptr->signature.data4[1] = identifier[9]; + cv_ptr->signature.data4[2] = identifier[10]; + cv_ptr->signature.data4[3] = identifier[11]; + cv_ptr->signature.data4[4] = identifier[12]; + cv_ptr->signature.data4[5] = identifier[13]; + cv_ptr->signature.data4[6] = identifier[14]; + cv_ptr->signature.data4[7] = identifier[15]; + } + return true; +} + +struct ModuleInfoCallbackCtx { + MinidumpFileWriter *minidump_writer; + const WriterArgument *writer_args; + TypedMDRVA *list; + int module_index; +}; + +bool ModuleInfoCallback(const ModuleInfo &module_info, + void *context) { + ModuleInfoCallbackCtx *callback_context = + static_cast(context); + // Skip those modules without name, or those that are not modules. + if (strlen(module_info.name) == 0 || + !strchr(module_info.name, '/')) + return true; + + MDRawModule module; + memset(&module, 0, sizeof(module)); + MDLocationDescriptor loc; + if (!callback_context->minidump_writer->WriteString(module_info.name, 0, + &loc)) + return false; + module.base_of_image = (u_int64_t)module_info.start_addr; + module.size_of_image = module_info.size; + module.module_name_rva = loc.rva; + + if (!WriteCVRecord(callback_context->minidump_writer, &module, + module_info.name)) + return false; + callback_context->list->CopyIndexAfterObject( + callback_context->module_index++, &module, MD_MODULE_SIZE); + return true; +} + +bool WriteModuleListStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA list(minidump_writer); + int module_count = writer_args->thread_lister->GetModuleCount(); + if (module_count <= 0 || + !list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE)) + return false; + dir->stream_type = MD_MODULE_LIST_STREAM; + dir->location = list.location(); + list.get()->number_of_modules = module_count; + ModuleInfoCallbackCtx context; + context.minidump_writer = minidump_writer; + context.writer_args = writer_args; + context.list = &list; + context.module_index = 0; + CallbackParam callback(ModuleInfoCallback, &context); + return writer_args->thread_lister->ListModules(&callback) == module_count; +} + +bool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA sys_info(minidump_writer); + if (!sys_info.Allocate()) + return false; + dir->stream_type = MD_SYSTEM_INFO_STREAM; + dir->location = sys_info.location(); + + return WriteCPUInformation(sys_info.get()) && + WriteOSInformation(minidump_writer, sys_info.get()); +} + +bool WriteExceptionStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + // This happenes when this is not a crash, but a requested dump. + if (writer_args->sig_ctx == NULL) + return false; + + TypedMDRVA exception(minidump_writer); + if (!exception.Allocate()) + return false; + + dir->stream_type = MD_EXCEPTION_STREAM; + dir->location = exception.location(); + exception.get()->thread_id = writer_args->crashed_pid; + exception.get()->exception_record.exception_code = writer_args->signo; + exception.get()->exception_record.exception_flags = 0; + if (writer_args->sig_ctx != NULL) { + exception.get()->exception_record.exception_address = + writer_args->sig_ctx->eip; + } else { + return true; + } + + // Write context of the exception. + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + exception.get()->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); + return WriteContext(context.get(), writer_args->sig_ctx, NULL); +} + +bool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA info(minidump_writer); + if (!info.Allocate()) + return false; + + dir->stream_type = MD_MISC_INFO_STREAM; + dir->location = info.location(); + info.get()->size_of_info = sizeof(MDRawMiscInfo); + info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID; + info.get()->process_id = writer_args->requester_pid; + + return true; +} + +bool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA info(minidump_writer); + if (!info.Allocate()) + return false; + + dir->stream_type = MD_BREAKPAD_INFO_STREAM; + dir->location = info.location(); + + info.get()->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; + info.get()->dump_thread_id = getpid(); + info.get()->requesting_thread_id = writer_args->requester_pid; + return true; +} + +// Prototype of writer functions. +typedef bool (*WriteStringFN)(MinidumpFileWriter *, + const WriterArgument *, + MDRawDirectory *); + +// Function table to writer a full minidump. +WriteStringFN writers[] = { + WriteThreadListStream, + WriteModuleListStream, + WriteSystemInfoStream, + WriteExceptionStream, + WriteMiscInfoStream, + WriteBreakpadInfoStream, +}; + +// Will call each writer function in the writers table. +// It runs in a different process from the crashing process, but sharing +// the same address space. This enables it to use ptrace functions. +int Write(void *argument) { + WriterArgument *writer_args = + static_cast(argument); + + if (!writer_args->thread_lister->SuspendAllThreads()) + return -1; + + if (writer_args->sighandler_ebp != 0 && + writer_args->thread_lister->FindSigContext(writer_args->sighandler_ebp, + &writer_args->sig_ctx)) { + writer_args->crashed_stack_bottom = + writer_args->thread_lister->GetThreadStackBottom( + writer_args->sig_ctx->ebp); + int crashed_pid = FindCrashingThread(writer_args->crashed_stack_bottom, + writer_args->requester_pid, + writer_args->thread_lister); + if (crashed_pid > 0) + writer_args->crashed_pid = crashed_pid; + } + + + MinidumpFileWriter *minidump_writer = writer_args->minidump_writer; + TypedMDRVA header(minidump_writer); + TypedMDRVA dir(minidump_writer); + if (!header.Allocate()) + return 0; + + int writer_count = sizeof(writers) / sizeof(writers[0]); + // Need directory space for all writers. + if (!dir.AllocateArray(writer_count)) + return 0; + header.get()->signature = MD_HEADER_SIGNATURE; + header.get()->version = MD_HEADER_VERSION; + header.get()->time_date_stamp = time(NULL); + header.get()->stream_count = writer_count; + header.get()->stream_directory_rva = dir.position(); + + int dir_index = 0; + MDRawDirectory local_dir; + for (int i = 0; i < writer_count; ++i) { + if (writers[i](minidump_writer, writer_args, &local_dir)) + dir.CopyIndex(dir_index++, &local_dir); + } + + writer_args->thread_lister->ResumeAllThreads(); + return 0; +} + +} // namespace + +namespace google_breakpad { + +MinidumpGenerator::MinidumpGenerator() { + AllocateStack(); +} + +MinidumpGenerator::~MinidumpGenerator() { +} + +void MinidumpGenerator::AllocateStack() { + stack_.reset(new char[kStackSize]); +} + +bool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname, + int signo, + uintptr_t sighandler_ebp, + struct sigcontext **sig_ctx) const { + assert(file_pathname != NULL); + assert(stack_ != NULL); + + if (stack_ == NULL || file_pathname == NULL) + return false; + + MinidumpFileWriter minidump_writer; + if (minidump_writer.Open(file_pathname)) { + WriterArgument argument; + memset(&argument, 0, sizeof(argument)); + LinuxThread thread_lister(getpid()); + argument.thread_lister = &thread_lister; + argument.minidump_writer = &minidump_writer; + argument.requester_pid = getpid(); + argument.crashed_pid = getpid(); + argument.signo = signo; + argument.sighandler_ebp = sighandler_ebp; + argument.sig_ctx = NULL; + + int cloned_pid = clone(Write, stack_.get() + kStackSize, + CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, + (void*)&argument); + waitpid(cloned_pid, NULL, __WALL); + if (sig_ctx != NULL) + *sig_ctx = argument.sig_ctx; + return true; + } + + return false; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.h b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.h new file mode 100644 index 00000000..7c0511f5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_generator.h @@ -0,0 +1,73 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ +#define CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" +#include "processor/scoped_ptr.h" + +struct sigcontext; + +namespace google_breakpad { + +// +// MinidumpGenerator +// +// Write a minidump to file based on the signo and sig_ctx. +// A minidump generator should be created before any exception happen. +// +class MinidumpGenerator { + public: + MinidumpGenerator(); + + ~MinidumpGenerator(); + + // Write minidump. + bool WriteMinidumpToFile(const char *file_pathname, + int signo, + uintptr_t sighandler_ebp, + struct sigcontext **sig_ctx) const; + private: + // Allocate memory for stack. + void AllocateStack(); + + private: + // Stack size of the writer thread. + static const int kStackSize = 1024 * 1024; + scoped_array stack_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_test.cc b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_test.cc new file mode 100644 index 00000000..f8c4e784 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/linux/handler/minidump_test.cc @@ -0,0 +1,86 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Author: Li Liu +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include + +#include +#include +#include +#include + +#include "client/linux/handler/minidump_generator.h" + +using namespace google_breakpad; + +// Thread use this to see if it should stop working. +static bool should_exit = false; + +static void foo2(int arg) { + // Stack variable, used for debugging stack dumps. + int c = arg; + c = 0xcccccccc; + while (!should_exit) + sleep(1); +} + +static void foo(int arg) { + // Stack variable, used for debugging stack dumps. + int b = arg; + b = 0xbbbbbbbb; + foo2(b); +} + +static void *thread_main(void *) { + // Stack variable, used for debugging stack dumps. + int a = 0xaaaaaaaa; + foo(a); + return NULL; +} + +static void CreateThread(int num) { + pthread_t h; + for (int i = 0; i < num; ++i) { + pthread_create(&h, NULL, thread_main, NULL); + pthread_detach(h); + } +} + +int main(int argc, char *argv[]) { + CreateThread(10); + google_breakpad::MinidumpGenerator mg; + if (mg.WriteMinidumpToFile("minidump_test.out", -1, 0, NULL)) + printf("Succeeded written minidump\n"); + else + printf("Failed to write minidump\n"); + should_exit = true; + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.c b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.c new file mode 100644 index 00000000..19f36b19 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.c @@ -0,0 +1,1750 @@ +/* + * IDENTIFICATION: + * stub generated Mon Jun 16 18:08:10 2008 + * with a MiG generated Tue Feb 19 02:01:43 PST 2008 by root@b75.local + * OPTIONS: + */ + +/* Module exc */ + +#define __MIG_check__Request__exc_subsystem__ 1 +#define __NDR_convert__Request__exc_subsystem__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* typedefs for all requests */ + +#ifndef __Request__exc_subsystem__defined +#define __Request__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + } __Request__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__exc_subsystem__defined */ + +/* typedefs for all replies */ + +#ifndef __Reply__exc_subsystem__defined +#define __Reply__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__breakpad_exc_subsystem__defined +#define __ReplyUnion__breakpad_exc_subsystem__defined +union __ReplyUnion__breakpad_exc_subsystem { + __Reply__exception_raise_t Reply_exception_raise; + __Reply__exception_raise_state_t Reply_exception_raise_state; + __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity; +}; +#endif /* __RequestUnion__breakpad_exc_subsystem__defined */ +/* Forward Declarations */ + + +mig_internal novalue _Xexception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xexception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xexception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__exc_subsystem__ +#if !defined(__MIG_check__Request__exception_raise_t__defined) +#define __MIG_check__Request__exception_raise_t__defined +#ifndef __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exc__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t) +#elif defined(__NDR_convert__int_rep__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(a, f) \ + __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exc__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t) +#elif defined(__NDR_convert__char_rep__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exc__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t) +#elif defined(__NDR_convert__float_rep__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_t__code__defined */ + + +mig_internal kern_return_t __MIG_check__Request__exception_raise_t(__attribute__((__unused__)) __Request__exception_raise_t *In0P) +{ + + typedef __Request__exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 8)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)) +) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 8) + ((4 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { +#if defined(__NDR_convert__int_rep__Request__exception_raise_t__exception__defined) + __NDR_convert__int_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__exception__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_t__code__defined) + __NDR_convert__int_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); +#endif /* __NDR_convert__int_rep__Request__exception_raise_t__code__defined */ + } +#endif /* defined(__NDR_convert__int_rep...) */ + +#if defined(__NDR_convert__char_rep__Request__exception_raise_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__exception_raise_t__code__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { +#if defined(__NDR_convert__char_rep__Request__exception_raise_t__exception__defined) + __NDR_convert__char_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.char_rep); +#endif /* __NDR_convert__char_rep__Request__exception_raise_t__exception__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_t__code__defined) + __NDR_convert__char_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); +#endif /* __NDR_convert__char_rep__Request__exception_raise_t__code__defined */ + } +#endif /* defined(__NDR_convert__char_rep...) */ + +#if defined(__NDR_convert__float_rep__Request__exception_raise_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__exception_raise_t__code__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { +#if defined(__NDR_convert__float_rep__Request__exception_raise_t__exception__defined) + __NDR_convert__float_rep__Request__exception_raise_t__exception(&In0P->exception, In0P->NDR.float_rep); +#endif /* __NDR_convert__float_rep__Request__exception_raise_t__exception__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_t__code__defined) + __NDR_convert__float_rep__Request__exception_raise_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); +#endif /* __NDR_convert__float_rep__Request__exception_raise_t__code__defined */ + } +#endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__exception_raise_t__defined) */ +#endif /* __MIG_check__Request__exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t breakpad_exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine exception_raise */ +mig_internal novalue _Xexception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + mach_msg_trailer_t trailer; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__exception_raise_t __Request; + typedef __Reply__exception_raise_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__exception_raise_t__defined */ + + __DeclareRcvRpc(2401, "exception_raise") + __BeforeRcvRpc(2401, "exception_raise") + +#if defined(__MIG_check__Request__exception_raise_t__defined) + check_result = __MIG_check__Request__exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__exception_raise_t__defined) */ + + OutP->RetCode = breakpad_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2401, "exception_raise") +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__exc_subsystem__ +#if !defined(__MIG_check__Request__exception_raise_state_t__defined) +#define __MIG_check__Request__exception_raise_state_t__defined +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exc__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t) +#elif defined(__NDR_convert__int_rep__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(a, f) \ + __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__int_rep__exc__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__int_rep__exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__int_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exc__natural_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__exc__uint32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined +#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exc__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t) +#elif defined(__NDR_convert__char_rep__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__char_rep__exc__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__char_rep__exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__char_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exc__natural_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__exc__uint32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exc__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t) +#elif defined(__NDR_convert__float_rep__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__float_rep__exc__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__float_rep__exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__float_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exc__natural_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__exc__uint32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined */ + + +mig_internal kern_return_t __MIG_check__Request__exception_raise_state_t(__attribute__((__unused__)) __Request__exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_t **In1PP) +{ + + typedef __Request__exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (4 * In0P->codeCnt); +#if __MigTypeCheck + if (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584) + msgh_size_delta) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8); + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 584) + ((4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined) + __NDR_convert__int_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__exception__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__code__defined) + __NDR_convert__int_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__code__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined) + __NDR_convert__int_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__flavor__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined) + __NDR_convert__int_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__int_rep...) */ + +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined) + __NDR_convert__char_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.char_rep); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__exception__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__code__defined) + __NDR_convert__char_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__code__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined) + __NDR_convert__char_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.char_rep); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__flavor__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined) + __NDR_convert__char_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__char_rep...) */ + +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined) + __NDR_convert__float_rep__Request__exception_raise_state_t__exception(&In0P->exception, In0P->NDR.float_rep); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__exception__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__code__defined) + __NDR_convert__float_rep__Request__exception_raise_state_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__code__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined) + __NDR_convert__float_rep__Request__exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.float_rep); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__flavor__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined) + __NDR_convert__float_rep__Request__exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t breakpad_exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine exception_raise_state */ +mig_internal novalue _Xexception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + mach_msg_trailer_t trailer; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__exception_raise_state_t __Request; + typedef __Reply__exception_raise_state_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__exception_raise_state_t__defined */ + + __DeclareRcvRpc(2402, "exception_raise_state") + __BeforeRcvRpc(2402, "exception_raise_state") + +#if defined(__MIG_check__Request__exception_raise_state_t__defined) + check_result = __MIG_check__Request__exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 144; + + OutP->RetCode = breakpad_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2402, "exception_raise_state") +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__exc_subsystem__ +#if !defined(__MIG_check__Request__exception_raise_state_identity_t__defined) +#define __MIG_check__Request__exception_raise_state_identity_t__defined +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__int_rep__exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__int_rep__exc__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__int_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exception_data_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__int_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exc__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__exc__integer_t) +#elif defined(__NDR_convert__int_rep__integer_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__int_rep__integer_t) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__exc__int32_t) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__int_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(a, f) \ + __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__int_rep__exc__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__int_rep__exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__int_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__exc__natural_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__exc__uint32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined */ + +#ifndef __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined +#if defined(__NDR_convert__int_rep__exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__char_rep__exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__char_rep__exc__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__char_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exception_data_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__char_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exc__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__exc__integer_t) +#elif defined(__NDR_convert__char_rep__integer_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__char_rep__integer_t) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__exc__int32_t) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__char_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__char_rep__exc__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__char_rep__exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__char_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__exc__natural_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__exc__uint32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__float_rep__exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__float_rep__exc__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__float_rep__exc__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exception_data_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__float_rep__exception_data_t((exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exc__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__exc__integer_t) +#elif defined(__NDR_convert__float_rep__integer_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((integer_t *)(a), f, c, __NDR_convert__float_rep__integer_t) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__exc__int32_t) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int32_t *)(a), f, c, __NDR_convert__float_rep__int32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__float_rep__exc__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__float_rep__exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__float_rep__exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__exc__natural_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__exc__uint32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined */ + + +mig_internal kern_return_t __MIG_check__Request__exception_raise_state_identity_t(__attribute__((__unused__)) __Request__exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)) +) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (4 * In0P->codeCnt); +#if __MigTypeCheck + if (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 584) + msgh_size_delta) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8); + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 584) + ((4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined) || \ + defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__exception__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__code__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__flavor__defined */ +#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined) + __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__int_rep...) */ + +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined) + __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.char_rep); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__exception__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined) + __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__code__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined) + __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.char_rep); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__flavor__defined */ +#if defined(__NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined) + __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__char_rep__Request__exception_raise_state_identity_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__char_rep...) */ + +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined) + __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.float_rep); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__exception__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined) + __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__code__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined) + __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.float_rep); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__flavor__defined */ +#if defined(__NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined) + __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt); +#endif /* __NDR_convert__float_rep__Request__exception_raise_state_identity_t__old_state__defined */ + } +#endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t breakpad_exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine exception_raise_state_identity */ +mig_internal novalue _Xexception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + mach_msg_trailer_t trailer; + } Request; +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__exception_raise_state_identity_t __Request; + typedef __Reply__exception_raise_state_identity_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2403, "exception_raise_state_identity") + __BeforeRcvRpc(2403, "exception_raise_state_identity") + +#if defined(__MIG_check__Request__exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 144; + + OutP->RetCode = breakpad_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2403, "exception_raise_state_identity") +} + + +extern boolean_t exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +extern mig_routine_t exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +const struct breakpad_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} breakpad_exc_subsystem = { + exc_server_routine, + 2401, + 2404, + (mach_msg_size_t)sizeof(union __ReplyUnion__breakpad_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xexception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xexception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xexception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + + if ((InHeadP->msgh_id > 2403) || (InHeadP->msgh_id < 2401) || + ((routine = breakpad_exc_subsystem.routine[InHeadP->msgh_id - 2401].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2401; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return breakpad_exc_subsystem.routine[msgh_id].stub_routine; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.h new file mode 100644 index 00000000..c05f25a8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_exc_server.h @@ -0,0 +1,258 @@ +#ifndef _exc_user_ +#define _exc_user_ + +/* Module exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef exc_MSG_COUNT +#define exc_MSG_COUNT 3 +#endif /* exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__BEGIN_DECLS + + +/* Routine exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__exc_subsystem__defined +#define __Request__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + } __Request__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__exc_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__exc_subsystem__defined +#define __RequestUnion__exc_subsystem__defined +union __RequestUnion__exc_subsystem { + __Request__exception_raise_t Request_exception_raise; + __Request__exception_raise_state_t Request_exception_raise_state; + __Request__exception_raise_state_identity_t Request_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__exc_subsystem__defined +#define __Reply__exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__exc_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__exc_subsystem__defined +#define __ReplyUnion__exc_subsystem__defined +union __ReplyUnion__exc_subsystem { + __Reply__exception_raise_t Reply_exception_raise; + __Reply__exception_raise_state_t Reply_exception_raise_state; + __Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_exc +#define subsystem_to_name_map_exc \ + { "exception_raise", 2401 },\ + { "exception_raise_state", 2402 },\ + { "exception_raise_state_identity", 2403 } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + +#endif /* _exc_user_ */ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.cc new file mode 100644 index 00000000..c220d88d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.cc @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* 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. +*/ + +#ifdef __LP64__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "breakpad_nlist_64.h" +#include +#include +#include + +/* Stuff lifted from and since they are gone */ +/* + * Header prepended to each a.out file. + */ +struct exec { + unsigned short a_machtype; /* machine type */ + unsigned short a_magic; /* magic number */ + unsigned long a_text; /* size of text segment */ + unsigned long a_data; /* size of initialized data */ + unsigned long a_bss; /* size of uninitialized data */ + unsigned long a_syms; /* size of symbol table */ + unsigned long a_entry; /* entry point */ + unsigned long a_trsize; /* size of text relocation */ + unsigned long a_drsize; /* size of data relocation */ +}; + +#define OMAGIC 0407 /* old impure format */ +#define NMAGIC 0410 /* read-only text */ +#define ZMAGIC 0413 /* demand load format */ + +#define N_BADMAG(x) \ + (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC) +#define N_TXTOFF(x) \ + ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec)) +#define N_SYMOFF(x) \ + (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize) + +int +__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames); + +/* + * 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; + + fd = open(name, O_RDONLY, 0); + if (fd < 0) + return (-1); + n = __breakpad_fdnlist_64(fd, list, symbolNames); + (void)close(fd); + return (n); +} + +/* 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)]; + + const register char *s1, *s2; + register int n, m; + int maxlen, nreq; + off_t sa; /* symbol address */ + off_t ss; /* start of strings */ + struct exec buf; + unsigned arch_offset = 0; + + maxlen = 500; + for (q = list, nreq = 0; + 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; + } + + if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) || + (N_BADMAG(buf) && *((long *)&buf) != MH_MAGIC && + NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC) && + /* nealsid: The following is the big-endian ppc64 check */ + (*((uint32_t*)&buf)) != FAT_MAGIC) { + return (-1); + } + + /* Deal with fat file if necessary */ + if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC || + /* nealsid: The following is the big-endian ppc64 check */ + *((int*)&buf) == FAT_MAGIC) { + 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); + } + mach_port_deallocate(mach_task_self(), host); + + /* Read in the fat header */ + lseek(fd, 0, SEEK_SET); + if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) { + return (-1); + } + + /* Convert fat_narchs to host byte order */ + fh.nfat_arch = NXSwapBigLongToHost(fh.nfat_arch); + + /* Read in the fat archs */ + fat_archs = (struct fat_arch *)malloc(fh.nfat_arch * + sizeof(struct fat_arch)); + if (fat_archs == NULL) { + return (-1); + } + if (read(fd, (char *)fat_archs, + sizeof(struct fat_arch) * fh.nfat_arch) != + sizeof(struct fat_arch) * fh.nfat_arch) { + free(fat_archs); + return (-1); + } + + /* + * Convert archs to host byte ordering (a constraint of + * cpusubtype_getbestarch() + */ + for (i = 0; i < fh.nfat_arch; i++) { + fat_archs[i].cputype = + NXSwapBigLongToHost(fat_archs[i].cputype); + fat_archs[i].cpusubtype = + NXSwapBigLongToHost(fat_archs[i].cpusubtype); + fat_archs[i].offset = + NXSwapBigLongToHost(fat_archs[i].offset); + fat_archs[i].size = + NXSwapBigLongToHost(fat_archs[i].size); + fat_archs[i].align = + NXSwapBigLongToHost(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); + } + } + + if (*((int *)&buf) == MH_MAGIC_64) { + struct mach_header_64 mh; + struct load_command *load_commands, *lcp; + struct symtab_command *stp; + long i; + + 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); + } + else { + sa = N_SYMOFF(buf) + arch_offset; + ss = sa + buf.a_syms + arch_offset; + n = buf.a_syms; + } + + 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) + 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; + + // 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); + } + +#endif /* __LP64__ */ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.h new file mode 100644 index 00000000..ee10afb9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/breakpad_nlist_64.h @@ -0,0 +1,43 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// breakpad_nlist.h +// +// This file is meant to provide a header for clients of the modified +// nlist function implemented to work on 64-bit. + +#ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ + +typedef struct nlist_64 breakpad_nlist; + +int +breakpad_nlist_64(const char *name, + breakpad_nlist *list, + const char **symbolNames); + +#endif /* CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.cc new file mode 100644 index 00000000..a2d62700 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.cc @@ -0,0 +1,456 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { // needed to compile on Leopard + #include + #include + #include + #include +} + +#include "breakpad_nlist_64.h" +#include +#include +#include +#include "client/mac/handler/dynamic_images.h" + +namespace google_breakpad { + +//============================================================================== +// 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, + mach_vm_size_t *size_to_end) { + mach_vm_address_t region_base = (mach_vm_address_t)address; + mach_vm_size_t region_size; + natural_t nesting_level = 0; + vm_region_submap_info_64 submap_info; + mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64; + + // Get information about the vm region containing |address| + vm_region_recurse_info_t region_info; + region_info = reinterpret_cast(&submap_info); + + kern_return_t result = + mach_vm_region_recurse(target_task, + ®ion_base, + ®ion_size, + &nesting_level, + region_info, + &info_count); + + if (result == KERN_SUCCESS) { + // Get distance from |address| to the end of this region + *size_to_end = region_base + region_size -(mach_vm_address_t)address; + + // If we want to handle strings as long as 4096 characters we may need + // to check if there's a vm region immediately following the first one. + // If so, we need to extend |*size_to_end| to go all the way to the end + // of the second region. + if (*size_to_end < 4096) { + // Second region starts where the first one ends + mach_vm_address_t region_base2 = + (mach_vm_address_t)(region_base + region_size); + mach_vm_size_t region_size2; + + // Get information about the following vm region + result = + mach_vm_region_recurse(target_task, + ®ion_base2, + ®ion_size2, + &nesting_level, + region_info, + &info_count); + + // Extend region_size to go all the way to the end of the 2nd region + if (result == KERN_SUCCESS + && region_base2 == region_base + region_size) { + region_size += region_size2; + } + } + + *size_to_end = region_base + region_size -(mach_vm_address_t)address; + } else { + region_size = 0; + *size_to_end = 0; + } + + return region_size; +} + +#define kMaxStringLength 8192 +//============================================================================== +// Reads a NULL-terminated string from another task. +// +// Warning! This will not read any strings longer than kMaxStringLength-1 +// +static void* ReadTaskString(task_port_t target_task, + const void* 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_to_read, &kr); + } + + return NULL; +} + +//============================================================================== +// 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; + 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(address) & (-systemPageSize); + + mach_vm_address_t last_page_address = + (reinterpret_cast(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(&local_start), + &local_length); + + + if (kr != NULL) { + *kr = 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; +} + +#pragma mark - + +//============================================================================== +// 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 + + uint32_t versionSize = 0; +#ifdef __LP64__ + const uint32_t segmentLoadCommand = LC_SEGMENT_64; + char* sectVersion = getsectdatafromheader_64(header, SEG_DATA, "__version", &versionSize); +#else + const uint32_t segmentLoadCommand = LC_SEGMENT; + char* sectVersion = getsectdatafromheader(header, SEG_DATA, "__version", &versionSize); +#endif + + if (versionSize == 4) { + version_ = NXSwapHostLongToBig(*(unsigned long*)sectVersion); + } + + const struct load_command *cmd = + reinterpret_cast(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(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(cmd); + + version_ = dc->dylib.current_version; + foundDylibIDCommand = true; + } + } + + if (foundDylibIDCommand && foundTextSection) { + return; + } + + cmd = reinterpret_cast + (reinterpret_cast(cmd) + cmd->cmdsize); + } + +} + +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(GetVMAddr())); + printf("vmsize\t\t: %llu\n", GetVMSize()); + printf("slide\t\t: %td\n", GetVMAddrSlide()); +} + +#pragma mark - + +//============================================================================== +// Loads information about dynamically loaded code in the given task. +DynamicImages::DynamicImages(mach_port_t task) + : task_(task) { + 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) ); + + // 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(imageSymbolName); + nlist(dyldPath,&list); + if(list.n_value) { + return reinterpret_cast(list.n_value); + } + + 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" }; + + int invalidEntriesCount = breakpad_nlist_64(dyldPath,&list,symbolNames); + + if(invalidEntriesCount != 0) { + return NULL; + } + assert(list.n_value); + return reinterpret_cast(list.n_value); +#endif + +} +//============================================================================== +// This code was written using dyld_debug.c (from Darwin) as a guide. +void DynamicImages::ReadImageInfoForTask() { + void *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 + (ReadTaskMemory(task_, + reinterpret_cast(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 + (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 + (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. + unsigned int header_size = + sizeof(breakpad_mach_header) + header->sizeofcmds; + + free(header); + + header = reinterpret_cast + (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 + (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::iterator it = unique(image_list_.begin(), + image_list_.end() ); + image_list_.erase(it, image_list_.end()); + } + } +} + +//============================================================================== +DynamicImage *DynamicImages::GetExecutableImage() { + int executable_index = GetExecutableImageIndex(); + + if (executable_index >= 0) { + return GetImage(executable_index); + } + + return NULL; +} + +//============================================================================== +// returns -1 if failure to find executable +int DynamicImages::GetExecutableImageIndex() { + int image_count = GetImageCount(); + + for (int i = 0; i < image_count; ++i) { + DynamicImage *image = GetImage(i); + if (image->GetMachHeader()->filetype == MH_EXECUTE) { + return i; + } + } + + return -1; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.h new file mode 100644 index 00000000..85ba8cf9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/dynamic_images.h @@ -0,0 +1,297 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dynamic_images.h +// +// Implements most of the function of the dyld API, but allowing an +// arbitrary task to be introspected, unlike the dyld API which +// only allows operation on the current task. The current implementation +// is limited to use by 32-bit tasks. + +#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ +#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ + +#include +#include +#include +#include +#include + +namespace google_breakpad { + +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; + +//============================================================================== +// 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 { + uint32_t version; // == 1 in Mac OS X 10.4 + uint32_t infoArrayCount; + const struct dyld_image_info *infoArray; + void* notification; + bool processDetachedFromSharedRegion; +} dyld_all_image_infos; + +// 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) {} + + 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_; +}; + +//============================================================================== +// Represents a single dynamically loaded mach-o image +class DynamicImage { + public: + DynamicImage(breakpad_mach_header *header, // we take ownership + int header_size, // includes load commands + breakpad_mach_header *load_address, + char *inFilePath, + uintptr_t image_mod_date, + mach_port_t task) + : header_(header), + header_size_(header_size), + load_address_(load_address), + file_mod_date_(image_mod_date), + task_(task) { + InitializeFilePath(inFilePath); + 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 + int GetHeaderSize() const {return header_size_;} + + // Full path to mach-o binary + char *GetFilePath() {return file_path_;} + + uintptr_t GetModDate() const {return file_mod_date_;} + + // Actual address where the image was loaded + breakpad_mach_header *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_;} + + uint32_t GetVersion() {return version_;} + // For sorting + bool operator<(const DynamicImage &inInfo) { + return GetLoadAddress() < inInfo.GetLoadAddress(); + } + + // Debugging + void Print(); + + private: + 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(malloc(path_size)); + strlcpy(file_path_, inFilePath, path_size); + } else { + file_path_ = NULL; + } + } + + // Initializes vmaddr_, vmsize_, and slide_ + void CalculateMemoryAndVersionInfo(); + + breakpad_mach_header *header_; // our local copy of the header + int header_size_; // mach_header plus load commands + breakpad_mach_header *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 + uintptr_t file_mod_date_; // time_t of image file + + mach_port_t 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<(). +// +class DynamicImageRef { + public: + explicit DynamicImageRef(DynamicImage *inP) : p(inP) {} + // The copy constructor is required by STL + DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {} + + bool operator<(const DynamicImageRef &inRef) const { + return (*const_cast(this)->p) + < (*const_cast(inRef).p); + } + + bool operator==(const DynamicImageRef &inInfo) const { + return (*const_cast(this)->p).GetLoadAddress() == + (*const_cast(inInfo)).GetLoadAddress(); + } + + // Be just like DynamicImage* + DynamicImage *operator->() {return p;} + operator DynamicImage*() {return p;} + + private: + DynamicImage *p; +}; + +//============================================================================== +// An object of type DynamicImages may be created to allow introspection of +// an arbitrary task's dynamically loaded mach-o binaries. This makes the +// assumption that the current task has send rights to the target task. +class DynamicImages { + public: + explicit DynamicImages(mach_port_t task); + + ~DynamicImages() { + for (int i = 0; i < (int)image_list_.size(); ++i) { + delete image_list_[i]; + } + } + + // Returns the number of dynamically loaded mach-o images. + int GetImageCount() const {return image_list_.size();} + + // Returns an individual image. + DynamicImage *GetImage(int i) { + if (i < (int)image_list_.size()) { + return image_list_[i]; + } + return NULL; + } + + // Returns the image corresponding to the main executable. + DynamicImage *GetExecutableImage(); + int GetExecutableImageIndex(); + + // Returns the task which we're looking at. + mach_port_t GetTask() const {return task_;} + + // Debugging + void Print() { + for (int i = 0; i < (int)image_list_.size(); ++i) { + image_list_[i]->Print(); + } + } + + void TestPrint() { + const breakpad_mach_header *header; + for (int i = 0; i < (int)image_list_.size(); ++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(imageHeader); + + MachHeader(*header).Print(); + } + } + + private: + bool IsOurTask() {return task_ == mach_task_self();} + + // Initialization + void ReadImageInfoForTask(); + void* GetDyldAllImageInfosPointer(); + + mach_port_t task_; + vector image_list_; +}; + +// Returns a malloced block containing 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); + +} // namespace google_breakpad + +#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.cc new file mode 100644 index 00000000..60fde473 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.cc @@ -0,0 +1,722 @@ +// 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 +#include + +#include "client/mac/handler/exception_handler.h" +#include "client/mac/handler/minidump_generator.h" +#include "common/mac/macho_utilities.h" + +#ifndef USE_PROTECTED_ALLOCATIONS +#define USE_PROTECTED_ALLOCATIONS 0 +#endif + +// If USE_PROTECTED_ALLOCATIONS is activated then the +// gBreakpadAllocator needs to be setup in other code +// ahead of time. Please see ProtectedMemoryAllocator.h +// for more details. +#if USE_PROTECTED_ALLOCATIONS + #include "protected_memory_allocator.h" + extern ProtectedMemoryAllocator *gBreakpadAllocator; +#endif + + +namespace google_breakpad { + +using std::map; + +// These structures and techniques are illustrated in +// Mac OS X Internals, Amit Singh, ch 9.7 +struct ExceptionMessage { + mach_msg_header_t header; + mach_msg_body_t body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + NDR_record_t ndr; + exception_type_t exception; + mach_msg_type_number_t code_count; + integer_t code[EXCEPTION_CODE_MAX]; + char padding[512]; +}; + +struct ExceptionParameters { + ExceptionParameters() : count(0) {} + mach_msg_type_number_t count; + exception_mask_t masks[EXC_TYPES_COUNT]; + mach_port_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; +}; + +struct ExceptionReplyMessage { + mach_msg_header_t header; + NDR_record_t ndr; + kern_return_t return_code; +}; + +// Only catch these three exceptions. The other ones are nebulously defined +// and may result in treating a non-fatal exception as fatal. +exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS | +EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT; + +extern "C" +{ + // Forward declarations for functions that need "C" style compilation + boolean_t exc_server(mach_msg_header_t *request, + mach_msg_header_t *reply); + + kern_return_t catch_exception_raise(mach_port_t target_port, + mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); + + kern_return_t ForwardException(mach_port_t task, + mach_port_t failed_thread, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); + + kern_return_t exception_raise(mach_port_t target_port, + mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t exception_code, + mach_msg_type_number_t exception_code_count); + + kern_return_t + exception_raise_state(mach_port_t target_port, + mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t exception_code, + mach_msg_type_number_t code_count, + thread_state_flavor_t *target_flavor, + thread_state_t thread_state, + mach_msg_type_number_t thread_state_count, + thread_state_t thread_state, + mach_msg_type_number_t *thread_state_count); + + kern_return_t + exception_raise_state_identity(mach_port_t target_port, + mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t exception_code, + mach_msg_type_number_t exception_code_count, + thread_state_flavor_t *target_flavor, + thread_state_t thread_state, + mach_msg_type_number_t thread_state_count, + thread_state_t thread_state, + mach_msg_type_number_t *thread_state_count); + + kern_return_t breakpad_exception_raise_state(mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt + ); + + kern_return_t breakpad_exception_raise_state_identity(mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt + ); + + kern_return_t breakpad_exception_raise(mach_port_t port, mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); +} + + + +kern_return_t breakpad_exception_raise_state(mach_port_t exception_port, + exception_type_t exception, + const exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt + ) +{ + return KERN_SUCCESS; +} + +kern_return_t breakpad_exception_raise_state_identity(mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt + ) +{ + return KERN_SUCCESS; +} + +kern_return_t breakpad_exception_raise(mach_port_t port, mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count) { + + if (task != mach_task_self()) { + return KERN_FAILURE; + } + return ForwardException(task, failed_thread, exception, code, code_count); +} + + +ExceptionHandler::ExceptionHandler(const string &dump_path, + FilterCallback filter, + MinidumpCallback callback, + void *callback_context, + bool install_handler) + : dump_path_(), + filter_(filter), + callback_(callback), + callback_context_(callback_context), + directCallback_(NULL), + handler_thread_(NULL), + handler_port_(MACH_PORT_NULL), + previous_(NULL), + installed_exception_handler_(false), + is_in_teardown_(false), + last_minidump_write_result_(false), + use_minidump_write_mutex_(false) { + // This will update to the ID and C-string pointers + set_dump_path(dump_path); + MinidumpGenerator::GatherSystemInformation(); + Setup(install_handler); +} + +// special constructor if we want to bypass minidump writing and +// simply get a callback with the exception information +ExceptionHandler::ExceptionHandler(DirectCallback callback, + void *callback_context, + bool install_handler) + : dump_path_(), + filter_(NULL), + callback_(NULL), + callback_context_(callback_context), + directCallback_(callback), + handler_thread_(NULL), + handler_port_(MACH_PORT_NULL), + previous_(NULL), + installed_exception_handler_(false), + is_in_teardown_(false), + last_minidump_write_result_(false), + use_minidump_write_mutex_(false) { + MinidumpGenerator::GatherSystemInformation(); + Setup(install_handler); +} + +ExceptionHandler::~ExceptionHandler() { + Teardown(); +} + +bool ExceptionHandler::WriteMinidump() { + // If we're currently writing, just return + if (use_minidump_write_mutex_) + return false; + + use_minidump_write_mutex_ = true; + last_minidump_write_result_ = false; + + // Lock the mutex. Since we just created it, this will return immediately. + if (pthread_mutex_lock(&minidump_write_mutex_) == 0) { + // Send an empty message to the handle port so that a minidump will + // be written + SendEmptyMachMessage(); + + // Wait for the minidump writer to complete its writing. It will unlock + // the mutex when completed + pthread_mutex_lock(&minidump_write_mutex_); + } + + use_minidump_write_mutex_ = false; + UpdateNextID(); + return last_minidump_write_result_; +} + +// static +bool ExceptionHandler::WriteMinidump(const string &dump_path, + MinidumpCallback callback, + void *callback_context) { + ExceptionHandler handler(dump_path, NULL, callback, callback_context, false); + return handler.WriteMinidump(); +} + +bool ExceptionHandler::WriteMinidumpWithException(int exception_type, + int exception_code, + mach_port_t thread_name) { + bool result = false; + + if (directCallback_) { + if (directCallback_(callback_context_, + exception_type, + exception_code, + thread_name) ) { + if (exception_type && exception_code) + _exit(exception_type); + } + } else { + string minidump_id; + + // Putting the MinidumpGenerator in its own context will ensure that the + // destructor is executed, closing the newly created minidump file. + if (!dump_path_.empty()) { + MinidumpGenerator md; + if (exception_type && exception_code) { + // If this is a real exception, give the filter (if any) a chance to + // decided if this should be sent + if (filter_ && !filter_(callback_context_)) + return false; + + md.SetExceptionInformation(exception_type, exception_code, thread_name); + } + + result = md.Write(next_minidump_path_c_); + } + + // Call user specified callback (if any) + if (callback_) { + // If the user callback returned true and we're handling an exception + // (rather than just writing out the file), then we should exit without + // forwarding the exception to the next handler. + if (callback_(dump_path_c_, next_minidump_id_c_, callback_context_, + result)) { + if (exception_type && exception_code) + _exit(exception_type); + } + } + } + + return result; +} + +kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count) { + // At this time, we should have called Uninstall() on the exception handler + // so that the current exception ports are the ones that we should be + // forwarding to. + ExceptionParameters current; + + current.count = EXC_TYPES_COUNT; + mach_port_t current_task = mach_task_self(); + kern_return_t result = task_get_exception_ports(current_task, + s_exception_mask, + current.masks, + ¤t.count, + current.ports, + current.behaviors, + current.flavors); + + // Find the first exception handler that matches the exception + unsigned int found; + for (found = 0; found < current.count; ++found) { + if (current.masks[found] & (1 << exception)) { + break; + } + } + + // Nothing to forward + if (found == current.count) { + fprintf(stderr, "** No previous ports for forwarding!! \n"); + exit(KERN_FAILURE); + } + + mach_port_t target_port = current.ports[found]; + exception_behavior_t target_behavior = current.behaviors[found]; + thread_state_flavor_t target_flavor = current.flavors[found]; + + mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; + breakpad_thread_state_data_t thread_state; + switch (target_behavior) { + case EXCEPTION_DEFAULT: + result = exception_raise(target_port, failed_thread, task, exception, + code, code_count); + break; + + case EXCEPTION_STATE: + result = thread_get_state(failed_thread, target_flavor, thread_state, + &thread_state_count); + if (result == KERN_SUCCESS) + result = exception_raise_state(target_port, failed_thread, task, + exception, code, + code_count, &target_flavor, + thread_state, thread_state_count, + thread_state, &thread_state_count); + if (result == KERN_SUCCESS) + result = thread_set_state(failed_thread, target_flavor, thread_state, + thread_state_count); + break; + + case EXCEPTION_STATE_IDENTITY: + result = thread_get_state(failed_thread, target_flavor, thread_state, + &thread_state_count); + if (result == KERN_SUCCESS) + result = exception_raise_state_identity(target_port, failed_thread, + task, exception, code, + code_count, &target_flavor, + thread_state, + thread_state_count, + thread_state, + &thread_state_count); + if (result == KERN_SUCCESS) + result = thread_set_state(failed_thread, target_flavor, thread_state, + thread_state_count); + break; + + default: + fprintf(stderr, "** Unknown exception behavior\n"); + result = KERN_FAILURE; + break; + } + + return result; +} + +// Callback from exc_server() +kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count) { + return ForwardException(task, failed_thread, exception, code, code_count); +} + +// static +void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { + ExceptionHandler *self = + reinterpret_cast(exception_handler_class); + ExceptionMessage receive; + + // Wait for the exception info + while (1) { + receive.header.msgh_local_port = self->handler_port_; + receive.header.msgh_size = sizeof(receive); + kern_return_t result = mach_msg(&(receive.header), + MACH_RCV_MSG | MACH_RCV_LARGE, 0, + sizeof(receive), self->handler_port_, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + + if (result == KERN_SUCCESS) { + // Uninstall our handler so that we don't get in a loop if the process of + // writing out a minidump causes an exception. However, if the exception + // was caused by a fork'd process, don't uninstall things + + // If the actual exception code is zero, then we're calling this handler + // in a way that indicates that we want to either exit this thread or + // generate a minidump + // + // While reporting, all threads (except this one) must be suspended + // to avoid misleading stacks. If appropriate they will be resumed + // afterwards. + if (!receive.exception) { + if (self->is_in_teardown_) + return NULL; + + self->SuspendThreads(); + +#if USE_PROTECTED_ALLOCATIONS + if(gBreakpadAllocator) + gBreakpadAllocator->Unprotect(); +#endif + + // Write out the dump and save the result for later retrieval + self->last_minidump_write_result_ = + self->WriteMinidumpWithException(0, 0, 0); + + self->UninstallHandler(false); + +#if USE_PROTECTED_ALLOCATIONS + if(gBreakpadAllocator) + gBreakpadAllocator->Protect(); +#endif + + self->ResumeThreads(); + + if (self->use_minidump_write_mutex_) + pthread_mutex_unlock(&self->minidump_write_mutex_); + } else { + + // When forking a child process with the exception handler installed, + // if the child crashes, it will send the exception back to the parent + // process. The check for task == self_task() ensures that only + // exceptions that occur in the parent process are caught and + // processed. If the exception was not caused by this task, we + // still need to call into the exception server and have it return + // KERN_FAILURE (see breakpad_exception_raise) in order for the kernel + // to move onto the host exception handler for the child task + if (receive.task.name == mach_task_self()) { + self->SuspendThreads(); + +#if USE_PROTECTED_ALLOCATIONS + if(gBreakpadAllocator) + gBreakpadAllocator->Unprotect(); +#endif + + // Generate the minidump with the exception data. + self->WriteMinidumpWithException(receive.exception, receive.code[0], + receive.thread.name); + + self->UninstallHandler(true); + +#if USE_PROTECTED_ALLOCATIONS + if(gBreakpadAllocator) + gBreakpadAllocator->Protect(); +#endif + } + // Pass along the exception to the server, which will setup the + // message and call breakpad_exception_raise() and put the return + // code into the reply. + ExceptionReplyMessage reply; + if (!exc_server(&receive.header, &reply.header)) + exit(1); + + // Send a reply and exit + result = mach_msg(&(reply.header), MACH_SEND_MSG, + reply.header.msgh_size, 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + } + } + } + + return NULL; +} + +bool ExceptionHandler::InstallHandler() { + try { +#if USE_PROTECTED_ALLOCATIONS + previous_ = new (gBreakpadAllocator->Allocate(sizeof(ExceptionParameters)) ) + ExceptionParameters(); +#else + previous_ = new ExceptionParameters(); +#endif + + } + catch (std::bad_alloc) { + return false; + } + + // Save the current exception ports so that we can forward to them + previous_->count = EXC_TYPES_COUNT; + mach_port_t current_task = mach_task_self(); + kern_return_t result = task_get_exception_ports(current_task, + s_exception_mask, + previous_->masks, + &previous_->count, + previous_->ports, + previous_->behaviors, + previous_->flavors); + + // Setup the exception ports on this task + if (result == KERN_SUCCESS) + result = task_set_exception_ports(current_task, s_exception_mask, + handler_port_, EXCEPTION_DEFAULT, + THREAD_STATE_NONE); + + installed_exception_handler_ = (result == KERN_SUCCESS); + + return installed_exception_handler_; +} + +bool ExceptionHandler::UninstallHandler(bool in_exception) { + kern_return_t result = KERN_SUCCESS; + + if (installed_exception_handler_) { + mach_port_t current_task = mach_task_self(); + + // Restore the previous ports + for (unsigned int i = 0; i < previous_->count; ++i) { + result = task_set_exception_ports(current_task, previous_->masks[i], + previous_->ports[i], + previous_->behaviors[i], + previous_->flavors[i]); + if (result != KERN_SUCCESS) + return false; + } + + // this delete should NOT happen if an exception just occurred! + if (!in_exception) { +#if USE_PROTECTED_ALLOCATIONS + previous_->~ExceptionParameters(); +#else + delete previous_; +#endif + } + + previous_ = NULL; + installed_exception_handler_ = false; + } + + return result == KERN_SUCCESS; +} + +bool ExceptionHandler::Setup(bool install_handler) { + if (pthread_mutex_init(&minidump_write_mutex_, NULL)) + return false; + + // Create a receive right + mach_port_t current_task = mach_task_self(); + kern_return_t result = mach_port_allocate(current_task, + MACH_PORT_RIGHT_RECEIVE, + &handler_port_); + // Add send right + if (result == KERN_SUCCESS) + result = mach_port_insert_right(current_task, handler_port_, handler_port_, + MACH_MSG_TYPE_MAKE_SEND); + + if (install_handler && result == KERN_SUCCESS) + if (!InstallHandler()) + return false; + + if (result == KERN_SUCCESS) { + // Install the handler in its own thread, detached as we won't be joining. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + int thread_create_result = pthread_create(&handler_thread_, &attr, + &WaitForMessage, this); + pthread_attr_destroy(&attr); + result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS; + } + + return result == KERN_SUCCESS ? true : false; +} + +bool ExceptionHandler::Teardown() { + kern_return_t result = KERN_SUCCESS; + is_in_teardown_ = true; + + if (!UninstallHandler(false)) + return false; + + // Send an empty message so that the handler_thread exits + if (SendEmptyMachMessage()) { + mach_port_t current_task = mach_task_self(); + result = mach_port_deallocate(current_task, handler_port_); + if (result != KERN_SUCCESS) + return false; + } else { + return false; + } + + handler_thread_ = NULL; + handler_port_ = NULL; + pthread_mutex_destroy(&minidump_write_mutex_); + + return result == KERN_SUCCESS; +} + +bool ExceptionHandler::SendEmptyMachMessage() { + ExceptionMessage empty; + memset(&empty, 0, sizeof(empty)); + empty.header.msgh_size = sizeof(empty) - sizeof(empty.padding); + empty.header.msgh_remote_port = handler_port_; + empty.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, + MACH_MSG_TYPE_MAKE_SEND_ONCE); + kern_return_t result = mach_msg(&(empty.header), + MACH_SEND_MSG | MACH_SEND_TIMEOUT, + empty.header.msgh_size, 0, 0, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + return result == KERN_SUCCESS; +} + +void ExceptionHandler::UpdateNextID() { + next_minidump_path_ = + (MinidumpGenerator::UniqueNameInDirectory(dump_path_, &next_minidump_id_)); + + next_minidump_path_c_ = next_minidump_path_.c_str(); + next_minidump_id_c_ = next_minidump_id_.c_str(); +} + +bool ExceptionHandler::SuspendThreads() { + thread_act_port_array_t threads_for_task; + mach_msg_type_number_t thread_count; + + if (task_threads(mach_task_self(), &threads_for_task, &thread_count)) + return false; + + // suspend all of the threads except for this one + for (unsigned int i = 0; i < thread_count; ++i) { + if (threads_for_task[i] != mach_thread_self()) { + if (thread_suspend(threads_for_task[i])) + return false; + } + } + + return true; +} + +bool ExceptionHandler::ResumeThreads() { + thread_act_port_array_t threads_for_task; + mach_msg_type_number_t thread_count; + + if (task_threads(mach_task_self(), &threads_for_task, &thread_count)) + return false; + + // resume all of the threads except for this one + for (unsigned int i = 0; i < thread_count; ++i) { + if (threads_for_task[i] != mach_thread_self()) { + if (thread_resume(threads_for_task[i])) + return false; + } + } + + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.h new file mode 100644 index 00000000..2a8ee1e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler.h @@ -0,0 +1,212 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// exception_handler.h: MacOS exception handler +// This class can install a Mach exception port handler to trap most common +// programming errors. If an exception occurs, a minidump file will be +// generated which contains detailed information about the process and the +// exception. + +#ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ + +#include + +#include + +namespace google_breakpad { + +using std::string; + +struct ExceptionParameters; + +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, Breakpad + // will immediately report the exception as unhandled without writing a + // minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void *context); + + // A callback function to run after the minidump has been written. + // |minidump_id| is a unique id for the dump, so the minidump + // file is /.dmp. + // |context| is the value passed into the constructor. + // |succeeded| indicates whether a minidump file was successfully written. + // Return true if the exception was fully handled and breakpad should exit. + // Return false to allow any other exception handlers to process the + // exception. + typedef bool (*MinidumpCallback)(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded); + + // A callback function which will be called directly if an exception occurs. + // This bypasses the minidump file writing and simply gives the client + // the exception information. + typedef bool (*DirectCallback)( void *context, + int exception_type, + int exception_code, + mach_port_t thread_name); + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Minidump files will be written to dump_path, and the optional callback + // is called after writing the dump file, as described above. + // If install_handler is true, then a minidump will be written whenever + // an unhandled exception occurs. If it is false, minidumps will only + // be written when WriteMinidump is called. + ExceptionHandler(const string &dump_path, + FilterCallback filter, MinidumpCallback callback, + void *callback_context, bool install_handler); + + // A special constructor if we want to bypass minidump writing and + // simply get a callback with the exception information. + ExceptionHandler(DirectCallback callback, + void *callback_context, + bool install_handler); + + ~ExceptionHandler(); + + // Get and set the minidump path. + string dump_path() const { return dump_path_; } + void set_dump_path(const string &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const string &dump_path, MinidumpCallback callback, + void *callback_context); + + private: + // Install the mach exception handler + bool InstallHandler(); + + // Uninstall the mach exception handler (if any) + bool UninstallHandler(bool in_exception); + + // Setup the handler thread, and if |install_handler| is true, install the + // mach exception port handler + bool Setup(bool install_handler); + + // Uninstall the mach exception handler (if any) and terminate the helper + // thread + bool Teardown(); + + // Send an "empty" mach message to the exception handler. Return true on + // success, false otherwise + bool SendEmptyMachMessage(); + + // All minidump writing goes through this one routine + bool WriteMinidumpWithException(int exception_type, int exception_code, + mach_port_t thread_name); + + // When installed, this static function will be call from a newly created + // pthread with |this| as the argument + static void *WaitForMessage(void *exception_handler_class); + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); + + // Generates a new ID and stores it in next_minidump_id_, and stores the + // path of the next minidump to be written in next_minidump_path_. + void UpdateNextID(); + + // These functions will suspend/resume all threads except for the + // reporting thread + bool SuspendThreads(); + bool ResumeThreads(); + + // The destination directory for the minidump + string dump_path_; + + // The basename of the next minidump w/o extension + string next_minidump_id_; + + // The full path to the next minidump to be written, including extension + string next_minidump_path_; + + // Pointers to the UTF-8 versions of above + const char *dump_path_c_; + const char *next_minidump_id_c_; + const char *next_minidump_path_c_; + + // The callback function and pointer to be passed back after the minidump + // has been written + FilterCallback filter_; + MinidumpCallback callback_; + void *callback_context_; + + // The callback function to be passed back when we don't want a minidump + // file to be written + DirectCallback directCallback_; + + // The thread that is created for the handler + pthread_t handler_thread_; + + // The port that is waiting on an exception message to be sent, if the + // handler is installed + mach_port_t handler_port_; + + // These variables save the previous exception handler's data so that it + // can be re-installed when this handler is uninstalled + ExceptionParameters *previous_; + + // True, if we've installed the exception handler + bool installed_exception_handler_; + + // True, if we're in the process of uninstalling the exception handler and + // the thread. + bool is_in_teardown_; + + // Save the last result of the last minidump + bool last_minidump_write_result_; + + // A mutex for use when writing out a minidump that was requested on a + // thread other than the exception handler. + pthread_mutex_t minidump_write_mutex_; + + // True, if we're using the mutext to indicate when mindump writing occurs + bool use_minidump_write_mutex_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler_test.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler_test.cc new file mode 100644 index 00000000..59944377 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/exception_handler_test.cc @@ -0,0 +1,107 @@ +// 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. + +/* +g++ -framework CoreFoundation -I../../.. \ + ../../minidump_file_writer.cc \ + ../../../common/convert_UTF.c \ + ../../../common/string_conversion.cc \ + ../../../common/mac/string_utilities.cc \ + exception_handler.cc \ + minidump_generator.cc \ + exception_handler_test.cc \ + -o exception_handler_test +*/ + +#include +#include +#include + +#include + +#include "exception_handler.h" +#include "minidump_generator.h" + +using std::string; +using google_breakpad::ExceptionHandler; + +static void *SleepyFunction(void *) { + while (1) { + sleep(10000); + } +} + +static void Crasher() { + int *a = NULL; + + fprintf(stdout, "Going to crash...\n"); + fprintf(stdout, "A = %d", *a); +} + +static void SoonToCrash() { + Crasher(); +} + +bool MDCallback(const char *dump_dir, const char *file_name, + void *context, bool success) { + string path(dump_dir); + string dest(dump_dir); + path.append(file_name); + path.append(".dmp"); + + fprintf(stdout, "Minidump: %s\n", path.c_str()); + // Indicate that we've handled the callback + return true; +} + +int main(int argc, char * const argv[]) { + char buffer[PATH_MAX]; + struct passwd *user = getpwuid(getuid()); + + // Home dir + snprintf(buffer, sizeof(buffer), "/Users/%s/Desktop/", user->pw_name); + + string path(buffer); + ExceptionHandler eh(path, NULL, MDCallback, NULL, true); + pthread_t t; + + if (pthread_create(&t, NULL, SleepyFunction, NULL) == 0) { + pthread_detach(t); + } else { + perror("pthread_create"); + } + + // Dump a test + eh.WriteMinidump(); + + // Test the handler + SoonToCrash(); + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.cc new file mode 100644 index 00000000..e6ebce4f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.cc @@ -0,0 +1,989 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "client/mac/handler/minidump_generator.h" +#include "client/minidump_file_writer-inl.h" +#include "common/mac/file_id.h" +#include "common/mac/string_utilities.h" + +using MacStringUtils::ConvertToString; +using MacStringUtils::IntegerValueAtIndex; + +namespace google_breakpad { + +// constructor when generating from within the crashed process +MinidumpGenerator::MinidumpGenerator() + : exception_type_(0), + exception_code_(0), + exception_thread_(0), + crashing_task_(mach_task_self()), + handler_thread_(mach_thread_self()), + dynamic_images_(NULL) { + GatherSystemInformation(); +} + +// constructor when generating from a different process than the +// crashed process +MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, + mach_port_t handler_thread) + : exception_type_(0), + exception_code_(0), + exception_thread_(0), + crashing_task_(crashing_task), + handler_thread_(handler_thread) { + if (crashing_task != mach_task_self()) { + dynamic_images_ = new DynamicImages(crashing_task_); + } else { + dynamic_images_ = NULL; + } + + GatherSystemInformation(); +} + +MinidumpGenerator::~MinidumpGenerator() { + delete dynamic_images_; +} + +char MinidumpGenerator::build_string_[16]; +int MinidumpGenerator::os_major_version_ = 0; +int MinidumpGenerator::os_minor_version_ = 0; +int MinidumpGenerator::os_build_number_ = 0; + +// static +void MinidumpGenerator::GatherSystemInformation() { + // If this is non-zero, then we've already gathered the information + if (os_major_version_) + return; + + // This code extracts the version and build information from the OS + CFStringRef vers_path = + CFSTR("/System/Library/CoreServices/SystemVersion.plist"); + CFURLRef sys_vers = + CFURLCreateWithFileSystemPath(NULL, + vers_path, + kCFURLPOSIXPathStyle, + false); + CFDataRef data; + SInt32 error; + CFURLCreateDataAndPropertiesFromResource(NULL, sys_vers, &data, NULL, NULL, + &error); + + if (!data) + return; + + CFDictionaryRef list = static_cast + (CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, + NULL)); + if (!list) + return; + + CFStringRef build_version = static_cast + (CFDictionaryGetValue(list, CFSTR("ProductBuildVersion"))); + CFStringRef product_version = static_cast + (CFDictionaryGetValue(list, CFSTR("ProductVersion"))); + string build_str = ConvertToString(build_version); + string product_str = ConvertToString(product_version); + + CFRelease(list); + CFRelease(sys_vers); + CFRelease(data); + + strlcpy(build_string_, build_str.c_str(), sizeof(build_string_)); + + // Parse the string that looks like "10.4.8" + os_major_version_ = IntegerValueAtIndex(product_str, 0); + os_minor_version_ = IntegerValueAtIndex(product_str, 1); + os_build_number_ = IntegerValueAtIndex(product_str, 2); +} + +string MinidumpGenerator::UniqueNameInDirectory(const string &dir, + string *unique_name) { + CFUUIDRef uuid = CFUUIDCreate(NULL); + CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid); + CFRelease(uuid); + string file_name(ConvertToString(uuid_cfstr)); + CFRelease(uuid_cfstr); + string path(dir); + + // Ensure that the directory (if non-empty) has a trailing slash so that + // we can append the file name and have a valid pathname. + if (!dir.empty()) { + if (dir.at(dir.size() - 1) != '/') + path.append(1, '/'); + } + + path.append(file_name); + path.append(".dmp"); + + if (unique_name) + *unique_name = file_name; + + return path; +} + +bool MinidumpGenerator::Write(const char *path) { + WriteStreamFN writers[] = { + &MinidumpGenerator::WriteThreadListStream, + &MinidumpGenerator::WriteSystemInfoStream, + &MinidumpGenerator::WriteModuleListStream, + &MinidumpGenerator::WriteMiscInfoStream, + &MinidumpGenerator::WriteBreakpadInfoStream, + // Exception stream needs to be the last entry in this array as it may + // be omitted in the case where the minidump is written without an + // exception. + &MinidumpGenerator::WriteExceptionStream, + }; + bool result = true; + + // If opening was successful, create the header, directory, and call each + // writer. The destructor for the TypedMDRVAs will cause the data to be + // flushed. The destructor for the MinidumpFileWriter will close the file. + if (writer_.Open(path)) { + TypedMDRVA header(&writer_); + TypedMDRVA dir(&writer_); + + if (!header.Allocate()) + return false; + + int writer_count = sizeof(writers) / sizeof(writers[0]); + + // If we don't have exception information, don't write out the + // exception stream + if (!exception_thread_ && !exception_type_) + --writer_count; + + // Add space for all writers + if (!dir.AllocateArray(writer_count)) + return false; + + MDRawHeader *header_ptr = header.get(); + header_ptr->signature = MD_HEADER_SIGNATURE; + header_ptr->version = MD_HEADER_VERSION; + time(reinterpret_cast(&(header_ptr->time_date_stamp))); + header_ptr->stream_count = writer_count; + header_ptr->stream_directory_rva = dir.position(); + + MDRawDirectory local_dir; + for (int i = 0; (result) && (i < writer_count); ++i) { + result = (this->*writers[i])(&local_dir); + + if (result) + dir.CopyIndex(i, &local_dir); + } + } + return result; +} + +size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) { + mach_vm_address_t stack_region_base = start_addr; + mach_vm_size_t stack_region_size; + natural_t nesting_level = 0; + vm_region_submap_info_64 submap_info; + mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64; + + vm_region_recurse_info_t region_info; + region_info = reinterpret_cast(&submap_info); + + if (start_addr == 0) { + return 0; + } + + kern_return_t result = + mach_vm_region_recurse(crashing_task_, &stack_region_base, + &stack_region_size, &nesting_level, + region_info, + &info_count); + + if (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) { + // 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 + + // Because of the above, we'll add 4k to include the original + // stack frame page. + // This method of finding the stack region needs to be done in + // a better way; the breakpad issue 247 is tracking this. + stack_region_size += 0x1000; + } + + return result == KERN_SUCCESS ? + stack_region_base + stack_region_size - start_addr : 0; +} + +bool MinidumpGenerator::WriteStackFromStartAddress( + mach_vm_address_t start_addr, + MDMemoryDescriptor *stack_location) { + UntypedMDRVA memory(&writer_); + + bool result = false; + size_t size = CalculateStackSize(start_addr); + + if (size == 0) { + // In some situations the stack address for the thread can come back 0. + // In these cases we skip over the threads in question and stuff the + // stack with a clearly borked value. + start_addr = 0xDEADBEEF; + size = 16; + if (!memory.Allocate(size)) + return false; + + unsigned long long dummy_stack[2]; // Fill dummy stack with 16 bytes of + // junk. + dummy_stack[0] = 0xDEADBEEF; + dummy_stack[1] = 0xDEADBEEF; + + result = memory.Copy(dummy_stack, size); + } else { + + if (!memory.Allocate(size)) + return false; + + if (dynamic_images_) { + + kern_return_t kr; + + void *stack_memory = ReadTaskMemory(crashing_task_, + (void*)start_addr, + size, + &kr); + + if (stack_memory == NULL) { + return false; + } + + result = memory.Copy(stack_memory, size); + free(stack_memory); + } else { + result = memory.Copy(reinterpret_cast(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(state); +#if TARGET_CPU_PPC + mach_vm_address_t start_addr = machine_state->r1; +#else + mach_vm_address_t start_addr = machine_state->__r1; +#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(state); + +#if TARGET_CPU_PPC + return machine_state->srr0; +#else + return machine_state->__srr0; +#endif +} + +bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, + MDLocationDescriptor *register_location) { + TypedMDRVA context(&writer_); + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + if (!context.Allocate()) + return false; + + *register_location = context.location(); + MinidumpContext *context_ptr = context.get(); + context_ptr->context_flags = MD_CONTEXT_PPC_BASE; + +#if TARGET_CPU_PPC64 +#define AddReg(a) context_ptr->a = machine_state->__ ## a +#define AddGPR(a) context_ptr->gpr[a] = machine_state->__r ## a +#else +#define AddReg(a) context_ptr->a = machine_state->a +#define AddGPR(a) context_ptr->gpr[a] = machine_state->r ## a +#endif + + 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); + +#if TARGET_CPU_PPC + /* The mq register is only for PPC */ + AddReg(mq); +#endif + + + 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(state); + +#if TARGET_CPU_X86_64 + mach_vm_address_t start_addr = machine_state->__rsp; +#else + mach_vm_address_t start_addr = 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(state); + +#if TARGET_CPU_X86_64 + return machine_state->__rip; +#else + return machine_state->eip; +#endif +} + +bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, + MDLocationDescriptor *register_location) { + TypedMDRVA context(&writer_); + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + if (!context.Allocate()) + return false; + + *register_location = context.location(); + MinidumpContext *context_ptr = context.get(); + +#if TARGET_CPU_X86 + context_ptr->context_flags = MD_CONTEXT_X86; + +#define AddReg(a) context_ptr->a = machine_state->a + AddReg(eax); + AddReg(ebx); + AddReg(ecx); + AddReg(edx); + AddReg(esi); + AddReg(edi); + AddReg(ebp); + AddReg(esp); + + AddReg(cs); + AddReg(ds); + AddReg(ss); + AddReg(es); + AddReg(fs); + AddReg(gs); + AddReg(eflags); + + AddReg(eip); +#else + +#define AddReg(a) context_ptr->a = machine_state->__ ## a + context_ptr->context_flags = MD_CONTEXT_AMD64; + AddReg(rax); + AddReg(rbx); + AddReg(rcx); + AddReg(rdx); + AddReg(rdi); + AddReg(rsi); + AddReg(rbp); + AddReg(rsp); + AddReg(r8); + AddReg(r9); + AddReg(r10); + AddReg(r11); + AddReg(r12); + AddReg(r13); + AddReg(r14); + AddReg(r15); + AddReg(rip); + // according to AMD's software developer guide, bits above 18 are + // not used in the flags register. Since the minidump format + // specifies 32 bits for the flags register, we can truncate safely + // with no loss. + context_ptr->eflags = machine_state->__rflags; + AddReg(cs); + AddReg(fs); + AddReg(gs); +#endif + + return true; +} +#endif + +bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id, + MDRawThread *thread) { + breakpad_thread_state_data_t state; + mach_msg_type_number_t state_count = sizeof(state); + + if (thread_get_state(thread_id, BREAKPAD_MACHINE_THREAD_STATE, + state, &state_count) == + KERN_SUCCESS) { + if (!WriteStack(state, &thread->stack)) + return false; + + if (!WriteContext(state, &thread->thread_context)) + return false; + + thread->thread_id = thread_id; + } else { + return false; + } + + return true; +} + +bool MinidumpGenerator::WriteThreadListStream( + MDRawDirectory *thread_list_stream) { + TypedMDRVA list(&writer_); + thread_act_port_array_t threads_for_task; + mach_msg_type_number_t thread_count; + int non_generator_thread_count; + + if (task_threads(crashing_task_, &threads_for_task, &thread_count)) + return false; + + // Don't include the generator thread + non_generator_thread_count = thread_count - 1; + if (!list.AllocateObjectAndArray(non_generator_thread_count, + sizeof(MDRawThread))) + return false; + + thread_list_stream->stream_type = MD_THREAD_LIST_STREAM; + thread_list_stream->location = list.location(); + + list.get()->number_of_threads = non_generator_thread_count; + + MDRawThread thread; + int thread_idx = 0; + + for (unsigned int i = 0; i < thread_count; ++i) { + memset(&thread, 0, sizeof(MDRawThread)); + + if (threads_for_task[i] != handler_thread_) { + if (!WriteThreadStream(threads_for_task[i], &thread)) + return false; + + list.CopyIndexAfterObject(thread_idx++, &thread, sizeof(MDRawThread)); + } + } + + return true; +} + +bool +MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) { + TypedMDRVA exception(&writer_); + + if (!exception.Allocate()) + return false; + + exception_stream->stream_type = MD_EXCEPTION_STREAM; + exception_stream->location = exception.location(); + MDRawExceptionStream *exception_ptr = exception.get(); + exception_ptr->thread_id = exception_thread_; + + // 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 = sizeof(state); + + if (thread_get_state(exception_thread_, + BREAKPAD_MACHINE_THREAD_STATE, + state, + &stateCount) != KERN_SUCCESS) + return false; + + if (!WriteContext(state, &exception_ptr->thread_context)) + return false; + + exception_ptr->exception_record.exception_address = CurrentPCForStack(state); + + return true; +} + +bool MinidumpGenerator::WriteSystemInfoStream( + MDRawDirectory *system_info_stream) { + TypedMDRVA info(&writer_); + + if (!info.Allocate()) + return false; + + system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM; + system_info_stream->location = info.location(); + + // CPU Information + uint32_t 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); + sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0); + MDRawSystemInfo *info_ptr = info.get(); + + switch (cpu_type) { + case CPU_TYPE_POWERPC: + info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC; + break; + case CPU_TYPE_I386: + info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86; +#ifdef __i386__ + // ebx is used for PIC code, so we need + // to preserve it. +#define cpuid(op,eax,ebx,ecx,edx) \ + asm ("pushl %%ebx \n\t" \ + "cpuid \n\t" \ + "movl %%ebx,%1 \n\t" \ + "popl %%ebx" \ + : "=a" (eax), \ + "=g" (ebx), \ + "=c" (ecx), \ + "=d" (edx) \ + : "0" (op)) + int unused, unused2; + // get vendor id + cpuid(0, unused, info_ptr->cpu.x86_cpu_info.vendor_id[0], + info_ptr->cpu.x86_cpu_info.vendor_id[2], + info_ptr->cpu.x86_cpu_info.vendor_id[1]); + // get version and feature info + cpuid(1, info_ptr->cpu.x86_cpu_info.version_information, unused, unused2, + info_ptr->cpu.x86_cpu_info.feature_information); + // family + info_ptr->processor_level = + (info_ptr->cpu.x86_cpu_info.version_information & 0xF00) >> 8; + // 0xMMSS (Model, Stepping) + info_ptr->processor_revision = + (info_ptr->cpu.x86_cpu_info.version_information & 0xF) | + ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0) << 4); +#endif // __i386__ + break; + default: + info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; + break; + } + + info_ptr->number_of_processors = number_of_processors; + info_ptr->platform_id = MD_OS_MAC_OS_X; + + MDLocationDescriptor build_string_loc; + + if (!writer_.WriteString(build_string_, 0, + &build_string_loc)) + return false; + + info_ptr->csd_version_rva = build_string_loc.rva; + info_ptr->major_version = os_major_version_; + info_ptr->minor_version = os_minor_version_; + info_ptr->build_number = os_build_number_; + + return true; +} + +void setVersion(MDRawModule *module, uint32_t version, bool isMainExecutable) +{ + module->version_info.signature = MD_VSFIXEDFILEINFO_SIGNATURE; + module->version_info.struct_version |= MD_VSFIXEDFILEINFO_VERSION; + if (!isMainExecutable) { + // Convert MAC dylib version format, which is a 32 bit number, to the + // format used by minidump. The mac format is <16 bits>.<8 bits>.<8 bits> + // so it fits nicely into the windows version with some massaging + // The mapping is: + // 1) upper 16 bits of MAC version go to lower 16 bits of product HI + // 2) Next most significant 8 bits go to upper 16 bits of product LO + // 3) Least significant 8 bits go to lower 16 bits of product LO + module->version_info.file_version_hi = 0; + module->version_info.file_version_hi = version >> 16; + module->version_info.file_version_lo = (version & 0xff00) << 8; + module->version_info.file_version_lo |= (version & 0xff); + } else { + // Convert the __TEXT __version section of the main executable + module->version_info.file_version_hi = (version & 0xff000000) >> 8; + module->version_info.file_version_hi |= (version & 0x00ff0000) >> 16; + module->version_info.file_version_lo = (version & 0x0000ff00) << 8; + module->version_info.file_version_lo |= (version & 0x000000ff); + } +} + +bool MinidumpGenerator::WriteModuleStream(unsigned int index, + MDRawModule *module) { + if (dynamic_images_) { + // we're in a different process than the crashed process + DynamicImage *image = dynamic_images_->GetImage(index); + + if (!image) + return false; + + 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)) + return false; + + module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide(); + module->size_of_image = image->GetVMSize(); + module->module_name_rva = string_location.rva; + + setVersion(module, image->GetVersion(), index == (uint32_t)FindExecutableModule()); + + if (!WriteCVRecord(module, cpu_type, name)) { + return false; + } + } else { + // we're 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); + + if(header->magic != MH_MAGIC_64) + return false; +#else + assert(header->magic == MH_MAGIC); + + if(header->magic != MH_MAGIC) + return false; +#endif + + int cpu_type = header->cputype; + unsigned long slide = _dyld_get_image_vmaddr_slide(index); + const char* name = _dyld_get_image_name(index); + const struct load_command *cmd = + reinterpret_cast(header + 1); + + memset(module, 0, sizeof(MDRawModule)); + + for (unsigned int i = 0; cmd && (i < header->ncmds); i++) { + if (cmd->cmd == LC_SEGMENT) { + + const breakpad_mach_segment_command *seg = + reinterpret_cast(cmd); + + if (!strcmp(seg->segname, "__TEXT")) { + MDLocationDescriptor string_location; + + if (!writer_.WriteString(name, 0, &string_location)) + return false; + + module->base_of_image = seg->vmaddr + slide; + module->size_of_image = seg->vmsize; + module->module_name_rva = string_location.rva; + + // The header MUST NOT be copied, but as it is free'd by the DynamicImage destructor, we have to leak the DynamicImage + // The other option is to rewrite the content of DynamicImage::CalculateMemoryAndVersionInfo() to get the version + DynamicImage *image = new DynamicImage((breakpad_mach_header*)header, 0, NULL, (char*)name, 0, MACH_PORT_NULL); + setVersion(module, image->GetVersion(), index == (uint32_t)FindExecutableModule()); + + if (!WriteCVRecord(module, cpu_type, name)) + return false; + + return true; + } + } + + cmd = reinterpret_cast((char *)cmd + cmd->cmdsize); + } + } + + return true; +} + +int MinidumpGenerator::FindExecutableModule() { + if (dynamic_images_) { + int index = dynamic_images_->GetExecutableImageIndex(); + + if (index >= 0) { + return index; + } + } else { + int image_count = _dyld_image_count(); + const struct mach_header *header; + + for (int index = 0; index < image_count; ++index) { + header = _dyld_get_image_header(index); + + if (header->filetype == MH_EXECUTE) + return index; + } + } + + // failed - just use the first image + return 0; +} + +bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type, + const char *module_path) { + TypedMDRVA cv(&writer_); + + // Only return the last path component of the full module path + const char *module_name = strrchr(module_path, '/'); + + // Increment past the slash + if (module_name) + ++module_name; + else + module_name = ""; + + size_t module_name_length = strlen(module_name); + + if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t))) + return false; + + if (!cv.CopyIndexAfterObject(0, module_name, module_name_length)) + return false; + + module->cv_record = cv.location(); + MDCVInfoPDB70 *cv_ptr = cv.get(); + cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE; + cv_ptr->age = 0; + + // Get the module identifier + FileID file_id(module_path); + unsigned char identifier[16]; + + if (file_id.MachoIdentifier(cpu_type, identifier)) { + cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 | + (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 | + (uint32_t)identifier[3]; + cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5]; + cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7]; + cv_ptr->signature.data4[0] = identifier[8]; + cv_ptr->signature.data4[1] = identifier[9]; + cv_ptr->signature.data4[2] = identifier[10]; + cv_ptr->signature.data4[3] = identifier[11]; + cv_ptr->signature.data4[4] = identifier[12]; + cv_ptr->signature.data4[5] = identifier[13]; + cv_ptr->signature.data4[6] = identifier[14]; + cv_ptr->signature.data4[7] = identifier[15]; + } + + return true; +} + +bool MinidumpGenerator::WriteModuleListStream( + MDRawDirectory *module_list_stream) { + TypedMDRVA list(&writer_); + + int image_count = dynamic_images_ ? + dynamic_images_->GetImageCount() : _dyld_image_count(); + + if (!list.AllocateObjectAndArray(image_count, MD_MODULE_SIZE)) + return false; + + module_list_stream->stream_type = MD_MODULE_LIST_STREAM; + module_list_stream->location = list.location(); + list.get()->number_of_modules = image_count; + + // Write out the executable module as the first one + MDRawModule module; + int executableIndex = FindExecutableModule(); + + if (!WriteModuleStream(executableIndex, &module)) { + return false; + } + + list.CopyIndexAfterObject(0, &module, MD_MODULE_SIZE); + int destinationIndex = 1; // Write all other modules after this one + + for (int i = 0; i < image_count; ++i) { + if (i != executableIndex) { + if (!WriteModuleStream(i, &module)) { + return false; + } + + list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE); + } + } + + return true; +} + +bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *misc_info_stream) { + TypedMDRVA info(&writer_); + + if (!info.Allocate()) + return false; + + misc_info_stream->stream_type = MD_MISC_INFO_STREAM; + misc_info_stream->location = info.location(); + + MDRawMiscInfo *info_ptr = info.get(); + info_ptr->size_of_info = sizeof(MDRawMiscInfo); + info_ptr->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID | + MD_MISCINFO_FLAGS1_PROCESS_TIMES | + MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO; + + // Process ID + info_ptr->process_id = getpid(); + + // Times + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage) != -1) { + // Omit the fractional time since the MDRawMiscInfo only wants seconds + info_ptr->process_user_time = usage.ru_utime.tv_sec; + info_ptr->process_kernel_time = usage.ru_stime.tv_sec; + } + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, info_ptr->process_id }; + size_t size; + if (!sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &size, NULL, 0)) { + mach_vm_address_t addr; + if (mach_vm_allocate(mach_task_self(), + &addr, + size, + true) == KERN_SUCCESS) { + struct kinfo_proc *proc = (struct kinfo_proc *)addr; + if (!sysctl(mib, sizeof(mib) / sizeof(mib[0]), proc, &size, NULL, 0)) + info_ptr->process_create_time = proc->kp_proc.p_starttime.tv_sec; + mach_vm_deallocate(mach_task_self(), addr, size); + } + } + + // Speed + uint64_t speed; + size = sizeof(speed); + sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0); + info_ptr->processor_max_mhz = speed / (1000 * 1000); + info_ptr->processor_mhz_limit = speed / (1000 * 1000); + size = sizeof(speed); + sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0); + info_ptr->processor_current_mhz = speed / (1000 * 1000); + + return true; +} + +bool MinidumpGenerator::WriteBreakpadInfoStream( + MDRawDirectory *breakpad_info_stream) { + TypedMDRVA info(&writer_); + + if (!info.Allocate()) + return false; + + breakpad_info_stream->stream_type = MD_BREAKPAD_INFO_STREAM; + breakpad_info_stream->location = info.location(); + MDRawBreakpadInfo *info_ptr = info.get(); + + if (exception_thread_ && exception_type_) { + info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; + info_ptr->dump_thread_id = handler_thread_; + info_ptr->requesting_thread_id = exception_thread_; + } else { + info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID; + info_ptr->dump_thread_id = handler_thread_; + info_ptr->requesting_thread_id = 0; + } + + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.h new file mode 100644 index 00000000..0d3424c3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator.h @@ -0,0 +1,157 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_generator.h: Create a minidump of the current MacOS process. + +#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ +#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ + +#include + +#include + +#include "client/minidump_file_writer.h" +#include "google_breakpad/common/minidump_format.h" +#include "common/mac/macho_utilities.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 + +// Creates a minidump file of the current process. If there is exception data, +// use SetExceptionInformation() to add this to the minidump. The minidump +// file is generated by the Write() function. +// Usage: +// MinidumpGenerator minidump(); +// minidump.Write("/tmp/minidump"); +// +class MinidumpGenerator { + public: + MinidumpGenerator(); + MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread); + + ~MinidumpGenerator(); + + // Return /.dmp + // Sets |unique_name| (if requested) to the unique name for the minidump + static string UniqueNameInDirectory(const string &dir, string *unique_name); + + // Write out the minidump into |path| + // All of the components of |path| must exist and be writable + // Return true if successful, false otherwise + bool Write(const char *path); + + // Specify some exception information, if applicable + void SetExceptionInformation(int type, int code, mach_port_t thread_name) { + exception_type_ = type; + exception_code_ = code; + exception_thread_ = thread_name; + } + + // Gather system information. This should be call at least once before using + // the MinidumpGenerator class. + static void GatherSystemInformation(); + + private: + typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *); + + // Stream writers + bool WriteThreadListStream(MDRawDirectory *thread_list_stream); + 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 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(); + + // 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_; + mach_port_t exception_thread_; + mach_port_t crashing_task_; + mach_port_t handler_thread_; + + // 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 + DynamicImages *dynamic_images_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator_test.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator_test.cc new file mode 100644 index 00000000..62530832 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_generator_test.cc @@ -0,0 +1,82 @@ +// 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 + +#include +#include + +#include + +#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; + struct passwd *user = getpwuid(getuid()); + + // Write it to the desktop + snprintf(buffer, + sizeof(buffer), + "/Users/%s/Desktop/test.dmp", + user->pw_name); + + 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; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests32-Info.plist b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests32-Info.plist new file mode 100644 index 00000000..921ebf35 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests32-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.breakpad.minidump_tests32 + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests64-Info.plist b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests64-Info.plist new file mode 100644 index 00000000..acfbd309 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/minidump_tests64-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.breakpad.minidump_tests64 + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + yes + + diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/obj-cTestCases-Info.plist b/thirdparty/google-breakpad/r318/src/client/mac/handler/obj-cTestCases-Info.plist new file mode 100644 index 00000000..65013556 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/obj-cTestCases-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.cc new file mode 100644 index 00000000..10768541 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// ProtectedMemoryAllocator +// +// See the header file for documentation + +#include "protected_memory_allocator.h" +#include + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ProtectedMemoryAllocator::ProtectedMemoryAllocator(vm_size_t pool_size) + : pool_size_(pool_size), + next_alloc_offset_(0), + valid_(false) { + + kern_return_t result = vm_allocate(mach_task_self(), + &base_address_, + pool_size, + TRUE + ); + + valid_ = (result == KERN_SUCCESS); + assert(valid_); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ProtectedMemoryAllocator::~ProtectedMemoryAllocator() { + vm_deallocate(mach_task_self(), + base_address_, + pool_size_ + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +char *ProtectedMemoryAllocator::Allocate(size_t bytes) { + if (valid_ && next_alloc_offset_ + bytes <= pool_size_) { + char *p = (char*)base_address_ + next_alloc_offset_; + next_alloc_offset_ += bytes; + return p; + } + + return NULL; // ran out of memory in our allocation block +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +kern_return_t ProtectedMemoryAllocator::Protect() { + kern_return_t result = vm_protect(mach_task_self(), + base_address_, + pool_size_, + FALSE, + VM_PROT_READ); + + return result; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +kern_return_t ProtectedMemoryAllocator::Unprotect() { + kern_return_t result = vm_protect(mach_task_self(), + base_address_, + pool_size_, + FALSE, + VM_PROT_READ | VM_PROT_WRITE); + + return result; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.h new file mode 100644 index 00000000..ed4f51d5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/protected_memory_allocator.h @@ -0,0 +1,85 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// ProtectedMemoryAllocator +// +// A very simple allocator class which allows allocation, but not deallocation. +// The allocations can be made read-only with the Protect() method. +// This class is NOT useful as a general-purpose memory allocation system, +// since it does not allow deallocation. It is useful to use for a group +// of allocations which are created in the same time-frame and destroyed +// in the same time-frame. It is useful for making allocations of memory +// which will not need to change often once initialized. This memory can then +// be protected from memory smashers by calling the Protect() method. + +#ifndef PROTECTED_MEMORY_ALLOCATOR_H__ +#define PROTECTED_MEMORY_ALLOCATOR_H__ + +#include + +// +class ProtectedMemoryAllocator { + public: + ProtectedMemoryAllocator(vm_size_t pool_size); + ~ProtectedMemoryAllocator(); + + // Returns a pointer to an allocation of size n within the pool. + // Fails by returning NULL is no more space is available. + // Please note that the pointers returned from this method should not + // be freed in any way (for example by calling free() on them ). + char * Allocate(size_t n); + + // Returns the base address of the allocation pool. + char * GetBaseAddress() { return (char*)base_address_; } + + // Returns the size of the allocation pool, including allocated + // plus free space. + vm_size_t GetTotalSize() { return pool_size_; } + + // Returns the number of bytes already allocated in the pool. + vm_size_t GetAllocatedSize() { return next_alloc_offset_; } + + // Returns the number of bytes available for allocation. + vm_size_t GetFreeSize() { return pool_size_ - next_alloc_offset_; } + + // Makes the entire allocation pool read-only including, of course, + // all allocations made from the pool. + kern_return_t Protect(); + + // Makes the entire allocation pool read/write. + kern_return_t Unprotect(); + + private: + vm_size_t pool_size_; + vm_address_t base_address_; + int next_alloc_offset_; + bool valid_; +}; + +#endif // PROTECTED_MEMORY_ALLOCATOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.cc new file mode 100644 index 00000000..cb76eb10 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// DynamicImagesTests.cpp +// minidump_test +// +// Created by Neal Sidhwaney on 4/17/08. +// Copyright 2008 Google Inc. All rights reserved. +// + +#include "client/mac/handler/testcases/DynamicImagesTests.h" +#include "client/mac/handler/dynamic_images.h" + +DynamicImagesTests test2(TEST_INVOCATION(DynamicImagesTests, + ReadTaskMemoryTest)); +DynamicImagesTests test3(TEST_INVOCATION(DynamicImagesTests, + ReadLibrariesFromLocalTaskTest)); + +DynamicImagesTests::DynamicImagesTests(TestInvocation *invocation) + : TestCase(invocation) { +} + +DynamicImagesTests::~DynamicImagesTests() { +} + +void DynamicImagesTests::ReadTaskMemoryTest() { + kern_return_t kr; + + // pick test2 as a symbol we know to be valid to read + // anything will work, really + void *addr = reinterpret_cast(&test2); + void *buf; + + fprintf(stderr, "reading 0x%p\n", addr); + buf = google_breakpad::ReadTaskMemory(mach_task_self(), + addr, + getpagesize(), + &kr); + + CPTAssert(kr == KERN_SUCCESS); + + CPTAssert(buf != NULL); + + CPTAssert(0 == memcmp(buf, (const void*)addr, getpagesize())); + + free(buf); +} + +void DynamicImagesTests::ReadLibrariesFromLocalTaskTest() { + + mach_port_t me = mach_task_self(); + google_breakpad::DynamicImages *d = new google_breakpad::DynamicImages(me); + + fprintf(stderr,"Local task image count: %d\n", d->GetImageCount()); + + d->TestPrint(); + + CPTAssert(d->GetImageCount() > 0); +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.h new file mode 100644 index 00000000..e1e79993 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/DynamicImagesTests.h @@ -0,0 +1,52 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// DynamicImagesTests.h +// minidump_test +// +// Created by Neal Sidhwaney on 4/17/08. +// Copyright 2008 Google Inc. All rights reserved. +// +// + +#ifndef _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__ +#define _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__ + +#include + +class DynamicImagesTests : public TestCase { + public: + explicit DynamicImagesTests(TestInvocation* invocation); + virtual ~DynamicImagesTests(); + + void ReadTaskMemoryTest(); + void ReadLibrariesFromLocalTaskTest(); +}; + +#endif /* _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.cc b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.cc new file mode 100644 index 00000000..e7332bfb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// breakpad_nlist_test.cc +// minidump_test +// +// Created by Neal Sidhwaney on 4/13/08. +// Copyright 2008 Google Inc. All rights reserved. +// + +#include "client/mac/handler/testcases/breakpad_nlist_test.h" +#include +#include "client/mac/handler/breakpad_nlist_64.h" + +BreakpadNlistTest test1(TEST_INVOCATION(BreakpadNlistTest, CompareToNM)); + +BreakpadNlistTest::BreakpadNlistTest(TestInvocation *invocation) + : TestCase(invocation) { +} + + +BreakpadNlistTest::~BreakpadNlistTest() { +} + +void BreakpadNlistTest::CompareToNM() { +#if TARGET_CPU_X86_64 + system("/usr/bin/nm -arch x86_64 /usr/lib/dyld > /tmp/dyld-namelist.txt"); +#elif TARGET_CPU_PPC64 + system("/usr/bin/nm -arch ppc64 /usr/lib/dyld > /tmp/dyld-namelist.txt"); +#endif + + FILE *fd = fopen("/tmp/dyld-namelist.txt", "rt"); + + char oneNMAddr[30]; + char symbolType; + char symbolName[500]; + while (!feof(fd)) { + fscanf(fd, "%s %c %s", oneNMAddr, &symbolType, symbolName); + breakpad_nlist symbolList[2]; + breakpad_nlist &list = symbolList[0]; + + memset(symbolList, 0, sizeof(breakpad_nlist)*2); + const char *symbolNames[2]; + symbolNames[0] = (const char*)symbolName; + symbolNames[1] = "\0"; + breakpad_nlist_64("/usr/lib/dyld", &list, symbolNames); + uint64_t nmAddr = strtol(oneNMAddr, NULL, 16); + if (!IsSymbolMoreThanOnceInDyld(symbolName)) { + CPTAssert(nmAddr == symbolList[0].n_value); + } + } + + fclose(fd); +} + +bool BreakpadNlistTest::IsSymbolMoreThanOnceInDyld(const char *symbolName) { + // These are the symbols that occur more than once when nm dumps + // the symbol table of /usr/lib/dyld. Our nlist program returns + // the first address because it's doing a search so we need to exclude + // these from causing the test to fail + const char *multipleSymbols[] = { + "__Z41__static_initialization_and_destruction_0ii", + "___tcf_0", + "___tcf_1", + "_read_encoded_value_with_base", + "_read_sleb128", + "_read_uleb128", + "\0"}; + + bool found = false; + + for (int i = 0; multipleSymbols[i][0]; i++) { + if (!strcmp(multipleSymbols[i], symbolName)) { + found = true; + break; + } + } + + return found; +} diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.h new file mode 100644 index 00000000..e93657cc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/breakpad_nlist_test.h @@ -0,0 +1,62 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// breakpad_nlist_test.h +// minidump_test +// +// Created by Neal Sidhwaney on 4/13/08. +// Copyright 2008 Google Inc. All rights reserved. +// +// + +#ifndef CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__ +#define CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__ + +#include + +class BreakpadNlistTest : public TestCase { + private: + + // nm dumps multiple addresses for the same symbol in + // /usr/lib/dyld. So we track those so we don't report failures + // in mismatches between what our nlist returns and what nm has + // for the duplicate symbols. + bool IsSymbolMoreThanOnceInDyld(const char *symbolName); + + public: + explicit BreakpadNlistTest(TestInvocation* invocation); + virtual ~BreakpadNlistTest(); + + + /* This test case runs nm on /usr/lib/dyld and then compares the + output of every symbol to what our nlist implementation returns */ + void CompareToNM(); +}; + +#endif /* CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__*/ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.h b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.h new file mode 100644 index 00000000..21ff7a44 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.h @@ -0,0 +1,46 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// dwarftests.h +// minidump_test +// +// Created by Neal Sidhwaney on 9/24/08. +// Copyright 2008 Google Inc. All rights reserved. +// + +#import + + +@interface dwarftests : SenTestCase { + +} + +- (void) testDWARFSymbolFileGeneration; + +@end diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.mm b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.mm new file mode 100644 index 00000000..40c69aff --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/dwarftests.mm @@ -0,0 +1,60 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// dwarftests.m +// minidump_test +// +// Created by Neal Sidhwaney on 9/24/08. +// Copyright 2008 Google Inc. All rights reserved. +// + +#import "dwarftests.h" +#import "dump_syms.h" + +@implementation dwarftests +- (void) testDWARFSymbolFileGeneration { + NSString *inputBreakpadSymbolFile = @"testcases/testdata/dump_syms_i386_breakpad.sym"; + NSString *outputBreakpadSymbolFile = @"/tmp/dump_syms_i386.breakpad"; + + DumpSymbols *dump = [[DumpSymbols alloc] initWithContentsOfFile:@"testcases/testdata/dump_syms_dwarf_data"]; + + STAssertNotNil(dump, @"DumpSymbols is nil"); + [dump setArchitecture:@"i386"]; + [dump writeSymbolFile:outputBreakpadSymbolFile]; + + NSData *d = [[NSData alloc] initWithContentsOfFile:inputBreakpadSymbolFile]; + STAssertNotNil(d, @"Input breakpad symbol file not found"); + + NSData *d1 = [[NSData alloc] initWithContentsOfFile:outputBreakpadSymbolFile]; + STAssertNotNil(d1, @"Output breakpad symbol file not found"); + + STAssertTrue([d isEqualToData:d1], + @"Symbol files were not equal!",nil); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_dwarf_data b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_dwarf_data new file mode 100644 index 00000000..5be17aee Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_dwarf_data differ diff --git a/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym new file mode 100644 index 00000000..bca43c10 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym @@ -0,0 +1,5300 @@ +MODULE mac x86 94BF873C47A73BC07125291390B4C5F10 dump_syms_dwarf_data +FILE 1 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h +FILE 2 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h +FILE 3 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dump_syms.mm +FILE 4 /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSRange.h +FILE 5 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/new +FILE 6 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_fun.h +FILE 7 ../../../common/mac/dwarf/dwarf2reader.h +FILE 8 ../../../common/mac/file_id.h +FILE 9 ../../../common/mac/dwarf/functioninfo.h +FILE 10 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h +FILE 11 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h +FILE 12 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h +FILE 13 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h +FILE 14 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h +FILE 15 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h +FILE 16 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h +FILE 17 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h +FILE 18 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h +FILE 19 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algo.h +FILE 20 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h +FILE 21 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h +FILE 22 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h +FILE 23 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map +FILE 24 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h +FILE 25 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h +FILE 26 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h +FILE 27 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc +FILE 28 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h +FILE 29 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc +FILE 30 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/functioninfo.cc +FILE 31 ../../../common/mac/dwarf/dwarf2reader.h +FILE 32 ../../../common/mac/dwarf/functioninfo.h +FILE 33 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h +FILE 34 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h +FILE 35 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory +FILE 36 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h +FILE 37 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h +FILE 38 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h +FILE 39 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h +FILE 40 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h +FILE 41 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h +FILE 42 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map +FILE 43 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h +FILE 44 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h +FILE 45 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h +FILE 46 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h +FILE 47 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc +FILE 48 /g/code/breakpad-staging/src/tools/mac/dump_syms/dump_syms_tool.mm +FILE 49 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/file_id.cc +FILE 50 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h +FILE 51 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_id.cc +FILE 52 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h +FILE 53 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h +FILE 54 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_walker.cc +FILE 55 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h +FILE 56 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h +FILE 57 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_utilities.cc +FILE 58 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/bytereader.cc +FILE 59 ../../../common/mac/dwarf/bytereader-inl.h +FILE 60 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/dwarf2reader.cc +FILE 61 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h +FILE 62 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_deque.h +FILE 63 ../../../common/mac/dwarf/bytereader.h +FILE 64 ../../../common/mac/dwarf/bytereader-inl.h +FILE 65 ../../../common/mac/dwarf/line_state_machine.h +FILE 66 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h +FILE 67 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory +FILE 68 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h +FILE 69 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h +FILE 70 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h +FILE 71 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h +FILE 72 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h +FILE 73 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h +FILE 74 ../../../common/mac/dwarf/dwarf2reader.h +FILE 75 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_stack.h +FILE 76 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/deque.tcc +FILE 77 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc +FILE 78 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc +FILE 79 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h +FILE 80 /var/tmp/gcc/gcc-5484~1/src/gcc/libgcc2.c +FUNC 162a 28 0 _OSSwapInt16 +162a 10 44 55 +163a 16 46 55 +1650 2 47 55 +FUNC 1652 1c 0 _OSSwapInt32 +1652 f 53 55 +1661 8 55 55 +1669 3 56 55 +166c 2 57 55 +FUNC 166e 2b 0 _OSSwapInt64 +166e 12 64 55 +1680 11 69 55 +1691 6 70 55 +1697 2 71 55 +1699 1 71 55 +FUNC 169a 1e 0 NXSwapShort +169a 10 43 56 +16aa c 45 56 +16b6 2 46 56 +FUNC 16b8 19 0 NXSwapInt +16b8 f 52 56 +16c7 8 54 56 +16cf 2 55 56 +16d1 1 55 56 +FUNC 16d2 19 0 NXSwapLong +16d2 f 61 56 +16e1 8 63 56 +16e9 2 64 56 +16eb 1 64 56 +FUNC 16ec 1f 0 NXSwapLongLong +16ec 12 70 56 +16fe b 72 56 +1709 2 73 56 +170b 1 73 56 +FUNC 170c 181 0 -[DumpSymbols convertCPlusPlusSymbols:] +170c 14 128 3 +1720 54 130 3 +1774 f 132 3 +1783 7 133 3 +178a 1a 136 3 +17a4 5 138 3 +17a9 1a 139 3 +17c3 23 140 3 +17e6 7 141 3 +17ed 44 142 3 +1831 1e 145 3 +184f 29 138 3 +1878 b 148 3 +1883 3 150 3 +1886 7 151 3 +188d 1 151 3 +FUNC 188e 323 0 -[DumpSymbols convertSymbols] +188e 14 154 3 +18a2 1f 155 3 +18c1 3e 156 3 +18ff 2b 160 3 +192a c 162 3 +1936 43 164 3 +1979 2a 165 3 +19a3 20 168 3 +19c3 d 169 3 +19d0 1e 171 3 +19ee 11 162 3 +19ff 7 181 3 +1a06 6 182 3 +1a0c 5 184 3 +1a11 15 185 3 +1a26 6 18 4 +1a2c 6 19 4 +1a32 6 20 4 +1a38 6 185 3 +1a3e 28 186 3 +1a66 21 187 3 +1a87 1a 188 3 +1aa1 a 190 3 +1aab c 194 3 +1ab7 43 198 3 +1afa 21 199 3 +1b1b 20 202 3 +1b3b 2e 203 3 +1b69 1e 194 3 +1b87 c 184 3 +1b93 17 207 3 +1baa 7 208 3 +1bb1 1 208 3 +FUNC 1bb2 4a2 0 -[DumpSymbols addFunction:line:address:section:] +1bb2 21 211 3 +1bd3 2f 212 3 +1c02 e 214 3 +1c10 4 219 3 +1c14 2a 221 3 +1c3e 22 223 3 +1c60 6 224 3 +1c66 2a 225 3 +1c90 4 226 3 +1c94 2e 230 3 +1cc2 2e 233 3 +1cf0 2e 236 3 +1d1e a 239 3 +1d28 2b 253 3 +1d53 e 254 3 +1d61 3c 255 3 +1d9d 22 32 4 +1dbf 3 256 3 +1dc2 6 259 3 +1dc8 a 260 3 +1dd2 3c 261 3 +1e0e 25 262 3 +1e33 2a 263 3 +1e5d 22 265 3 +1e7f 26 270 3 +1ea5 6 272 3 +1eab 37 273 3 +1ee2 2a 274 3 +1f0c 17 275 3 +1f23 43 278 3 +1f66 2e 279 3 +1f94 23 282 3 +1fb7 43 285 3 +1ffa 52 287 3 +204c 8 289 3 +FUNC 2054 5a4 0 -[DumpSymbols processSymbolItem:stringTable:] +2054 18 292 3 +206c 8 293 3 +2074 4 294 3 +2078 16 297 3 +208e c 298 3 +209a f 300 3 +20a9 b 301 3 +20b4 16 303 3 +20ca 4d 309 3 +2117 38 311 3 +214f 30 315 3 +217f 60 317 3 +21df d 322 3 +21ec 2b 325 3 +2217 3a 327 3 +2251 f 332 3 +2260 2d 333 3 +228d 1a 334 3 +22a7 32 335 3 +22d9 20 342 3 +22f9 c 343 3 +2305 24 348 3 +2329 a 349 3 +2333 3c 350 3 +236f 2a 352 3 +2399 1c 353 3 +23b5 9 354 3 +23be f 356 3 +23cd 2d 357 3 +23fa 2f 358 3 +2429 20 360 3 +2449 c 361 3 +2455 7 363 3 +245c 21 365 3 +247d 4a 368 3 +24c7 9 370 3 +24d0 1a 371 3 +24ea 4b 372 3 +2535 4 373 3 +2539 5 371 3 +253e 29 374 3 +2567 2d 376 3 +2594 4b 378 3 +25df 4 379 3 +25e3 a 382 3 +25ed b 383 3 +FUNC 25f8 c9 0 -[DumpSymbols loadSymbolInfo:offset:] +25f8 13 391 3 +260b 2b 392 3 +2636 2a 393 3 +2660 2d 395 3 +268d 2e 398 3 +26bb 6 399 3 +26c1 1 399 3 +FUNC 26c2 2be 0 -[DumpSymbols loadSTABSSymbolInfo:offset:] +26c2 16 537 3 +26d8 9 538 3 +26e1 10 539 3 +26f1 2e 540 3 +271f 9 542 3 +2728 22 543 3 +274a 4 544 3 +274e a 546 3 +2758 3c 547 3 +2794 c 549 3 +27a0 e 550 3 +27ae 6 551 3 +27b4 25 552 3 +27d9 25 553 3 +27fe 25 554 3 +2823 c 555 3 +282f c 556 3 +283b c 559 3 +2847 23 562 3 +286a a 563 3 +2874 a 564 3 +287e 2e 565 3 +28ac 39 566 3 +28e5 2e 570 3 +2913 4 571 3 +2917 17 559 3 +292e 25 575 3 +2953 9 576 3 +295c 17 549 3 +2973 4 579 3 +2977 9 580 3 +FUNC 2980 28a 0 -[DumpSymbols loadSymbolInfo64:offset:] +2980 16 583 3 +2996 9 585 3 +299f 10 586 3 +29af 2e 587 3 +29dd 9 589 3 +29e6 22 590 3 +2a08 4 591 3 +2a0c c 593 3 +2a18 e 594 3 +2a26 6 595 3 +2a2c 25 596 3 +2a51 25 597 3 +2a76 25 598 3 +2a9b 9 599 3 +2aa4 c 600 3 +2ab0 c 603 3 +2abc 17 604 3 +2ad3 23 609 3 +2af6 a 610 3 +2b00 a 611 3 +2b0a 2e 612 3 +2b38 37 613 3 +2b6f 2e 615 3 +2b9d 4 616 3 +2ba1 17 603 3 +2bb8 25 620 3 +2bdd 9 621 3 +2be6 17 593 3 +2bfd 4 624 3 +2c01 9 625 3 +FUNC 2c0a 199 0 -[DumpSymbols loadSymbolInfoForArchitecture] +2c0a 13 628 3 +2c1d 41 630 3 +2c5e 2b 631 3 +2c89 1a 632 3 +2ca3 40 634 3 +2ce3 40 635 3 +2d23 5f 637 3 +2d82 17 639 3 +2d99 4 640 3 +2d9d 6 641 3 +2da3 1 641 3 +FUNC 2da4 3e5 0 -[DumpSymbols loadHeader:offset:] +2da4 18 728 3 +2dbc 9 729 3 +2dc5 10 730 3 +2dd5 2e 731 3 +2e03 9 733 3 +2e0c 2b 734 3 +2e37 1e 736 3 +2e55 c 738 3 +2e61 e 739 3 +2e6f 6 740 3 +2e75 50 742 3 +2ec5 2e 743 3 +2ef3 2e 744 3 +2f21 2e 745 3 +2f4f 20 746 3 +2f6f 1b7 755 3 +3126 9 757 3 +312f 25 761 3 +3154 9 762 3 +315d 17 738 3 +3174 a 765 3 +317e b 766 3 +3189 1 766 3 +FUNC 318a 41d 0 -[DumpSymbols loadHeader64:offset:] +318a 18 769 3 +31a2 9 771 3 +31ab 10 772 3 +31bb 2e 773 3 +31e9 9 775 3 +31f2 c 777 3 +31fe 2b 778 3 +3229 e 779 3 +3237 6 780 3 +323d 50 781 3 +328d 49 782 3 +32d6 49 783 3 +331f 2e 784 3 +334d 9 785 3 +3356 29 786 3 +337f 1c5 794 3 +3544 9 795 3 +354d 25 799 3 +3572 9 800 3 +357b 17 777 3 +3592 a 803 3 +359c b 804 3 +35a7 1 804 3 +FUNC 35a8 52a 0 -[DumpSymbols loadModuleInfo] +35a8 14 807 3 +35bc e 808 3 +35ca 41 810 3 +360b 1a 811 3 +3625 6 812 3 +362b 6 814 3 +3631 17 815 3 +3648 c 816 3 +3654 29 820 3 +367d 29 821 3 +36a6 29 822 3 +36cf 35 824 3 +3704 12 826 3 +3716 17 827 3 +372d c 828 3 +3739 3c 832 3 +3775 a 834 3 +377f 9 836 3 +3788 25 837 3 +37ad c 839 3 +37b9 54 840 3 +380d 57 841 3 +3864 57 842 3 +38bb 57 843 3 +3912 57 844 3 +3969 1c 846 3 +3985 4b 847 3 +39d0 49 849 3 +3a19 13 839 3 +3a2c 6 851 3 +3a32 3c 852 3 +3a6e 3a 854 3 +3aa8 17 857 3 +3abf c 858 3 +3acb 7 859 3 +FUNC 3ad2 b6 0 WriteFormat +3ad2 10 862 3 +3ae2 6 867 3 +3ae8 24 868 3 +3b0c 27 869 3 +3b33 40 870 3 +3b73 c 873 3 +3b7f 9 874 3 +FUNC 3b88 35 0 -[DumpSymbols availableArchitectures] +3b88 13 1140 3 +3b9b 1c 1141 3 +3bb7 6 1142 3 +3bbd 1 1142 3 +FUNC 3bbe 1b4 0 -[DumpSymbols setArchitecture:] +3bbe 13 1158 3 +3bd1 1a 1159 3 +3beb 4 1160 3 +3bef 2a 1162 3 +3c19 9 1163 3 +3c22 2a 1165 3 +3c4c 9 1166 3 +3c55 9 1167 3 +3c5e 2a 1169 3 +3c88 6 1170 3 +3c8e 2a 1172 3 +3cb8 6 1173 3 +3cbe 2a 1175 3 +3ce8 4 1176 3 +3cec 6 1179 3 +3cf2 2c 1180 3 +3d1e 9 1181 3 +3d27 1c 1183 3 +3d43 1f 1184 3 +3d62 a 1187 3 +3d6c 6 1188 3 +FUNC 3d72 14 0 -[DumpSymbols architecture] +3d72 c 1191 3 +3d7e 6 1192 3 +3d84 2 1193 3 +FUNC 3d86 e7 0 -[DumpSymbols writeSymbolFile:] +3d86 13 1196 3 +3d99 1a 1197 3 +3db3 48 1200 3 +3dfb 9 1201 3 +3e04 1e 1203 3 +3e22 6 1205 3 +3e28 9 1206 3 +3e31 21 1208 3 +3e52 b 1210 3 +3e5d a 1212 3 +3e67 6 1213 3 +3e6d 1 1213 3 +FUNC 3e6e 65 0 -[MachSection initWithMachSection:andNumber:] +3e6e 13 1219 3 +3e81 37 1220 3 +3eb8 9 1221 3 +3ec1 9 1222 3 +3eca 3 1225 3 +3ecd 6 1226 3 +3ed3 1 1226 3 +FUNC 3ed4 14 0 -[MachSection sectionPointer] +3ed4 c 1228 3 +3ee0 6 1229 3 +3ee6 2 1230 3 +FUNC 3ee8 14 0 -[MachSection sectionNumber] +3ee8 c 1232 3 +3ef4 6 1233 3 +3efa 2 1234 3 +FUNC 3efc 17c 0 -[DumpSymbols processDWARFSourceFileInfo:] +3efc 14 459 3 +3f10 a 460 3 +3f1a 3c 461 3 +3f56 20 463 3 +3f76 5 464 3 +3f7b 3a 465 3 +3fb5 1d 466 3 +3fd2 3a 467 3 +400c 2a 468 3 +4036 3b 464 3 +4071 7 471 3 +FUNC 4078 1d7 0 DumpFunctionMap(std::map, std::allocator > >) +4078 15 82 3 +408d 13 83 3 +40a0 1e 85 3 +40be 42 89 3 +4100 20 90 3 +4120 2b 91 3 +414b 1a 92 3 +4165 23 93 3 +4188 46 96 3 +41ce 46 99 3 +4214 33 83 3 +4247 8 102 3 +424f 1 102 3 +FUNC 4250 3ef 0 -[DumpSymbols processDWARFFunctionInfo:] +4250 15 473 3 +4265 25 474 3 +428a 1e 476 3 +42a8 a 480 3 +42b2 3c 481 3 +42ee 3d 483 3 +432b 23 485 3 +434e 26 487 3 +4374 6 489 3 +437a 37 490 3 +43b1 2a 491 3 +43db 17 492 3 +43f2 30 496 3 +4422 3d 497 3 +445f 2e 498 3 +448d 30 502 3 +44bd 64 504 3 +4521 34 507 3 +4555 9d 509 3 +45f2 45 474 3 +4637 8 513 3 +463f 1 513 3 +FUNC 4640 1f5 0 -[DumpSymbols processDWARFLineNumberInfo:] +4640 15 515 3 +4655 25 516 3 +467a 39 520 3 +46b3 26 521 3 +46d9 6 523 3 +46df 37 524 3 +4716 2a 525 3 +4740 17 526 3 +4757 30 529 3 +4787 61 531 3 +47e8 45 516 3 +482d 8 534 3 +4835 1 534 3 +FUNC 4836 10f 0 -[DumpSymbols dealloc] +4836 13 1145 3 +4849 1c 1146 3 +4865 1c 1147 3 +4881 1c 1148 3 +489d 1c 1149 3 +48b9 1c 1150 3 +48d5 1c 1151 3 +48f1 25 1152 3 +4916 29 1154 3 +493f 6 1155 3 +4945 1 1155 3 +FUNC 4946 512 0 -[DumpSymbols loadDWARFSymbolInfo:offset:] +4946 17 402 3 +495d 9 405 3 +4966 10 406 3 +4976 2b 408 3 +49a1 38 409 3 +49d9 3a 410 3 +4a13 2e 411 3 +4a41 31 416 3 +4a72 e 418 3 +4a80 24 420 3 +4aa4 5 422 3 +4aa9 b 424 3 +4ab4 b 425 3 +4abf e 426 3 +4acd 2b 427 3 +4af8 2b 428 3 +4b23 2c 431 3 +4b4f 52 439 3 +4ba1 34 444 3 +4bd5 1a 446 3 +4bef 21 451 3 +4c10 1e 452 3 +4c2e 21 453 3 +4c4f 40 422 3 +4c8f 6 453 3 +4c95 170 422 3 +4e05 43 456 3 +4e48 10 457 3 +FUNC 4e58 4fd 0 -[DumpSymbols generateSectionDictionary:] +4e58 18 663 3 +4e70 10 665 3 +4e80 2e 666 3 +4eae 9 668 3 +4eb7 2b 669 3 +4ee2 7 670 3 +4ee9 2e 672 3 +4f17 d 676 3 +4f24 32 678 3 +4f56 29 680 3 +4f7f a 684 3 +4f89 3c 685 3 +4fc5 31 688 3 +4ff6 5d 689 3 +5053 26 692 3 +5079 21 694 3 +509a c 698 3 +50a6 e 699 3 +50b4 6 700 3 +50ba 9 701 3 +50c3 2e 702 3 +50f1 c 704 3 +50fd 3c 706 3 +5139 66 709 3 +519f 1c 712 3 +51bb fb 714 3 +52b6 6 717 3 +52bc 5 718 3 +52c1 19 704 3 +52da 25 714 3 +52ff 2e 722 3 +532d 9 723 3 +5336 17 698 3 +534d 8 725 3 +5355 1 725 3 +FUNC 5356 24a 0 -[DumpSymbols getSectionMapForArchitecture:] +5356 14 643 3 +536a 43 645 3 +53ad 1a 648 3 +53c7 1c 645 3 +53e3 18 648 3 +53fb 40 650 3 +543b 20 651 3 +545b 17 652 3 +5472 16 651 3 +5488 cb 652 3 +5553 11 654 3 +5564 32 657 3 +5596 a 658 3 +FUNC 55a0 3fe 0 -[DumpSymbols initWithContentsOfFile:] +55a0 14 1056 3 +55b4 3b 1057 3 +55ef 44 1059 3 +5633 17 1060 3 +564a c 1061 3 +5656 1f 1064 3 +5675 2b 1067 3 +56a0 a 1069 3 +56aa 35 1083 3 +56df 2 1087 3 +56e1 1a 1088 3 +56fb 3d 1087 3 +5738 33 1092 3 +576b 6 1094 3 +5771 e 1095 3 +577f 17 1096 3 +5796 c 1097 3 +57a2 1c 1101 3 +57be 1f 1103 3 +57dd 18 1104 3 +57f5 23 1107 3 +5818 25 1109 3 +583d 1c 1107 3 +5859 17 1110 3 +5870 c 1111 3 +587c 2a 1115 3 +58a6 8 1116 3 +58ae a 1118 3 +58b8 9 1119 3 +58c1 d 1122 3 +58ce 29 1124 3 +58f7 20 1126 3 +5917 20 1128 3 +5937 57 1132 3 +598e 9 1136 3 +5997 7 1137 3 +FUNC 599e d74 0 -[DumpSymbols outputSymbolFile:] +599e 18 877 3 +59b6 2e 879 3 +59e4 30 880 3 +5a14 5d 882 3 +5a71 30 883 3 +5aa1 5d 885 3 +5afe 2e 888 3 +5b2c 38 891 3 +5b64 46 892 3 +5baa 26 893 3 +5bd0 20 895 3 +5bf0 20 904 3 +5c10 30 898 3 +5c40 f 899 3 +5c4f 1e 904 3 +5c6d 17 907 3 +5c84 17 908 3 +5c9b 44 911 3 +5cdf 44 914 3 +5d23 a 917 3 +5d2d 36 921 3 +5d63 30 923 3 +5d93 9 18 4 +5d9c 9 19 4 +5da5 c 20 4 +5db1 56 923 3 +5e07 74 925 3 +5e7b f 927 3 +5e8a 44 932 3 +5ece 20 933 3 +5eee c 934 3 +5efa 4e 935 3 +5f48 41 936 3 +5f89 f 937 3 +5f98 14 934 3 +5fac 7 941 3 +5fb3 14 942 3 +5fc7 14 943 3 +5fdb 1d 946 3 +5ff8 c 948 3 +6004 24 949 3 +6028 29 950 3 +6051 9 953 3 +605a 28 954 3 +6082 2e 955 3 +60b0 1e 957 3 +60ce 7 959 3 +60d5 26 962 3 +60fb 2a 963 3 +6125 2a 964 3 +614f 6 966 3 +6155 2a 967 3 +617f e 971 3 +618d 43 972 3 +61d0 4c 974 3 +621c 8 975 3 +6224 2e 979 3 +6252 2e 982 3 +6280 2e 985 3 +62ae 2e 988 3 +62dc 2e 991 3 +630a 2e 994 3 +6338 2e 997 3 +6366 2e 1000 3 +6394 54 1004 3 +63e8 c 1005 3 +63f4 e 1007 3 +6402 27 1008 3 +6429 8 1009 3 +6431 34 1010 3 +6465 24 1012 3 +6489 2 1013 3 +648b 2a 1017 3 +64b5 a 1019 3 +64bf 14 1020 3 +64d3 1d 1021 3 +64f0 a 1025 3 +64fa 32 1026 3 +652c 33 1028 3 +655f c 1029 3 +656b 55 1034 3 +65c0 f 1036 3 +65cf 16 1040 3 +65e5 61 1041 3 +6646 f 1043 3 +6655 47 1046 3 +669c c 1048 3 +66a8 11 948 3 +66b9 4e 1052 3 +6707 b 1053 3 +FUNC 6712 11 0 operator new(unsigned long, void*) +6712 c 94 5 +671e 5 94 5 +6723 1 94 5 +FUNC 6724 e 0 operator delete(void*, void*) +6724 c 98 5 +6730 2 98 5 +673e 7 76 6 +6745 2 77 6 +6747 1a 78 6 +6761 d 77 6 +676e 3 79 6 +6771 2 80 6 +6773 1 80 6 +6780 d 95 6 +678d 1 95 6 +678e 13 127 74 +67a1 2a 127 74 +67cb 1 127 74 +67cc 13 127 74 +67df 2a 127 74 +6809 1 127 74 +680a 13 127 74 +681d 2a 127 74 +6847 1 127 74 +FUNC 6848 e 0 dwarf2reader::LineInfoHandler::DefineDir(std::string const&, unsigned int) +6848 c 131 7 +6854 2 131 74 +FUNC 6856 26 0 dwarf2reader::LineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long) +6856 24 142 7 +687a 2 142 74 +FUNC 687c 1a 0 dwarf2reader::LineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int) +687c 18 150 7 +6894 2 150 74 +6896 12 299 74 +68a8 12 299 74 +68ba 13 301 74 +68cd 2a 301 74 +68f7 1 301 74 +68f8 13 301 74 +690b 2a 301 74 +6935 1 301 74 +6936 13 301 74 +6949 2a 301 74 +6973 1 301 74 +FUNC 6974 44 0 dwarf2reader::Dwarf2Handler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char) +6974 39 308 7 +69ad b 308 74 +FUNC 69b8 1f 0 dwarf2reader::Dwarf2Handler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list, std::allocator > > const&) +69b8 18 314 7 +69d0 7 314 74 +69d7 1 314 74 +FUNC 69d8 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long) +69d8 24 323 7 +69fc 2 323 74 +FUNC 69fe 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeSigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, long long) +69fe 24 332 7 +6a22 2 332 74 +FUNC 6a24 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeBuffer(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, char const*, unsigned long long) +6a24 24 345 7 +6a48 2 345 74 +FUNC 6a4a 1a 0 dwarf2reader::Dwarf2Handler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&) +6a4a 18 354 7 +6a62 2 354 74 +FUNC 6a64 1a 0 dwarf2reader::Dwarf2Handler::EndDIE(unsigned long long) +6a64 18 360 7 +6a7c 2 360 74 +6a7e c 44 8 +6a8a 2 44 8 +6a8c 13 55 32 +6a9f 35 55 32 +6ad4 13 91 32 +6ae7 73 96 32 +6b5a 13 98 32 +6b6d 35 98 32 +6bae 1a 75 3 +6bc8 2 76 3 +FUNC 6bca 20 0 std::_Rb_tree_const_iterator >::operator!=(std::_Rb_tree_const_iterator > const&) const +6bca c 287 10 +6bd6 14 288 40 +FUNC 6bea 16 0 std::_Rb_tree_const_iterator >::operator->() const +6bea c 249 10 +6bf6 a 250 40 +6c0c 7 614 72 +6c13 1 614 72 +6c14 c 241 40 +6c20 c 242 40 +FUNC 6c2c 16 0 std::_Rb_tree_const_iterator >::operator*() const +6c2c c 245 11 +6c38 a 246 40 +6c42 c 241 40 +6c4e c 242 40 +FUNC 6c5a 20 0 std::_Rb_tree_const_iterator > >::operator!=(std::_Rb_tree_const_iterator > > const&) const +6c5a c 287 11 +6c66 14 288 40 +FUNC 6c7a 16 0 std::_Rb_tree_const_iterator > >::operator->() const +6c7a c 249 11 +6c86 a 250 40 +6c90 c 185 34 +6c9c 18 186 34 +6cc0 14 204 34 +6cd4 c 69 70 +6ce0 d 69 70 +6ced 1 69 70 +6cee c 89 70 +6cfa 20 90 70 +6d1a c 69 70 +6d26 d 69 70 +6d33 1 69 70 +6d34 c 69 70 +6d40 d 69 70 +6d4d 1 69 70 +FUNC 6d4e 25 0 std::_Rb_tree_const_iterator >::operator++() +6d4e c 253 13 +6d5a 14 255 40 +6d6e 5 256 40 +6d73 1 256 40 +FUNC 6d74 25 0 std::_Rb_tree_const_iterator > >::operator++() +6d74 c 253 13 +6d80 14 255 40 +6d94 5 256 40 +6d99 1 256 40 +FUNC 6d9a 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_begin() +6d9a c 461 13 +6da6 8 462 40 +FUNC 6dae 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_begin() +6dae c 461 13 +6dba 8 462 40 +6dc2 c 65 68 +6dce 2 65 68 +6dd0 c 72 68 +6ddc 2 72 68 +6dde c 97 69 +6dea d 97 69 +6df7 1 97 69 +6df8 c 105 69 +6e04 d 105 69 +6e11 1 105 69 +6e12 c 105 69 +6e1e d 105 69 +6e2b 1 105 69 +6e2c c 67 68 +6e38 2 67 68 +6e3a c 99 69 +6e46 14 100 69 +6e5a c 99 69 +6e66 14 100 69 +FUNC 6e7a 2b 0 std::_Vector_base >::get_allocator() const +6e7a 10 93 16 +6e8a 1b 94 71 +6ea5 1 94 71 +6ea6 c 65 68 +6eb2 2 65 68 +6eb4 c 72 68 +6ec0 2 72 68 +6ec2 c 97 69 +6ece d 97 69 +6edb 1 97 69 +6edc c 105 69 +6ee8 d 105 69 +6ef5 1 105 69 +6ef6 c 105 69 +6f02 d 105 69 +6f0f 1 105 69 +6f10 c 67 68 +6f1c 2 67 68 +6f1e c 99 69 +6f2a 14 100 69 +6f3e c 99 69 +6f4a 14 100 69 +FUNC 6f5e 2b 0 std::_Vector_base >::get_allocator() const +6f5e 10 93 16 +6f6e 1b 94 71 +6f89 1 94 71 +6f8a c 603 72 +6f96 c 603 72 +FUNC 6fa2 23 0 std::vector >::begin() +6fa2 c 333 16 +6fae 17 334 71 +6fc5 1 334 71 +FUNC 6fc6 26 0 std::vector >::end() +6fc6 c 351 16 +6fd2 1a 352 71 +6ff8 5 666 72 +6ffd 1 666 72 +6ffe c 608 72 +700a 14 609 72 +702a 5 666 72 +702f 1 666 72 +FUNC 7030 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) +7030 d 693 16 +703d 28 694 72 +7065 1 694 72 +7066 c 603 72 +7072 c 603 72 +708a 27 629 72 +70b1 1 629 72 +70b2 c 84 70 +70be 1f 85 70 +70dd 1 85 70 +FUNC 70de 32 0 std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*> std::make_pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*>(std::string, __gnu_cxx::hash_map, __gnu_cxx::hash, std::equal_to, std::allocator > >*) +70de 10 144 16 +70ee 22 145 70 +711c a 190 34 +7132 d 194 34 +713f 1 194 34 +7140 c 84 70 +714c 17 85 70 +7163 1 85 70 +FUNC 7164 2d 0 std::pair std::make_pair(char const*, unsigned long) +7164 c 144 16 +7170 21 145 70 +7191 1 145 70 +7192 c 84 70 +719e 1d 85 70 +71bb 1 85 70 +FUNC 71bc 30 0 std::pair > std::make_pair >(char*, std::pair) +71bc 10 144 16 +71cc 20 145 70 +71ec c 89 70 +71f8 20 90 70 +7218 d 89 70 +7225 70 90 70 +7295 1 90 70 +FUNC 7296 12 0 std::iterator_traits::iterator_category std::__iterator_category(unsigned long const* const&) +7296 c 164 17 +72a2 6 165 17 +FUNC 72a8 1d 0 std::iterator_traits::difference_type std::__distance(unsigned long const*, unsigned long const*, std::random_access_iterator_tag) +72a8 c 92 18 +72b4 11 97 18 +72c5 1 97 18 +FUNC 72c6 33 0 std::iterator_traits::difference_type std::distance(unsigned long const*, unsigned long const*) +72c6 c 114 18 +72d2 27 118 18 +72f9 1 118 18 +FUNC 72fa 20 0 void std::__advance(unsigned long const*&, int, std::random_access_iterator_tag) +72fa c 150 18 +7306 14 155 18 +FUNC 731a 33 0 void std::advance(unsigned long const*&, int) +731a c 172 18 +7326 27 175 18 +734d 1 175 18 +FUNC 734e 7a 0 unsigned long const* std::lower_bound(unsigned long const*, unsigned long const*, unsigned long const&) +734e c 2625 19 +735a 15 2642 19 +736f 2 2646 19 +7371 8 2648 19 +7379 6 2649 19 +737f 12 2650 19 +7391 e 2651 19 +739f 6 2653 19 +73a5 4 2654 19 +73a9 e 2655 19 +73b7 6 2658 19 +73bd 6 2646 19 +73c3 5 2660 19 +73db b 227 34 +73e6 e 228 34 +73f4 1c 229 34 +7410 20 230 34 +7430 6 231 34 +7436 c 72 68 +7442 2 72 68 +7444 c 105 69 +7450 d 105 69 +745d 1 105 69 +745e c 105 69 +746a d 105 69 +7477 1 105 69 +7478 c 80 71 +7484 d 80 71 +7491 1 80 71 +7492 c 67 68 +749e 2 67 68 +74a0 c 99 69 +74ac 14 100 69 +FUNC 74c0 2b 0 std::_Vector_base >::get_allocator() const +74c0 10 93 19 +74d0 1b 94 71 +74eb 1 94 71 +74ec c 238 40 +74f8 a 239 40 +FUNC 7502 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::begin() const +7502 c 585 19 +750e 1a 588 40 +FUNC 7528 19 0 std::map, std::allocator > >::begin() const +7528 c 243 20 +7534 d 244 45 +7541 1 244 45 +FUNC 7542 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::end() const +7542 c 596 20 +754e 1a 597 40 +FUNC 7568 19 0 std::map, std::allocator > >::end() const +7568 c 260 20 +7574 d 261 45 +7581 1 261 45 +7582 c 65 68 +758e 2 65 68 +7590 c 72 68 +759c 2 72 68 +759e c 97 69 +75aa d 97 69 +75b7 1 97 69 +75b8 c 105 69 +75c4 d 105 69 +75d1 1 105 69 +75d2 c 72 68 +75de 2 72 68 +75e0 c 105 69 +75ec d 105 69 +75f9 1 105 69 +75fa c 397 40 +7606 d 397 40 +7613 1 397 40 +7614 c 105 69 +7620 d 105 69 +762d 1 105 69 +FUNC 762e 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_right(std::_Rb_tree_node_base*) +762e c 496 20 +763a 8 497 40 +FUNC 7642 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_left(std::_Rb_tree_node_base*) +7642 c 488 20 +764e 8 489 40 +7656 c 65 68 +7662 2 65 68 +7664 c 72 68 +7670 2 72 68 +7672 c 97 69 +767e d 97 69 +768b 1 97 69 +768c c 105 69 +7698 d 105 69 +76a5 1 105 69 +76a6 c 72 68 +76b2 2 72 68 +76b4 c 105 69 +76c0 d 105 69 +76cd 1 105 69 +76ce c 397 40 +76da d 397 40 +76e7 1 397 40 +76e8 c 105 69 +76f4 d 105 69 +7701 1 105 69 +FUNC 7702 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_right(std::_Rb_tree_node_base*) +7702 c 496 20 +770e 8 497 40 +FUNC 7716 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_left(std::_Rb_tree_node_base*) +7716 c 488 20 +7722 8 489 40 +772a c 84 71 +7736 2f 85 71 +7765 2 86 71 +7767 1 86 71 +7768 c 80 71 +7774 d 80 71 +7781 1 80 71 +7782 c 96 71 +778e 12 97 71 +77a0 2 98 71 +77a2 c 84 71 +77ae 2f 85 71 +77dd 2 86 71 +77df 1 86 71 +77e0 c 80 71 +77ec d 80 71 +77f9 1 80 71 +77fa c 96 71 +7806 12 97 71 +7818 2 98 71 +7826 d 107 68 +7833 1 107 68 +FUNC 7834 2e 0 void std::_Destroy >(std::string*, std::string*, std::allocator) +7834 c 171 21 +7840 2 173 73 +7842 12 174 73 +7854 c 173 73 +7860 2 174 73 +7862 c 167 40 +786e a 168 40 +FUNC 7878 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::begin() +7878 c 581 21 +7884 1a 582 40 +FUNC 789e 19 0 std::map, std::allocator > >::begin() +789e c 234 21 +78aa d 235 45 +78b7 1 235 45 +FUNC 78b8 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::end() +78b8 c 592 21 +78c4 1a 593 40 +FUNC 78de 19 0 std::map, std::allocator > >::end() +78de c 251 21 +78ea d 252 45 +78f7 1 252 45 +78f8 c 167 40 +7904 a 168 40 +FUNC 790e 26 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::begin() +790e c 581 21 +791a 1a 582 40 +FUNC 7934 19 0 std::map, std::less, std::allocator > > >::begin() +7934 c 234 21 +7940 d 235 45 +794d 1 235 45 +FUNC 794e 26 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::end() +794e c 592 21 +795a 1a 593 40 +FUNC 7974 19 0 std::map, std::less, std::allocator > > >::end() +7974 c 251 21 +7980 d 252 45 +798d 1 252 45 +FUNC 798e 11 0 std::_Select1st, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >::operator()(std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*>&) const +798e c 546 22 +799a 5 547 41 +799f 1 547 41 +79a0 c 128 34 +79ac 13 129 34 +79bf 1 129 34 +79cc 22 396 34 +79fa d 199 42 +7a07 1 199 42 +7a08 c 65 68 +7a14 2 65 68 +7a16 c 72 68 +7a22 2 72 68 +7a24 c 97 69 +7a30 d 97 69 +7a3d 1 97 69 +7a3e c 105 69 +7a4a d 105 69 +7a57 1 105 69 +7a58 c 65 68 +7a64 2 65 68 +7a66 c 72 68 +7a72 2 72 68 +7a74 c 105 69 +7a80 d 105 69 +7a8d 1 105 69 +7a8e c 97 69 +7a9a d 97 69 +7aa7 1 97 69 +7aa8 c 72 68 +7ab4 2 72 68 +7ab6 c 105 69 +7ac2 d 105 69 +7acf 1 105 69 +7adc d 94 68 +7ae9 1 94 68 +FUNC 7aea 2f 0 std::_Vector_base >::_M_deallocate(dwarf2reader::CompilationUnit::Abbrev*, unsigned long) +7aea c 120 23 +7af6 6 122 71 +7afc 1d 123 71 +7b19 1 123 71 +7b1a c 108 71 +7b26 43 109 71 +7b69 1 109 71 +7b6a c 65 68 +7b76 2 65 68 +7b78 c 103 69 +7b84 d 103 69 +7b91 1 103 69 +7b92 c 65 68 +7b9e 2 65 68 +7ba0 c 103 69 +7bac d 103 69 +7bb9 1 103 69 +7bc6 d 94 68 +7bd3 1 94 68 +FUNC 7bd4 2f 0 std::_Vector_base >::_M_deallocate(dwarf2reader::SourceFileInfo*, unsigned long) +7bd4 c 120 23 +7be0 6 122 71 +7be6 1d 123 71 +7c03 1 123 71 +7c04 c 108 71 +7c10 43 109 71 +7c53 1 109 71 +7c54 c 188 71 +7c60 12 189 71 +7c72 2 190 71 +7c74 c 35 32 +7c80 d 35 32 +7c8d 1 35 32 +7c9a d 107 68 +7ca7 1 107 68 +FUNC 7ca8 2e 0 void std::_Destroy >(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, std::allocator) +7ca8 c 171 23 +7cb4 2 173 73 +7cb6 12 174 73 +7cc8 c 173 73 +7cd4 2 174 73 +7cd6 d 272 71 +7ce3 8c 273 71 +7d6f 1 273 71 +7d7c d 94 68 +7d89 1 94 68 +FUNC 7d8a 2f 0 std::_Vector_base >::_M_deallocate(std::string*, unsigned long) +7d8a c 120 23 +7d96 6 122 71 +7d9c 1d 123 71 +7db9 1 123 71 +7dba c 108 71 +7dc6 3d 109 71 +7e03 1 109 71 +7e04 c 188 71 +7e10 12 189 71 +7e22 2 190 71 +7e24 d 272 71 +7e31 8c 273 71 +7ebd 1 273 71 +7eca 2b 596 34 +7ef5 1 596 34 +7f02 7 614 72 +7f09 1 614 72 +7f0a c 65 68 +7f16 2 65 68 +7f18 c 72 68 +7f24 2 72 68 +7f26 c 103 69 +7f32 d 103 69 +7f3f 1 103 69 +7f40 c 105 69 +7f4c d 105 69 +7f59 1 105 69 +7f5a c 65 68 +7f66 2 65 68 +7f68 c 72 68 +7f74 2 72 68 +7f76 c 103 69 +7f82 d 103 69 +7f8f 1 103 69 +7f90 c 105 69 +7f9c d 105 69 +7fa9 1 105 69 +7faa c 105 69 +7fb6 d 105 69 +7fc3 1 105 69 +7fd0 d 575 34 +7fdd 1 575 34 +7fea d 575 34 +7ff7 1 575 34 +FUNC 7ff8 11 0 std::_Select1st, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >::operator()(std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*> const&) const +7ff8 c 550 23 +8004 5 551 41 +8009 1 551 41 +8016 2f 600 34 +8045 1 600 34 +8046 c 84 70 +8052 1e 85 70 +FUNC 8070 11 0 std::_Select1st > >::operator()(std::pair >&) const +8070 c 546 23 +807c 5 547 41 +8081 1 547 41 +FUNC 8082 11 0 std::_Select1st > >::operator()(std::pair > const&) const +8082 c 550 23 +808e 5 551 41 +8093 1 551 41 +8094 c 128 34 +80a0 13 129 34 +80b3 1 129 34 +80b4 c 84 70 +80c0 1e 85 70 +80de c 65 68 +80ea 2 65 68 +80ec c 103 69 +80f8 d 103 69 +8105 1 103 69 +8106 c 65 68 +8112 2 65 68 +8114 c 72 68 +8120 2 72 68 +8122 c 105 69 +812e d 105 69 +813b 1 105 69 +813c c 103 69 +8148 d 103 69 +8155 1 103 69 +8156 c 105 69 +8162 d 105 69 +816f 1 105 69 +8170 c 80 71 +817c d 80 71 +8189 1 80 71 +818a c 67 68 +8196 2 67 68 +8198 c 99 69 +81a4 14 100 69 +FUNC 81b8 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::get_allocator() const +81b8 10 93 23 +81c8 1b 94 71 +81e3 1 94 71 +81e4 c 99 69 +81f0 14 100 69 +8210 2 107 68 +FUNC 8212 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) +8212 c 171 23 +821e 2 173 73 +8220 12 174 73 +8232 c 173 73 +823e 2 174 73 +824c d 107 68 +8259 1 107 68 +825a c 67 68 +8266 2 67 68 +8268 c 99 69 +8274 14 100 69 +8288 c 403 40 +8294 1c 404 40 +82b0 a 406 40 +82ba a 407 40 +82c4 c 408 40 +82d0 e 409 40 +82de c 553 40 +82ea 36 554 40 +8320 2 555 40 +8322 c 103 69 +832e d 103 69 +833b 1 103 69 +FUNC 833c 2b 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::get_allocator() const +833c 10 350 23 +834c 1b 351 40 +8367 1 351 40 +8368 c 69 70 +8374 2 69 70 +8382 d 107 68 +838f 1 107 68 +839c d 94 68 +83a9 1 94 68 +FUNC 83aa 2a 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_put_node(std::_Rb_tree_node >*) +83aa c 359 23 +83b6 1e 360 40 +FUNC 83d4 59 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::destroy_node(std::_Rb_tree_node >*) +83d4 d 387 23 +83e1 35 389 40 +8416 17 390 40 +842d 1 390 40 +FUNC 842e 56 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +842e c 1051 23 +843a 2 1054 40 +843c 1a 1056 40 +8456 e 1057 40 +8464 12 1058 40 +8476 6 1059 40 +847c 6 1054 40 +8482 2 1059 40 +8484 d 569 40 +8491 58 570 40 +84e9 1 570 40 +84ea c 147 45 +84f6 31 148 45 +8527 1 148 45 +8528 c 92 45 +8534 d 92 45 +8541 1 92 45 +8542 c 67 68 +854e 2 67 68 +8550 c 99 69 +855c 14 100 69 +8570 c 403 40 +857c 1c 404 40 +8598 a 406 40 +85a2 a 407 40 +85ac c 408 40 +85b8 e 409 40 +85c6 c 553 40 +85d2 36 554 40 +8608 2 555 40 +860a c 103 69 +8616 d 103 69 +8623 1 103 69 +FUNC 8624 2b 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::get_allocator() const +8624 10 350 23 +8634 1b 351 40 +864f 1 351 40 +8650 c 69 70 +865c d 69 70 +8669 1 69 70 +866a c 69 70 +8676 30 69 70 +86b2 d 107 68 +86bf 1 107 68 +86cc d 94 68 +86d9 1 94 68 +FUNC 86da 2a 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_put_node(std::_Rb_tree_node > >*) +86da c 359 23 +86e6 1e 360 40 +FUNC 8704 59 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::destroy_node(std::_Rb_tree_node > >*) +8704 d 387 23 +8711 35 389 40 +8746 17 390 40 +875d 1 390 40 +FUNC 875e 56 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +875e c 1051 23 +876a 2 1054 40 +876c 1a 1056 40 +8786 e 1057 40 +8794 12 1058 40 +87a6 6 1059 40 +87ac 6 1054 40 +87b2 2 1059 40 +87b4 d 569 40 +87c1 58 570 40 +8819 1 570 40 +881a c 147 45 +8826 31 148 45 +8857 1 148 45 +8858 c 92 45 +8864 d 92 45 +8871 1 92 45 +8872 c 603 72 +887e c 603 72 +FUNC 888a 23 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::begin() +888a c 333 23 +8896 17 334 71 +88ad 1 334 71 +88ba 2a 654 72 +FUNC 88e4 42 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::operator[](unsigned long) +88e4 c 494 23 +88f0 36 495 71 +FUNC 8926 26 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::end() +8926 c 351 23 +8932 1a 352 71 +FUNC 894c 28 0 bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) +894c c 2115 24 +8958 1c 2116 37 +FUNC 8974 23 0 std::equal_to::operator()(std::string const&, std::string const&) const +8974 c 199 24 +8980 17 200 41 +8997 1 200 41 +8998 c 80 71 +89a4 d 80 71 +89b1 1 80 71 +89b2 c 67 68 +89be 2 67 68 +89c0 c 99 69 +89cc 14 100 69 +FUNC 89e0 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::get_allocator() const +89e0 10 93 24 +89f0 1b 94 71 +8a0b 1 94 71 +8a0c c 99 69 +8a18 14 100 69 +8a2c c 84 71 +8a38 2f 85 71 +8a67 2 86 71 +8a69 1 86 71 +8a6a c 96 71 +8a76 12 97 71 +8a88 2 98 71 +8a96 2 107 68 +FUNC 8a98 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node > >**, std::allocator<__gnu_cxx::_Hashtable_node > >*> >(__gnu_cxx::_Hashtable_node > >**, __gnu_cxx::_Hashtable_node > >**, std::allocator<__gnu_cxx::_Hashtable_node > >*>) +8a98 c 171 24 +8aa4 2 173 73 +8aa6 12 174 73 +8ab8 c 173 73 +8ac4 2 174 73 +FUNC 8ac6 13 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::max_size() const +8ac6 c 407 24 +8ad2 7 408 71 +8ad9 1 408 71 +8ada c 603 72 +8ae6 c 603 72 +FUNC 8af2 26 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::end() +8af2 c 351 24 +8afe 1a 352 71 +FUNC 8b18 23 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::begin() +8b18 c 333 24 +8b24 17 334 71 +8b3b 1 334 71 +8b48 2a 654 72 +8b7e 7 614 72 +8b85 1 614 72 +FUNC 8b86 42 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::operator[](unsigned long) +8b86 c 494 24 +8b92 36 495 71 +8bd4 d 107 68 +8be1 1 107 68 +FUNC 8be2 28 0 void std::swap<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**&, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**&) +8be2 c 92 25 +8bee 8 97 61 +8bf6 a 98 61 +8c00 a 99 61 +FUNC 8c0a 50 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >&) +8c0a c 733 25 +8c16 12 735 71 +8c28 18 736 71 +8c40 1a 737 71 +8c66 2b 596 34 +8c91 1 596 34 +8c9e 2f 600 34 +8ccd 1 600 34 +FUNC 8cce 28 0 void std::swap<__gnu_cxx::_Hashtable_node > >**>(__gnu_cxx::_Hashtable_node > >**&, __gnu_cxx::_Hashtable_node > >**&) +8cce c 92 25 +8cda 8 97 61 +8ce2 a 98 61 +8cec a 99 61 +FUNC 8cf6 50 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >&) +8cf6 c 733 25 +8d02 12 735 71 +8d14 18 736 71 +8d2c 1a 737 71 +8d46 c 84 71 +8d52 2f 85 71 +8d81 2 86 71 +8d83 1 86 71 +8d84 c 96 71 +8d90 12 97 71 +8da2 2 98 71 +FUNC 8da4 13 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::max_size() const +8da4 c 407 25 +8db0 7 408 71 +8db7 1 408 71 +8dc4 d 94 68 +8dd1 1 94 68 +FUNC 8dd2 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long) +8dd2 c 120 25 +8dde 6 122 71 +8de4 1d 123 71 +8e01 1 123 71 +8e02 c 108 71 +8e0e 3d 109 71 +8e4b 1 109 71 +8e4c c 272 71 +8e58 4b 273 71 +8ea3 1 273 71 +8ea4 c 188 71 +8eb0 12 189 71 +8ec2 2 190 71 +8ec4 c 603 72 +8ed0 c 603 72 +FUNC 8edc 2b 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::begin() const +8edc c 342 25 +8ee8 1f 343 71 +8f07 1 343 71 +FUNC 8f08 2c 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::end() const +8f08 c 360 25 +8f14 20 361 71 +8f40 5 666 72 +8f45 1 666 72 +8f53 2b 759 72 +FUNC 8f7e 3c 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::size() const +8f7e c 402 25 +8f8a 30 403 71 +8fc6 26 588 34 +8ff8 15 511 34 +900d 79 513 34 +9086 21 517 34 +90a7 1 517 34 +90b4 14 225 42 +90d4 26 592 34 +FUNC 90fa 49 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::capacity() const +90fa c 449 25 +9106 3d 451 71 +9143 1 451 71 +9144 c 103 69 +9150 d 103 69 +915d 1 103 69 +916e 1b 286 34 +9189 1 286 34 +9196 d 94 68 +91a3 1 94 68 +91b0 1e 301 34 +91db 56 622 34 +9231 17 623 34 +9254 9 1080 34 +925d 1a 1082 34 +9277 2 1083 34 +9279 8 1085 34 +9281 12 1086 34 +9293 6 1087 34 +9299 6 1083 34 +929f 1b 1089 34 +92ba 1d 1080 34 +92d7 c 1091 34 +92e3 1 1091 34 +92e4 d 360 34 +92f1 77 361 34 +9368 c 93 42 +9374 d 93 42 +9381 1 93 42 +9382 c 72 68 +938e 2 72 68 +9390 c 105 69 +939c d 105 69 +93a9 1 105 69 +93aa c 301 66 +93b6 d 301 66 +93c3 1 301 66 +93d0 d 94 68 +93dd 1 94 68 +FUNC 93de 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node > >**, unsigned long) +93de c 120 26 +93ea 6 122 71 +93f0 1d 123 71 +940d 1 123 71 +940e c 108 71 +941a 3d 109 71 +9457 1 109 71 +9458 c 188 71 +9464 12 189 71 +9476 2 190 71 +9478 c 272 71 +9484 4b 273 71 +94cf 1 273 71 +94d0 c 603 72 +94dc c 603 72 +FUNC 94e8 2b 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::begin() const +94e8 c 342 26 +94f4 1f 343 71 +9513 1 343 71 +FUNC 9514 2c 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::end() const +9514 c 360 26 +9520 20 361 71 +954c 2d 662 72 +9579 1 662 72 +FUNC 957a 2d 0 unsigned long const& std::max(unsigned long const&, unsigned long const&) +957a c 206 26 +9586 e 211 61 +9594 8 212 61 +959c b 213 61 +95a7 1 213 61 +95b4 19 650 72 +95cd 1 650 72 +95da 5 666 72 +95df 1 666 72 +95ed 2b 759 72 +9624 5 666 72 +9629 1 666 72 +9637 2b 759 72 +FUNC 9662 49 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::capacity() const +9662 c 449 26 +966e 3d 451 71 +96ab 1 451 71 +FUNC 96ac 3c 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::size() const +96ac c 402 26 +96b8 30 403 71 +96f4 26 588 34 +9726 26 592 34 +974c c 103 69 +9758 d 103 69 +9765 1 103 69 +9776 1b 286 34 +9791 1 286 34 +979e d 94 68 +97ab 1 94 68 +97b8 1e 301 34 +97e3 56 622 34 +9839 17 623 34 +985c 9 1080 34 +9865 1a 1082 34 +987f 2 1083 34 +9881 8 1085 34 +9889 12 1086 34 +989b 6 1087 34 +98a1 6 1083 34 +98a7 1b 1089 34 +98c2 1d 1080 34 +98df c 1091 34 +98eb 1 1091 34 +98ec d 360 34 +98f9 77 361 34 +9970 c 69 70 +997c 20 69 70 +99a9 5c 104 68 +9a05 1 104 68 +9a06 c 69 70 +9a12 2c 69 70 +9a4b 5c 104 68 +9aa7 1 104 68 +9ab4 2d 662 72 +9ae1 1 662 72 +9aee 19 650 72 +9b07 1 650 72 +9b14 5 666 72 +9b19 1 666 72 +9b27 2b 759 72 +9b52 c 72 68 +9b5e 2 72 68 +9b60 c 105 69 +9b6c d 105 69 +9b79 1 105 69 +9b7a c 69 70 +9b86 2 69 70 +9b94 d 107 68 +9ba1 1 107 68 +9bae d 94 68 +9bbb 1 94 68 +FUNC 9bbc 2a 0 std::_List_base, std::allocator > >::_M_put_node(std::_List_node >*) +9bbc c 315 26 +9bc8 1e 316 66 +FUNC 9be6 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > const&) +9be6 d 699 26 +9bf3 28 700 72 +9c1b 1 700 72 +9c28 d 623 72 +9c35 5 624 72 +FUNC 9c3a 4b 0 void std::__fill::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >* const&) +9c3a c 539 61 +9c46 8 541 61 +9c4e 2 542 61 +9c50 12 543 61 +9c62 21 542 61 +9c83 2 543 61 +9c85 1 543 61 +FUNC 9c86 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >* const&) +9c86 c 560 26 +9c92 4 567 61 +9c96 1b 568 61 +9cb1 1 568 61 +FUNC 9cb2 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node > >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node > >*>) +9cb2 c 171 26 +9cbe 2 173 73 +9cc0 1a 174 73 +9cda 21 173 73 +9cfb 2 174 73 +9cfd 1 174 73 +9d0a 7 98 68 +9d11 1 98 68 +9d1e 1d 85 68 +9d3b 5 86 68 +9d40 16 88 68 +9d62 1d 297 34 +9d7f 1 297 34 +9d8d e 605 34 +9d9b 9 606 34 +9da4 3c 609 34 +9de0 b 610 34 +9deb 11 609 34 +9dfc b 612 34 +9e07 12 614 34 +9e19 b 615 34 +9e24 13 612 34 +9e37 8 615 34 +9e3f 1 615 34 +9e4d 15 751 34 +9e62 1a 752 34 +9e7c b 754 34 +9e87 49 755 34 +9ed0 3b 756 34 +9f0b 12 754 34 +9f1d 15 758 34 +9f32 8 759 34 +9f3a 1c 760 34 +9f56 f 761 34 +9f65 41 762 34 +9fb2 7 98 68 +9fb9 1 98 68 +9fc6 1d 85 68 +9fe3 5 86 68 +9fe8 17 88 68 +9fff 1 88 68 +a00c 1d 297 34 +a029 1 297 34 +a037 e 605 34 +a045 9 606 34 +a04e 3c 609 34 +a08a b 610 34 +a095 11 609 34 +a0a6 b 612 34 +a0b1 12 614 34 +a0c3 b 615 34 +a0ce 13 612 34 +a0e1 8 615 34 +a0e9 1 615 34 +a0f7 15 751 34 +a10c 1a 752 34 +a126 b 754 34 +a131 49 755 34 +a17a 3b 756 34 +a1b5 12 754 34 +a1c7 15 758 34 +a1dc 8 759 34 +a1e4 1c 760 34 +a200 f 761 34 +a20f 41 762 34 +FUNC a250 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > > const&) +a250 d 699 26 +a25d 28 700 72 +a285 1 700 72 +a292 d 623 72 +a29f 5 624 72 +FUNC a2a4 4b 0 void std::__fill::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +a2a4 c 539 61 +a2b0 8 541 61 +a2b8 2 542 61 +a2ba 12 543 61 +a2cc 21 542 61 +a2ed 2 543 61 +a2ef 1 543 61 +FUNC a2f0 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +a2f0 c 560 26 +a2fc 4 567 61 +a300 1b 568 61 +a31b 1 568 61 +FUNC a31c 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) +a31c c 171 26 +a328 2 173 73 +a32a 1a 174 73 +a344 21 173 73 +a365 2 174 73 +a367 1 174 73 +a368 c 65 68 +a374 2 65 68 +a376 c 103 69 +a382 d 103 69 +a38f 1 103 69 +FUNC a390 2b 0 std::_List_base, std::allocator > >::get_allocator() const +a390 10 322 26 +a3a0 1b 324 66 +a3bb 1 324 66 +FUNC a3bc 7b 0 std::_List_base, std::allocator > >::_M_clear() +a3bc d 69 27 +a3c9 8 72 77 +a3d1 2 73 77 +a3d3 6 75 77 +a3d9 8 76 77 +a3e1 35 77 77 +a416 12 78 77 +a428 a 73 77 +a432 5 78 77 +a437 1 78 77 +a438 c 331 66 +a444 18 332 66 +a45c c 392 66 +a468 d 392 66 +a475 1 392 66 +a476 c 211 74 +a482 10 211 74 +a49e d 107 68 +a4ab 1 107 68 +FUNC a4ac 2e 0 void std::_Destroy >(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) +a4ac c 171 27 +a4b8 2 173 73 +a4ba 12 174 73 +a4cc c 173 73 +a4d8 2 174 73 +a4da c 272 71 +a4e6 4b 273 71 +a531 1 273 71 +a532 13 196 74 +a545 10 196 74 +a555 2f 197 74 +a584 1a 198 74 +a59e 13 196 74 +a5b1 10 196 74 +a5c1 2f 197 74 +a5f0 1a 198 74 +a616 7 98 68 +a61d 1 98 68 +a62a 1d 85 68 +a647 5 86 68 +a64c 10 88 68 +FUNC a65c 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_allocate(unsigned long) +a65c c 116 27 +a668 1e 117 71 +a686 d 100 71 +a693 12 101 71 +a6a5 19 103 71 +a6be b 104 71 +a6c9 3a 105 71 +a703 1 105 71 +a710 7 98 68 +a717 1 98 68 +a724 1d 85 68 +a741 5 86 68 +a746 10 88 68 +FUNC a756 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_allocate(unsigned long) +a756 c 116 27 +a762 1e 117 71 +a780 d 100 71 +a78d 12 101 71 +a79f 19 103 71 +a7b8 b 104 71 +a7c3 3a 105 71 +a7fd 1 105 71 +a80b 12 424 61 +a81d 2e 425 61 +a84b 13 426 61 +a86a 4 440 61 +a86e 1b 443 61 +a889 1 443 61 +a898 56 482 61 +a8fa 4 514 61 +a8fe 4 515 61 +a902 1b 517 61 +a91d 1 517 61 +a92a 8 616 61 +a932 2 617 61 +a934 8 618 61 +a93c f 617 61 +a94b 5 619 61 +a95c 4 641 61 +a960 1b 642 61 +a97b 1 642 61 +FUNC a97c 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, __true_type) +a97c c 182 28 +a988 1b 183 79 +a9a3 1 183 79 +FUNC a9a4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +a9a4 c 214 28 +a9b0 23 218 79 +a9d3 1 218 79 +FUNC a9d4 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) +a9d4 c 308 28 +a9e0 1b 310 79 +a9fb 1 310 79 +a9fc c 200 71 +aa08 19 201 71 +aa21 42 203 71 +aa63 15 205 71 +aa85 11 992 34 +aa96 c 993 34 +aaa2 15 995 34 +aab7 c 996 34 +aac3 4a 998 34 +ab0d f 1001 34 +ab1c 1c 998 34 +ab38 1a 1003 34 +ab52 5 1004 34 +ab57 1f 1007 34 +ab76 1c 1008 34 +ab92 19 1009 34 +abab 19 1010 34 +abc4 1a 1011 34 +abde a 1004 34 +abe8 11 1001 34 +abf9 15 1014 34 +ac0e 13 1028 34 +ac21 b 1016 34 +ac2c 9 1018 34 +ac35 19 1023 34 +ac4e 23 1024 34 +ac71 19 1025 34 +ac8a 1d 1021 34 +aca7 1a 1018 34 +acc1 b 1028 34 +accc b 1016 34 +acd7 1e 1028 34 +acf5 1 1028 34 +ad06 16 438 34 +ad1c 37 439 34 +ad53 1 439 34 +ad64 37 212 42 +ad9b 1 212 42 +ada8 8 616 61 +adb0 2 617 61 +adb2 8 618 61 +adba f 617 61 +adc9 5 619 61 +adda 4 641 61 +adde 1b 642 61 +adf9 1 642 61 +FUNC adfa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, __true_type) +adfa c 182 28 +ae06 1b 183 79 +ae21 1 183 79 +FUNC ae22 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) +ae22 c 214 28 +ae2e 23 218 79 +ae51 1 218 79 +FUNC ae52 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, std::allocator<__gnu_cxx::_Hashtable_node > >*>) +ae52 c 308 28 +ae5e 1b 310 79 +ae79 1 310 79 +ae7a c 200 71 +ae86 19 201 71 +ae9f 42 203 71 +aee1 15 205 71 +af03 11 992 34 +af14 c 993 34 +af20 15 995 34 +af35 c 996 34 +af41 4a 998 34 +af8b f 1001 34 +af9a 1c 998 34 +afb6 1a 1003 34 +afd0 5 1004 34 +afd5 1f 1007 34 +aff4 1c 1008 34 +b010 19 1009 34 +b029 19 1010 34 +b042 1a 1011 34 +b05c a 1004 34 +b066 11 1001 34 +b077 15 1014 34 +b08c 13 1028 34 +b09f b 1016 34 +b0aa 9 1018 34 +b0b3 19 1023 34 +b0cc 23 1024 34 +b0ef 19 1025 34 +b108 1d 1021 34 +b125 1a 1018 34 +b13f b 1028 34 +b14a b 1016 34 +b155 1e 1028 34 +b173 1 1028 34 +b184 16 438 34 +b19a 37 439 34 +b1d1 1 439 34 +b1e2 37 212 42 +b219 1 212 42 +b227 12 424 61 +b239 2e 425 61 +b267 13 426 61 +b286 4 440 61 +b28a 1b 443 61 +b2a5 1 443 61 +b2b4 56 482 61 +b316 4 514 61 +b31a 4 515 61 +b31e 1b 517 61 +b339 1 517 61 +b346 8 616 61 +b34e 2 617 61 +b350 12 618 61 +b362 16 617 61 +b378 5 619 61 +b37d 1 619 61 +b38a 4 641 61 +b38e 1b 642 61 +b3a9 1 642 61 +FUNC b3aa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, __true_type) +b3aa c 182 28 +b3b6 1b 183 79 +b3d1 1 183 79 +FUNC b3d2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) +b3d2 c 214 28 +b3de 23 218 79 +b401 1 218 79 +FUNC b402 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, std::allocator<__gnu_cxx::_Hashtable_node > >*>) +b402 c 308 28 +b40e 1b 310 79 +b429 1 310 79 +b436 8 616 61 +b43e 2 617 61 +b440 12 618 61 +b452 16 617 61 +b468 5 619 61 +b46d 1 619 61 +b47a 4 641 61 +b47e 1b 642 61 +b499 1 642 61 +FUNC b49a 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, __true_type) +b49a c 182 28 +b4a6 1b 183 79 +b4c1 1 183 79 +FUNC b4c2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +b4c2 c 214 28 +b4ce 23 218 79 +b4f1 1 218 79 +FUNC b4f2 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) +b4f2 c 308 28 +b4fe 1b 310 79 +b519 1 310 79 +b526 22 300 61 +b548 11 301 61 +b559 1 301 61 +b566 4 315 61 +b56a 1b 317 61 +b585 1 317 61 +b592 1b 326 61 +b5ad 1 326 61 +b5ba 4 384 61 +b5be 4 385 61 +b5c2 1b 387 61 +b5dd 1 387 61 +b5ea 1b 74 79 +b605 1 74 79 +b612 23 113 79 +b635 1 113 79 +b642 1b 254 79 +b65d 1 254 79 +b66a 15 763 71 +b67f 40 766 71 +b6bf 3 768 71 +b6c2 2 773 71 +FUNC b6c4 124 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::reserve(unsigned long) +b6c4 13 69 29 +b6d7 15 71 78 +b6ec e 72 78 +b6fa 19 73 78 +b713 e 75 78 +b721 28 78 78 +b749 3e 79 78 +b787 30 81 78 +b7b7 8 84 78 +b7bf 11 85 78 +b7d0 18 86 78 +b7f5 33 335 61 +b834 4 384 61 +b838 4 385 61 +b83c 1b 387 61 +b857 1 387 61 +b864 1b 74 79 +b87f 1 74 79 +b88c 23 113 79 +b8af 1 113 79 +b8bc 1b 254 79 +b8d7 1 254 79 +b8e6 56 354 61 +b948 4 384 61 +b94c 4 385 61 +b950 1b 387 61 +b96b 1 387 61 +b978 1b 74 79 +b993 1 74 79 +b9a0 23 113 79 +b9c3 1 113 79 +b9d0 1b 254 79 +b9eb 1 254 79 +FUNC b9ec 46e 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) +b9ec 14 311 29 +ba00 b 313 78 +ba0b 24 315 78 +ba2f 8 318 78 +ba37 23 319 78 +ba5a 15 320 78 +ba6f c 321 78 +ba7b 51 323 78 +bacc 14 327 78 +bae0 30 328 78 +bb10 35 330 78 +bb45 48 334 78 +bb8d 17 338 78 +bba4 43 339 78 +bbe7 14 342 78 +bbfb 1e 343 78 +bc19 e 348 78 +bc27 1e 349 78 +bc45 e 350 78 +bc53 1d 353 78 +bc70 8 354 78 +bc78 e 355 78 +bc86 27 357 78 +bcad 6 358 78 +bcb3 4d 361 78 +bd00 40 365 78 +bd40 18 367 78 +bd58 4d 368 78 +bda5 3e 379 78 +bde3 30 381 78 +be13 12 384 78 +be25 13 385 78 +be38 22 386 78 +FUNC be5a 2e 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) +be5a c 657 29 +be66 22 658 71 +be94 15 580 34 +bea9 15 581 34 +bebe 37 582 34 +bef5 c 583 34 +bf01 1 583 34 +bf02 d 335 34 +bf0f 4e 337 34 +bf5d 4d 338 34 +bfaa d 134 42 +bfb7 65 135 42 +c028 22 300 61 +c04a 11 301 61 +c05b 1 301 61 +c068 4 315 61 +c06c 1b 317 61 +c087 1 317 61 +c094 1b 326 61 +c0af 1 326 61 +c0bc 4 384 61 +c0c0 4 385 61 +c0c4 1b 387 61 +c0df 1 387 61 +c0ec 1b 74 79 +c107 1 74 79 +c114 23 113 79 +c137 1 113 79 +c144 1b 254 79 +c15f 1 254 79 +c16c 15 763 71 +c181 40 766 71 +c1c1 3 768 71 +c1c4 2 773 71 +FUNC c1c6 124 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::reserve(unsigned long) +c1c6 13 69 29 +c1d9 15 71 78 +c1ee e 72 78 +c1fc 19 73 78 +c215 e 75 78 +c223 28 78 78 +c24b 3e 79 78 +c289 30 81 78 +c2b9 8 84 78 +c2c1 11 85 78 +c2d2 18 86 78 +c2f7 33 335 61 +c336 4 384 61 +c33a 4 385 61 +c33e 1b 387 61 +c359 1 387 61 +c366 1b 74 79 +c381 1 74 79 +c38e 23 113 79 +c3b1 1 113 79 +c3be 1b 254 79 +c3d9 1 254 79 +c3e8 56 354 61 +c44a 4 384 61 +c44e 4 385 61 +c452 1b 387 61 +c46d 1 387 61 +c47a 1b 74 79 +c495 1 74 79 +c4a2 23 113 79 +c4c5 1 113 79 +c4d2 1b 254 79 +c4ed 1 254 79 +FUNC c4ee 46e 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +c4ee 14 311 29 +c502 b 313 78 +c50d 24 315 78 +c531 8 318 78 +c539 23 319 78 +c55c 15 320 78 +c571 c 321 78 +c57d 51 323 78 +c5ce 14 327 78 +c5e2 30 328 78 +c612 35 330 78 +c647 48 334 78 +c68f 17 338 78 +c6a6 43 339 78 +c6e9 14 342 78 +c6fd 1e 343 78 +c71b e 348 78 +c729 1e 349 78 +c747 e 350 78 +c755 1d 353 78 +c772 8 354 78 +c77a e 355 78 +c788 27 357 78 +c7af 6 358 78 +c7b5 4d 361 78 +c802 40 365 78 +c842 18 367 78 +c85a 4d 368 78 +c8a7 3e 379 78 +c8e5 30 381 78 +c915 12 384 78 +c927 13 385 78 +c93a 22 386 78 +FUNC c95c 2e 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) +c95c c 657 29 +c968 22 658 71 +c996 15 580 34 +c9ab 15 581 34 +c9c0 37 582 34 +c9f7 c 583 34 +ca03 1 583 34 +ca04 d 335 34 +ca11 4e 337 34 +ca5f 4d 338 34 +caac d 134 42 +cab9 65 135 42 +FUNC cb1e 44 0 dwarf2reader::CUFunctionInfoHandler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char) +cb1e 39 135 42 +cb57 5 102 30 +cb5c 6 103 30 +FUNC cb62 41 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&) +cb62 18 136 30 +cb7a 10 137 30 +cb8a 17 138 30 +cba1 2 139 30 +cba3 1 139 30 +FUNC cba4 2a5 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long) +cba4 2d 144 30 +cbd1 a 145 30 +cbdb 58 146 30 +cc33 35 147 30 +cc68 32 146 30 +cc9a 2a 147 30 +ccc4 82 152 30 +cd46 18 153 30 +cd5e 1c 152 30 +cd7a 2f 153 30 +cda9 e 154 30 +cdb7 28 155 30 +cddf 12 157 30 +cdf1 2 158 30 +cdf3 12 160 30 +ce05 2 161 30 +ce07 c 163 30 +ce13 2 164 30 +ce15 2c 166 30 +ce41 8 172 30 +ce49 1 172 30 +FUNC ce4a 19c 0 dwarf2reader::CULineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int) +ce4a 20 84 30 +ce6a 1c 85 30 +ce86 9c 87 30 +cf22 4f 89 30 +cf71 19 87 30 +cf8a 25 90 30 +cfaf 30 93 30 +cfdf 7 95 30 +FUNC cfe6 9f 0 dwarf2reader::CUFunctionInfoHandler::EndDIE(unsigned long long) +cfe6 19 174 30 +cfff 1c 175 30 +d01b 65 177 30 +d080 5 178 30 +d085 1 178 30 +FUNC d086 164 0 dwarf2reader::CUFunctionInfoHandler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list, std::allocator > > const&) +d086 20 111 30 +d0a6 1c 112 30 +d0c2 c 126 30 +d0ce 23 115 30 +d0f1 26 116 30 +d117 1a 117 30 +d131 d 118 30 +d13e 1b 119 30 +d159 5f 120 30 +d1b8 c 124 30 +d1c4 1c 115 30 +d1e0 3 126 30 +d1e3 7 129 30 +FUNC d1ea 73 0 dwarf2reader::CULineInfoHandler::DefineDir(std::string const&, unsigned int) +d1ea 13 52 30 +d1fd 45 54 30 +d242 15 55 30 +d257 6 56 30 +d25d 1 56 30 +FUNC d25e 23b 0 dwarf2reader::CULineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long) +d25e 2c 60 30 +d28a 45 62 30 +d2cf 2f 65 30 +d2fe 24 66 30 +d322 b 68 30 +d32d e 69 30 +d33b 19 71 30 +d354 17 72 30 +d36b 93 74 30 +d3fe 64 77 30 +d462 30 79 30 +d492 7 81 30 +d499 1 81 30 +d49a 14 38 30 +d4ae 36 40 30 +d4e4 41 43 30 +d525 41 44 30 +d566 67 45 30 +d5cd 10 46 30 +d5dd 13 45 30 +d5f0 15 47 30 +d605 e 48 30 +d613 3d 49 30 +d650 20 50 30 +d670 14 38 30 +d684 36 40 30 +d6ba 41 43 30 +d6fb 41 44 30 +d73c 67 45 30 +d7a3 10 46 30 +d7b3 13 45 30 +d7c6 15 47 30 +d7db e 48 30 +d7e9 3d 49 30 +d826 20 50 30 +d846 12 125 74 +d858 12 125 74 +d86a 13 55 32 +d87d 35 55 32 +d8b2 13 98 32 +d8c5 35 98 32 +d8fa c 35 32 +d906 d 35 32 +d913 1 35 32 +d914 d 22 32 +d921 40 22 32 +d961 1 22 32 +d962 c 89 70 +d96e 1e 90 70 +d998 14 208 34 +d9ac c 190 67 +d9b8 a 190 67 +d9c2 c 259 67 +d9ce 21 259 67 +d9ef 1 259 67 +FUNC d9f0 13 0 std::auto_ptr::operator->() const +d9f0 c 283 35 +d9fc 7 286 67 +da03 1 286 67 +da11 5c 104 68 +da6d 1 104 68 +FUNC da6e 28 0 bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, char const*) +da6e c 2139 37 +da7a 1c 2140 37 +FUNC da96 5d 0 std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, char const*) +da96 d 2081 37 +daa3 12 2083 37 +dab5 1a 2084 37 +dacf 24 2085 37 +daf3 1 2085 37 +FUNC daf4 5d 0 std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) +daf4 d 2044 37 +db01 12 2046 37 +db13 1a 2047 37 +db2d 24 2048 37 +db51 1 2048 37 +db52 c 84 70 +db5e 17 85 70 +db75 1 85 70 +FUNC db76 2d 0 std::pair std::make_pair(char const*, unsigned int) +db76 c 144 37 +db82 21 145 70 +dba3 1 145 70 +dba4 c 84 70 +dbb0 23 85 70 +dbd3 1 85 70 +FUNC dbd4 3c 0 std::pair > std::make_pair >(unsigned long long, std::pair) +dbd4 1c 144 37 +dbf0 20 145 70 +dc10 d 89 70 +dc1d 64 90 70 +dc81 1 90 70 +dc82 c 89 70 +dc8e 2a 90 70 +dcb8 c 84 70 +dcc4 1d 85 70 +dce1 1 85 70 +FUNC dce2 3c 0 std::pair std::make_pair(unsigned long long, dwarf2reader::FunctionInfo*) +dce2 1c 144 37 +dcfe 20 145 70 +dd2a a 190 34 +dd40 d 194 34 +dd4d 1 194 34 +dd4e c 603 72 +dd5a c 603 72 +FUNC dd66 2b 0 std::vector >::begin() const +dd66 c 342 39 +dd72 1f 343 71 +dd91 1 343 71 +FUNC dd92 2c 0 std::vector >::end() const +dd92 c 360 39 +dd9e 20 361 71 +ddca 5 666 72 +ddcf 1 666 72 +dddd 2b 759 72 +FUNC de08 3c 0 std::vector >::size() const +de08 c 402 39 +de14 30 403 71 +FUNC de44 2b 0 std::vector >::begin() const +de44 c 342 39 +de50 1f 343 71 +de6f 1 343 71 +FUNC de70 2c 0 std::vector >::end() const +de70 c 360 39 +de7c 20 361 71 +dea9 31 759 72 +FUNC deda 3c 0 std::vector >::size() const +deda c 402 39 +dee6 30 403 71 +df16 c 603 72 +df22 c 603 72 +FUNC df2e 26 0 std::vector >::end() +df2e c 351 39 +df3a 1a 352 71 +df60 7 614 72 +df67 1 614 72 +FUNC df68 13 0 std::vector >::max_size() const +df68 c 407 39 +df74 7 408 71 +df7b 1 408 71 +df88 5 666 72 +df8d 1 666 72 +df9a d 623 72 +dfa7 5 624 72 +FUNC dfac 23 0 std::vector >::begin() +dfac c 333 39 +dfb8 17 334 71 +dfcf 1 334 71 +dfd0 c 35 32 +dfdc 26 35 32 +e00f 5c 104 68 +e06b 1 104 68 +e078 7 614 72 +e07f 1 614 72 +FUNC e080 35 0 dwarf2reader::SourceFileInfo::operator=(dwarf2reader::SourceFileInfo const&) +e080 c 35 39 +e08c 29 35 32 +e0b5 1 35 32 +FUNC e0b6 13 0 std::vector >::max_size() const +e0b6 c 407 39 +e0c2 7 408 71 +e0c9 1 408 71 +e0d6 d 623 72 +e0e3 5 624 72 +FUNC e0e8 3c 0 std::vector >::_M_range_check(unsigned long) const +e0e8 13 515 39 +e0fb 15 517 71 +e110 14 518 71 +FUNC e124 3c 0 std::vector >::_M_range_check(unsigned long) const +e124 13 515 39 +e137 15 517 71 +e14c 14 518 71 +e16c 2a 654 72 +FUNC e196 42 0 std::vector >::operator[](unsigned long) +e196 c 494 39 +e1a2 36 495 71 +FUNC e1d8 32 0 std::vector >::at(unsigned long) +e1d8 c 534 39 +e1e4 12 536 71 +e1f6 14 537 71 +e216 32 654 72 +FUNC e248 42 0 std::vector >::operator[](unsigned long) +e248 c 494 39 +e254 36 495 71 +FUNC e28a 32 0 std::vector >::at(unsigned long) +e28a c 534 39 +e296 12 536 71 +e2a8 14 537 71 +FUNC e2bc 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_end() +e2bc c 472 40 +e2c8 8 473 40 +FUNC e2d0 11 0 std::_Select1st > >::operator()(std::pair > const&) const +e2d0 c 550 41 +e2dc 5 551 41 +e2e1 1 551 41 +FUNC e2e2 53 0 std::less::operator()(unsigned long long const&, unsigned long long const&) const +e2e2 c 226 41 +e2ee 47 227 41 +e335 1 227 41 +FUNC e336 20 0 std::_Rb_tree_iterator > >::operator==(std::_Rb_tree_iterator > > const&) const +e336 c 209 41 +e342 14 210 40 +e356 c 84 70 +e362 18 85 70 +FUNC e37a 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_end() +e37a c 472 41 +e386 8 473 40 +FUNC e38e 11 0 std::_Select1st >::operator()(std::pair const&) const +e38e c 550 41 +e39a 5 551 41 +e39f 1 551 41 +FUNC e3a0 20 0 std::_Rb_tree_iterator >::operator==(std::_Rb_tree_iterator > const&) const +e3a0 c 209 41 +e3ac 14 210 40 +e3c0 c 84 70 +e3cc 18 85 70 +e3e4 c 180 34 +e3f0 13 181 34 +e403 1 181 34 +e410 22 409 34 +e43e d 207 42 +e44b 1 207 42 +FUNC e44c 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) +e44c d 699 42 +e459 28 700 72 +e481 1 700 72 +FUNC e482 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) +e482 c 171 43 +e48e 2 173 73 +e490 1a 174 73 +e4aa 21 173 73 +e4cb 2 174 73 +e4cd 1 174 73 +FUNC e4ce 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) +e4ce d 699 43 +e4db 28 700 72 +e503 1 700 72 +FUNC e504 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) +e504 c 171 43 +e510 2 173 73 +e512 1a 174 73 +e52c 21 173 73 +e54d 2 174 73 +e54f 1 174 73 +FUNC e550 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_value(std::_Rb_tree_node > > const*) +e550 c 480 43 +e55c 8 481 40 +FUNC e564 28 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_key(std::_Rb_tree_node > > const*) +e564 c 484 43 +e570 1c 485 40 +FUNC e58c 25 0 std::_Rb_tree_iterator >::operator--() +e58c c 194 43 +e598 14 196 40 +e5ac 5 197 40 +e5b1 1 197 40 +FUNC e5b2 25 0 std::_Rb_tree_iterator > >::operator--() +e5b2 c 194 43 +e5be 14 196 40 +e5d2 5 197 40 +e5d7 1 197 40 +FUNC e5d8 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_value(std::_Rb_tree_node_base const*) +e5d8 c 504 43 +e5e4 8 505 40 +FUNC e5ec 28 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_key(std::_Rb_tree_node_base const*) +e5ec c 508 43 +e5f8 1c 509 40 +FUNC e614 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_value(std::_Rb_tree_node > const*) +e614 c 480 43 +e620 8 481 40 +FUNC e628 28 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_key(std::_Rb_tree_node > const*) +e628 c 484 43 +e634 1c 485 40 +FUNC e650 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_value(std::_Rb_tree_node_base const*) +e650 c 504 43 +e65c 8 505 40 +FUNC e664 28 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_key(std::_Rb_tree_node_base const*) +e664 c 508 43 +e670 1c 509 40 +e698 7 614 72 +e69f 1 614 72 +e6ac 7 98 68 +e6b3 1 98 68 +e6c0 1d 85 68 +e6dd 5 86 68 +e6e2 10 88 68 +FUNC e6f2 2a 0 std::_Vector_base >::_M_allocate(unsigned long) +e6f2 c 116 43 +e6fe 1e 117 71 +e728 7 98 68 +e72f 1 98 68 +e73c 1d 85 68 +e759 5 86 68 +e75e 16 88 68 +FUNC e774 2a 0 std::_Vector_base >::_M_allocate(unsigned long) +e774 c 116 43 +e780 1e 117 71 +e7aa 3a 104 68 +e7f0 2a 654 72 +FUNC e81a 42 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::operator[](unsigned long) const +e81a c 509 43 +e826 36 510 71 +FUNC e85c 4e 0 std::string* std::__copy_backward::copy_b(std::string*, std::string*, std::string*) +e85c c 408 61 +e868 14 411 61 +e87c 1e 412 61 +e89a b 411 61 +e8a5 5 413 61 +FUNC e8aa 2b 0 std::string* std::__copy_backward_aux(std::string*, std::string*, std::string*) +e8aa c 432 44 +e8b6 4 440 61 +e8ba 1b 443 61 +e8d5 1 443 61 +e8e4 56 482 61 +e946 4 514 61 +e94a 4 515 61 +e94e 1b 517 61 +e969 1 517 61 +FUNC e96a 69 0 void std::_Construct(std::string*, std::string const&) +e96a d 77 44 +e977 5c 81 73 +e9d3 1 81 73 +FUNC e9d4 54 0 dwarf2reader::SourceFileInfo* std::__copy_backward::copy_b(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*) +e9d4 c 408 61 +e9e0 1a 411 61 +e9fa 1e 412 61 +ea18 b 411 61 +ea23 5 413 61 +FUNC ea28 2b 0 dwarf2reader::SourceFileInfo* std::__copy_backward_aux(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*) +ea28 c 432 44 +ea34 4 440 61 +ea38 1b 443 61 +ea53 1 443 61 +ea62 56 482 61 +eac4 4 514 61 +eac8 4 515 61 +eacc 1b 517 61 +eae7 1 517 61 +FUNC eae8 69 0 void std::_Construct(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo const&) +eae8 d 77 44 +eaf5 5c 81 73 +eb51 1 81 73 +eb52 c 69 70 +eb5e 20 69 70 +eb7e c 69 70 +eb8a 2a 69 70 +ebc1 5c 104 68 +ec1d 1 104 68 +ec2a 15 523 34 +ec3f 79 525 34 +ecb8 21 529 34 +ecd9 1 529 34 +ece6 14 229 42 +ed06 7 98 68 +ed0d 1 98 68 +ed1a 1d 85 68 +ed37 5 86 68 +ed3c 10 88 68 +FUNC ed4c 29 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_get_node() +ed4c c 355 44 +ed58 1d 356 40 +ed75 1 356 40 +FUNC ed76 b6 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_create_node(std::pair > const&) +ed76 d 363 44 +ed83 e 365 40 +ed91 3c 367 40 +edcd b 373 40 +edd8 11 367 40 +ede9 b 368 40 +edf4 12 370 40 +ee06 b 371 40 +ee11 13 368 40 +ee24 8 373 40 +FUNC ee2c cd 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair > const&) +ee2c d 787 44 +ee39 15 789 40 +ee4e 5d 792 40 +eeab 24 796 40 +eecf f 798 40 +eede 1b 799 40 +eef9 1 799 40 +FUNC eefa 1ef 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::insert_unique(std::pair > const&) +eefa d 869 44 +ef07 e 871 40 +ef15 e 872 40 +ef23 4 873 40 +ef27 2 874 40 +ef29 6 876 40 +ef2f 35 877 40 +ef64 2a 878 40 +ef8e 6 874 40 +ef94 12 880 40 +efa6 a 881 40 +efb0 24 882 40 +efd4 51 883 40 +f025 b 885 40 +f030 36 886 40 +f066 4e 887 40 +f0b4 35 888 40 +f0e9 1 888 40 +FUNC f0ea 20 0 std::map, std::less, std::allocator > > >::insert(std::pair > const&) +f0ea c 359 45 +f0f6 14 360 45 +f116 7 98 68 +f11d 1 98 68 +f12a 1d 85 68 +f147 5 86 68 +f14c 1d 88 68 +f169 1 88 68 +FUNC f16a 29 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_get_node() +f16a c 355 45 +f176 1d 356 40 +f193 1 356 40 +FUNC f194 5f 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_create_node(std::pair const&) +f194 d 363 45 +f1a1 e 365 40 +f1af 3c 367 40 +f1eb 8 373 40 +f1f3 1 373 40 +FUNC f1f4 cd 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair const&) +f1f4 d 787 45 +f201 15 789 40 +f216 5d 792 40 +f273 24 796 40 +f297 f 798 40 +f2a6 1b 799 40 +f2c1 1 799 40 +FUNC f2c2 1ef 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::insert_unique(std::pair const&) +f2c2 d 869 45 +f2cf e 871 40 +f2dd e 872 40 +f2eb 4 873 40 +f2ef 2 874 40 +f2f1 6 876 40 +f2f7 35 877 40 +f32c 2a 878 40 +f356 6 874 40 +f35c 12 880 40 +f36e a 881 40 +f378 24 882 40 +f39c 51 883 40 +f3ed b 885 40 +f3f8 36 886 40 +f42e 4e 887 40 +f47c 35 888 40 +f4b1 1 888 40 +FUNC f4b2 20 0 std::map, std::allocator > >::insert(std::pair const&) +f4b2 c 359 45 +f4be 14 360 45 +FUNC f4d2 19 0 void std::_Destroy(std::string*) +f4d2 c 106 45 +f4de d 107 73 +f4eb 1 107 73 +FUNC f4ec 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) +f4ec c 119 45 +f4f8 2 121 73 +f4fa 13 122 73 +f50d 21 121 73 +f52e 2 122 73 +FUNC f530 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +f530 c 148 45 +f53c 1c 155 73 +f565 6 82 79 +f56b 2 85 79 +f56d 24 86 79 +f591 2c 85 79 +f5bd b 87 79 +f5c8 b 89 79 +f5d3 12 91 79 +f5e5 b 92 79 +f5f0 13 89 79 +f603 9 92 79 +f618 23 113 79 +f63b 1 113 79 +f648 1b 254 79 +f663 1 254 79 +FUNC f664 430 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, std::string const&) +f664 14 249 47 +f678 14 251 78 +f68c 22 253 78 +f6ae f 255 78 +f6bd 12 256 78 +f6cf 55 257 78 +f724 4b 260 78 +f76f e 264 78 +f77d 15 265 78 +f792 e 266 78 +f7a0 1d 271 78 +f7bd 8 272 78 +f7c5 e 273 78 +f7d3 27 275 78 +f7fa 6 276 78 +f800 55 279 78 +f855 25 284 78 +f87a b 285 78 +f885 4f 286 78 +f8d4 3 284 78 +f8d7 13 279 78 +f8ea e 286 78 +f8f8 4d 298 78 +f945 30 299 78 +f975 12 302 78 +f987 13 303 78 +f99a 23 304 78 +f9bd 3 298 78 +f9c0 13 286 78 +f9d3 b 292 78 +f9de 39 294 78 +fa17 23 295 78 +fa3a 8 296 78 +fa42 16 294 78 +fa58 3 296 78 +fa5b 19 292 78 +fa74 19 298 78 +fa8d 7 304 78 +FUNC fa94 70 0 std::vector >::push_back(std::string const&) +fa94 c 602 47 +faa0 10 604 71 +fab0 1e 606 71 +face 11 607 71 +fadf 25 610 71 +FUNC fb04 19 0 void std::_Destroy(dwarf2reader::SourceFileInfo*) +fb04 c 106 47 +fb10 d 107 73 +fb1d 1 107 73 +FUNC fb1e 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) +fb1e c 119 47 +fb2a 2 121 73 +fb2c 13 122 73 +fb3f 21 121 73 +fb60 2 122 73 +FUNC fb62 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +fb62 c 148 47 +fb6e 1c 155 73 +fb97 6 82 79 +fb9d 2 85 79 +fb9f 24 86 79 +fbc3 2c 85 79 +fbef b 87 79 +fbfa b 89 79 +fc05 12 91 79 +fc17 b 92 79 +fc22 13 89 79 +fc35 9 92 79 +fc4a 23 113 79 +fc6d 1 113 79 +fc7a 1b 254 79 +fc95 1 254 79 +FUNC fc96 43d 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, dwarf2reader::SourceFileInfo const&) +fc96 14 249 47 +fcaa 14 251 78 +fcbe 22 253 78 +fce0 f 255 78 +fcef 12 256 78 +fd01 55 257 78 +fd56 4b 260 78 +fda1 e 264 78 +fdaf 15 265 78 +fdc4 e 266 78 +fdd2 1d 271 78 +fdef 8 272 78 +fdf7 e 273 78 +fe05 27 275 78 +fe2c 6 276 78 +fe32 55 279 78 +fe87 25 284 78 +feac b 285 78 +feb7 4f 286 78 +ff06 3 284 78 +ff09 13 279 78 +ff1c e 286 78 +ff2a 4d 298 78 +ff77 36 299 78 +ffad 12 302 78 +ffbf 13 303 78 +ffd2 2a 304 78 +fffc 3 298 78 +ffff 13 286 78 +10012 b 292 78 +1001d 39 294 78 +10056 23 295 78 +10079 8 296 78 +10081 16 294 78 +10097 3 296 78 +1009a 19 292 78 +100b3 19 298 78 +100cc 7 304 78 +100d3 1 304 78 +FUNC 100d4 70 0 std::vector >::push_back(dwarf2reader::SourceFileInfo const&) +100d4 c 602 47 +100e0 10 604 71 +100f0 1e 606 71 +1010e 11 607 71 +1011f 25 610 71 +FUNC 10144 16c 0 Start +10144 17 610 71 +1015b 40 49 48 +1019b 6 51 48 +101a1 3f 53 48 +101e0 7 54 48 +101e7 5 55 48 +101ec 2a 58 48 +10216 61 61 48 +10277 7 62 48 +1027e 2 63 48 +10280 29 66 48 +102a9 7 67 48 +FUNC 102b0 108 0 Usage +102b0 19 70 48 +102c9 30 71 48 +102f9 29 73 48 +10322 30 74 48 +10352 30 75 48 +10382 30 76 48 +103b2 6 77 48 +FUNC 103b8 3af 0 SetupOptions +103b8 21 80 48 +103d9 8 82 48 +103e1 6 85 48 +103e7 10 86 48 +103f7 2e 88 48 +10425 2f 94 48 +10454 2a 91 48 +1047e 23 95 48 +104a1 3e 97 48 +104df 11 98 48 +104f0 7c 99 48 +1056c c 100 48 +10578 5 99 48 +1057d 3e 101 48 +105bb 11 102 48 +105cc 3e 103 48 +1060a 11 104 48 +1061b 37 106 48 +10652 b 107 48 +1065d c 108 48 +10669 b 113 48 +10674 c 114 48 +10680 14 119 48 +10694 30 120 48 +106c4 b 121 48 +106cf c 122 48 +106db 81 127 48 +1075c b 128 48 +10767 1 128 48 +FUNC 10768 a7 0 main +10768 13 131 48 +1077b 37 132 48 +107b2 1e 135 48 +107d0 e 136 48 +107de 8 137 48 +107e6 17 139 48 +107fd c 141 48 +10809 6 142 48 +1080f 1 142 48 +10810 c 47 49 +1081c 1a 48 49 +10836 2 49 49 +10838 c 47 49 +10844 1a 48 49 +1085e 2 49 49 +FUNC 10860 cb 0 google_breakpad::FileID::FileIdentifier(unsigned char*) +10860 f 51 49 +1086f 16 52 49 +10885 6 53 49 +1088b f 54 49 +1089a b 57 49 +108a5 7 62 49 +108ac 2 63 49 +108ae 1c 64 49 +108ca 32 63 49 +108fc b 67 49 +10907 12 68 49 +10919 10 70 49 +10929 2 71 49 +1092b 1 71 49 +FUNC 1092c f2 0 google_breakpad::FileID::MachoIdentifier(int, unsigned char*) +1092c 10 73 49 +1093c 15 74 49 +10951 20 76 49 +10971 f 77 49 +10980 20 79 49 +109a0 c 80 49 +109ac 69 82 49 +10a15 9 83 49 +FUNC 10a1e fb 0 google_breakpad::FileID::ConvertIdentifierToString(unsigned char const*, char*, int) +10a1e c 87 49 +10a2a 7 88 49 +10a31 c 89 49 +10a3d 15 90 49 +10a52 12 91 49 +10a64 18 93 49 +10a7c e 94 49 +10a8a 2b 96 49 +10ab5 2b 97 49 +10ae0 17 89 49 +10af7 20 101 49 +10b17 2 102 49 +10b19 1 102 49 +FUNC 10b1a 13 0 NXHostByteOrder +10b1a c 144 56 +10b26 5 147 56 +10b2b 2 153 56 +10b2d 1 153 56 +10b2e c 56 51 +10b3a 1a 57 51 +10b54 1e 58 51 +10b72 2 59 51 +10b74 c 56 51 +10b80 1a 57 51 +10b9a 1e 58 51 +10bb8 2 59 51 +10bba c 61 51 +10bc6 e 62 51 +10bd4 11 63 51 +10be5 2 64 51 +10be7 1 64 51 +10be8 c 61 51 +10bf4 e 62 51 +10c02 11 63 51 +10c13 2 64 51 +10c15 1 64 51 +FUNC 10c16 477 0 MacFileUtilities::MachoID::UpdateCRC(unsigned char*, unsigned long) +10c16 c 74 51 +10c22 11 82 51 +10c33 14 83 51 +10c47 5 86 51 +10c4c 9 87 51 +10c55 7 88 51 +10c5c 18b 90 51 +10de7 6 91 51 +10ded 14 89 51 +10e01 23 93 51 +10e24 23 94 51 +10e47 d 86 51 +10e54 f 98 51 +10e63 6 100 51 +10e69 18b 101 51 +10ff4 6 102 51 +10ffa c 99 51 +11006 13 105 51 +11019 8 106 51 +11021 10 104 51 +11031 23 108 51 +11054 23 109 51 +11077 14 110 51 +1108b 2 112 51 +1108d 1 112 51 +FUNC 1108e 2c 0 MacFileUtilities::MachoID::UpdateMD5(unsigned char*, unsigned long) +1108e c 114 51 +1109a 1e 115 51 +110b8 2 116 51 +FUNC 110ba 2c 0 MacFileUtilities::MachoID::UpdateSHA1(unsigned char*, unsigned long) +110ba c 118 51 +110c6 1e 119 51 +110e4 2 120 51 +FUNC 110e6 121 0 MacFileUtilities::MachoID::Update(MacFileUtilities::MachoWalker*, unsigned long, unsigned long) +110e6 f 122 51 +110f5 1b 123 51 +11110 e 129 51 +1111e 5 130 51 +11123 9 131 51 +1112c 7 132 51 +11133 a 133 51 +1113d 6 135 51 +11143 7 136 51 +1114a 35 139 51 +1117f 6c 142 51 +111eb 10 143 51 +111fb a 130 51 +11205 2 145 51 +11207 1 145 51 +FUNC 11208 cf 0 MacFileUtilities::MachoID::UUIDCommand(int, unsigned char*) +11208 14 147 51 +1121c 25 149 51 +11241 7 151 51 +11248 19 152 51 +11261 9 153 51 +1126a 8 157 51 +11272 1f 158 51 +11291 9 159 51 +1129a 36 162 51 +112d0 7 163 51 +112d7 1 163 51 +FUNC 112d8 224 0 MacFileUtilities::MachoID::IDCommand(int, unsigned char*) +112d8 15 165 51 +112ed 25 167 51 +11312 7 169 51 +11319 19 170 51 +11332 c 171 51 +1133e c 175 51 +1134a 6 180 51 +11350 7 181 51 +11357 9 182 51 +11360 9 183 51 +11369 28 185 51 +11391 33 186 51 +113c4 1e 185 51 +113e2 10 189 51 +113f2 10 190 51 +11402 10 191 51 +11412 d 192 51 +1141f 10 193 51 +1142f 10 194 51 +1143f 10 195 51 +1144f d 196 51 +1145c 17 197 51 +11473 17 198 51 +1148a 17 199 51 +114a1 14 200 51 +114b5 9 202 51 +114be 36 205 51 +114f4 8 206 51 +FUNC 114fc d1 0 MacFileUtilities::MachoID::Adler32(int) +114fc 14 208 51 +11510 25 209 51 +11535 27 210 51 +1155c d 211 51 +11569 19 213 51 +11582 9 214 51 +1158b 3b 216 51 +115c6 7 217 51 +115cd 1 217 51 +FUNC 115ce f8 0 MacFileUtilities::MachoID::MD5(int, unsigned char*) +115ce 14 219 51 +115e2 25 220 51 +11607 27 221 51 +1162e 19 223 51 +11647 19 224 51 +11660 9 225 51 +11669 17 227 51 +11680 9 228 51 +11689 36 231 51 +116bf 7 232 51 +FUNC 116c6 f8 0 MacFileUtilities::MachoID::SHA1(int, unsigned char*) +116c6 14 234 51 +116da 25 235 51 +116ff 27 236 51 +11726 19 238 51 +1173f 19 239 51 +11758 9 240 51 +11761 17 242 51 +11778 9 243 51 +11781 36 246 51 +117b7 7 247 51 +FUNC 117be 378 0 MacFileUtilities::MachoID::WalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) +117be 2b 251 51 +117e9 6 252 51 +117ef e 254 51 +117fd 38 257 51 +11835 f 258 51 +11844 9 260 51 +1184d 17 261 51 +11864 20 266 51 +11884 f 267 51 +11893 d 271 51 +118a0 c 273 51 +118ac 38 274 51 +118e4 f 275 51 +118f3 9 277 51 +118fc 1f 278 51 +1191b 14 282 51 +1192f 2b 283 51 +1195a d 285 51 +11967 19 273 51 +11980 e 287 51 +1198e 38 290 51 +119c6 f 291 51 +119d5 9 293 51 +119de 17 294 51 +119f5 20 299 51 +11a15 f 300 51 +11a24 d 304 51 +11a31 c 306 51 +11a3d 38 307 51 +11a75 f 308 51 +11a84 9 310 51 +11a8d 1f 311 51 +11aac 1a 315 51 +11ac6 39 316 51 +11aff d 318 51 +11b0c 11 306 51 +11b1d 10 323 51 +11b2d 9 324 51 +FUNC 11b36 95 0 MacFileUtilities::MachoID::UUIDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) +11b36 1e 328 51 +11b54 a 329 51 +11b5e 6 331 51 +11b64 2f 333 51 +11b93 9 335 51 +11b9c 6 337 51 +11ba2 14 338 51 +11bb6 9 340 51 +11bbf a 344 51 +11bc9 2 345 51 +11bcb 1 345 51 +FUNC 11bcc 95 0 MacFileUtilities::MachoID::IDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) +11bcc 1e 349 51 +11bea a 350 51 +11bf4 6 351 51 +11bfa 2f 353 51 +11c29 9 354 51 +11c32 6 356 51 +11c38 14 357 51 +11c4c 9 359 51 +11c55 a 363 51 +11c5f 2 364 51 +11c61 1 364 51 +FUNC 11c62 1c 0 _OSSwapInt32 +11c62 f 53 55 +11c71 8 55 55 +11c79 3 56 55 +11c7c 2 57 55 +FUNC 11c7e 19 0 NXSwapInt +11c7e f 52 56 +11c8d 8 54 56 +11c95 2 55 56 +11c97 1 55 56 +FUNC 11c98 13 0 NXHostByteOrder +11c98 c 144 56 +11ca4 5 147 56 +11ca9 2 153 56 +11cab 1 153 56 +11cac c 52 54 +11cb8 12 54 54 +11cca 1a 55 54 +11ce4 2 56 54 +11ce6 c 52 54 +11cf2 12 54 54 +11d04 1a 55 54 +11d1e 2 56 54 +11d20 c 58 54 +11d2c a 59 54 +11d36 d 60 54 +11d43 2 61 54 +11d45 1 61 54 +11d46 c 58 54 +11d52 a 59 54 +11d5c d 60 54 +11d69 2 61 54 +11d6b 1 61 54 +FUNC 11d6c 37 0 MacFileUtilities::MachoWalker::ValidateCPUType(int) +11d6c c 63 54 +11d78 6 66 54 +11d7e 8 67 54 +11d86 6 68 54 +11d8c b 69 54 +11d97 7 74 54 +11d9e 3 80 54 +11da1 2 81 54 +11da3 1 81 54 +FUNC 11da4 50 0 MacFileUtilities::MachoWalker::ReadBytes(void*, unsigned long, long long) +11da4 18 96 54 +11dbc 36 97 54 +11df2 2 98 54 +FUNC 11df4 73 0 MacFileUtilities::MachoWalker::CurrentHeader(mach_header_64*, long long*) +11df4 c 100 54 +11e00 a 101 54 +11e0a 37 102 54 +11e41 11 103 54 +11e52 9 104 54 +11e5b a 107 54 +11e65 2 108 54 +11e67 1 108 54 +FUNC 11e68 2a6 0 MacFileUtilities::MachoWalker::FindHeader(int, long long&) +11e68 c 110 54 +11e74 15 111 54 +11e89 31 114 54 +11eba c 115 54 +11ec6 10 117 54 +11ed6 4 120 54 +11eda 14 121 54 +11eee 4 122 54 +11ef2 11 129 54 +11f03 28 124 54 +11f2b c 126 54 +11f37 31 133 54 +11f68 c 134 54 +11f74 14 136 54 +11f88 b 137 54 +11f93 8 139 54 +11f9b c 140 54 +11fa7 10 142 54 +11fb7 c 143 54 +11fc3 10 146 54 +11fd3 31 148 54 +12004 c 149 54 +12010 f 151 54 +1201f 14 152 54 +12033 16 154 54 +12049 c 158 54 +12055 31 159 54 +12086 9 160 54 +1208f f 162 54 +1209e 1c 163 54 +120ba 8 165 54 +120c2 10 166 54 +120d2 9 167 54 +120db 16 170 54 +120f1 11 158 54 +12102 a 174 54 +1210c 2 175 54 +FUNC 1210e 109 0 MacFileUtilities::MachoWalker::WalkHeaderCore(long long, unsigned int, bool) +1210e 1e 224 54 +1212c c 225 54 +12138 2f 227 54 +12167 c 228 54 +12173 6 230 54 +12179 14 231 54 +1218d 5b 234 54 +121e8 12 237 54 +121fa 11 225 54 +1220b a 240 54 +12215 2 241 54 +12217 1 241 54 +FUNC 12218 10e 0 MacFileUtilities::MachoWalker::WalkHeader64AtOffset(long long) +12218 18 203 54 +12230 2f 205 54 +1225f c 206 54 +1226b e 208 54 +12279 6 209 54 +1227f 14 210 54 +12293 9 212 54 +1229c a 213 54 +122a6 f 214 54 +122b5 15 215 54 +122ca 2b 216 54 +122f5 a 217 54 +122ff a 218 54 +12309 11 219 54 +1231a a 220 54 +12324 2 221 54 +FUNC 12326 143 0 MacFileUtilities::MachoWalker::WalkHeaderAtOffset(long long) +12326 18 177 54 +1233e 2f 179 54 +1236d c 180 54 +12379 e 182 54 +12387 6 183 54 +1238d 14 184 54 +123a1 2e 189 54 +123cf 7 190 54 +123d6 9 192 54 +123df a 193 54 +123e9 f 194 54 +123f8 15 195 54 +1240d 2b 196 54 +12438 a 197 54 +12442 a 198 54 +1244c 11 199 54 +1245d a 200 54 +12467 2 201 54 +12469 1 201 54 +FUNC 1246a 99 0 MacFileUtilities::MachoWalker::WalkHeader(int) +1246a c 83 54 +12476 15 84 54 +1248b 1d 86 54 +124a8 d 87 54 +124b5 21 88 54 +124d6 21 90 54 +124f7 a 93 54 +12501 2 94 54 +12503 1 94 54 +FUNC 12504 1c 0 _OSSwapInt32 +12504 f 53 55 +12513 8 55 55 +1251b 3 56 55 +1251e 2 57 55 +FUNC 12520 2b 0 _OSSwapInt64 +12520 12 64 55 +12532 11 69 55 +12543 6 70 55 +12549 2 71 55 +1254b 1 71 55 +FUNC 1254c 19 0 NXSwapLong +1254c f 61 56 +1255b 8 63 56 +12563 2 64 56 +12565 1 64 56 +FUNC 12566 1f 0 NXSwapLongLong +12566 12 70 56 +12578 b 72 56 +12583 2 73 56 +12585 1 73 56 +FUNC 12586 32 0 breakpad_swap_uuid_command(breakpad_uuid_command*, NXByteOrder) +12586 c 37 57 +12592 11 39 57 +125a3 13 40 57 +125b6 2 41 57 +FUNC 125b8 da 0 breakpad_swap_segment_command_64(segment_command_64*, NXByteOrder) +125b8 c 44 57 +125c4 11 46 57 +125d5 13 47 57 +125e8 17 49 57 +125ff 17 50 57 +12616 17 51 57 +1262d 17 52 57 +12644 13 54 57 +12657 13 55 57 +1266a 13 56 57 +1267d 13 57 57 +12690 2 58 57 +FUNC 12692 a4 0 breakpad_swap_mach_header_64(mach_header_64*, NXByteOrder) +12692 c 61 57 +1269e 11 63 57 +126af 13 64 57 +126c2 13 65 57 +126d5 13 66 57 +126e8 13 67 57 +126fb 13 68 57 +1270e 13 69 57 +12721 13 70 57 +12734 2 71 57 +FUNC 12736 1d1 0 breakpad_swap_section_64(section_64*, unsigned int, NXByteOrder) +12736 d 75 57 +12743 c 77 57 +1274f 33 78 57 +12782 33 79 57 +127b5 2d 81 57 +127e2 2d 82 57 +1280f 2d 83 57 +1283c 2d 84 57 +12869 2d 85 57 +12896 2d 86 57 +128c3 2d 87 57 +128f0 11 77 57 +12901 6 89 57 +12907 1 89 57 +12908 12 9 58 +1291a 4f 11 58 +12969 2 12 58 +1296b 1 12 58 +1296c 12 9 58 +1297e 4f 11 58 +129cd 2 12 58 +129cf 1 12 58 +129d0 13 14 58 +129e3 2a 14 58 +12a0d 1 14 58 +12a0e 13 14 58 +12a21 2a 14 58 +12a4b 1 14 58 +12a4c 13 14 58 +12a5f 2a 14 58 +12a89 1 14 58 +FUNC 12a8a bb 0 dwarf2reader::ByteReader::SetOffsetSize(unsigned char) +12a8a 19 16 58 +12aa3 a 17 58 +12aad 48 18 58 +12af5 6 19 58 +12afb 23 20 58 +12b1e 21 22 58 +12b3f 6 24 58 +12b45 1 24 58 +FUNC 12b46 bb 0 dwarf2reader::ByteReader::SetAddressSize(unsigned char) +12b46 19 26 58 +12b5f a 27 58 +12b69 48 28 58 +12bb1 6 29 58 +12bb7 23 30 58 +12bda 21 32 58 +12bfb 6 34 58 +12c01 1 34 58 +FUNC 12c02 a2 0 dwarf2reader::ByteReader::ReadFourBytes(char const*) const +12c02 c 24 59 +12c0e c 25 64 +12c1a d 26 64 +12c27 f 27 64 +12c36 f 28 64 +12c45 b 29 64 +12c50 27 30 64 +12c77 2b 32 64 +12ca2 2 34 64 +FUNC 12ca4 40e 0 dwarf2reader::ByteReader::ReadEightBytes(char const*) const +12ca4 11 36 59 +12cb5 1a 37 64 +12ccf 1b 38 64 +12cea 1d 39 64 +12d07 1d 40 64 +12d24 1d 41 64 +12d41 1d 42 64 +12d5e 1d 43 64 +12d7b 1d 44 64 +12d98 f 45 64 +12da7 18f 47 64 +12f36 172 50 64 +130a8 a 52 64 +130b2 2 52 64 +FUNC 130b4 a6 0 ReadInitialLength +130b4 15 29 60 +130c9 18 30 60 +130e1 6 31 60 +130e7 d 35 60 +130f4 13 36 60 +13107 9 37 60 +13110 1a 38 60 +1312a 13 40 60 +1313d 9 41 60 +13146 12 43 60 +13158 2 44 60 +1315a 1f 47 60 +13179 65 50 60 +131de 1f 47 60 +131fd 65 50 60 +FUNC 13262 393 0 dwarf2reader::CompilationUnit::SkipAttribute(char const*, dwarf2reader::DwarfForm) +13262 14 133 60 +13276 82 136 60 +132f8 1f 139 60 +13317 a 140 60 +13321 21 141 60 +13342 c 147 60 +1334e e 151 60 +1335c e 155 60 +1336a e 159 60 +13378 27 162 60 +1339f 1c 166 60 +133bb 10 167 60 +133cb 1c 171 60 +133e7 10 172 60 +133f7 1e 175 60 +13415 56 180 60 +1346b d 181 60 +13478 1e 182 60 +13496 11 183 60 +134a7 1e 184 60 +134c5 24 189 60 +134e9 26 192 60 +1350f 23 195 60 +13532 22 198 60 +13554 15 199 60 +13569 1b 203 60 +13584 30 206 60 +135b4 30 208 60 +135e4 a 209 60 +135ee 7 210 60 +135f5 1 210 60 +FUNC 135f6 29b 0 dwarf2reader::CompilationUnit::ReadHeader() +135f6 14 217 60 +1360a 9 218 60 +13613 4e 221 60 +13661 17 223 60 +13678 a 224 60 +13682 f 225 60 +13691 4e 227 60 +136df 1e 228 60 +136fd 6 229 60 +13703 5e 231 60 +13761 1e 232 60 +1377f 18 233 60 +13797 4c 235 60 +137e3 1d 236 60 +13800 1c 237 60 +1381c 5 238 60 +13821 9 240 60 +1382a 60 245 60 +1388a 7 247 60 +13891 1 247 60 +FUNC 13892 a57 0 dwarf2reader::CompilationUnit::ProcessAttribute(unsigned long long, char const*, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm) +13892 24 299 60 +138b6 8a 302 60 +13940 1f 307 60 +1395f a 308 60 +13969 36 309 60 +1399f 5b 316 60 +139fa c 317 60 +13a06 5b 322 60 +13a61 e 323 60 +13a6f 55 328 60 +13ac4 e 329 60 +13ad2 55 334 60 +13b27 e 335 60 +13b35 6 338 60 +13b3b 9a 340 60 +13bd5 33 341 60 +13c08 25 340 60 +13c2d 5c 348 60 +13c89 10 349 60 +13c99 5c 354 60 +13cf5 10 355 60 +13d05 55 359 60 +13d5a 1e 360 60 +13d78 56 365 60 +13dce d 366 60 +13ddb 55 368 60 +13e30 1e 369 60 +13e4e 11 370 60 +13e5f 55 372 60 +13eb4 1e 373 60 +13ed2 29 378 60 +13efb 4a 380 60 +13f45 f 381 60 +13f54 29 385 60 +13f7d 4c 387 60 +13fc9 11 388 60 +13fda 1b 392 60 +13ff5 4c 394 60 +14041 11 395 60 +14052 22 399 60 +14074 4e 401 60 +140c2 15 402 60 +140d7 3c 406 60 +14113 1b 408 60 +1412e 54 409 60 +14182 f 411 60 +14191 9a 413 60 +1422b 24 414 60 +1424f 25 413 60 +14274 30 418 60 +142a4 30 420 60 +142d4 a 421 60 +142de b 422 60 +142e9 1 422 60 +142ea 1f 489 60 +14309 3a 491 60 +14343 a 492 60 +1434d 6 493 60 +14353 1 493 60 +14354 1f 489 60 +14373 3a 491 60 +143ad a 492 60 +143b7 6 493 60 +143bd 1 493 60 +FUNC 143be b5 0 dwarf2reader::CompilationUnit::ProcessDIE(unsigned long long, char const*, dwarf2reader::CompilationUnit::Abbrev const&) +143be 19 426 60 +143d7 13 427 60 +143ea 46 430 60 +14430 3a 427 60 +1446a 3 432 60 +1446d 6 433 60 +14473 1 433 60 +FUNC 14474 85 0 dwarf2reader::CompilationUnit::SkipDIE(char const*, dwarf2reader::CompilationUnit::Abbrev const&) +14474 c 122 60 +14480 13 123 60 +14493 27 126 60 +144ba 3a 123 60 +144f4 3 128 60 +144f7 2 129 60 +144f9 1 129 60 +FUNC 144fa be4 0 dwarf2reader::LineInfo::ProcessOneOpcode(dwarf2reader::ByteReader*, dwarf2reader::LineInfoHandler*, dwarf2reader::LineInfoHeader const&, char const*, dwarf2reader::LineStateMachine*, unsigned long*, unsigned long, bool*) +144fa 18 593 60 +14512 a 594 60 +1451c 18 596 60 +14534 8 597 60 +1453c 5 598 60 +14541 19 602 60 +1455a f 603 60 +14569 50 605 60 +145b9 46 607 60 +145ff e0 610 60 +146df 6 612 60 +146e5 22 615 60 +14707 22 616 60 +14729 7 617 60 +14730 b 618 60 +1473b f 619 60 +1474a 5a 623 60 +147a4 7 625 60 +147ab b 626 60 +147b6 f 627 60 +147c5 28 631 60 +147ed e 632 60 +147fb 144 635 60 +1493f 6 637 60 +14945 9e 640 60 +149e3 5 642 60 +149e8 22 644 60 +14a0a e 645 60 +14a18 1c 646 60 +14a34 2b 652 60 +14a5f b 653 60 +14a6a 22 658 60 +14a8c e 659 60 +14a9a 8 660 60 +14aa2 5 662 60 +14aa7 22 664 60 +14ac9 e 665 60 +14ad7 9 666 60 +14ae0 5 668 60 +14ae5 12 670 60 +14af7 5 672 60 +14afc 7 674 60 +14b03 5 676 60 +14b08 16 678 60 +14b1e 9 679 60 +14b27 d9 682 60 +14c00 6 684 60 +14c06 1f 687 60 +14c25 5 689 60 +14c2a 40 693 60 +14c6a d6 696 60 +14d40 6 698 60 +14d46 1c 701 60 +14d62 5 703 60 +14d67 1f 706 60 +14d86 d 707 60 +14d93 13 708 60 +14da6 26 710 60 +14dcc 5 711 60 +14dd1 50 713 60 +14e21 7 715 60 +14e28 b 716 60 +14e33 f 717 60 +14e42 18 725 60 +14e5a f 726 60 +14e69 5 728 60 +14e6e 6 730 60 +14e74 28 732 60 +14e9c d 733 60 +14ea9 22 735 60 +14ecb e 736 60 +14ed9 22 739 60 +14efb e 740 60 +14f09 22 743 60 +14f2b e 744 60 +14f39 a 746 60 +14f43 fd 748 60 +15040 a 758 60 +1504a 9 759 60 +15053 1c 761 60 +1506f d 762 60 +1507c e 763 60 +1508a 2e 759 60 +150b8 b 769 60 +150c3 10 770 60 +150d3 b 771 60 +FUNC 150de 14b 0 dwarf2reader::LineInfo::ReadLines() +150de e 773 60 +150ec 9 778 60 +150f5 17 782 60 +1510c 8 783 60 +15114 6 785 60 +1511a 9 787 60 +15123 5 788 60 +15128 19 789 60 +15141 5 790 60 +15146 4a 793 60 +15190 6 794 60 +15196 4a 796 60 +151e0 a 797 60 +151ea f 790 60 +151f9 15 788 60 +1520e 14 801 60 +15222 7 802 60 +15229 1 802 60 +FUNC 1522a 4fd 0 dwarf2reader::CompilationUnit::ReadAbbrevs() +1522a 18 60 60 +15242 e 61 60 +15250 58 65 60 +152a8 38 66 60 +152e0 44 65 60 +15324 2a 66 60 +1534e 45 68 60 +15393 16 69 60 +153a9 1d 75 60 +153c6 6 76 60 +153cc 40 77 60 +1540c b 80 60 +15417 1f 82 60 +15436 e 84 60 +15444 6 77 60 +1544a 1f 68 60 +15469 a 84 60 +15473 1d 79 60 +15490 6 86 60 +15496 a 87 60 +154a0 3d 89 60 +154dd 1f 90 60 +154fc a 91 60 +15506 6 92 60 +1550c 3d 94 60 +15549 1d 95 60 +15566 5 96 60 +1556b 3d 98 60 +155a8 1f 101 60 +155c7 a 102 60 +155d1 3d 104 60 +1560e 1f 105 60 +1562d a 106 60 +15637 c 107 60 +15643 6 111 60 +15649 6 112 60 +1564f 32 113 60 +15681 47 115 60 +156c8 30 116 60 +156f8 24 79 60 +1571c b 118 60 +15727 1 118 60 +FUNC 15728 5dc 0 dwarf2reader::LineInfo::ReadHeader() +15728 18 503 60 +15740 9 504 60 +15749 17 508 60 +15760 a 510 60 +1576a f 511 60 +15779 60 512 60 +157d9 44 516 60 +1581d 1e 518 60 +1583b 6 519 60 +15841 1e 521 60 +1585f 18 522 60 +15877 1d 524 60 +15894 5 525 60 +15899 20 527 60 +158b9 5 528 60 +158be c 530 60 +158ca 5 531 60 +158cf 1d 533 60 +158ec 5 534 60 +158f1 1d 536 60 +1590e 5 537 60 +15913 45 539 60 +15958 1f 540 60 +15977 19 541 60 +15990 15 542 60 +159a5 1f 539 60 +159c4 30 543 60 +159f4 5 544 60 +159f9 14 542 60 +15a0d e 548 60 +15a1b 7 549 60 +15a22 5 550 60 +15a27 6 551 60 +15a2d 8b 552 60 +15ab8 28 553 60 +15ae0 5 554 60 +15ae5 16 550 60 +15afb 25 552 60 +15b20 5 557 60 +15b25 e 560 60 +15b33 7 561 60 +15b3a 5 563 60 +15b3f 6 564 60 +15b45 28 565 60 +15b6d 22 567 60 +15b8f a 568 60 +15b99 22 570 60 +15bbb a 571 60 +15bc5 22 573 60 +15be7 a 574 60 +15bf1 ba 576 60 +15cab 5 577 60 +15cb0 16 563 60 +15cc6 25 576 60 +15ceb 5 580 60 +15cf0 9 582 60 +15cf9 b 583 60 +FUNC 15d04 3d 0 dwarf2reader::LineInfo::Start() +15d04 c 495 60 +15d10 b 496 60 +15d1b b 497 60 +15d26 19 498 60 +15d3f 2 499 60 +15d41 1 499 60 +FUNC 15d42 304 0 dwarf2reader::CompilationUnit::ProcessDIEs() +15d42 11 435 60 +15d53 9 436 60 +15d5c 9 441 60 +15d65 17 445 60 +15d7c 8 446 60 +15d84 6 448 60 +15d8a 6c 453 60 +15df6 8 455 60 +15dfe 16 453 60 +15e14 3 455 60 +15e17 2f 453 60 +15e46 29 458 60 +15e6f 22 460 60 +15e91 a 462 60 +15e9b a 465 60 +15ea5 1e 466 60 +15ec3 13 467 60 +15ed6 2b 468 60 +15f01 18 472 60 +15f19 9 473 60 +15f22 42 474 60 +15f64 1e 475 60 +15f82 2a 477 60 +15fac b 480 60 +15fb7 1e 481 60 +15fd5 26 483 60 +15ffb 1d 455 60 +16018 24 485 60 +1603c a 486 60 +FUNC 16046 35f 0 dwarf2reader::CompilationUnit::Start() +16046 18 249 60 +1605e 58 251 60 +160b6 35 252 60 +160eb 32 251 60 +1611d 2a 252 60 +16147 20 255 60 +16167 37 256 60 +1619e b 259 60 +161a9 f 264 60 +161b8 17 265 60 +161cf c 266 60 +161db a 268 60 +161e5 95 271 60 +1627a 11 276 60 +1628b b 279 60 +16296 58 282 60 +162ee 2f 283 60 +1631d 32 282 60 +1634f 14 284 60 +16363 1a 285 60 +1637d b 289 60 +16388 12 291 60 +1639a b 292 60 +163a5 1 292 60 +FUNC 163a6 3a 0 std::fill(unsigned char*, unsigned char*, unsigned char const&) +163a6 c 573 61 +163b2 9 576 61 +163bb 23 577 61 +163de 2 578 61 +FUNC 163e0 33 0 std::__deque_buf_size(unsigned long) +163e0 c 83 62 +163ec 27 84 62 +16413 1 84 62 +FUNC 16414 18 0 dwarf2reader::ByteReader::OffsetSize() const +16414 c 38 63 +16420 c 38 63 +FUNC 1642c 18 0 dwarf2reader::ByteReader::AddressSize() const +1642c c 41 63 +16438 c 41 63 +FUNC 16444 17 0 dwarf2reader::ByteReader::ReadOneByte(char const*) const +16444 c 10 64 +16450 9 11 64 +16459 2 12 64 +1645b 1 12 64 +FUNC 1645c 63 0 dwarf2reader::ByteReader::ReadTwoBytes(char const*) const +1645c c 14 64 +16468 d 15 64 +16475 e 16 64 +16483 b 17 64 +1648e 17 18 64 +164a5 18 20 64 +164bd 2 22 64 +164bf 1 22 64 +FUNC 164c0 98 0 dwarf2reader::ByteReader::ReadUnsignedLEB128(char const*, unsigned long*) const +164c0 e 59 64 +164ce e 60 64 +164dc 7 61 64 +164e3 7 62 64 +164ea e 66 64 +164f8 5 67 64 +164fd 38 69 64 +16535 6 71 64 +1653b 8 65 64 +16543 8 75 64 +1654b 6 77 64 +16551 7 78 64 +FUNC 16558 ee 0 dwarf2reader::ByteReader::ReadSignedLEB128(char const*, unsigned long*) const +16558 e 84 64 +16566 e 85 64 +16574 7 86 64 +1657b 7 87 64 +16582 e 91 64 +16590 5 92 64 +16595 44 93 64 +165d9 6 94 64 +165df 8 90 64 +165e7 14 97 64 +165fb 36 98 64 +16631 8 99 64 +16639 6 100 64 +1663f 7 101 64 +FUNC 16646 a2 0 dwarf2reader::ByteReader::ReadOffset(char const*) const +16646 13 103 64 +16659 3f 104 64 +16698 4a 105 64 +166e2 6 106 64 +FUNC 166e8 a2 0 dwarf2reader::ByteReader::ReadAddress(char const*) const +166e8 13 108 64 +166fb 3f 109 64 +1673a 4a 110 64 +16784 6 111 64 +FUNC 1678a 61 0 dwarf2reader::LineStateMachine::Reset(bool) +1678a 12 12 65 +1679c 9 13 65 +167a5 11 14 65 +167b6 11 15 65 +167c7 a 16 65 +167d1 a 17 65 +167db 7 18 65 +167e2 7 19 65 +167e9 2 20 65 +167eb 1 20 65 +FUNC 167ec 20 0 std::_List_const_iterator >::operator!=(std::_List_const_iterator > const&) const +167ec c 253 66 +167f8 14 254 66 +FUNC 1680c 25 0 std::_List_const_iterator >::operator++(int) +1680c c 226 66 +16818 8 228 66 +16820 c 229 66 +1682c 5 230 66 +16831 1 230 66 +FUNC 16832 16 0 std::_List_const_iterator >::operator->() const +16832 c 215 66 +1683e a 216 66 +16848 c 190 67 +16854 a 190 67 +FUNC 1685e 13 0 std::auto_ptr > > >::operator->() const +1685e c 283 67 +1686a 7 286 67 +16871 1 286 67 +16872 c 65 68 +1687e 2 65 68 +16880 c 97 69 +1688c d 97 69 +16899 1 97 69 +1689a c 99 69 +168a6 14 100 69 +168ba c 97 69 +168c6 d 97 69 +168d3 1 97 69 +168d4 c 84 70 +168e0 17 85 70 +168f7 1 85 70 +FUNC 168f8 2d 0 std::pair std::make_pair(dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm) +168f8 c 144 70 +16904 21 145 70 +16925 1 145 70 +16926 c 202 66 +16932 a 203 66 +FUNC 1693c 25 0 std::list, std::allocator > >::begin() const +1693c c 588 70 +16948 19 589 66 +16961 1 589 66 +FUNC 16962 23 0 std::list, std::allocator > >::end() const +16962 c 605 70 +1696e 17 606 66 +16985 1 606 66 +16986 c 65 68 +16992 2 65 68 +16994 c 72 68 +169a0 2 72 68 +169a2 c 97 69 +169ae d 97 69 +169bb 1 97 69 +169bc c 105 69 +169c8 d 105 69 +169d5 1 105 69 +169d6 c 105 69 +169e2 d 105 69 +169ef 1 105 69 +169f0 c 67 68 +169fc 2 67 68 +169fe c 99 69 +16a0a 14 100 69 +16a1e c 99 69 +16a2a 14 100 69 +16a3e c 129 62 +16a4a 30 131 62 +16a7a c 65 68 +16a86 2 65 68 +16a88 c 72 68 +16a94 2 72 68 +16a96 c 97 69 +16aa2 d 97 69 +16aaf 1 97 69 +16ab0 c 105 69 +16abc d 105 69 +16ac9 1 105 69 +16aca c 105 69 +16ad6 d 105 69 +16ae3 1 105 69 +16ae4 c 67 68 +16af0 2 67 68 +16af2 c 99 69 +16afe 14 100 69 +16b12 c 99 69 +16b1e 14 100 69 +FUNC 16b32 2b 0 std::_Vector_base >::get_allocator() const +16b32 10 93 71 +16b42 1b 94 71 +16b5d 1 94 71 +16b6a 7 614 72 +16b71 1 614 72 +16b72 c 80 71 +16b7e d 80 71 +16b8b 1 80 71 +16b98 2 107 68 +FUNC 16b9a 2d 0 void std::_Destroy >(unsigned char*, unsigned char*, std::allocator) +16b9a c 171 73 +16ba6 2 173 73 +16ba8 12 174 73 +16bba b 173 73 +16bc5 2 174 73 +16bc7 1 174 73 +16bc8 c 84 71 +16bd4 2f 85 71 +16c03 2 86 71 +16c05 1 86 71 +16c06 c 96 71 +16c12 12 97 71 +16c24 2 98 71 +FUNC 16c26 1f 0 std::_List_base, std::allocator > >::_M_init() +16c26 c 338 73 +16c32 8 340 66 +16c3a b 341 66 +16c45 1 341 66 +16c46 c 105 69 +16c52 d 105 69 +16c5f 1 105 69 +16c60 c 125 66 +16c6c a 126 66 +FUNC 16c76 25 0 std::list, std::allocator > >::begin() +16c76 c 579 73 +16c82 19 580 66 +16c9b 1 580 66 +FUNC 16c9c 23 0 std::list, std::allocator > >::end() +16c9c c 597 73 +16ca8 17 597 66 +16cbf 1 597 66 +16cc0 c 603 72 +16ccc c 603 72 +FUNC 16cd8 2b 0 std::vector >::begin() const +16cd8 c 342 73 +16ce4 1f 343 71 +16d03 1 343 71 +FUNC 16d04 2c 0 std::vector >::end() const +16d04 c 360 73 +16d10 20 361 71 +16d3c 5 666 72 +16d41 1 666 72 +16d4f 31 759 72 +FUNC 16d80 3c 0 std::vector >::size() const +16d80 c 402 73 +16d8c 30 403 71 +16dbc c 603 72 +16dc8 c 603 72 +FUNC 16dd4 23 0 std::vector >::begin() +16dd4 c 333 73 +16de0 17 334 71 +16df7 1 334 71 +16e04 33 654 72 +16e37 1 654 72 +FUNC 16e38 26 0 std::vector >::end() +16e38 c 351 73 +16e44 1a 352 71 +16e6a 7 614 72 +16e71 1 614 72 +FUNC 16e72 42 0 std::vector >::operator[](unsigned long) +16e72 c 494 73 +16e7e 36 495 71 +FUNC 16eb4 13 0 std::vector >::max_size() const +16eb4 c 407 73 +16ec0 7 408 71 +16ec7 1 408 71 +16ed4 5 666 72 +16ed9 1 666 72 +16ee6 d 623 72 +16ef3 5 624 72 +16ef8 c 382 62 +16f04 d 382 62 +16f11 1 382 62 +FUNC 16f12 2b 0 std::_Deque_base >::get_allocator() const +16f12 10 360 73 +16f22 1b 361 62 +16f3d 1 361 62 +FUNC 16f3e 2d 0 std::deque >::get_allocator() const +16f3e 10 764 73 +16f4e 1d 765 62 +16f6b 1 765 62 +FUNC 16f6c 13 0 std::_Deque_iterator::operator*() const +16f6c c 134 73 +16f78 7 135 62 +16f7f 1 135 62 +16f8c 2 107 68 +16f8e c 129 62 +16f9a 30 131 62 +FUNC 16fca 2c 0 std::deque >::end() const +16fca 10 799 73 +16fda 1c 800 62 +FUNC 16ff6 2c 0 std::deque >::begin() const +16ff6 10 781 73 +17006 1c 782 62 +FUNC 17022 2e 0 std::deque >::end() +17022 10 790 73 +17032 1e 791 62 +FUNC 17050 3c 0 std::vector >::_M_range_check(unsigned long) const +17050 13 515 73 +17063 15 517 71 +17078 14 518 71 +FUNC 1708c 32 0 std::vector >::at(unsigned long) +1708c c 534 73 +17098 12 536 71 +170aa 14 537 71 +170ca 2e 104 68 +170f8 c 84 71 +17104 2f 85 71 +17133 2 86 71 +17135 1 86 71 +17136 c 96 71 +17142 12 97 71 +17154 2 98 71 +17156 c 603 72 +17162 c 603 72 +FUNC 1716e 23 0 std::vector >::begin() +1716e c 333 73 +1717a 17 334 71 +17191 1 334 71 +1719e 27 654 72 +171c5 1 654 72 +FUNC 171c6 42 0 std::vector >::operator[](unsigned long) +171c6 c 494 73 +171d2 36 495 71 +FUNC 17208 26 0 std::vector >::end() +17208 c 351 73 +17214 1a 352 71 +1723a d 94 68 +17247 1 94 68 +FUNC 17248 2f 0 std::_Vector_base >::_M_deallocate(unsigned char*, unsigned long) +17248 c 120 73 +17254 6 122 71 +1725a 1d 123 71 +17277 1 123 71 +17278 c 108 71 +17284 3a 109 71 +172be c 188 71 +172ca 12 189 71 +172dc 2 190 71 +172de c 272 71 +172ea 4b 273 71 +17335 1 273 71 +17336 13 62 74 +17349 10 62 74 +17359 a 63 74 +17363 25 64 74 +17388 1a 66 74 +173a2 13 62 74 +173b5 10 62 74 +173c5 a 63 74 +173cf 25 64 74 +173f4 1a 66 74 +1740e c 188 71 +1741a 12 189 71 +1742c 2 190 71 +1743b 31 759 72 +1746c c 65 68 +17478 2 65 68 +1747a c 103 69 +17486 d 103 69 +17493 1 103 69 +FUNC 17494 2d 0 std::list, std::allocator > >::get_allocator() const +17494 10 570 74 +174a4 1d 571 66 +174c1 1 571 66 +174ce 2e 104 68 +FUNC 174fc 20 0 std::_List_iterator >::operator!=(std::_List_iterator > const&) const +174fc c 172 74 +17508 14 173 66 +FUNC 1751c 1d 0 std::_List_const_iterator >::operator++() +1751c c 219 74 +17528 c 221 66 +17534 5 222 66 +17539 1 222 66 +FUNC 1753a 1d 0 std::_List_iterator >::operator++() +1753a c 138 74 +17546 c 140 66 +17552 5 141 66 +17557 1 141 66 +FUNC 17558 16 0 std::_List_const_iterator >::operator*() const +17558 c 211 74 +17564 a 212 66 +FUNC 1756e 16 0 std::_List_iterator >::operator*() const +1756e c 130 74 +1757a a 131 66 +FUNC 17584 20 0 std::_List_const_iterator >::operator==(std::_List_const_iterator > const&) const +17584 c 249 74 +17590 14 250 66 +FUNC 175a4 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) +175a4 d 699 74 +175b1 28 700 72 +175d9 1 700 72 +FUNC 175da 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) +175da c 171 74 +175e6 2 173 73 +175e8 1a 174 73 +17602 21 173 73 +17623 2 174 73 +17625 1 174 73 +17626 c 127 62 +17632 29 127 62 +1765b 1 127 62 +1765c c 388 62 +17668 41 389 62 +176a9 2 390 62 +176ab 1 390 62 +176b8 d 94 68 +176c5 1 94 68 +FUNC 176c6 20 0 bool std::operator==(std::_Deque_iterator const&, std::_Deque_iterator const&) +176c6 c 243 74 +176d2 14 244 62 +FUNC 176e6 26 0 bool std::operator!=(std::_Deque_iterator const&, std::_Deque_iterator const&) +176e6 c 256 74 +176f2 1a 257 62 +FUNC 1770c 1a 0 std::_Deque_iterator::_S_buffer_size() +1770c c 106 74 +17718 e 107 62 +FUNC 17726 3e 0 std::_Deque_iterator::_M_set_node(unsigned long long**) +17726 d 229 74 +17733 9 231 62 +1773c b 232 62 +17747 1d 233 62 +FUNC 17764 50 0 std::_Deque_iterator::operator++() +17764 c 142 74 +17770 d 144 62 +1777d f 145 62 +1778c 18 147 62 +177a4 b 148 62 +177af 5 150 62 +FUNC 177b4 4b 0 void std::_Destroy, std::allocator >(std::_Deque_iterator, std::_Deque_iterator, std::allocator) +177b4 c 171 74 +177c0 2 173 73 +177c2 1a 174 73 +177dc 21 173 73 +177fd 2 174 73 +177ff 1 174 73 +FUNC 17800 50 0 std::_Deque_iterator::operator--() +17800 c 162 74 +1780c f 164 62 +1781b 18 166 62 +17833 b 167 62 +1783e d 169 62 +1784b 5 170 62 +FUNC 17850 39 0 std::deque >::back() +17850 c 988 74 +1785c 15 990 62 +17871 b 991 62 +1787c d 992 62 +17889 1 992 62 +FUNC 1788a 19 0 std::stack > >::top() +1788a c 163 75 +17896 d 166 75 +178a3 1 166 75 +FUNC 178a4 66 0 std::_Deque_iterator::difference_type std::operator-(std::_Deque_iterator const&, std::_Deque_iterator const&) +178a4 d 328 75 +178b1 59 333 62 +FUNC 1790a 26 0 std::deque >::size() const +1790a c 840 75 +17916 1a 841 62 +1793c 36 662 72 +1797e 23 650 72 +179a1 1 650 72 +179a2 c 67 68 +179ae 2 67 68 +179b0 c 99 69 +179bc 14 100 69 +179d0 c 303 66 +179dc 12 304 66 +179ee 2 305 66 +179f0 c 326 66 +179fc 2f 327 66 +17a2b d 328 66 +17a38 c 457 66 +17a44 14 458 66 +17a58 c 211 74 +17a64 2d 211 74 +17a91 1 211 74 +17a9e 7 98 68 +17aa5 1 98 68 +17ab2 1d 85 68 +17acf 5 86 68 +17ad4 17 88 68 +17aeb 1 88 68 +FUNC 17aec 2a 0 std::_Vector_base >::_M_allocate(unsigned long) +17aec c 116 75 +17af8 1e 117 71 +17b22 d 94 68 +17b2f 1 94 68 +FUNC 17b30 34 0 std::_Deque_base >::_M_deallocate_node(unsigned long long*) +17b30 c 402 75 +17b3c 28 403 62 +FUNC 17b64 38 0 std::_Deque_base >::_M_destroy_nodes(unsigned long long**, unsigned long long**) +17b64 c 504 75 +17b70 8 506 62 +17b78 14 507 62 +17b8c e 506 62 +17b9a 2 507 62 +FUNC 17b9c 62 0 std::deque >::_M_pop_back_aux() +17b9c c 391 76 +17ba8 15 393 76 +17bbd 1b 394 76 +17bd8 f 395 76 +17be7 17 396 76 +FUNC 17bfe 4f 0 std::deque >::pop_back() +17bfe c 1081 76 +17c0a 10 1083 62 +17c1a f 1086 62 +17c29 17 1087 62 +17c40 d 1090 62 +17c4d 1 1090 62 +FUNC 17c4e 19 0 std::stack > >::pop() +17c4e c 205 76 +17c5a d 208 75 +17c67 1 208 75 +17c68 c 72 68 +17c74 2 72 68 +17c76 c 105 69 +17c82 d 105 69 +17c8f 1 105 69 +17c90 c 603 72 +17c9c c 603 72 +FUNC 17ca8 2b 0 std::vector >::begin() const +17ca8 c 342 76 +17cb4 1f 343 71 +17cd3 1 343 71 +FUNC 17cd4 2c 0 std::vector >::end() const +17cd4 c 360 76 +17ce0 20 361 71 +17d0c 5 666 72 +17d11 1 666 72 +17d1f 28 759 72 +17d47 1 759 72 +FUNC 17d48 3c 0 std::vector >::size() const +17d48 c 402 76 +17d54 30 403 71 +17d90 d 623 72 +17d9d 5 624 72 +17dae 5 666 72 +17db3 1 666 72 +FUNC 17db4 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) +17db4 d 699 76 +17dc1 28 700 72 +17de9 1 700 72 +FUNC 17dea 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) +17dea c 171 76 +17df6 2 173 73 +17df8 1a 174 73 +17e12 21 173 73 +17e33 2 174 73 +17e35 1 174 73 +17e43 28 759 72 +17e6b 1 759 72 +17e78 2a 662 72 +FUNC 17ea2 13 0 std::vector >::max_size() const +17ea2 c 407 76 +17eae 7 408 71 +17eb5 1 408 71 +17ec2 16 650 72 +17ee4 7 98 68 +17eeb 1 98 68 +17ef8 1d 85 68 +17f15 5 86 68 +17f1a 10 88 68 +FUNC 17f2a 29 0 std::_List_base, std::allocator > >::_M_get_node() +17f2a c 311 76 +17f36 1d 312 66 +17f53 1 312 66 +FUNC 17f54 5f 0 std::list, std::allocator > >::_M_create_node(std::pair const&) +17f54 d 435 76 +17f61 e 437 66 +17f6f 3c 440 66 +17fab 8 447 66 +17fb3 1 447 66 +FUNC 17fb4 35 0 std::list, std::allocator > >::_M_insert(std::_List_iterator >, std::pair const&) +17fb4 c 1149 76 +17fc0 15 1151 66 +17fd5 14 1152 66 +17fe9 1 1152 66 +FUNC 17fea 52 0 void std::list, std::allocator > >::_M_insert_dispatch > >(std::_List_iterator >, std::_List_const_iterator >, std::_List_const_iterator >, __false_type) +17fea c 1126 66 +17ff6 2 1128 66 +17ff8 21 1129 66 +18019 21 1128 66 +1803a 2 1129 66 +FUNC 1803c 36 0 void std::list, std::allocator > >::insert > >(std::_List_iterator >, std::_List_const_iterator >, std::_List_const_iterator >) +1803c c 838 66 +18048 2a 842 66 +18072 e 491 66 +18080 32 492 66 +180b2 64 493 66 +18116 c 211 74 +18122 3d 211 74 +1815f 1 211 74 +1816d 5c 104 68 +181c9 1 104 68 +FUNC 181ca 31 0 std::list, std::allocator > >::push_back(std::pair const&) +181ca c 772 76 +181d6 25 773 66 +181fb 1 773 66 +FUNC 181fc 69 0 void std::_Construct(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev const&) +181fc d 77 76 +18209 5c 81 73 +18265 1 81 73 +18272 7 98 68 +18279 1 98 68 +18286 1d 85 68 +182a3 5 86 68 +182a8 10 88 68 +182b8 c 65 68 +182c4 2 65 68 +182c6 c 103 69 +182d2 d 103 69 +182df 1 103 69 +FUNC 182e0 4d 0 std::_Deque_base >::_M_get_map_allocator() const +182e0 11 394 76 +182f1 3c 395 62 +1832d 1 395 62 +FUNC 1832e 75 0 std::_Deque_base >::_M_allocate_map(unsigned long) +1832e d 406 76 +1833b 68 407 62 +183a3 1 407 62 +FUNC 183a4 47 0 std::_Deque_base >::_M_deallocate_map(unsigned long long**, unsigned long) +183a4 c 410 76 +183b0 3b 411 62 +183eb 1 411 62 +183ec c 424 62 +183f8 9 426 62 +18401 22 428 62 +18423 2b 430 62 +1844e c 714 62 +1845a 70 715 62 +184ca c 111 75 +184d6 d 111 75 +184e3 1 111 75 +184e4 c 259 67 +184f0 26 259 67 +18522 7 98 68 +18529 1 98 68 +18536 1d 85 68 +18553 5 86 68 +18558 10 88 68 +FUNC 18568 33 0 std::_Deque_base >::_M_allocate_node() +18568 c 398 76 +18574 27 399 62 +1859b 1 399 62 +FUNC 1859c 82 0 std::_Deque_base >::_M_create_nodes(unsigned long long**, unsigned long long**) +1859c d 486 76 +185a9 8 491 62 +185b1 12 492 62 +185c3 13 491 62 +185d6 b 494 62 +185e1 19 496 62 +185fa b 497 62 +18605 13 494 62 +18618 6 497 62 +FUNC 1861e 17b 0 std::_Deque_base >::_M_initialize_map(unsigned long) +1861e d 447 76 +1862b 1e 450 62 +18649 2a 452 62 +18673 1c 454 62 +1868f 19 462 62 +186a8 c 463 62 +186b4 1e 466 62 +186d2 b 467 62 +186dd 1e 469 62 +186fb 9 470 62 +18704 a 471 62 +1870e b 472 62 +18719 13 467 62 +1872c 15 475 62 +18741 18 476 62 +18759 c 477 62 +18765 34 478 62 +18799 1 478 62 +1879a d 366 62 +187a7 12 367 62 +187b9 39 368 62 +187f2 c 645 62 +187fe 1c 646 62 +FUNC 1881a 4d 0 void std::__fill::fill<__gnu_cxx::__normal_iterator > >, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char const&) +1881a c 539 61 +18826 9 541 61 +1882f 2 542 61 +18831 13 543 61 +18844 21 542 61 +18865 2 543 61 +18867 1 543 61 +FUNC 18868 2b 0 void std::fill<__gnu_cxx::__normal_iterator > >, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char const&) +18868 c 560 76 +18874 4 567 61 +18878 1b 568 61 +18893 1 568 61 +FUNC 18894 6a 0 std::list, std::allocator > >::_M_erase(std::_List_iterator >) +18894 d 1157 76 +188a1 b 1159 66 +188ac 6 1160 66 +188b2 35 1161 66 +188e7 17 1162 66 +FUNC 188fe 37 0 std::list, std::allocator > >::erase(std::_List_iterator >) +188fe c 95 77 +1890a 14 97 77 +1891e 12 98 77 +18930 5 99 77 +18935 1 99 77 +FUNC 18936 3e 0 std::list, std::allocator > >::erase(std::_List_iterator >, std::_List_iterator >) +18936 c 883 77 +18942 2 885 66 +18944 15 886 66 +18959 16 885 66 +1896f 5 887 66 +FUNC 18974 129 0 std::list, std::allocator > >::operator=(std::list, std::allocator > > const&) +18974 e 120 77 +18982 c 122 77 +1898e e 124 77 +1899c e 125 77 +189aa e 126 77 +189b8 e 127 77 +189c6 2 128 77 +189c8 20 130 77 +189e8 5a 128 77 +18a42 16 131 77 +18a58 1b 132 77 +18a73 20 134 77 +18a93 a 136 77 +18a9d 1 136 77 +FUNC 18a9e 4c 0 dwarf2reader::CompilationUnit::Abbrev::operator=(dwarf2reader::CompilationUnit::Abbrev const&) +18a9e c 211 77 +18aaa 40 211 74 +FUNC 18aea 52 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy::copy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +18aea c 280 61 +18af6 1a 283 61 +18b10 12 285 61 +18b22 4 286 61 +18b26 6 287 61 +18b2c b 283 61 +18b37 5 289 61 +FUNC 18b3c 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +18b3c c 307 77 +18b48 4 315 61 +18b4c 1b 317 61 +18b67 1 317 61 +18b76 56 354 61 +18bd8 4 384 61 +18bdc 4 385 61 +18be0 1b 387 61 +18bfb 1 387 61 +FUNC 18bfc ac 0 std::vector >::erase(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +18bfc d 122 78 +18c09 26 124 78 +18c2f 43 125 78 +18c72 2e 126 78 +18ca0 8 127 78 +FUNC 18ca8 54 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward::copy_b(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +18ca8 c 408 61 +18cb4 1a 411 61 +18cce 1e 412 61 +18cec b 411 61 +18cf7 5 413 61 +FUNC 18cfc 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +18cfc c 432 78 +18d08 4 440 61 +18d0c 1b 443 61 +18d27 1 443 61 +18d36 56 482 61 +18d98 4 514 61 +18d9c 4 515 61 +18da0 1b 517 61 +18dbb 1 517 61 +FUNC 18dbc 4d 0 void std::__fill::fill<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) +18dbc c 526 61 +18dc8 2 528 61 +18dca 1c 529 61 +18de6 21 528 61 +18e07 2 529 61 +18e09 1 529 61 +FUNC 18e0a 2b 0 void std::fill<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) +18e0a c 560 78 +18e16 4 567 61 +18e1a 1b 568 61 +18e35 1 568 61 +FUNC 18e36 3f 0 unsigned char* std::__copy::copy(unsigned char const*, unsigned char const*, unsigned char*) +18e36 c 298 61 +18e42 22 300 61 +18e64 11 301 61 +18e75 1 301 61 +FUNC 18e76 2b 0 unsigned char* std::__copy_aux(unsigned char*, unsigned char*, unsigned char*) +18e76 c 307 78 +18e82 4 315 61 +18e86 1b 317 61 +18ea1 1 317 61 +18eb0 56 354 61 +18f12 4 384 61 +18f16 4 385 61 +18f1a 1b 387 61 +18f35 1 387 61 +FUNC 18f36 a0 0 std::vector >::erase(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +18f36 d 122 78 +18f43 26 124 78 +18f69 43 125 78 +18fac 22 126 78 +18fce 8 127 78 +18fe2 7 98 68 +18fe9 1 98 68 +18ff6 1d 85 68 +19013 5 86 68 +19018 d 88 68 +19025 1 88 68 +FUNC 19026 2a 0 std::_Vector_base >::_M_allocate(unsigned long) +19026 c 116 78 +19032 1e 117 71 +1905c 1b 74 79 +19077 1 74 79 +19084 23 113 79 +190a7 1 113 79 +190b4 1b 254 79 +190cf 1 254 79 +FUNC 190d0 19 0 void std::_Destroy(dwarf2reader::CompilationUnit::Abbrev*) +190d0 c 106 79 +190dc d 107 73 +190e9 1 107 73 +FUNC 190ea 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) +190ea c 119 79 +190f6 2 121 73 +190f8 13 122 73 +1910b 21 121 73 +1912c 2 122 73 +FUNC 1912e 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +1912e c 148 79 +1913a 1c 155 73 +FUNC 19156 8d 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type) +19156 d 188 79 +19163 6 190 79 +19169 2 193 79 +1916b 1c 194 79 +19187 1b 193 79 +191a2 b 196 79 +191ad 12 198 79 +191bf b 199 79 +191ca 13 196 79 +191dd 6 199 79 +191e3 1 199 79 +FUNC 191e4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) +191e4 c 214 79 +191f0 23 218 79 +19213 1 218 79 +FUNC 19214 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator) +19214 c 308 79 +19220 1b 310 79 +1923b 1 310 79 +19249 6 82 79 +1924f 2 85 79 +19251 24 86 79 +19275 2c 85 79 +192a1 b 87 79 +192ac b 89 79 +192b7 12 91 79 +192c9 b 92 79 +192d4 13 89 79 +192e7 9 92 79 +192fc 23 113 79 +1931f 1 113 79 +1932c 1b 254 79 +19347 1 254 79 +FUNC 19348 409 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) +19348 14 249 79 +1935c 14 251 78 +19370 22 253 78 +19392 f 255 78 +193a1 12 256 78 +193b3 55 257 78 +19408 4b 260 78 +19453 e 264 78 +19461 15 265 78 +19476 e 266 78 +19484 1d 271 78 +194a1 8 272 78 +194a9 e 273 78 +194b7 27 275 78 +194de 6 276 78 +194e4 55 279 78 +19539 25 284 78 +1955e b 285 78 +19569 4f 286 78 +195b8 3 284 78 +195bb 13 279 78 +195ce e 286 78 +195dc 4d 298 78 +19629 36 299 78 +1965f 12 302 78 +19671 13 303 78 +19684 2e 304 78 +196b2 13 286 78 +196c5 b 292 78 +196d0 39 294 78 +19709 23 295 78 +1972c b 296 78 +19737 13 292 78 +1974a 7 304 78 +19751 1 304 78 +FUNC 19752 70 0 std::vector >::push_back(dwarf2reader::CompilationUnit::Abbrev const&) +19752 c 602 79 +1975e 10 604 71 +1976e 1e 606 71 +1978c 11 607 71 +1979d 25 610 71 +FUNC 197c2 50 0 unsigned char* std::__copy_backward::copy_b(unsigned char const*, unsigned char const*, unsigned char*) +197c2 d 422 61 +197cf f 424 61 +197de 24 425 61 +19802 10 426 61 +FUNC 19812 2b 0 unsigned char* std::__copy_backward_aux(unsigned char*, unsigned char*, unsigned char*) +19812 c 432 79 +1981e 4 440 61 +19822 1b 443 61 +1983d 1 443 61 +1984c 56 482 61 +198ae 4 514 61 +198b2 4 515 61 +198b6 1b 517 61 +198d1 1 517 61 +FUNC 198d2 32 0 unsigned char* std::fill_n(unsigned char*, unsigned long, unsigned char const&) +198d2 c 647 79 +198de 1e 649 61 +198fc 8 650 61 +FUNC 19904 27 0 void std::__uninitialized_fill_n_aux(unsigned char*, unsigned long, unsigned char const&, __true_type) +19904 c 182 79 +19910 1b 183 79 +1992b 1 183 79 +FUNC 1992c 2f 0 void std::uninitialized_fill_n(unsigned char*, unsigned long, unsigned char const&) +1992c c 214 79 +19938 23 218 79 +1995b 1 218 79 +FUNC 1995c 27 0 void std::__uninitialized_fill_n_a(unsigned char*, unsigned long, unsigned char const&, std::allocator) +1995c c 308 79 +19968 1b 310 79 +19983 1 310 79 +FUNC 19984 27 0 void std::__destroy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type) +19984 c 119 79 +19990 2 121 73 +19992 b 122 73 +1999d c 121 73 +199a9 2 122 73 +199ab 1 122 73 +FUNC 199ac 28 0 void std::_Destroy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +199ac c 148 79 +199b8 1c 155 73 +FUNC 199d4 88 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type) +199d4 d 80 79 +199e1 6 82 79 +199e7 2 85 79 +199e9 12 86 79 +199fb 12 85 79 +19a0d b 87 79 +19a18 b 89 79 +19a23 12 91 79 +19a35 b 92 79 +19a40 13 89 79 +19a53 9 92 79 +FUNC 19a5c 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) +19a5c c 108 79 +19a68 23 113 79 +19a8b 1 113 79 +FUNC 19a8c 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) +19a8c c 252 79 +19a98 1b 254 79 +19ab3 1 254 79 +FUNC 19ab4 7e 0 void std::__uninitialized_fill_n_aux(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type) +19ab4 d 188 79 +19ac1 6 190 79 +19ac7 2 193 79 +19ac9 12 194 79 +19adb 16 193 79 +19af1 b 196 79 +19afc 12 198 79 +19b0e b 199 79 +19b19 13 196 79 +19b2c 6 199 79 +FUNC 19b32 2f 0 void std::uninitialized_fill_n(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) +19b32 c 214 79 +19b3e 23 218 79 +19b61 1 218 79 +FUNC 19b62 27 0 void std::__uninitialized_fill_n_a(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator) +19b62 c 308 79 +19b6e 1b 310 79 +19b89 1 310 79 +FUNC 19b8a a5 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, __false_type) +19b8a d 80 79 +19b97 6 82 79 +19b9d 2 85 79 +19b9f 1a 86 79 +19bb9 27 85 79 +19be0 b 87 79 +19beb b 89 79 +19bf6 12 91 79 +19c08 b 92 79 +19c13 13 89 79 +19c26 9 92 79 +19c2f 1 92 79 +FUNC 19c30 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*) +19c30 c 108 79 +19c3c 23 113 79 +19c5f 1 113 79 +FUNC 19c60 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) +19c60 c 252 79 +19c6c 1b 254 79 +19c87 1 254 79 +FUNC 19c88 5f8 0 std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) +19c88 15 311 79 +19c9d b 313 78 +19ca8 2a 315 78 +19cd2 12 318 78 +19ce4 23 319 78 +19d07 15 320 78 +19d1c c 321 78 +19d28 5a 323 78 +19d82 1c 327 78 +19d9e 35 328 78 +19dd3 16 323 78 +19de9 30 330 78 +19e19 10 343 78 +19e29 48 334 78 +19e71 21 338 78 +19e92 3d 339 78 +19ecf 13 334 78 +19ee2 b 339 78 +19eed 1c 342 78 +19f09 1e 343 78 +19f27 13 339 78 +19f3a 24 343 78 +19f5e e 348 78 +19f6c 1e 349 78 +19f8a e 350 78 +19f98 1d 353 78 +19fb5 8 354 78 +19fbd e 355 78 +19fcb 27 357 78 +19ff2 6 358 78 +19ff8 4d 361 78 +1a045 40 365 78 +1a085 18 367 78 +1a09d 44 368 78 +1a0e1 3 365 78 +1a0e4 19 361 78 +1a0fd 13 365 78 +1a110 e 368 78 +1a11e 3e 379 78 +1a15c 36 381 78 +1a192 12 384 78 +1a1a4 13 385 78 +1a1b7 2e 386 78 +1a1e5 e 368 78 +1a1f3 b 372 78 +1a1fe 39 374 78 +1a237 23 376 78 +1a25a b 377 78 +1a265 13 372 78 +1a278 8 386 78 +FUNC 1a280 2e 0 std::vector >::insert(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) +1a280 c 657 79 +1a28c 22 658 71 +FUNC 1a2ae ab 0 std::vector >::resize(unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) +1a2ae d 422 79 +1a2bb 15 424 71 +1a2d0 48 425 71 +1a318 41 427 71 +1a359 1 427 71 +FUNC 1a35a 63 0 std::vector >::resize(unsigned long) +1a35a d 441 79 +1a367 56 442 71 +1a3bd 1 442 71 +FUNC 1a3be 13 0 std::_Deque_iterator::operator*() const +1a3be c 134 79 +1a3ca 7 135 62 +1a3d1 1 135 62 +FUNC 1a3d2 3f 0 unsigned long long** std::__copy::copy(unsigned long long* const*, unsigned long long* const*, unsigned long long**) +1a3d2 c 298 61 +1a3de 22 300 61 +1a400 11 301 61 +1a411 1 301 61 +FUNC 1a412 2b 0 unsigned long long** std::__copy_aux(unsigned long long**, unsigned long long**, unsigned long long**) +1a412 c 307 79 +1a41e 4 315 61 +1a422 1b 317 61 +1a43d 1 317 61 +FUNC 1a43e 27 0 unsigned long long** std::__copy_normal::copy_n(unsigned long long**, unsigned long long**, unsigned long long**) +1a43e c 325 61 +1a44a 1b 326 61 +1a465 1 326 61 +FUNC 1a466 2f 0 unsigned long long** std::copy(unsigned long long**, unsigned long long**, unsigned long long**) +1a466 c 376 79 +1a472 4 384 61 +1a476 4 385 61 +1a47a 1b 387 61 +1a495 1 387 61 +FUNC 1a496 60 0 unsigned long long** std::__copy_backward::copy_b(unsigned long long* const*, unsigned long long* const*, unsigned long long**) +1a496 d 422 61 +1a4a3 12 424 61 +1a4b5 2e 425 61 +1a4e3 13 426 61 +FUNC 1a4f6 2b 0 unsigned long long** std::__copy_backward_aux(unsigned long long**, unsigned long long**, unsigned long long**) +1a4f6 c 432 79 +1a502 4 440 61 +1a506 1b 443 61 +1a521 1 443 61 +FUNC 1a522 27 0 unsigned long long** std::__copy_backward_normal::copy_b_n(unsigned long long**, unsigned long long**, unsigned long long**) +1a522 c 451 61 +1a52e 1b 452 61 +1a549 1 452 61 +FUNC 1a54a 2f 0 unsigned long long** std::copy_backward(unsigned long long**, unsigned long long**, unsigned long long**) +1a54a c 504 79 +1a556 4 514 61 +1a55a 4 515 61 +1a55e 1b 517 61 +1a579 1 517 61 +FUNC 1a57a 1df 0 std::deque >::_M_reallocate_map(unsigned long, bool) +1a57a 13 723 79 +1a58d 1b 726 76 +1a5a8 9 727 76 +1a5b1 13 730 76 +1a5c4 39 732 76 +1a5fd b 735 76 +1a608 27 736 76 +1a62f 2f 740 76 +1a65e 26 748 76 +1a684 15 750 76 +1a699 36 751 76 +1a6cf 22 753 76 +1a6f1 1e 756 76 +1a70f 8 758 76 +1a717 9 759 76 +1a720 15 762 76 +1a735 24 763 76 +1a759 1 763 76 +FUNC 1a75a 59 0 std::deque >::_M_reserve_map_at_back(unsigned long) +1a75a e 1443 79 +1a768 2a 1445 62 +1a792 21 1447 62 +1a7b3 1 1447 62 +FUNC 1a7b4 8c 0 std::deque >::_M_push_back_aux(unsigned long long const&) +1a7b4 c 345 79 +1a7c0 e 347 76 +1a7ce 13 348 76 +1a7e1 18 349 76 +1a7f9 1e 352 76 +1a817 1b 353 76 +1a832 c 355 76 +1a83e 2 360 76 +FUNC 1a840 62 0 std::deque >::push_back(unsigned long long const&) +1a840 c 1039 79 +1a84c 13 1041 62 +1a85f 1e 1044 62 +1a87d 11 1045 62 +1a88e 14 1048 62 +FUNC 1a8a2 20 0 std::stack > >::push(unsigned long long const&) +1a8a2 c 190 79 +1a8ae 14 191 75 +FUNC 1a8c2 27 0 unsigned char* std::__copy_normal::copy_n(unsigned char*, unsigned char*, unsigned char*) +1a8c2 c 325 61 +1a8ce 1b 326 61 +1a8e9 1 326 61 +FUNC 1a8ea 2f 0 unsigned char* std::copy(unsigned char*, unsigned char*, unsigned char*) +1a8ea c 376 79 +1a8f6 4 384 61 +1a8fa 4 385 61 +1a8fe 1b 387 61 +1a919 1 387 61 +FUNC 1a91a 27 0 unsigned char* std::__uninitialized_copy_aux(unsigned char*, unsigned char*, unsigned char*, __true_type) +1a91a c 73 79 +1a926 1b 74 79 +1a941 1 74 79 +FUNC 1a942 2f 0 unsigned char* std::uninitialized_copy(unsigned char*, unsigned char*, unsigned char*) +1a942 c 108 79 +1a94e 23 113 79 +1a971 1 113 79 +FUNC 1a972 27 0 unsigned char* std::__uninitialized_copy_a(unsigned char*, unsigned char*, unsigned char*, std::allocator) +1a972 c 252 79 +1a97e 1b 254 79 +1a999 1 254 79 +FUNC 1a99a 40 0 unsigned char* std::__copy_normal::copy_n<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) +1a99a d 334 61 +1a9a7 33 335 61 +FUNC 1a9da 2f 0 unsigned char* std::copy<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) +1a9da c 376 79 +1a9e6 4 384 61 +1a9ea 4 385 61 +1a9ee 1b 387 61 +1aa09 1 387 61 +FUNC 1aa0a 27 0 unsigned char* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*, __true_type) +1aa0a c 73 79 +1aa16 1b 74 79 +1aa31 1 74 79 +FUNC 1aa32 2f 0 unsigned char* std::uninitialized_copy<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) +1aa32 c 108 79 +1aa3e 23 113 79 +1aa61 1 113 79 +FUNC 1aa62 27 0 unsigned char* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, unsigned char*, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*, std::allocator) +1aa62 c 252 79 +1aa6e 1b 254 79 +1aa89 1 254 79 +1aa96 9 616 61 +1aa9f 2 617 61 +1aaa1 13 618 61 +1aab4 16 617 61 +1aaca 5 619 61 +1aacf 1 619 61 +1aadc 4 641 61 +1aae0 1b 642 61 +1aafb 1 642 61 +FUNC 1aafc 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&, __true_type) +1aafc c 182 79 +1ab08 1b 183 79 +1ab23 1 183 79 +FUNC 1ab24 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) +1ab24 c 214 79 +1ab30 23 218 79 +1ab53 1 218 79 +FUNC 1ab54 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&, std::allocator) +1ab54 c 308 79 +1ab60 1b 310 79 +1ab7b 1 310 79 +FUNC 1ab7c 45a 0 std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) +1ab7c 14 311 79 +1ab90 b 313 78 +1ab9b 21 315 78 +1abbc 9 318 78 +1abc5 23 319 78 +1abe8 15 320 78 +1abfd c 321 78 +1ac09 4e 323 78 +1ac57 11 327 78 +1ac68 30 328 78 +1ac98 35 330 78 +1accd 48 334 78 +1ad15 14 338 78 +1ad29 43 339 78 +1ad6c 11 342 78 +1ad7d 1e 343 78 +1ad9b e 348 78 +1ada9 1e 349 78 +1adc7 e 350 78 +1add5 1d 353 78 +1adf2 8 354 78 +1adfa e 355 78 +1ae08 27 357 78 +1ae2f 6 358 78 +1ae35 4d 361 78 +1ae82 40 365 78 +1aec2 18 367 78 +1aeda 4d 368 78 +1af27 3e 379 78 +1af65 2d 381 78 +1af92 12 384 78 +1afa4 13 385 78 +1afb7 1f 386 78 +FUNC 1afd6 2e 0 std::vector >::insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) +1afd6 c 657 79 +1afe2 22 658 71 +FUNC 1b004 ab 0 std::vector >::resize(unsigned long, unsigned char const&) +1b004 d 422 79 +1b011 15 424 71 +1b026 48 425 71 +1b06e 41 427 71 +1b0af 1 427 71 +FUNC 1b0b0 2b 0 std::vector >::resize(unsigned long) +1b0b0 c 441 79 +1b0bc 1f 442 71 +1b0db 1 442 71 +FUNC 1b0dc 1a 0 std::_Deque_iterator::_S_buffer_size() +1b0dc c 106 79 +1b0e8 e 107 62 +FUNC 1b0f6 66 0 std::_Deque_iterator::difference_type std::operator-(std::_Deque_iterator const&, std::_Deque_iterator const&) +1b0f6 d 328 79 +1b103 59 333 62 +FUNC 1b15c 3e 0 std::_Deque_iterator::_M_set_node(unsigned long long**) +1b15c d 229 79 +1b169 9 231 62 +1b172 b 232 62 +1b17d 1d 233 62 +FUNC 1b19a 50 0 std::_Deque_iterator::operator++() +1b19a c 142 79 +1b1a6 d 144 62 +1b1b3 f 145 62 +1b1c2 18 147 62 +1b1da b 148 62 +1b1e5 5 150 62 +FUNC 1b1ea 84 0 std::_Deque_iterator std::__copy::copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) +1b1ea e 280 61 +1b1f8 17 283 61 +1b20f 20 285 61 +1b22f b 286 61 +1b23a b 287 61 +1b245 b 283 61 +1b250 1e 289 61 +FUNC 1b26e 7e 0 std::_Deque_iterator std::__copy_aux, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) +1b26e 11 307 79 +1b27f 4 315 61 +1b283 69 317 61 +FUNC 1b2ec 7a 0 std::_Deque_iterator std::__copy_normal::copy_n, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) +1b2ec 11 325 61 +1b2fd 69 326 61 +FUNC 1b366 82 0 std::_Deque_iterator std::copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) +1b366 11 376 79 +1b377 4 384 61 +1b37b 4 385 61 +1b37f 69 387 61 +FUNC 1b3e8 7a 0 std::_Deque_iterator std::__uninitialized_copy_aux, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator, __true_type) +1b3e8 11 73 79 +1b3f9 69 74 79 +FUNC 1b462 82 0 std::_Deque_iterator std::uninitialized_copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) +1b462 11 108 79 +1b473 71 113 79 +FUNC 1b4e4 7a 0 std::_Deque_iterator std::__uninitialized_copy_a, std::_Deque_iterator, unsigned long long>(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator, std::allocator) +1b4e4 11 252 79 +1b4f5 69 254 79 +1b55e 10 679 62 +1b56e 64 680 62 +1b5d2 e8 681 62 +1b6ba c 143 75 +1b6c6 14 144 75 +1b6da 6 144 75 +FUNC 1b6e0 4d 0 __eprintf +1b6e0 6 1826 80 +1b6e6 3 1832 80 +1b6e9 c 1826 80 +1b6f5 29 1832 80 +1b71e a 1837 80 +1b728 5 1838 80 +1b72d e8d3 1838 80 diff --git a/thirdparty/google-breakpad/r318/src/client/minidump_file_writer-inl.h b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer-inl.h new file mode 100644 index 00000000..7c556a27 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer-inl.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_file_writer-inl.h: Minidump file writer implementation. +// +// See minidump_file_writer.h for documentation. + +#ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__ +#define CLIENT_MINIDUMP_FILE_WRITER_INL_H__ + +#include + +#include "client/minidump_file_writer.h" +#include "google_breakpad/common/minidump_size.h" + +namespace google_breakpad { + +template +inline bool TypedMDRVA::Allocate() { + allocation_state_ = SINGLE_OBJECT; + return UntypedMDRVA::Allocate(minidump_size::size()); +} + +template +inline bool TypedMDRVA::Allocate(size_t additional) { + allocation_state_ = SINGLE_OBJECT; + return UntypedMDRVA::Allocate(minidump_size::size() + additional); +} + +template +inline bool TypedMDRVA::AllocateArray(size_t count) { + assert(count); + allocation_state_ = ARRAY; + return UntypedMDRVA::Allocate(minidump_size::size() * count); +} + +template +inline bool TypedMDRVA::AllocateObjectAndArray(unsigned int count, + size_t size) { + assert(count && size); + allocation_state_ = SINGLE_OBJECT_WITH_ARRAY; + return UntypedMDRVA::Allocate(minidump_size::size() + count * size); +} + +template +inline bool TypedMDRVA::CopyIndex(unsigned int index, MDType *item) { + assert(allocation_state_ == ARRAY); + return writer_->Copy(position_ + index * minidump_size::size(), item, + minidump_size::size()); +} + +template +inline bool TypedMDRVA::CopyIndexAfterObject(unsigned int index, + const void *src, + size_t size) { + assert(allocation_state_ == SINGLE_OBJECT_WITH_ARRAY); + return writer_->Copy(position_ + minidump_size::size() + index * size, + src, size); +} + +template +inline bool TypedMDRVA::Flush() { + return writer_->Copy(position_, &data_, minidump_size::size()); +} + +} // namespace google_breakpad + +#endif // CLIENT_MINIDUMP_FILE_WRITER_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.cc b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.cc new file mode 100644 index 00000000..fdd59198 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.cc @@ -0,0 +1,251 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_file_writer.cc: Minidump file writer implementation. +// +// See minidump_file_writer.h for documentation. + +#include +#include +#include +#include +#include + +#include "client/minidump_file_writer-inl.h" +#include "common/string_conversion.h" + +namespace google_breakpad { + +const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast(-1); + +MinidumpFileWriter::MinidumpFileWriter() : file_(-1), position_(0), size_(0) { +} + +MinidumpFileWriter::~MinidumpFileWriter() { + Close(); +} + +bool MinidumpFileWriter::Open(const char *path) { + assert(file_ == -1); + file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); + + return file_ != -1; +} + +bool MinidumpFileWriter::Close() { + bool result = true; + + if (file_ != -1) { + ftruncate(file_, position_); + result = (close(file_) == 0); + file_ = -1; + } + + return result; +} + +bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str, + unsigned int length, + TypedMDRVA *mdstring) { + bool result = true; + if (sizeof(wchar_t) == sizeof(u_int16_t)) { + // Shortcut if wchar_t is the same size as MDString's buffer + result = mdstring->Copy(str, mdstring->get()->length); + } else { + u_int16_t out[2]; + int out_idx = 0; + + // Copy the string character by character + while (length && result) { + UTF32ToUTF16Char(*str, out); + if (!out[0]) + return false; + + // Process one character at a time + --length; + ++str; + + // Append the one or two UTF-16 characters. The first one will be non- + // zero, but the second one may be zero, depending on the conversion from + // UTF-32. + int out_count = out[1] ? 2 : 1; + int out_size = sizeof(u_int16_t) * out_count; + result = mdstring->CopyIndexAfterObject(out_idx, out, out_size); + out_idx += out_count; + } + } + return result; +} + +bool MinidumpFileWriter::CopyStringToMDString(const char *str, + unsigned int length, + TypedMDRVA *mdstring) { + bool result = true; + u_int16_t out[2]; + int out_idx = 0; + + // Copy the string character by character + while (length && result) { + int conversion_count = UTF8ToUTF16Char(str, length, out); + if (!conversion_count) + return false; + + // Move the pointer along based on the nubmer of converted characters + length -= conversion_count; + str += conversion_count; + + // Append the one or two UTF-16 characters + int out_count = out[1] ? 2 : 1; + int out_size = sizeof(u_int16_t) * out_count; + result = mdstring->CopyIndexAfterObject(out_idx, out, out_size); + out_idx += out_count; + } + return result; +} + +template +bool MinidumpFileWriter::WriteStringCore(const CharType *str, + unsigned int length, + MDLocationDescriptor *location) { + assert(str); + assert(location); + // Calculate the mdstring length by either limiting to |length| as passed in + // or by finding the location of the NULL character. + unsigned int mdstring_length = 0; + if (!length) + length = INT_MAX; + for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length) + ; + + // Allocate the string buffer + TypedMDRVA mdstring(this); + if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(u_int16_t))) + return false; + + // Set length excluding the NULL and copy the string + mdstring.get()->length = mdstring_length * sizeof(u_int16_t); + bool result = CopyStringToMDString(str, mdstring_length, &mdstring); + + // NULL terminate + if (result) { + u_int16_t ch = 0; + result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch)); + + if (result) + *location = mdstring.location(); + } + + return result; +} + +bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length, + MDLocationDescriptor *location) { + return WriteStringCore(str, length, location); +} + +bool MinidumpFileWriter::WriteString(const char *str, unsigned int length, + MDLocationDescriptor *location) { + return WriteStringCore(str, length, location); +} + +bool MinidumpFileWriter::WriteMemory(const void *src, size_t size, + MDMemoryDescriptor *output) { + assert(src); + assert(output); + UntypedMDRVA mem(this); + + if (!mem.Allocate(size)) + return false; + if (!mem.Copy(src, mem.size())) + return false; + + output->start_of_memory_range = reinterpret_cast(src); + output->memory = mem.location(); + + return true; +} + +MDRVA MinidumpFileWriter::Allocate(size_t size) { + assert(size); + assert(file_ != -1); + size_t aligned_size = (size + 7) & ~7; // 64-bit alignment + + if (position_ + aligned_size > size_) { + size_t growth = aligned_size; + size_t minimal_growth = getpagesize(); + + // Ensure that the file grows by at least the size of a memory page + if (growth < minimal_growth) + growth = minimal_growth; + + size_t new_size = size_ + growth; + if (ftruncate(file_, new_size) != 0) + return kInvalidMDRVA; + + size_ = new_size; + } + + MDRVA current_position = position_; + position_ += static_cast(aligned_size); + + return current_position; +} + +bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) { + assert(src); + assert(size); + assert(file_ != -1); + + // Ensure that the data will fit in the allocated space + if (size + position > size_) + return false; + + // Seek and write the data + if (lseek(file_, position, SEEK_SET) == static_cast(position)) + if (write(file_, src, size) == size) + return true; + + return false; +} + +bool UntypedMDRVA::Allocate(size_t size) { + assert(size_ == 0); + size_ = size; + position_ = writer_->Allocate(size_); + return position_ != MinidumpFileWriter::kInvalidMDRVA; +} + +bool UntypedMDRVA::Copy(MDRVA position, const void *src, size_t size) { + assert(src); + assert(size); + assert(position + size <= position_ + size_); + return writer_->Copy(position, src, size); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.h b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.h new file mode 100644 index 00000000..f569a553 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer.h @@ -0,0 +1,250 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_file_writer.h: Implements file-based minidump generation. It's +// intended to be used with the Google Breakpad open source crash handling +// project. + +#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__ +#define CLIENT_MINIDUMP_FILE_WRITER_H__ + +#include + +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +class UntypedMDRVA; +template class TypedMDRVA; + +// The user of this class can Open() a file and add minidump streams, data, and +// strings using the definitions in minidump_format.h. Since this class is +// expected to be used in a situation where the current process may be +// damaged, it will not allocate heap memory. +// Sample usage: +// MinidumpFileWriter writer; +// writer.Open("/tmp/minidump.dmp"); +// TypedMDRVA header(&writer_); +// header.Allocate(); +// header->get()->signature = MD_HEADER_SIGNATURE; +// : +// writer.Close(); +class MinidumpFileWriter { +public: + // Invalid MDRVA (Minidump Relative Virtual Address) + // returned on failed allocation + static const MDRVA kInvalidMDRVA; + + MinidumpFileWriter(); + ~MinidumpFileWriter(); + + // Open |path| as the destination of the minidump data. Any existing file + // will be overwritten. + // Return true on success, or false on failure + bool Open(const char *path); + + // Close the current file + // Return true on success, or false on failure + bool Close(); + + // Copy the contents of |str| to a MDString and write it to the file. + // |str| is expected to be either UTF-16 or UTF-32 depending on the size + // of wchar_t. + // Maximum |length| of characters to copy from |str|, or specify 0 to use the + // entire NULL terminated string. Copying will stop at the first NULL. + // |location| the allocated location + // Return true on success, or false on failure + bool WriteString(const wchar_t *str, unsigned int length, + MDLocationDescriptor *location); + + // Same as above, except with |str| as a UTF-8 string + bool WriteString(const char *str, unsigned int length, + MDLocationDescriptor *location); + + // Write |size| bytes starting at |src| into the current position. + // Return true on success and set |output| to position, or false on failure + bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output); + + // Copies |size| bytes from |src| to |position| + // Return true on success, or false on failure + bool Copy(MDRVA position, const void *src, ssize_t size); + + // Return the current position for writing to the minidump + inline MDRVA position() const { return position_; } + + private: + friend class UntypedMDRVA; + + // Allocates an area of |size| bytes. + // Returns the position of the allocation, or kInvalidMDRVA if it was + // unable to allocate the bytes. + MDRVA Allocate(size_t size); + + // The file descriptor for the output file + int file_; + + // Current position in buffer + MDRVA position_; + + // Current allocated size + size_t size_; + + // Copy |length| characters from |str| to |mdstring|. These are distinct + // because the underlying MDString is a UTF-16 based string. The wchar_t + // variant may need to create a MDString that has more characters than the + // source |str|, whereas the UTF-8 variant may coalesce characters to form + // a single UTF-16 character. + bool CopyStringToMDString(const wchar_t *str, unsigned int length, + TypedMDRVA *mdstring); + bool CopyStringToMDString(const char *str, unsigned int length, + TypedMDRVA *mdstring); + + // The common templated code for writing a string + template + bool WriteStringCore(const CharType *str, unsigned int length, + MDLocationDescriptor *location); +}; + +// Represents an untyped allocated chunk +class UntypedMDRVA { + public: + explicit UntypedMDRVA(MinidumpFileWriter *writer) + : writer_(writer), + position_(writer->position()), + size_(0) {} + + // Allocates |size| bytes. Must not call more than once. + // Return true on success, or false on failure + bool Allocate(size_t size); + + // Returns the current position or kInvalidMDRVA if allocation failed + inline MDRVA position() const { return position_; } + + // Number of bytes allocated + inline size_t size() const { return size_; } + + // Return size and position + inline MDLocationDescriptor location() const { + MDLocationDescriptor location = { size_, position_ }; + return location; + } + + // Copy |size| bytes starting at |src| into the minidump at |position| + // Return true on success, or false on failure + bool Copy(MDRVA position, const void *src, size_t size); + + // Copy |size| bytes from |src| to the current position + inline bool Copy(const void *src, size_t size) { + return Copy(position_, src, size); + } + + protected: + // Writer we associate with + MinidumpFileWriter *writer_; + + // Position of the start of the data + MDRVA position_; + + // Allocated size + size_t size_; +}; + +// Represents a Minidump object chunk. Additional memory can be allocated at +// the end of the object as a: +// - single allocation +// - Array of MDType objects +// - A MDType object followed by an array +template +class TypedMDRVA : public UntypedMDRVA { + public: + // Constructs an unallocated MDRVA + explicit TypedMDRVA(MinidumpFileWriter *writer) + : UntypedMDRVA(writer), + data_(), + allocation_state_(UNALLOCATED) {} + + inline ~TypedMDRVA() { + // Ensure that the data_ object is written out + if (allocation_state_ != ARRAY) + Flush(); + } + + // Address of object data_ of MDType. This is not declared const as the + // typical usage will be to access the underlying |data_| object as to + // alter its contents. + MDType *get() { return &data_; } + + // Allocates minidump_size::size() bytes. + // Must not call more than once. + // Return true on success, or false on failure + bool Allocate(); + + // Allocates minidump_size::size() + |additional| bytes. + // Must not call more than once. + // Return true on success, or false on failure + bool Allocate(size_t additional); + + // Allocate an array of |count| elements of MDType. + // Must not call more than once. + // Return true on success, or false on failure + bool AllocateArray(size_t count); + + // Allocate an array of |count| elements of |size| after object of MDType + // Must not call more than once. + // Return true on success, or false on failure + bool AllocateObjectAndArray(unsigned int count, size_t size); + + // Copy |item| to |index| + // Must have been allocated using AllocateArray(). + // Return true on success, or false on failure + bool CopyIndex(unsigned int index, MDType *item); + + // Copy |size| bytes starting at |str| to |index| + // Must have been allocated using AllocateObjectAndArray(). + // Return true on success, or false on failure + bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size); + + // Write data_ + bool Flush(); + + private: + enum AllocationState { + UNALLOCATED = 0, + SINGLE_OBJECT, + ARRAY, + SINGLE_OBJECT_WITH_ARRAY + }; + + MDType data_; + AllocationState allocation_state_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_MINIDUMP_FILE_WRITER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/minidump_file_writer_unittest.cc b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer_unittest.cc new file mode 100644 index 00000000..8eadff46 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/minidump_file_writer_unittest.cc @@ -0,0 +1,174 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: waylonis@google.com (Dan Waylonis) + +/* + g++ -I../ ../common/convert_UTF.c \ + ../common/string_conversion.cc \ + minidump_file_writer.cc \ + minidump_file_writer_unittest.cc \ + -o minidump_file_writer_unittest + */ + +#include +#include + +#include "minidump_file_writer-inl.h" + +using google_breakpad::MinidumpFileWriter; + +#define ASSERT_TRUE(cond) \ +if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + return false; \ +} + +#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) +#define ASSERT_NE(e1, e2) ASSERT_TRUE((e1) != (e2)) + +struct StringStructure { + unsigned long integer_value; + MDLocationDescriptor first_string; + MDLocationDescriptor second_string; +}; + +struct ArrayStructure { + unsigned char char_value; + unsigned short short_value; + unsigned long long_value; +}; + +typedef struct { + unsigned long count; + ArrayStructure array[0]; +} ObjectAndArrayStructure; + +static bool WriteFile(const char *path) { + MinidumpFileWriter writer; + if (writer.Open(path)) { + // Test a single structure + google_breakpad::TypedMDRVA strings(&writer); + ASSERT_TRUE(strings.Allocate()); + strings.get()->integer_value = 0xBEEF; + const char *first = "First String"; + ASSERT_TRUE(writer.WriteString(first, 0, &strings.get()->first_string)); + const wchar_t *second = L"Second String"; + ASSERT_TRUE(writer.WriteString(second, 0, &strings.get()->second_string)); + + // Test an array structure + google_breakpad::TypedMDRVA array(&writer); + unsigned int count = 10; + ASSERT_TRUE(array.AllocateArray(count)); + for (unsigned int i = 0; i < count; ++i) { + ArrayStructure local; + local.char_value = i; + local.short_value = i + 1; + local.long_value = i + 2; + ASSERT_TRUE(array.CopyIndex(i, &local)); + } + + // Test an object followed by an array + google_breakpad::TypedMDRVA obj_array(&writer); + ASSERT_TRUE(obj_array.AllocateObjectAndArray(count, + sizeof(ArrayStructure))); + obj_array.get()->count = count; + for (unsigned int i = 0; i < count; ++i) { + ArrayStructure local; + local.char_value = i; + local.short_value = i + 1; + local.long_value = i + 2; + ASSERT_TRUE(obj_array.CopyIndexAfterObject(i, &local, sizeof(local))); + } + } + + return writer.Close(); +} + +static bool CompareFile(const char *path) { + unsigned long expected[] = { +#if defined(__BIG_ENDIAN__) + 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000, + 0x00000018, 0x00460069, 0x00720073, 0x00740020, 0x00530074, 0x00720069, + 0x006e0067, 0x00000000, 0x0000001a, 0x00530065, 0x0063006f, 0x006e0064, + 0x00200053, 0x00740072, 0x0069006e, 0x00670000, 0x00000001, 0x00000002, + 0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005, + 0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008, + 0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b, + 0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003, + 0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006, + 0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009, + 0x0000000a, 0x0900000a, 0x0000000b, 0x00000000 +#else + 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000, + 0x00000018, 0x00690046, 0x00730072, 0x00200074, 0x00740053, 0x00690072, + 0x0067006e, 0x00000000, 0x0000001a, 0x00650053, 0x006f0063, 0x0064006e, + 0x00530020, 0x00720074, 0x006e0069, 0x00000067, 0x0001da00, 0x00000002, + 0x0002da01, 0x00000003, 0x0003da02, 0x00000004, 0x0004da03, 0x00000005, + 0x0005da04, 0x00000006, 0x0006da05, 0x00000007, 0x0007da06, 0x00000008, + 0x0008da07, 0x00000009, 0x0009da08, 0x0000000a, 0x000ada09, 0x0000000b, + 0x0000000a, 0x00018700, 0x00000002, 0x00028701, 0x00000003, 0x00038702, + 0x00000004, 0x00048703, 0x00000005, 0x00058704, 0x00000006, 0x00068705, + 0x00000007, 0x00078706, 0x00000008, 0x00088707, 0x00000009, 0x00098708, + 0x0000000a, 0x000a8709, 0x0000000b, 0x00000000, +#endif + }; + unsigned int expected_byte_count = sizeof(expected); + int fd = open(path, O_RDONLY, 0600); + void *buffer = malloc(expected_byte_count); + ASSERT_NE(fd, -1); + ASSERT_TRUE(buffer); + ASSERT_EQ(read(fd, buffer, expected_byte_count), expected_byte_count); + + char *b1, *b2; + b1 = (char*)buffer; + b2 = (char*)expected; + while (*b1 == *b2) { + b1++; + b2++; + } + + printf("%d\n",b1 - (char*)buffer); + + + ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0); + return true; +} + +static bool RunTests() { + const char *path = "/tmp/minidump_file_writer_unittest.dmp"; + ASSERT_TRUE(WriteFile(path)); + ASSERT_TRUE(CompareFile(path)); + unlink(path); + return true; +} + +extern "C" int main(int argc, const char *argv[]) { + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/Makefile b/thirdparty/google-breakpad/r318/src/client/solaris/handler/Makefile new file mode 100644 index 00000000..9b642865 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/Makefile @@ -0,0 +1,78 @@ +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Author: Alfred Peng + +CC=cc +CXX=CC + +CPPFLAGS=-g -I../../.. -DNDEBUG -features=extensions -D_REENTRANT +LDFLAGS=-lpthread -lssl -lgnutls-openssl -lelf + +OBJ_DIR=. +BIN_DIR=. + +THREAD_SRC=solaris_lwp.cc +SHARE_SRC=../../minidump_file_writer.cc\ + ../../../common/md5.c\ + ../../../common/string_conversion.cc\ + ../../../common/solaris/file_id.cc\ + minidump_generator.cc +HANDLER_SRC=exception_handler.cc\ + ../../../common/solaris/guid_creator.cc +SHARE_C_SRC=../../../common/convert_UTF.c + +MINIDUMP_TEST_SRC=minidump_test.cc +EXCEPTION_TEST_SRC=exception_handler_test.cc + +THREAD_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(THREAD_SRC)) +SHARE_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(SHARE_SRC)) +HANDLER_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o,$(HANDLER_SRC)) +SHARE_C_OBJ=$(patsubst %.c,$(OBJ_DIR)/%.o,$(SHARE_C_SRC)) +MINIDUMP_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(MINIDUMP_TEST_SRC))\ + $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) $(HANDLER_OBJ) +EXCEPTION_TEST_OBJ=$(patsubst %.cc,$(OBJ_DIR)/%.o, $(EXCEPTION_TEST_SRC))\ + $(THREAD_OBJ) $(SHARE_OBJ) $(SHARE_C_OBJ) $(HANDLER_OBJ) + +BIN=$(BIN_DIR)/minidump_test\ + $(BIN_DIR)/exception_handler_test + +.PHONY:all clean + +all:$(BIN) + +$(BIN_DIR)/minidump_test:$(MINIDUMP_TEST_OBJ) + $(CXX) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ + +$(BIN_DIR)/exception_handler_test:$(EXCEPTION_TEST_OBJ) + $(CXX) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ + +clean: + rm -f $(BIN) *.o *.out *.dmp core ../../minidump_file_writer.o\ + ../../../common/*.o ../../../common/solaris/*.o diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.cc b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.cc new file mode 100644 index 00000000..7fc8d255 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.cc @@ -0,0 +1,258 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include +#include +#include + +#include +#include +#include + +#include "client/solaris/handler/exception_handler.h" +#include "common/solaris/guid_creator.h" +#include "common/solaris/message_output.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Signals that we are interested. +static const int kSigTable[] = { + SIGSEGV, + SIGABRT, + SIGFPE, + SIGILL, + SIGBUS +}; + +std::vector *ExceptionHandler::handler_stack_ = NULL; +int ExceptionHandler::handler_stack_index_ = 0; +pthread_mutex_t ExceptionHandler::handler_stack_mutex_ = + PTHREAD_MUTEX_INITIALIZER; + +ExceptionHandler::ExceptionHandler(const string &dump_path, + FilterCallback filter, + MinidumpCallback callback, + void *callback_context, + bool install_handler) + : filter_(filter), + callback_(callback), + callback_context_(callback_context), + dump_path_(), + installed_handler_(install_handler) { + set_dump_path(dump_path); + + if (install_handler) { + SetupHandler(); + } + + if (install_handler) { + pthread_mutex_lock(&handler_stack_mutex_); + + if (handler_stack_ == NULL) + handler_stack_ = new std::vector; + handler_stack_->push_back(this); + pthread_mutex_unlock(&handler_stack_mutex_); + } +} + +ExceptionHandler::~ExceptionHandler() { + TeardownAllHandlers(); + pthread_mutex_lock(&handler_stack_mutex_); + if (handler_stack_->back() == this) { + handler_stack_->pop_back(); + } else { + print_message1(2, "warning: removing Breakpad handler out of order\n"); + for (std::vector::iterator iterator = + handler_stack_->begin(); + iterator != handler_stack_->end(); + ++iterator) { + if (*iterator == this) { + handler_stack_->erase(iterator); + } + } + } + + if (handler_stack_->empty()) { + // When destroying the last ExceptionHandler that installed a handler, + // clean up the handler stack. + delete handler_stack_; + handler_stack_ = NULL; + } + pthread_mutex_unlock(&handler_stack_mutex_); +} + +bool ExceptionHandler::WriteMinidump() { + return InternalWriteMinidump(0, 0, NULL); +} + +// static +bool ExceptionHandler::WriteMinidump(const string &dump_path, + MinidumpCallback callback, + void *callback_context) { + ExceptionHandler handler(dump_path, NULL, callback, + callback_context, false); + return handler.InternalWriteMinidump(0, 0, NULL); +} + +void ExceptionHandler::SetupHandler() { + // Signal on a different stack to avoid using the stack + // of the crashing lwp. + struct sigaltstack sig_stack; + sig_stack.ss_sp = malloc(MINSIGSTKSZ); + if (sig_stack.ss_sp == NULL) + return; + sig_stack.ss_size = MINSIGSTKSZ; + sig_stack.ss_flags = 0; + + if (sigaltstack(&sig_stack, NULL) < 0) + return; + for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) + SetupHandler(kSigTable[i]); +} + +void ExceptionHandler::SetupHandler(int signo) { + struct sigaction act, old_act; + act.sa_handler = HandleException; + act.sa_flags = SA_ONSTACK; + if (sigaction(signo, &act, &old_act) < 0) + return; + old_handlers_[signo] = old_act.sa_handler; +} + +void ExceptionHandler::TeardownHandler(int signo) { + if (old_handlers_.find(signo) != old_handlers_.end()) { + struct sigaction act; + act.sa_handler = old_handlers_[signo]; + act.sa_flags = 0; + sigaction(signo, &act, 0); + } +} + +void ExceptionHandler::TeardownAllHandlers() { + for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) { + TeardownHandler(kSigTable[i]); + } +} + +// static +void ExceptionHandler::HandleException(int signo) { +//void ExceptionHandler::HandleException(int signo, siginfo_t *sip, ucontext_t *sig_ctx) { + // The context information about the signal is put on the stack of + // the signal handler frame as value parameter. For some reasons, the + // prototype of the handler doesn't declare this information as parameter, we + // will do it by hand. The stack layout for a signal handler frame is here: + // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81 + // + // However, if we are being called by another signal handler passing the + // signal up the chain, then we may not have this random extra parameter, + // so we may have to walk the stack to find it. We do the actual work + // on another thread, where it's a little safer, but we want the ebp + // from this frame to find it. + uintptr_t current_ebp = (uintptr_t)_getfp(); + + pthread_mutex_lock(&handler_stack_mutex_); + ExceptionHandler *current_handler = + handler_stack_->at(handler_stack_->size() - ++handler_stack_index_); + pthread_mutex_unlock(&handler_stack_mutex_); + + // Restore original handler. + current_handler->TeardownHandler(signo); + + ucontext_t *sig_ctx = NULL; + if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) { +// if (current_handler->InternalWriteMinidump(signo, &sig_ctx)) { + // Fully handled this exception, safe to exit. + exit(EXIT_FAILURE); + } else { + // Exception not fully handled, will call the next handler in stack to + // process it. + typedef void (*SignalHandler)(int signo); + SignalHandler old_handler = + reinterpret_cast(current_handler->old_handlers_[signo]); + if (old_handler != NULL) + old_handler(signo); + } + + pthread_mutex_lock(&handler_stack_mutex_); + current_handler->SetupHandler(signo); + --handler_stack_index_; + // All the handlers in stack have been invoked to handle the exception, + // normally the process should be terminated and should not reach here. + // In case we got here, ask the OS to handle it to avoid endless loop, + // normally the OS will generate a core and termiate the process. This + // may be desired to debug the program. + if (handler_stack_index_ == 0) + signal(signo, SIG_DFL); + pthread_mutex_unlock(&handler_stack_mutex_); +} + +bool ExceptionHandler::InternalWriteMinidump(int signo, + uintptr_t sighandler_ebp, + ucontext_t **sig_ctx) { + if (filter_ && !filter_(callback_context_)) + return false; + + bool success = false; + GUID guid; + char guid_str[kGUIDStringLength + 1]; + if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) { + char minidump_path[PATH_MAX]; + snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp", + dump_path_c_, guid_str); + + // Block all the signals we want to process when writing minidump. + // We don't want it to be interrupted. + sigset_t sig_blocked, sig_old; + bool blocked = true; + sigfillset(&sig_blocked); + for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) + sigdelset(&sig_blocked, kSigTable[i]); + if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) { + blocked = false; + print_message1(2, "HandleException: failed to block signals.\n"); + } + + success = minidump_generator_.WriteMinidumpToFile( + minidump_path, signo, sighandler_ebp, sig_ctx); + + // Unblock the signals. + if (blocked) + sigprocmask(SIG_SETMASK, &sig_old, &sig_old); + + if (callback_) + success = callback_(dump_path_c_, guid_str, callback_context_, success); + } + return success; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.h b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.h new file mode 100644 index 00000000..4d72485f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler.h @@ -0,0 +1,201 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Alfred Peng + +#ifndef CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ + +#include +#include +#include + +#include "client/solaris/handler/minidump_generator.h" + +namespace google_breakpad { + +using std::string; + +// +// ExceptionHandler +// +// ExceptionHandler can write a minidump file when an exception occurs, +// or when WriteMinidump() is called explicitly by your program. +// +// To have the exception handler write minidumps when an uncaught exception +// (crash) occurs, you should create an instance early in the execution +// of your program, and keep it around for the entire time you want to +// have crash handling active (typically, until shutdown). +// (NOTE): There should be only one this kind of exception handler +// object per process. +// +// If you want to write minidumps without installing the exception handler, +// you can create an ExceptionHandler with install_handler set to false, +// then call WriteMinidump. You can also use this technique if you want to +// use different minidump callbacks for different call sites. +// +// In either case, a callback function is called when a minidump is written, +// which receives the unqiue id of the minidump. The caller can use this +// id to collect and write additional application state, and to launch an +// external crash-reporting application. +// +// Caller should try to make the callbacks as crash-friendly as possible, +// it should avoid use heap memory allocation as much as possible. +// +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, + // Breakpad will immediately report the exception as unhandled without + // writing a minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void *context); + + // A callback function to run after the minidump has been written. + // minidump_id is a unique id for the dump, so the minidump + // file is /.dmp. context is the parameter supplied + // by the user as callback_context when the handler was created. succeeded + // indicates whether a minidump file was successfully written. + // + // If an exception occurred and the callback returns true, Breakpad will + // treat the exception as fully-handled, suppressing any other handlers from + // being notified of the exception. If the callback returns false, Breakpad + // will treat the exception as unhandled, and allow another handler to handle + // it. If there are no other handlers, Breakpad will report the exception to + // the system as unhandled, allowing a debugger or native crash dialog the + // opportunity to handle the exception. Most callback implementations + // should normally return the value of |succeeded|, or when they wish to + // not report an exception of handled, false. Callbacks will rarely want to + // return true directly (unless |succeeded| is true). + typedef bool (*MinidumpCallback)(const char *dump_path, + const char *minidump_id, + void *context, + bool succeeded); + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Before writing a minidump, the optional filter callback will be called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // If install_handler is true, then a minidump will be written whenever + // an unhandled exception occurs. If it is false, minidumps will only + // be written when WriteMinidump is called. + ExceptionHandler(const string &dump_path, + FilterCallback filter, MinidumpCallback callback, + void *callback_context, + bool install_handler); + ~ExceptionHandler(); + + // Get and Set the minidump path. + string dump_path() const { return dump_path_; } + void set_dump_path(const string &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const string &dump_path, + MinidumpCallback callback, + void *callback_context); + + private: + // Setup crash handler. + void SetupHandler(); + // Setup signal handler for a signal. + void SetupHandler(int signo); + // Teardown the handler for a signal. + void TeardownHandler(int signo); + // Teardown all handlers. + void TeardownAllHandlers(); + + // Runs the main loop for the exception handler thread. + static void* ExceptionHandlerThreadMain(void *lpParameter); + + // Signal handler. + static void HandleException(int signo); + + // Write all the information to the dump file. + // If called from a signal handler, sighandler_ebp is the ebp of + // that signal handler's frame, and sig_ctx is an out parameter + // that will be set to point at the ucontext_t that was placed + // on the stack by the kernel. You can pass zero and NULL + // for the second and third parameters if you are not calling + // this from a signal handler. + bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp, + ucontext_t **sig_ctx); + + private: + // The callbacks before and after writing the dump file. + FilterCallback filter_; + MinidumpCallback callback_; + void *callback_context_; + + // The directory in which a minidump will be written, set by the dump_path + // argument to the constructor, or set_dump_path. + string dump_path_; + // C style dump path. Keep this when setting dump path, since calling + // c_str() of std::string when crashing may not be safe. + const char *dump_path_c_; + + // True if the ExceptionHandler installed an unhandled exception filter + // when created (with an install_handler parameter set to true). + bool installed_handler_; + + // Keep the previous handlers for the signal. + typedef void (*sighandler_t)(int); + std::map old_handlers_; + + // The global exception handler stack. This is need becuase there may exist + // multiple ExceptionHandler instances in a process. Each will have itself + // registered in this stack. + static std::vector *handler_stack_; + // The index of the handler that should handle the next exception. + static int handler_stack_index_; + static pthread_mutex_t handler_stack_mutex_; + + // The minidump generator. + MinidumpGenerator minidump_generator_; + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); +}; + +} // namespace google_breakpad + +#endif // CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler_test.cc b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler_test.cc new file mode 100644 index 00000000..6bb8e18d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/exception_handler_test.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include + +#include +#include +#include +#include + +#include "client/solaris/handler/exception_handler.h" +#include "client/solaris/handler/solaris_lwp.h" + +using namespace google_breakpad; + +// Thread use this to see if it should stop working. +static bool should_exit = false; + +static int foo2(int arg) { + // Stack variable, used for debugging stack dumps. + int c = 0xcccccccc; + fprintf(stderr, "Thread trying to crash: %x\n", getpid()); + c = *reinterpret_cast(0x5); + return c; +} + +static int foo(int arg) { + // Stack variable, used for debugging stack dumps. + int b = 0xbbbbbbbb; + b = foo2(b); + return b; +} + +static void *thread_crash(void *) { + // Stack variable, used for debugging stack dumps. + int a = 0xaaaaaaaa; + sleep(3); + a = foo(a); + printf("%x\n", a); + return NULL; +} + +static void *thread_main(void *) { + while (!should_exit) + sleep(1); + return NULL; +} + +static void CreateCrashThread() { + pthread_t h; + pthread_create(&h, NULL, thread_crash, NULL); + pthread_detach(h); +} + +// Create working threads. +static void CreateThread(int num) { + pthread_t h; + for (int i = 0; i < num; ++i) { + pthread_create(&h, NULL, thread_main, NULL); + pthread_detach(h); + } +} + +// Callback when minidump written. +static bool MinidumpCallback(const char *dump_path, + const char *minidump_id, + void *context, + bool succeeded) { + int index = reinterpret_cast(context); + if (index == 0) { + should_exit = true; + return true; + } + // Don't process it. + return false; +} + +int main(int argc, char *argv[]) { + int handler_index = 1; + ExceptionHandler handler_ignore(".", NULL, MinidumpCallback, + (void*)handler_index, true); + CreateCrashThread(); + CreateThread(10); + + while (true) + sleep(20); + should_exit = true; + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.cc b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.cc new file mode 100644 index 00000000..ea046cff --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.cc @@ -0,0 +1,786 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "client/solaris/handler/minidump_generator.h" +#include "client/minidump_file_writer-inl.h" +#include "common/solaris/file_id.h" + +namespace { + +using namespace google_breakpad; + +// Argument for the writer function. +struct WriterArgument { + MinidumpFileWriter *minidump_writer; + + // Pid of the lwp who called WriteMinidumpToFile + int requester_pid; + + // The stack bottom of the lwp which caused the dump. + // Mainly used to find the lwp id of the crashed lwp since signal + // handler may not be called in the lwp who caused it. + uintptr_t crashed_stack_bottom; + + // Id of the crashing lwp. + int crashed_lwpid; + + // Signal number when crash happened. Can be 0 if this is a requested dump. + int signo; + + // The ebp of the signal handler frame on x86. Can be 0 if this is a + // requested dump. + uintptr_t sighandler_ebp; + + // User context when crash happens. Can be NULL if this is a requested dump. + // This is actually an out parameter, but it will be filled in at the start + // of the writer LWP. + ucontext_t *sig_ctx; + + // Used to get information about the lwps. + SolarisLwp *lwp_lister; +}; + +// Holding context information for the callback of finding the crashing lwp. +struct FindCrashLwpContext { + const SolarisLwp *lwp_lister; + uintptr_t crashing_stack_bottom; + int crashing_lwpid; + + FindCrashLwpContext() : + lwp_lister(NULL), + crashing_stack_bottom(0UL), + crashing_lwpid(-1) { + } +}; + +// Callback for list lwps. +// It will compare the stack bottom of the provided lwp with the stack +// bottom of the crashed lwp, it they are eqaul, this lwp is the one +// who crashed. +bool IsLwpCrashedCallback(lwpstatus_t *lsp, void *context) { + FindCrashLwpContext *crashing_context = + static_cast(context); + const SolarisLwp *lwp_lister = crashing_context->lwp_lister; + const prgregset_t *gregs = &(lsp->pr_reg); +#if TARGET_CPU_SPARC + uintptr_t last_ebp = (*gregs)[R_FP]; +#elif TARGET_CPU_X86 + uintptr_t last_ebp = (*gregs)[EBP]; +#endif + uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_ebp); + if (stack_bottom > last_ebp && + stack_bottom == crashing_context->crashing_stack_bottom) { + // Got it. Stop iteration. + crashing_context->crashing_lwpid = lsp->pr_lwpid; + return false; + } + + return true; +} + +// Find the crashing lwpid. +// This is done based on stack bottom comparing. +int FindCrashingLwp(uintptr_t crashing_stack_bottom, + int requester_pid, + const SolarisLwp *lwp_lister) { + FindCrashLwpContext context; + context.lwp_lister = lwp_lister; + context.crashing_stack_bottom = crashing_stack_bottom; + CallbackParam callback_param(IsLwpCrashedCallback, + &context); + lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param); + return context.crashing_lwpid; +} + +bool WriteLwpStack(const SolarisLwp *lwp_lister, + uintptr_t last_esp, + UntypedMDRVA *memory, + MDMemoryDescriptor *loc) { + uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_esp); + if (stack_bottom >= last_esp) { + int size = stack_bottom - last_esp; + if (size > 0) { + if (!memory->Allocate(size)) + return false; + memory->Copy(reinterpret_cast(last_esp), size); + loc->start_of_memory_range = last_esp; + loc->memory = memory->location(); + } + return true; + } + return false; +} + +#if TARGET_CPU_SPARC +bool WriteContext(MDRawContextSPARC *context, ucontext_t *sig_ctx) { + assert(sig_ctx != NULL); + int* regs = sig_ctx->uc_mcontext.gregs; + context->context_flags = MD_CONTEXT_SPARC_FULL; + + context->ccr = (unsigned int)(regs[0]); + context->pc = (unsigned int)(regs[REG_PC]); + context->npc = (unsigned int)(regs[REG_nPC]); + context->y = (unsigned int)(regs[REG_Y]); + context->asi = (unsigned int)(regs[19]); + context->fprs = (unsigned int)(regs[20]); + + for ( int i = 0 ; i < 32; ++i ) { + context->g_r[i] = 0; + } + + for ( int i = 1 ; i < 16; ++i ) { + context->g_r[i] = (uintptr_t)(sig_ctx->uc_mcontext.gregs[i + 3]); + } + context->g_r[30] = (uintptr_t)(((struct frame *)context->g_r[14])->fr_savfp); + + return true; +} + +bool WriteContext(MDRawContextSPARC *context, prgregset_t regs, + prfpregset_t *fp_regs) { + if (!context || !regs) + return false; + + context->context_flags = MD_CONTEXT_SPARC_FULL; + + context->ccr = (uintptr_t)(regs[32]); + context->pc = (uintptr_t)(regs[R_PC]); + context->npc = (uintptr_t)(regs[R_nPC]); + context->y = (uintptr_t)(regs[R_Y]); + context->asi = (uintptr_t)(regs[36]); + context->fprs = (uintptr_t)(regs[37]); + for ( int i = 0 ; i < 32 ; ++i ){ + context->g_r[i] = (uintptr_t)(regs[i]); + } + + return true; +} +#elif TARGET_CPU_X86 +bool WriteContext(MDRawContextX86 *context, prgregset_t regs, + prfpregset_t *fp_regs) { + if (!context || !regs) + return false; + + context->context_flags = MD_CONTEXT_X86_FULL; + + context->cs = regs[CS]; + context->ds = regs[DS]; + context->es = regs[ES]; + context->fs = regs[FS]; + context->gs = regs[GS]; + context->ss = regs[SS]; + context->edi = regs[EDI]; + context->esi = regs[ESI]; + context->ebx = regs[EBX]; + context->edx = regs[EDX]; + context->ecx = regs[ECX]; + context->eax = regs[EAX]; + context->ebp = regs[EBP]; + context->eip = regs[EIP]; + context->esp = regs[UESP]; + context->eflags = regs[EFL]; + + return true; +} +#endif /* TARGET_CPU_XXX */ + +// Write information about a crashed Lwp. +// When a lwp crash, kernel will write something on the stack for processing +// signal. This makes the current stack not reliable, and our stack walker +// won't figure out the whole call stack for this. So we write the stack at the +// time of the crash into the minidump file, not the current stack. +bool WriteCrashedLwpStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + const lwpstatus_t *lsp, + MDRawThread *lwp) { + assert(writer_args->sig_ctx != NULL); + + lwp->thread_id = lsp->pr_lwpid; + +#if TARGET_CPU_SPARC + UntypedMDRVA memory(minidump_writer); + if (!WriteLwpStack(writer_args->lwp_lister, + writer_args->sig_ctx->uc_mcontext.gregs[REG_O6], + &memory, + &lwp->stack)) + return false; + + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + lwp->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextSPARC)); + return WriteContext(context.get(), writer_args->sig_ctx); +#elif TARGET_CPU_X86 + UntypedMDRVA memory(minidump_writer); + if (!WriteLwpStack(writer_args->lwp_lister, + writer_args->sig_ctx->uc_mcontext.gregs[UESP], + &memory, + &lwp->stack)) + return false; + + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + lwp->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); + return WriteContext(context.get(), + (int *)&writer_args->sig_ctx->uc_mcontext.gregs, + &writer_args->sig_ctx->uc_mcontext.fpregs); +#endif +} + +bool WriteLwpStream(MinidumpFileWriter *minidump_writer, + const SolarisLwp *lwp_lister, + const lwpstatus_t *lsp, MDRawThread *lwp) { + prfpregset_t fp_regs = lsp->pr_fpreg; + const prgregset_t *gregs = &(lsp->pr_reg); + UntypedMDRVA memory(minidump_writer); +#if TARGET_CPU_SPARC + if (!WriteLwpStack(lwp_lister, + (*gregs)[R_SP], + &memory, + &lwp->stack)) + return false; + + // Write context + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + // should be the thread_id + lwp->thread_id = lsp->pr_lwpid; + lwp->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextSPARC)); +#elif TARGET_CPU_X86 + if (!WriteLwpStack(lwp_lister, + (*gregs)[UESP], + &memory, + &lwp->stack)) + return false; + + // Write context + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + // should be the thread_id + lwp->thread_id = lsp->pr_lwpid; + lwp->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); +#endif /* TARGET_CPU_XXX */ + return WriteContext(context.get(), (int *)gregs, &fp_regs); +} + +bool WriteCPUInformation(MDRawSystemInfo *sys_info) { + struct utsname uts; + char *major, *minor, *build; + + sys_info->number_of_processors = sysconf(_SC_NPROCESSORS_CONF); + sys_info->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; + if (uname(&uts) != -1) { + // Match "i86pc" as X86 architecture. + if (strcmp(uts.machine, "i86pc") == 0) + sys_info->processor_architecture = MD_CPU_ARCHITECTURE_X86; + else if (strcmp(uts.machine, "sun4u") == 0) + sys_info->processor_architecture = MD_CPU_ARCHITECTURE_SPARC; + } + + major = uts.release; + minor = strchr(major, '.'); + *minor = '\0'; + ++minor; + sys_info->major_version = atoi(major); + sys_info->minor_version = atoi(minor); + + build = strchr(uts.version, '_'); + ++build; + sys_info->build_number = atoi(build); + + return true; +} + +bool WriteOSInformation(MinidumpFileWriter *minidump_writer, + MDRawSystemInfo *sys_info) { + sys_info->platform_id = MD_OS_SOLARIS; + + struct utsname uts; + if (uname(&uts) != -1) { + char os_version[512]; + size_t space_left = sizeof(os_version); + memset(os_version, 0, space_left); + const char *os_info_table[] = { + uts.sysname, + uts.release, + uts.version, + uts.machine, + "OpenSolaris", + NULL + }; + for (const char **cur_os_info = os_info_table; + *cur_os_info != NULL; + ++cur_os_info) { + if (cur_os_info != os_info_table && space_left > 1) { + strcat(os_version, " "); + --space_left; + } + if (space_left > strlen(*cur_os_info)) { + strcat(os_version, *cur_os_info); + space_left -= strlen(*cur_os_info); + } else { + break; + } + } + + MDLocationDescriptor location; + if (!minidump_writer->WriteString(os_version, 0, &location)) + return false; + sys_info->csd_version_rva = location.rva; + } + return true; +} + +// Callback context for get writting lwp information. +struct LwpInfoCallbackCtx { + MinidumpFileWriter *minidump_writer; + const WriterArgument *writer_args; + TypedMDRVA *list; + int lwp_index; +}; + +bool LwpInformationCallback(lwpstatus_t *lsp, void *context) { + bool success = true; + LwpInfoCallbackCtx *callback_context = + static_cast(context); + + // The current lwp is the one to handle the crash. Ignore it. + if (lsp->pr_lwpid != pthread_self()) { + LwpInfoCallbackCtx *callback_context = + static_cast(context); + MDRawThread lwp; + memset(&lwp, 0, sizeof(MDRawThread)); + + if (lsp->pr_lwpid != callback_context->writer_args->crashed_lwpid || + callback_context->writer_args->sig_ctx == NULL) { + success = WriteLwpStream(callback_context->minidump_writer, + callback_context->writer_args->lwp_lister, + lsp, &lwp); + } else { + success = WriteCrashedLwpStream(callback_context->minidump_writer, + callback_context->writer_args, + lsp, &lwp); + } + if (success) { + callback_context->list->CopyIndexAfterObject( + callback_context->lwp_index++, + &lwp, sizeof(MDRawThread)); + } + } + + return success; +} + +bool WriteLwpListStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + // Get the lwp information. + const SolarisLwp *lwp_lister = writer_args->lwp_lister; + int lwp_count = lwp_lister->GetLwpCount(); + if (lwp_count < 0) + return false; + TypedMDRVA list(minidump_writer); + if (!list.AllocateObjectAndArray(lwp_count - 1, sizeof(MDRawThread))) + return false; + dir->stream_type = MD_THREAD_LIST_STREAM; + dir->location = list.location(); + list.get()->number_of_threads = lwp_count - 1; + + LwpInfoCallbackCtx context; + context.minidump_writer = minidump_writer; + context.writer_args = writer_args; + context.list = &list; + context.lwp_index = 0; + CallbackParam callback_param(LwpInformationCallback, + &context); + int written = + lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param); + return written == lwp_count; +} + +bool WriteCVRecord(MinidumpFileWriter *minidump_writer, + MDRawModule *module, + const char *module_path, + char *realname) { + TypedMDRVA cv(minidump_writer); + + char path[PATH_MAX]; + const char *module_name = module_path ? module_path : ""; + snprintf(path, sizeof(path), "/proc/self/object/%s", module_name); + + size_t module_name_length = strlen(realname); + if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t))) + return false; + if (!cv.CopyIndexAfterObject(0, realname, module_name_length)) + return false; + + module->cv_record = cv.location(); + MDCVInfoPDB70 *cv_ptr = cv.get(); + memset(cv_ptr, 0, sizeof(MDCVInfoPDB70)); + cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE; + cv_ptr->age = 0; + + // Get the module identifier + FileID file_id(path); + unsigned char identifier[16]; + + if (file_id.ElfFileIdentifier(identifier)) { + cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 | + (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 | + (uint32_t)identifier[3]; + cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5]; + cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7]; + cv_ptr->signature.data4[0] = identifier[8]; + cv_ptr->signature.data4[1] = identifier[9]; + cv_ptr->signature.data4[2] = identifier[10]; + cv_ptr->signature.data4[3] = identifier[11]; + cv_ptr->signature.data4[4] = identifier[12]; + cv_ptr->signature.data4[5] = identifier[13]; + cv_ptr->signature.data4[6] = identifier[14]; + cv_ptr->signature.data4[7] = identifier[15]; + } + return true; +} + +struct ModuleInfoCallbackCtx { + MinidumpFileWriter *minidump_writer; + const WriterArgument *writer_args; + TypedMDRVA *list; + int module_index; +}; + +bool ModuleInfoCallback(const ModuleInfo &module_info, void *context) { + ModuleInfoCallbackCtx *callback_context = + static_cast(context); + // Skip those modules without name, or those that are not modules. + if (strlen(module_info.name) == 0) + return true; + + MDRawModule module; + memset(&module, 0, sizeof(module)); + MDLocationDescriptor loc; + char path[PATH_MAX]; + char buf[PATH_MAX]; + char *realname; + int count; + + snprintf(path, sizeof (path), "/proc/self/path/%s", module_info.name); + if ((count = readlink(path, buf, PATH_MAX)) < 0) + return false; + buf[count] = '\0'; + + if ((realname = strrchr(buf, '/')) == NULL) + return false; + realname++; + + if (!callback_context->minidump_writer->WriteString(realname, 0, &loc)) + return false; + + module.base_of_image = (u_int64_t)module_info.start_addr; + module.size_of_image = module_info.size; + module.module_name_rva = loc.rva; + + if (!WriteCVRecord(callback_context->minidump_writer, &module, + module_info.name, realname)) + return false; + + callback_context->list->CopyIndexAfterObject( + callback_context->module_index++, &module, MD_MODULE_SIZE); + return true; +} + +bool WriteModuleListStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA list(minidump_writer); + int module_count = writer_args->lwp_lister->GetModuleCount(); + + if (module_count <= 0 || + !list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE)) { + return false; + } + + dir->stream_type = MD_MODULE_LIST_STREAM; + dir->location = list.location(); + list.get()->number_of_modules = module_count; + ModuleInfoCallbackCtx context; + context.minidump_writer = minidump_writer; + context.writer_args = writer_args; + context.list = &list; + context.module_index = 0; + CallbackParam callback(ModuleInfoCallback, &context); + return writer_args->lwp_lister->ListModules(&callback) == module_count; +} + +bool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA sys_info(minidump_writer); + + if (!sys_info.Allocate()) + return false; + + dir->stream_type = MD_SYSTEM_INFO_STREAM; + dir->location = sys_info.location(); + + return WriteCPUInformation(sys_info.get()) && + WriteOSInformation(minidump_writer, sys_info.get()); +} + +bool WriteExceptionStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + // This happenes when this is not a crash, but a requested dump. + if (writer_args->sig_ctx == NULL) + return false; + + TypedMDRVA exception(minidump_writer); + if (!exception.Allocate()) + return false; + + dir->stream_type = MD_EXCEPTION_STREAM; + dir->location = exception.location(); + exception.get()->thread_id = writer_args->crashed_lwpid; + exception.get()->exception_record.exception_code = writer_args->signo; + exception.get()->exception_record.exception_flags = 0; + +#if TARGET_CPU_SPARC + if (writer_args->sig_ctx != NULL) { + exception.get()->exception_record.exception_address = + writer_args->sig_ctx->uc_mcontext.gregs[REG_PC]; + } else { + return true; + } + + // Write context of the exception. + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + exception.get()->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextSPARC)); + return WriteContext(context.get(), writer_args->sig_ctx); +#elif TARGET_CPU_X86 + if (writer_args->sig_ctx != NULL) { + exception.get()->exception_record.exception_address = + writer_args->sig_ctx->uc_mcontext.gregs[EIP]; + } else { + return true; + } + + // Write context of the exception. + TypedMDRVA context(minidump_writer); + if (!context.Allocate()) + return false; + exception.get()->thread_context = context.location(); + memset(context.get(), 0, sizeof(MDRawContextX86)); + return WriteContext(context.get(), + (int *)&writer_args->sig_ctx->uc_mcontext.gregs, + NULL); +#endif +} + +bool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA info(minidump_writer); + + if (!info.Allocate()) + return false; + + dir->stream_type = MD_MISC_INFO_STREAM; + dir->location = info.location(); + info.get()->size_of_info = sizeof(MDRawMiscInfo); + info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID; + info.get()->process_id = writer_args->requester_pid; + + return true; +} + +bool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer, + const WriterArgument *writer_args, + MDRawDirectory *dir) { + TypedMDRVA info(minidump_writer); + + if (!info.Allocate()) + return false; + + dir->stream_type = MD_BREAKPAD_INFO_STREAM; + dir->location = info.location(); + + info.get()->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; + info.get()->dump_thread_id = getpid(); + info.get()->requesting_thread_id = writer_args->requester_pid; + return true; +} + +class AutoLwpResumer { + public: + AutoLwpResumer(SolarisLwp *lwp) : lwp_(lwp) {} + ~AutoLwpResumer() { lwp_->ControlAllLwps(false); } + private: + SolarisLwp *lwp_; +}; + +// Prototype of writer functions. +typedef bool (*WriteStreamFN)(MinidumpFileWriter *, + const WriterArgument *, + MDRawDirectory *); + +// Function table to writer a full minidump. +const WriteStreamFN writers[] = { + WriteLwpListStream, + WriteModuleListStream, + WriteSystemInfoStream, + WriteExceptionStream, + WriteMiscInfoStream, + WriteBreakpadInfoStream, +}; + +// Will call each writer function in the writers table. +//void* MinidumpGenerator::Write(void *argument) { +void* Write(void *argument) { + WriterArgument *writer_args = static_cast(argument); + + if (!writer_args->lwp_lister->ControlAllLwps(true)) + return NULL; + + AutoLwpResumer lwpResumer(writer_args->lwp_lister); + + if (writer_args->sighandler_ebp != 0 && + writer_args->lwp_lister->FindSigContext(writer_args->sighandler_ebp, + &writer_args->sig_ctx)) { + writer_args->crashed_stack_bottom = + writer_args->lwp_lister->GetLwpStackBottom( +#if TARGET_CPU_SPARC + writer_args->sig_ctx->uc_mcontext.gregs[REG_O6] +#elif TARGET_CPU_X86 + writer_args->sig_ctx->uc_mcontext.gregs[UESP] +#endif + ); + + int crashed_lwpid = FindCrashingLwp(writer_args->crashed_stack_bottom, + writer_args->requester_pid, + writer_args->lwp_lister); + if (crashed_lwpid > 0) + writer_args->crashed_lwpid = crashed_lwpid; + } + + MinidumpFileWriter *minidump_writer = writer_args->minidump_writer; + TypedMDRVA header(minidump_writer); + TypedMDRVA dir(minidump_writer); + if (!header.Allocate()) + return 0; + + int writer_count = sizeof(writers) / sizeof(writers[0]); + // Need directory space for all writers. + if (!dir.AllocateArray(writer_count)) + return 0; + header.get()->signature = MD_HEADER_SIGNATURE; + header.get()->version = MD_HEADER_VERSION; + header.get()->time_date_stamp = time(NULL); + header.get()->stream_count = writer_count; + header.get()->stream_directory_rva = dir.position(); + + int dir_index = 0; + MDRawDirectory local_dir; + for (int i = 0; i < writer_count; ++i) { + if ((*writers[i])(minidump_writer, writer_args, &local_dir)) + dir.CopyIndex(dir_index++, &local_dir); + } + + return 0; +} + +} // namespace + +namespace google_breakpad { + +MinidumpGenerator::MinidumpGenerator() { +} + +MinidumpGenerator::~MinidumpGenerator() { +} + +// Write minidump into file. +// It runs in a different thread from the crashing thread. +bool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname, + int signo, + uintptr_t sighandler_ebp, + ucontext_t **sig_ctx) const { + // The exception handler thread. + pthread_t handler_thread; + + assert(file_pathname != NULL); + + if (file_pathname == NULL) + return false; + + MinidumpFileWriter minidump_writer; + if (minidump_writer.Open(file_pathname)) { + WriterArgument argument; + memset(&argument, 0, sizeof(argument)); + SolarisLwp lwp_lister(getpid()); + argument.lwp_lister = &lwp_lister; + argument.minidump_writer = &minidump_writer; + argument.requester_pid = getpid(); + argument.crashed_lwpid = pthread_self(); + argument.signo = signo; + argument.sighandler_ebp = sighandler_ebp; + argument.sig_ctx = NULL; + + pthread_create(&handler_thread, NULL, Write, (void *)&argument); + pthread_join(handler_thread, NULL); + return true; + } + + return false; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.h b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.h new file mode 100644 index 00000000..882f9e1d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_generator.h @@ -0,0 +1,70 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#ifndef CLIENT_SOLARIS_HANDLER_MINIDUMP_GENERATOR_H__ +#define CLIENT_SOLARIS_HANDLER_MINIDUMP_GENERATOR_H__ + +#include + +#include "client/minidump_file_writer.h" +#include "client/solaris/handler/solaris_lwp.h" +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// +// MinidumpGenerator +// +// A minidump generator should be created before any exception happen. +// +class MinidumpGenerator { + // Callback run for writing lwp information in the process. + friend bool LwpInformationCallback(lwpstatus_t *lsp, void *context); + + // Callback run for writing module information in the process. + friend bool ModuleInfoCallback(const ModuleInfo &module_info, void *context); + + public: + MinidumpGenerator(); + + ~MinidumpGenerator(); + + // Write minidump. + bool WriteMinidumpToFile(const char *file_pathname, + int signo, + uintptr_t sighandler_ebp, + ucontext_t **sig_ctx) const; +}; + +} // namespace google_breakpad + +#endif // CLIENT_SOLARIS_HANDLER_MINIDUMP_GENERATOR_H_ diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_test.cc b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_test.cc new file mode 100644 index 00000000..33302d86 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/minidump_test.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include + +#include "client/minidump_file_writer.h" +#include "client/solaris/handler/minidump_generator.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), "./minidump_test.out"); + fprintf(stdout, "Writing %s\n", buffer); + + md.WriteMinidumpToFile(buffer, 0, 0, NULL); + 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; +} diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.cc b/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.cc new file mode 100644 index 00000000..0148997a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.cc @@ -0,0 +1,436 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "client/solaris/handler/solaris_lwp.h" +#include "common/solaris/message_output.h" + +using namespace google_breakpad; + +// This unamed namespace contains helper function. +namespace { + +uintptr_t stack_base_address = 0; +static const int HEADER_MAX = 2000; +static const int MAP_MAX = 1000; + +// Context information for the callbacks when validating address by listing +// modules. +struct AddressValidatingContext { + uintptr_t address; + bool is_mapped; + + AddressValidatingContext() : address(0UL), is_mapped(false) { + } +}; + +// Convert from string to int. +static bool LocalAtoi(char *s, int *r) { + assert(s != NULL); + assert(r != NULL); + char *endptr = NULL; + int ret = strtol(s, &endptr, 10); + if (endptr == s) + return false; + *r = ret; + return true; +} + +// Callback invoked for each mapped module. +// It uses the module's adderss range to validate the address. +static bool AddressNotInModuleCallback(const ModuleInfo &module_info, + void *context) { + AddressValidatingContext *addr = + reinterpret_cast(context); + if (addr->is_mapped = ((module_info.start_addr > 0) && + (addr->address >= module_info.start_addr) && + (addr->address <= module_info.start_addr + + module_info.size))) { + stack_base_address = module_info.start_addr + module_info.size; + } + + return !addr->is_mapped; +} + +static int IterateLwpAll(int pid, + CallbackParam *callback_param) { + char lwp_path[40]; + DIR *dir; + int count = 0; + + snprintf(lwp_path, sizeof (lwp_path), "/proc/%d/lwp", (int)pid); + if ((dir = opendir(lwp_path)) == NULL) + return -1; + + struct dirent *entry = NULL; + while ((entry = readdir(dir)) != NULL) { + if ((strcmp(entry->d_name, ".") != 0) && + (strcmp(entry->d_name, "..") != 0)) { + int lwpid = 0; + int last_pid = 0; + if (LocalAtoi(entry->d_name, &lwpid) && last_pid != lwpid) { + last_pid = lwpid; + ++count; + if (callback_param && + !(callback_param->call_back)(lwpid, callback_param->context)) { + break; + } + } + } + } + + closedir(dir); + return count; +} + +#if defined(__i386) && !defined(NO_FRAME_POINTER) +void *GetNextFrame(void **last_ebp) { + void *sp = *last_ebp; + if ((unsigned long)sp == (unsigned long)last_ebp) + return NULL; + if ((unsigned long)sp & (sizeof(void *) - 1)) + return NULL; + if ((unsigned long)sp - (unsigned long)last_ebp > 100000) + return NULL; + return sp; +} +#elif defined(__sparc) +void *GetNextFrame(void *last_ebp) { + return reinterpret_cast(last_ebp)->fr_savfp; +} +#else +void *GetNextFrame(void **last_ebp) { + return reinterpret_cast(last_ebp); +} +#endif + + +class AutoCloser { + public: + AutoCloser(int fd) : fd_(fd) {} + ~AutoCloser() { if (fd_) close(fd_); } + private: + int fd_; +}; + +// Control the execution of the lwp. +// Suspend/Resume lwp based on the value of context. +static bool ControlLwp(int lwpid, void *context) { + // The current thread is the one to handle the crash. Ignore it. + if (lwpid != pthread_self()) { + int ctlfd; + char procname[PATH_MAX]; + bool suspend = *(bool *)context; + + // Open the /proc/$pid/lwp/$lwpid/lwpctl files + snprintf(procname, sizeof (procname), "/proc/self/lwp/%d/lwpctl", lwpid); + + if ((ctlfd = open(procname, O_WRONLY|O_EXCL)) < 0) { + print_message2(2, "failed to open %s in ControlLwp\n", procname); + return false; + } + + AutoCloser autocloser(ctlfd); + + long ctl[2]; + ctl[0] = suspend ? PCSTOP : PCRUN; + ctl[1] = 0; + if (write(ctlfd, ctl, sizeof (ctl)) != sizeof (ctl)) { + print_message2(2, "failed in lwp %d\n", lwpid); + return false; + } + } + + return true; +} + +/* + * Utility function to read the contents of a file that contains a + * prheader_t at the start (/proc/$pid/lstatus or /proc/$pid/lpsinfo). + * Return true on success. + */ +static bool read_lfile(int pid, const char *lname, prheader_t *lhp) { + char lpath[PATH_MAX]; + struct stat statb; + int fd; + size_t size; + + snprintf(lpath, sizeof (lpath), "/proc/%d/%s", pid, lname); + if ((fd = open(lpath, O_RDONLY)) < 0) { + print_message2(2, "failed to open %s in read_lfile\n", lpath); + return false; + } + + AutoCloser autocloser(fd); + + if (fstat(fd, &statb) != 0) + return false; + + size = statb.st_size; + if ((size / sizeof (prheader_t)) + 32 > HEADER_MAX) { + print_message1(2, "map size overflow\n"); + return false; + } + + if (pread(fd, lhp, size, 0) <= sizeof (prheader_t)) + return false; + + return true; +} + +} // namespace + +namespace google_breakpad { + +SolarisLwp::SolarisLwp(int pid) : pid_(pid) { +} + +SolarisLwp::~SolarisLwp() { +} + +int SolarisLwp::ControlAllLwps(bool suspend) { + CallbackParam callback_param(ControlLwp, &suspend); + return IterateLwpAll(pid_, &callback_param); +} + +int SolarisLwp::GetLwpCount() const { + return IterateLwpAll(pid_, NULL); +} + +int SolarisLwp::Lwp_iter_all(int pid, + CallbackParam *callback_param) const { + lwpstatus_t *Lsp; + lwpstatus_t *sp; + prheader_t lphp[HEADER_MAX]; + prheader_t lhp[HEADER_MAX]; + prheader_t *Lphp = lphp; + prheader_t *Lhp = lhp; + lwpsinfo_t *Lpsp; + long nstat; + long ninfo; + int rv = 0; + + /* + * The /proc/pid/lstatus file has the array of lwpstatus_t's and the + * /proc/pid/lpsinfo file has the array of lwpsinfo_t's. + */ + if (read_lfile(pid, "lstatus", Lhp) == NULL) + return -1; + if (read_lfile(pid, "lpsinfo", Lphp) == NULL) { + return -1; + } + + Lsp = (lwpstatus_t *)(uintptr_t)(Lhp + 1); + Lpsp = (lwpsinfo_t *)(uintptr_t)(Lphp + 1); + + for (ninfo = Lphp->pr_nent; ninfo != 0; --ninfo) { + if (Lpsp->pr_sname != 'Z') { + sp = Lsp; + Lsp = (lwpstatus_t *)((uintptr_t)Lsp + Lhp->pr_entsize); + } else { + sp = NULL; + } + if (callback_param && + !(callback_param->call_back)(sp, callback_param->context)) + break; + ++rv; + Lpsp = (lwpsinfo_t *)((uintptr_t)Lpsp + Lphp->pr_entsize); + } + + return rv; +} + +uintptr_t SolarisLwp::GetLwpStackBottom(uintptr_t current_esp) const { + AddressValidatingContext addr; + addr.address = current_esp; + CallbackParam callback_param(AddressNotInModuleCallback, + &addr); + ListModules(&callback_param); + return stack_base_address; +} + +int SolarisLwp::GetModuleCount() const { + return ListModules(NULL); +} + +int SolarisLwp::ListModules( + CallbackParam *callback_param) const { + const char *maps_path = "/proc/self/map"; + struct stat status; + int fd = 0, num; + prmap_t map_array[MAP_MAX]; + prmap_t *maps = map_array; + size_t size; + + if ((fd = open(maps_path, O_RDONLY)) == -1) { + print_message2(2, "failed to open %s in ListModules\n", maps_path); + return -1; + } + + AutoCloser autocloser(fd); + + if (fstat(fd, &status)) + return -1; + + /* + * Determine number of mappings, this value must be + * larger than the actual module count + */ + size = status.st_size; + if ((num = (int)(size / sizeof (prmap_t))) > MAP_MAX) { + print_message1(2, "map size overflow\n"); + return -1; + } + + if (read(fd, (void *)maps, size) < 0) { + print_message2(2, "failed to read %d\n", fd); + return -1; + } + + prmap_t *_maps; + int _num; + int module_count = 0; + + /* + * Scan each mapping - note it is assummed that the mappings are + * presented in order. We fill holes between mappings. On intel + * the last mapping is usually the data segment of ld.so.1, after + * this comes a red zone into which non-fixed mapping won't get + * place. Thus we can simply bail from the loop after seeing the + * last mapping. + */ + for (_num = 0, _maps = maps; _num < num; ++_num, ++_maps) { + ModuleInfo module; + char *name = _maps->pr_mapname; + + memset(&module, 0, sizeof (module)); + module.start_addr = _maps->pr_vaddr; + module.size = _maps->pr_size; + if (strlen(name) > 0) { + int objectfd = 0; + char path[PATH_MAX]; + char buf[SELFMAG]; + + snprintf(path, sizeof (path), "/proc/self/object/%s", name); + if ((objectfd = open(path, O_RDONLY)) < 0) { + print_message1(2, "can't open module file\n"); + continue; + } + + AutoCloser autocloser(objectfd); + + if (read(objectfd, buf, SELFMAG) != SELFMAG) { + print_message1(2, "can't read module file\n"); + continue; + } + if (buf[0] != ELFMAG0 || buf[1] != ELFMAG1 || + buf[2] != ELFMAG2 || buf[3] != ELFMAG3) { + continue; + } + + strncpy(module.name, name, sizeof (module.name) - 1); + ++module_count; + } + if (callback_param && + (!callback_param->call_back(module, callback_param->context))) { + break; + } + } + + return module_count; +} + +// Check if the address is a valid virtual address. +// If the address is in any of the mapped modules, we take it as valid. +// Otherwise it is invalid. +bool SolarisLwp::IsAddressMapped(uintptr_t address) const { + AddressValidatingContext addr; + addr.address = address; + CallbackParam callback_param(AddressNotInModuleCallback, + &addr); + ListModules(&callback_param); + return addr.is_mapped; +} + +// We're looking for a ucontext_t as the second parameter +// to a signal handler function call. Luckily, the ucontext_t +// has an ebp(fp on SPARC) member which should match the ebp(fp) +// pointed to by the ebp(fp) of the signal handler frame. +// The Solaris stack looks like this: +// http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81 +bool SolarisLwp::FindSigContext(uintptr_t sighandler_ebp, + ucontext_t **sig_ctx) { + uintptr_t previous_ebp; + uintptr_t sig_ebp; + const int MAX_STACK_DEPTH = 50; + int depth_counter = 0; + + do { +#if TARGET_CPU_SPARC + previous_ebp = reinterpret_cast(GetNextFrame( + reinterpret_cast(sighandler_ebp))); + *sig_ctx = reinterpret_cast(sighandler_ebp + sizeof (struct frame)); + uintptr_t sig_esp = (*sig_ctx)->uc_mcontext.gregs[REG_O6]; + if (sig_esp < previous_ebp && sig_esp > sighandler_ebp) + sig_ebp = (uintptr_t)(((struct frame *)sig_esp)->fr_savfp); + +#elif TARGET_CPU_X86 + previous_ebp = reinterpret_cast(GetNextFrame( + reinterpret_cast(sighandler_ebp))); + *sig_ctx = reinterpret_cast(sighandler_ebp + sizeof (struct frame) + + 3 * sizeof(uintptr_t)); + sig_ebp = (*sig_ctx)->uc_mcontext.gregs[EBP]; +#endif + sighandler_ebp = previous_ebp; + depth_counter++; + } while(previous_ebp != sig_ebp && sighandler_ebp != 0 && + IsAddressMapped(sighandler_ebp) && depth_counter < MAX_STACK_DEPTH); + + return previous_ebp == sig_ebp && previous_ebp != 0; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.h b/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.h new file mode 100644 index 00000000..0914cfcd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/solaris/handler/solaris_lwp.h @@ -0,0 +1,160 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#ifndef CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ +#define CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ + +#if defined(sparc) || defined(__sparc) +#define TARGET_CPU_SPARC 1 +#elif defined(i386) || defined(__i386) +#define TARGET_CPU_X86 1 +#else +#error "cannot determine cpu type" +#endif + +#include +#include +#include +#include + +#ifndef _KERNEL +#define _KERNEL +#define MUST_UNDEF_KERNEL +#endif // _KERNEL +#include +#ifdef MUST_UNDEF_KERNEL +#undef _KERNEL +#undef MUST_UNDEF_KERNEL +#endif // MUST_UNDEF_KERNEL + +namespace google_breakpad { + +// Max module path name length. +static const int kMaxModuleNameLength = 256; + +// Holding infomaton about a module in the process. +struct ModuleInfo { + char name[kMaxModuleNameLength]; + uintptr_t start_addr; + int size; +}; + +// A callback to run when getting a lwp in the process. +// Return true will go on to the next lwp while return false will stop the +// iteration. +typedef bool (*LwpCallback)(lwpstatus_t* lsp, void *context); + +// A callback to run when a new module is found in the process. +// Return true will go on to the next module while return false will stop the +// iteration. +typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context); + +// A callback to run when getting a lwpid in the process. +// Return true will go on to the next lwp while return false will stop the +// iteration. +typedef bool (*LwpidCallback)(int lwpid, void *context); + +// Holding the callback information. +template +struct CallbackParam { + // Callback function address. + CallbackFunc call_back; + // Callback context; + void *context; + + CallbackParam() : call_back(NULL), context(NULL) { + } + + CallbackParam(CallbackFunc func, void *func_context) : + call_back(func), context(func_context) { + } +}; + +/////////////////////////////////////////////////////////////////////////////// + +// +// SolarisLwp +// +// Provides handy support for operation on Solaris lwps. +// It uses proc file system to get lwp information. +// +// TODO(Alfred): Currently it only supports x86. Add SPARC support. +// +class SolarisLwp { + public: + // Create a SolarisLwp instance to list all the lwps in a process. + explicit SolarisLwp(int pid); + ~SolarisLwp(); + + int getpid() const { return this->pid_; } + + // Control all the lwps in the process. + // Return the number of suspended/resumed lwps in the process. + // Return -1 means failed to control lwps. + int ControlAllLwps(bool suspend); + + // Get the count of lwps in the process. + // Return -1 means error. + int GetLwpCount() const; + + // Iterate the lwps of process. + // Whenever there is a lwp found, the callback will be invoked to process + // the information. + // Return the callback return value or -1 on error. + int Lwp_iter_all(int pid, CallbackParam *callback_param) const; + + // Get the module count of the current process. + int GetModuleCount() const; + + // Get the mapped modules in the address space. + // Whenever a module is found, the callback will be invoked to process the + // information. + // Return how may modules are found. + int ListModules(CallbackParam *callback_param) const; + + // Get the bottom of the stack from esp. + uintptr_t GetLwpStackBottom(uintptr_t current_esp) const; + + // Finds a signal context on the stack given the ebp of our signal handler. + bool FindSigContext(uintptr_t sighandler_ebp, ucontext_t **sig_ctx); + + private: + // Check if the address is a valid virtual address. + bool IsAddressMapped(uintptr_t address) const; + + private: + // The pid of the process we are listing lwps. + int pid_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/common/auto_critical_section.h b/thirdparty/google-breakpad/r318/src/client/windows/common/auto_critical_section.h new file mode 100644 index 00000000..82c7b7f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/common/auto_critical_section.h @@ -0,0 +1,63 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ +#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ + +#include + +namespace google_breakpad { + +// Automatically enters the critical section in the constructor and leaves +// the critical section in the destructor. +class AutoCriticalSection { + public: + // Creates a new instance with the given critical section object + // and enters the critical section immediately. + explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs) { + assert(cs_); + EnterCriticalSection(cs_); + } + + // Destructor: leaves the critical section. + ~AutoCriticalSection() { + LeaveCriticalSection(cs_); + } + + private: + // Disable copy ctor and operator=. + AutoCriticalSection(const AutoCriticalSection&); + AutoCriticalSection& operator=(const AutoCriticalSection&); + + CRITICAL_SECTION* cs_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/common/ipc_protocol.h b/thirdparty/google-breakpad/r318/src/client/windows/common/ipc_protocol.h new file mode 100644 index 00000000..cba8699c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/common/ipc_protocol.h @@ -0,0 +1,179 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ +#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ + +#include +#include +#include +#include +#include "common/windows/string_utils-inl.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Name/value pair for custom client information. +struct CustomInfoEntry { + // Maximum length for name and value for client custom info. + static const int kNameMaxLength = 64; + static const int kValueMaxLength = 64; + + CustomInfoEntry() { + // Putting name and value in initializer list makes VC++ show warning 4351. + set_name(NULL); + set_value(NULL); + } + + CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) { + set_name(name_arg); + set_value(value_arg); + } + + void set_name(const wchar_t* name_arg) { + if (!name_arg) { + name[0] = L'\0'; + return; + } + WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg); + } + + void set_value(const wchar_t* value_arg) { + if (!value_arg) { + value[0] = L'\0'; + return; + } + + WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg); + } + + void set(const wchar_t* name_arg, const wchar_t* value_arg) { + set_name(name_arg); + set_value(value_arg); + } + + wchar_t name[kNameMaxLength]; + wchar_t value[kValueMaxLength]; +}; + +// Constants for the protocol between client and the server. + +// Tags sent with each message indicating the purpose of +// the message. +enum MessageTag { + MESSAGE_TAG_NONE = 0, + MESSAGE_TAG_REGISTRATION_REQUEST = 1, + MESSAGE_TAG_REGISTRATION_RESPONSE = 2, + MESSAGE_TAG_REGISTRATION_ACK = 3 +}; + +struct CustomClientInfo { + const CustomInfoEntry* entries; + int count; +}; + +// Message structure for IPC between crash client and crash server. +struct ProtocolMessage { + ProtocolMessage() + : tag(MESSAGE_TAG_NONE), + pid(0), + dump_type(MiniDumpNormal), + thread_id(0), + exception_pointers(NULL), + assert_info(NULL), + custom_client_info(), + dump_request_handle(NULL), + dump_generated_handle(NULL), + server_alive_handle(NULL) { + } + + // Creates an instance with the given parameters. + ProtocolMessage(MessageTag arg_tag, + DWORD arg_pid, + MINIDUMP_TYPE arg_dump_type, + DWORD* arg_thread_id, + EXCEPTION_POINTERS** arg_exception_pointers, + MDRawAssertionInfo* arg_assert_info, + const CustomClientInfo& custom_info, + HANDLE arg_dump_request_handle, + HANDLE arg_dump_generated_handle, + HANDLE arg_server_alive) + : tag(arg_tag), + pid(arg_pid), + dump_type(arg_dump_type), + thread_id(arg_thread_id), + exception_pointers(arg_exception_pointers), + assert_info(arg_assert_info), + custom_client_info(custom_info), + dump_request_handle(arg_dump_request_handle), + dump_generated_handle(arg_dump_generated_handle), + server_alive_handle(arg_server_alive) { + } + + // Tag in the message. + MessageTag tag; + + // Process id. + DWORD pid; + + // Dump type requested. + MINIDUMP_TYPE dump_type; + + // Client thread id pointer. + DWORD* thread_id; + + // Exception information. + EXCEPTION_POINTERS** exception_pointers; + + // Assert information in case of an invalid parameter or + // pure call failure. + MDRawAssertionInfo* assert_info; + + // Custom client information. + CustomClientInfo custom_client_info; + + // Handle to signal the crash event. + HANDLE dump_request_handle; + + // Handle to check if server is done generating crash. + HANDLE dump_generated_handle; + + // Handle to a mutex that becomes signaled (WAIT_ABANDONED) + // if server process goes down. + HANDLE server_alive_handle; + + private: + // Disable copy ctor and operator=. + ProtocolMessage(const ProtocolMessage& msg); + ProtocolMessage& operator=(const ProtocolMessage& msg); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/ReadMe.txt b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/ReadMe.txt new file mode 100644 index 00000000..b54d0e11 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/ReadMe.txt @@ -0,0 +1,58 @@ +========================================================================= + State machine transitions for the Crash Generation Server +========================================================================= + +========================================================================= + | + STATE | ACTIONS + | +========================================================================= + ERROR | Clean up resources used to serve clients. + | Always remain in ERROR state. +------------------------------------------------------------------------- + INITIAL | Connect to the pipe asynchronously. + | If connection is successfully queued up asynchronously, + | go into CONNECTING state. + | If connection is done synchronously, go into CONNECTED + | state. + | For any unexpected problems, go into ERROR state. +------------------------------------------------------------------------- + CONNECTING | Get the result of async connection request. + | If I/O is still incomplete, remain in the CONNECTING + | state. + | If connection is complete, go into CONNECTED state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + CONNECTED | Read from the pipe asynchronously. + | If read request is successfully queued up asynchronously, + | go into READING state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + READING | Get the result of async read request. + | If read is done, go into READ_DONE state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + READ_DONE | Register the client, prepare the reply and write the + | reply to the pipe asynchronously. + | If write request is successfully queued up asynchronously, + | go into WRITING state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + WRITING | Get the result of the async write request. + | If write is done, go into WRITE_DONE state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + WRITE_DONE | Read from the pipe asynchronously (for an ACK). + | If read request is successfully queued up asynchonously, + | go into READING_ACK state. + | For any unexpected problems, go into DISCONNECTING state. +------------------------------------------------------------------------- + READING_ACK | Get the result of the async read request. + | If read is done, perform action for successful client + | connection. + | Go into DISCONNECTING state. +------------------------------------------------------------------------- + DISCONNECTING | Disconnect from the pipe, reset the event and go into + | INITIAL state and signal the event again. If anything + | fails, go into ERROR state. +========================================================================= diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.cc b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.cc new file mode 100644 index 00000000..4752c4ae --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.cc @@ -0,0 +1,210 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "client/windows/crash_generation/client_info.h" +#include "client/windows/common/ipc_protocol.h" + +static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime"; + +namespace google_breakpad { + +ClientInfo::ClientInfo(CrashGenerationServer* crash_server, + DWORD pid, + MINIDUMP_TYPE dump_type, + DWORD* thread_id, + EXCEPTION_POINTERS** ex_info, + MDRawAssertionInfo* assert_info, + const CustomClientInfo& custom_client_info) + : crash_server_(crash_server), + pid_(pid), + dump_type_(dump_type), + ex_info_(ex_info), + assert_info_(assert_info), + custom_client_info_(custom_client_info), + thread_id_(thread_id), + process_handle_(NULL), + dump_requested_handle_(NULL), + dump_generated_handle_(NULL), + dump_request_wait_handle_(NULL), + process_exit_wait_handle_(NULL) { + GetSystemTimeAsFileTime(&start_time_); +} + +bool ClientInfo::Initialize() { + process_handle_ = OpenProcess(GENERIC_ALL, FALSE, pid_); + if (!process_handle_) { + return false; + } + + dump_requested_handle_ = CreateEvent(NULL, // Security attributes. + TRUE, // Manual reset. + FALSE, // Initial state. + NULL); // Name. + if (!dump_requested_handle_) { + return false; + } + + dump_generated_handle_ = CreateEvent(NULL, // Security attributes. + TRUE, // Manual reset. + FALSE, // Initial state. + NULL); // Name. + return dump_generated_handle_ != NULL; +} + +ClientInfo::~ClientInfo() { + if (dump_request_wait_handle_) { + // Wait for callbacks that might already be running to finish. + UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE); + } + + if (process_exit_wait_handle_) { + // Wait for the callback that might already be running to finish. + UnregisterWaitEx(process_exit_wait_handle_, INVALID_HANDLE_VALUE); + } + + if (process_handle_) { + CloseHandle(process_handle_); + } + + if (dump_requested_handle_) { + CloseHandle(dump_requested_handle_); + } + + if (dump_generated_handle_) { + CloseHandle(dump_generated_handle_); + } +} + +bool ClientInfo::UnregisterWaits() { + bool success = true; + + if (dump_request_wait_handle_) { + if (!UnregisterWait(dump_request_wait_handle_)) { + success = false; + } else { + dump_request_wait_handle_ = NULL; + } + } + + if (process_exit_wait_handle_) { + if (!UnregisterWait(process_exit_wait_handle_)) { + success = false; + } else { + process_exit_wait_handle_ = NULL; + } + } + + return success; +} + +bool ClientInfo::GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const { + SIZE_T bytes_count = 0; + if (!ReadProcessMemory(process_handle_, + ex_info_, + ex_info, + sizeof(*ex_info), + &bytes_count)) { + return false; + } + + return bytes_count == sizeof(*ex_info); +} + +bool ClientInfo::GetClientThreadId(DWORD* thread_id) const { + SIZE_T bytes_count = 0; + if (!ReadProcessMemory(process_handle_, + thread_id_, + thread_id, + sizeof(*thread_id), + &bytes_count)) { + return false; + } + + return bytes_count == sizeof(*thread_id); +} + +void ClientInfo::SetProcessUptime() { + FILETIME now = {0}; + GetSystemTimeAsFileTime(&now); + + ULARGE_INTEGER time_start; + time_start.HighPart = start_time_.dwHighDateTime; + time_start.LowPart = start_time_.dwLowDateTime; + + ULARGE_INTEGER time_now; + time_now.HighPart = now.dwHighDateTime; + time_now.LowPart = now.dwLowDateTime; + + // Calculate the delay and convert it from 100-nanoseconds to milliseconds. + __int64 delay = (time_now.QuadPart - time_start.QuadPart) / 10 / 1000; + + // Convert it to a string. + wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value; + _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10); +} + +bool ClientInfo::PopulateCustomInfo() { + SIZE_T bytes_count = 0; + SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count; + + // If the scoped array for custom info already has an array, it will be + // the same size as what we need. This is because the number of custom info + // entries is always the same. So allocate memory only if scoped array has + // a NULL pointer. + if (!custom_info_entries_.get()) { + // Allocate an extra entry for reporting uptime for the client process. + custom_info_entries_.reset( + new CustomInfoEntry[custom_client_info_.count + 1]); + // Use the last element in the array for uptime. + custom_info_entries_.get()[custom_client_info_.count].set_name( + kCustomInfoProcessUptimeName); + } + + if (!ReadProcessMemory(process_handle_, + custom_client_info_.entries, + custom_info_entries_.get(), + read_count, + &bytes_count)) { + return false; + } + + SetProcessUptime(); + return (bytes_count != read_count); +} + +CustomClientInfo ClientInfo::GetCustomInfo() const { + CustomClientInfo custom_info; + custom_info.entries = custom_info_entries_.get(); + // Add 1 to the count from the client process to account for extra entry for + // process uptime. + custom_info.count = custom_client_info_.count + 1; + return custom_info; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.h b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.h new file mode 100644 index 00000000..774816fb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/client_info.h @@ -0,0 +1,170 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ + +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +class CrashGenerationServer; + +// Abstraction for a crash client process. +class ClientInfo { + public: + // Creates an instance with the given values. Gets the process + // handle for the given process id and creates necessary event + // objects. + ClientInfo(CrashGenerationServer* crash_server, + DWORD pid, + MINIDUMP_TYPE dump_type, + DWORD* thread_id, + EXCEPTION_POINTERS** ex_info, + MDRawAssertionInfo* assert_info, + const CustomClientInfo& custom_client_info); + + ~ClientInfo(); + + CrashGenerationServer* crash_server() const { return crash_server_; } + DWORD pid() const { return pid_; } + MINIDUMP_TYPE dump_type() const { return dump_type_; } + EXCEPTION_POINTERS** ex_info() const { return ex_info_; } + MDRawAssertionInfo* assert_info() const { return assert_info_; } + DWORD* thread_id() const { return thread_id_; } + HANDLE process_handle() const { return process_handle_; } + HANDLE dump_requested_handle() const { return dump_requested_handle_; } + HANDLE dump_generated_handle() const { return dump_generated_handle_; } + + HANDLE dump_request_wait_handle() const { + return dump_request_wait_handle_; + } + + void set_dump_request_wait_handle(HANDLE value) { + dump_request_wait_handle_ = value; + } + + HANDLE process_exit_wait_handle() const { + return process_exit_wait_handle_; + } + + void set_process_exit_wait_handle(HANDLE value) { + process_exit_wait_handle_ = value; + } + + // Unregister all waits for the client. + bool UnregisterWaits(); + + bool Initialize(); + bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const; + bool GetClientThreadId(DWORD* thread_id) const; + + // Reads the custom information from the client process address space. + bool PopulateCustomInfo(); + + // Returns the client custom information. + CustomClientInfo GetCustomInfo() const; + + private: + // Calcualtes the uptime for the client process, converts it to a string and + // stores it in the last entry of client custom info. + void SetProcessUptime(); + + // Crash generation server. + CrashGenerationServer* crash_server_; + + // Client process ID. + DWORD pid_; + + // Dump type requested by the client. + MINIDUMP_TYPE dump_type_; + + // Address of an EXCEPTION_POINTERS* variable in the client + // process address space that will point to an instance of + // EXCEPTION_POINTERS containing information about crash. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + EXCEPTION_POINTERS** ex_info_; + + // Address of an instance of MDRawAssertionInfo in the client + // process address space that will contain information about + // non-exception related crashes like invalid parameter assertion + // failures and pure calls. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + MDRawAssertionInfo* assert_info_; + + // Custom information about the client. + CustomClientInfo custom_client_info_; + + // Contains the custom client info entries read from the client process + // memory. This will be populated only if the method GetClientCustomInfo + // is called. + scoped_array custom_info_entries_; + + // Address of a variable in the client process address space that + // will contain the thread id of the crashing client thread. + // + // WARNING: Do not dereference these pointers as they are pointers + // in the address space of another process. + DWORD* thread_id_; + + // Client process handle. + HANDLE process_handle_; + + // Dump request event handle. + HANDLE dump_requested_handle_; + + // Dump generated event handle. + HANDLE dump_generated_handle_; + + // Wait handle for dump request event. + HANDLE dump_request_wait_handle_; + + // Wait handle for process exit event. + HANDLE process_exit_wait_handle_; + + // Time when the client process started. It is used to determine the uptime + // for the client process when it signals a crash. + FILETIME start_time_; + + // Disallow copy ctor and operator=. + ClientInfo(const ClientInfo& client_info); + ClientInfo& operator=(const ClientInfo& client_info); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.cc b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.cc new file mode 100644 index 00000000..197807ab --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.cc @@ -0,0 +1,337 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "client/windows/crash_generation/crash_generation_client.h" +#include +#include +#include "client/windows/common/ipc_protocol.h" + +namespace google_breakpad { + +const int kPipeBusyWaitTimeoutMs = 2000; + +#ifdef _DEBUG +const DWORD kWaitForServerTimeoutMs = INFINITE; +#else +const DWORD kWaitForServerTimeoutMs = 15000; +#endif + +const int kPipeConnectMaxAttempts = 2; + +const DWORD kPipeDesiredAccess = FILE_READ_DATA | + FILE_WRITE_DATA | + FILE_WRITE_ATTRIBUTES; + +const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION | + SECURITY_SQOS_PRESENT; + +const DWORD kPipeMode = PIPE_READMODE_MESSAGE; + +const size_t kWaitEventCount = 2; + +// This function is orphan for production code. It can be used +// for debugging to help repro some scenarios like the client +// is slow in writing to the pipe after connecting, the client +// is slow in reading from the pipe after writing, etc. The parameter +// overlapped below is not used and it is present to match the signature +// of this function to TransactNamedPipe Win32 API. Uncomment if needed +// for debugging. +/** +static bool TransactNamedPipeDebugHelper(HANDLE pipe, + const void* in_buffer, + DWORD in_size, + void* out_buffer, + DWORD out_size, + DWORD* bytes_count, + LPOVERLAPPED) { + // Uncomment the next sleep to create a gap before writing + // to pipe. + // Sleep(5000); + + if (!WriteFile(pipe, + in_buffer, + in_size, + bytes_count, + NULL)) { + return false; + } + + // Uncomment the next sleep to create a gap between write + // and read. + // Sleep(5000); + + return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE; +} +**/ + +CrashGenerationClient::CrashGenerationClient( + const wchar_t* pipe_name, + MINIDUMP_TYPE dump_type, + const CustomClientInfo* custom_info) + : pipe_name_(pipe_name), + dump_type_(dump_type), + thread_id_(0), + server_process_id_(0), + crash_event_(NULL), + crash_generated_(NULL), + server_alive_(NULL), + exception_pointers_(NULL), + custom_info_() { + memset(&assert_info_, 0, sizeof(assert_info_)); + if (custom_info) { + custom_info_ = *custom_info; + } +} + +CrashGenerationClient::~CrashGenerationClient() { + if (crash_event_) { + CloseHandle(crash_event_); + } + + if (crash_generated_) { + CloseHandle(crash_generated_); + } + + if (server_alive_) { + CloseHandle(server_alive_); + } +} + +// Performs the registration step with the server process. +// The registration step involves communicating with the server +// via a named pipe. The client sends the following pieces of +// data to the server: +// +// * Message tag indicating the client is requesting registration. +// * Process id of the client process. +// * Address of a DWORD variable in the client address space +// that will contain the thread id of the client thread that +// caused the crash. +// * Address of a EXCEPTION_POINTERS* variable in the client +// address space that will point to an instance of EXCEPTION_POINTERS +// when the crash happens. +// * Address of an instance of MDRawAssertionInfo that will contain +// relevant information in case of non-exception crashes like assertion +// failures and pure calls. +// +// In return the client expects the following information from the server: +// +// * Message tag indicating successful registration. +// * Server process id. +// * Handle to an object that client can signal to request dump +// generation from the server. +// * Handle to an object that client can wait on after requesting +// dump generation for the server to finish dump generation. +// * Handle to a mutex object that client can wait on to make sure +// server is still alive. +// +// If any step of the expected behavior mentioned above fails, the +// registration step is not considered successful and hence out-of-process +// dump generation service is not available. +// +// Returns true if the registration is successful; false otherwise. +bool CrashGenerationClient::Register() { + HANDLE pipe = ConnectToServer(); + if (!pipe) { + return false; + } + + bool success = RegisterClient(pipe); + CloseHandle(pipe); + return success; +} + +HANDLE CrashGenerationClient::ConnectToServer() { + HANDLE pipe = ConnectToPipe(pipe_name_.c_str(), + kPipeDesiredAccess, + kPipeFlagsAndAttributes); + if (!pipe) { + return NULL; + } + + DWORD mode = kPipeMode; + if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) { + CloseHandle(pipe); + pipe = NULL; + } + + return pipe; +} + +bool CrashGenerationClient::RegisterClient(HANDLE pipe) { + ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST, + GetCurrentProcessId(), + dump_type_, + &thread_id_, + &exception_pointers_, + &assert_info_, + custom_info_, + NULL, + NULL, + NULL); + ProtocolMessage reply; + DWORD bytes_count = 0; + // The call to TransactNamedPipe below can be changed to a call + // to TransactNamedPipeDebugHelper to help repro some scenarios. + // For details see comments for TransactNamedPipeDebugHelper. + if (!TransactNamedPipe(pipe, + &msg, + sizeof(msg), + &reply, + sizeof(ProtocolMessage), + &bytes_count, + NULL)) { + return false; + } + + if (!ValidateResponse(reply)) { + return false; + } + + ProtocolMessage ack_msg; + ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK; + + if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) { + return false; + } + crash_event_ = reply.dump_request_handle; + crash_generated_ = reply.dump_generated_handle; + server_alive_ = reply.server_alive_handle; + server_process_id_ = reply.pid; + + return true; +} + +HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, + DWORD pipe_access, + DWORD flags_attrs) { + for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { + HANDLE pipe = CreateFile(pipe_name, + pipe_access, + 0, + NULL, + OPEN_EXISTING, + flags_attrs, + NULL); + if (pipe != INVALID_HANDLE_VALUE) { + return pipe; + } + + // Cannot continue retrying if error is something other than + // ERROR_PIPE_BUSY. + if (GetLastError() != ERROR_PIPE_BUSY) { + break; + } + + // Cannot continue retrying if wait on pipe fails. + if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { + break; + } + } + + return NULL; +} + +bool CrashGenerationClient::ValidateResponse( + const ProtocolMessage& msg) const { + return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) && + (msg.pid != 0) && + (msg.dump_request_handle != NULL) && + (msg.dump_generated_handle != NULL) && + (msg.server_alive_handle != NULL); +} + +bool CrashGenerationClient::IsRegistered() const { + return crash_event_ != NULL; +} + +bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) { + if (!IsRegistered()) { + return false; + } + + exception_pointers_ = ex_info; + thread_id_ = GetCurrentThreadId(); + + assert_info_.line = 0; + assert_info_.type = 0; + assert_info_.expression[0] = 0; + assert_info_.file[0] = 0; + assert_info_.function[0] = 0; + + return SignalCrashEventAndWait(); +} + +bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) { + if (!IsRegistered()) { + return false; + } + + exception_pointers_ = NULL; + + if (assert_info) { + memcpy(&assert_info_, assert_info, sizeof(assert_info_)); + } else { + memset(&assert_info_, 0, sizeof(assert_info_)); + } + + thread_id_ = GetCurrentThreadId(); + + return SignalCrashEventAndWait(); +} + +bool CrashGenerationClient::SignalCrashEventAndWait() { + assert(crash_event_); + assert(crash_generated_); + assert(server_alive_); + + // Reset the dump generated event before signaling the crash + // event so that the server can set the dump generated event + // once it is done generating the event. + if (!ResetEvent(crash_generated_)) { + return false; + } + + if (!SetEvent(crash_event_)) { + return false; + } + + HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_}; + + DWORD result = WaitForMultipleObjects(kWaitEventCount, + wait_handles, + FALSE, + kWaitForServerTimeoutMs); + + // Crash dump was successfully generated only if the server + // signaled the crash generated event. + return result == WAIT_OBJECT_0; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.h b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.h new file mode 100644 index 00000000..81b0e6ca --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_client.h @@ -0,0 +1,159 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ + +#include +#include +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +struct CustomClientInfo; + +// Abstraction of client-side implementation of out of process +// crash generation. +// +// The process that desires to have out-of-process crash dump +// generation service can use this class in the following way: +// +// * Create an instance. +// * Call Register method so that the client tries to register +// with the server process and check the return value. If +// registration is not successful, out-of-process crash dump +// generation will not be available +// * Request dump generation by calling either of the two +// overloaded RequestDump methods - one in case of exceptions +// and the other in case of assertion failures +// +// Note that it is the responsibility of the client code of +// this class to set the unhandled exception filter with the +// system by calling the SetUnhandledExceptionFilter function +// and the client code should explicitly request dump generation. +class CrashGenerationClient { + public: + CrashGenerationClient(const wchar_t* pipe_name, + MINIDUMP_TYPE dump_type, + const CustomClientInfo* custom_info); + + ~CrashGenerationClient(); + + // Registers the client process with the crash server. + // + // Returns true if the registration is successful; false otherwise. + bool Register(); + + // Requests the crash server to generate a dump with the given + // exception information. + // + // Returns true if the dump was successful; false otherwise. Note that + // if the registration step was not performed or it was not successful, + // false will be returned. + bool RequestDump(EXCEPTION_POINTERS* ex_info); + + // Requests the crash server to generate a dump with the given + // assertion information. + // + // Returns true if the dump was successful; false otherwise. Note that + // if the registration step was not performed or it was not successful, + // false will be returned. + bool RequestDump(MDRawAssertionInfo* assert_info); + + private: + // Connects to the appropriate pipe and sets the pipe handle state. + // + // Returns the pipe handle if everything goes well; otherwise Returns NULL. + HANDLE ConnectToServer(); + + // Performs a handshake with the server over the given pipe which should be + // already connected to the server. + // + // Returns true if handshake with the server was successful; false otherwise. + bool RegisterClient(HANDLE pipe); + + // Validates the given server response. + bool ValidateResponse(const ProtocolMessage& msg) const; + + // Returns true if the registration step succeeded; false otherwise. + bool IsRegistered() const; + + // Connects to the given named pipe with given parameters. + // + // Returns true if the connection is successful; false otherwise. + HANDLE ConnectToPipe(const wchar_t* pipe_name, + DWORD pipe_access, + DWORD flags_attrs); + + // Signals the crash event and wait for the server to generate crash. + bool SignalCrashEventAndWait(); + + // Pipe name to use to talk to server. + std::wstring pipe_name_; + + // Custom client information + CustomClientInfo custom_info_; + + // Type of dump to generate. + MINIDUMP_TYPE dump_type_; + + // Event to signal in case of a crash. + HANDLE crash_event_; + + // Handle to wait on after signaling a crash for the server + // to finish generating crash dump. + HANDLE crash_generated_; + + // Handle to a mutex that will become signaled with WAIT_ABANDONED + // if the server process goes down. + HANDLE server_alive_; + + // Server process id. + DWORD server_process_id_; + + // Id of the thread that caused the crash. + DWORD thread_id_; + + // Exception pointers for an exception crash. + EXCEPTION_POINTERS* exception_pointers_; + + // Assertion info for an invalid parameter or pure call crash. + MDRawAssertionInfo assert_info_; + + // Disable copy ctor and operator=. + CrashGenerationClient(const CrashGenerationClient& crash_client); + CrashGenerationClient& operator=(const CrashGenerationClient& crash_client); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.cc b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.cc new file mode 100644 index 00000000..ac76e590 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.cc @@ -0,0 +1,852 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "client/windows/crash_generation/crash_generation_server.h" +#include +#include +#include +#include "client/windows/common/auto_critical_section.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +// Output buffer size. +static const size_t kOutBufferSize = 64; + +// Input buffer size. +static const size_t kInBufferSize = 64; + +// Access flags for the client on the dump request event. +static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE; + +// Access flags for the client on the dump generated event. +static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE | + SYNCHRONIZE; + +// Access flags for the client on the mutex. +static const DWORD kMutexAccess = SYNCHRONIZE; + +// Attribute flags for the pipe. +static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE | + PIPE_ACCESS_DUPLEX | + FILE_FLAG_OVERLAPPED; + +// Mode for the pipe. +static const DWORD kPipeMode = PIPE_TYPE_MESSAGE | + PIPE_READMODE_MESSAGE | + PIPE_WAIT; + +// For pipe I/O, execute the callback in the wait thread itself, +// since the callback does very little work. The callback executes +// the code for one of the states of the server state machine and +// the code for all of the states perform async I/O and hence +// finish very quickly. +static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD; + +// Dump request threads will, most likely, generate dumps. That may +// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag. +static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD | + WT_EXECUTELONGFUNCTION; + +// Maximum delay during server shutdown if some work items +// are still executing. +static const int kShutdownDelayMs = 10000; + +// Interval for each sleep during server shutdown. +static const int kShutdownSleepIntervalMs = 5; + +static bool IsClientRequestValid(const ProtocolMessage& msg) { + return msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST && + msg.pid != 0 && + msg.thread_id != NULL && + msg.exception_pointers != NULL && + msg.assert_info != NULL; +} + +CrashGenerationServer::CrashGenerationServer( + const std::wstring& pipe_name, + SECURITY_ATTRIBUTES* pipe_sec_attrs, + OnClientConnectedCallback connect_callback, + void* connect_context, + OnClientDumpRequestCallback dump_callback, + void* dump_context, + OnClientExitedCallback exit_callback, + void* exit_context, + bool generate_dumps, + const std::wstring* dump_path) + : pipe_name_(pipe_name), + pipe_sec_attrs_(pipe_sec_attrs), + pipe_(NULL), + pipe_wait_handle_(NULL), + server_alive_handle_(NULL), + connect_callback_(connect_callback), + connect_context_(connect_context), + dump_callback_(dump_callback), + dump_context_(dump_context), + exit_callback_(exit_callback), + exit_context_(exit_context), + generate_dumps_(generate_dumps), + dump_generator_(NULL), + server_state_(IPC_SERVER_STATE_INITIAL), + shutting_down_(false), + overlapped_(), + client_info_(NULL), + cleanup_item_count_(0) { + InitializeCriticalSection(&clients_sync_); + + if (dump_path) { + dump_generator_.reset(new MinidumpGenerator(*dump_path)); + } +} + +CrashGenerationServer::~CrashGenerationServer() { + // Indicate to existing threads that server is shutting down. + shutting_down_ = true; + + // Even if there are no current worker threads running, it is possible that + // an I/O request is pending on the pipe right now but not yet done. In fact, + // it's very likely this is the case unless we are in an ERROR state. If we + // don't wait for the pending I/O to be done, then when the I/O completes, + // it may write to invalid memory. AppVerifier will flag this problem too. + // So we disconnect from the pipe and then wait for the server to get into + // error state so that the pending I/O will fail and get cleared. + DisconnectNamedPipe(pipe_); + int num_tries = 100; + while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) { + Sleep(10); + } + + // Unregister wait on the pipe. + if (pipe_wait_handle_) { + // Wait for already executing callbacks to finish. + UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE); + } + + // Close the pipe to avoid further client connections. + if (pipe_) { + CloseHandle(pipe_); + } + + // Request all ClientInfo objects to unregister all waits. + // New scope to hold the lock for the shortest time. + { + AutoCriticalSection lock(&clients_sync_); + + std::list::iterator iter; + for (iter = clients_.begin(); iter != clients_.end(); ++iter) { + ClientInfo* client_info = *iter; + client_info->UnregisterWaits(); + } + } + + // Now that all waits have been unregistered, wait for some time + // for all pending work items to finish. + int total_wait = 0; + while (cleanup_item_count_ > 0) { + Sleep(kShutdownSleepIntervalMs); + + total_wait += kShutdownSleepIntervalMs; + + if (total_wait >= kShutdownDelayMs) { + break; + } + } + + // Clean up all the ClientInfo objects. + // New scope to hold the lock for the shortest time. + { + AutoCriticalSection lock(&clients_sync_); + + std::list::iterator iter; + for (iter = clients_.begin(); iter != clients_.end(); ++iter) { + ClientInfo* client_info = *iter; + delete client_info; + } + } + + if (server_alive_handle_) { + // Release the mutex before closing the handle so that clients requesting + // dumps wait for a long time for the server to generate a dump. + ReleaseMutex(server_alive_handle_); + CloseHandle(server_alive_handle_); + } + + DeleteCriticalSection(&clients_sync_); +} + +bool CrashGenerationServer::Start() { + server_state_ = IPC_SERVER_STATE_INITIAL; + + server_alive_handle_ = CreateMutex(NULL, TRUE, NULL); + if (!server_alive_handle_) { + return false; + } + + // Event to signal the client connection and pipe reads and writes. + overlapped_.hEvent = CreateEvent(NULL, // Security descriptor. + TRUE, // Manual reset. + FALSE, // Initially signaled. + NULL); // Name. + if (!overlapped_.hEvent) { + return false; + } + + // Register a callback with the thread pool for the client connection. + RegisterWaitForSingleObject(&pipe_wait_handle_, + overlapped_.hEvent, + OnPipeConnected, + this, + INFINITE, + kPipeIOThreadFlags); + + pipe_ = CreateNamedPipe(pipe_name_.c_str(), + kPipeAttr, + kPipeMode, + 1, + kOutBufferSize, + kInBufferSize, + 0, + pipe_sec_attrs_); + if (pipe_ == INVALID_HANDLE_VALUE) { + return false; + } + + // Signal the event to start a separate thread to handle + // client connections. + return SetEvent(overlapped_.hEvent) != FALSE; +} + +// If the server thread serving clients ever gets into the +// ERROR state, reset the event, close the pipe and remain +// in the error state forever. Error state means something +// that we didn't account for has happened, and it's dangerous +// to do anything unknowingly. +void CrashGenerationServer::HandleErrorState() { + assert(server_state_ == IPC_SERVER_STATE_ERROR); + + // If the server is shutting down anyway, don't clean up + // here since shut down process will clean up. + if (shutting_down_) { + return; + } + + if (pipe_wait_handle_) { + UnregisterWait(pipe_wait_handle_); + pipe_wait_handle_ = NULL; + } + + if (pipe_) { + CloseHandle(pipe_); + pipe_ = NULL; + } + + if (overlapped_.hEvent) { + CloseHandle(overlapped_.hEvent); + overlapped_.hEvent = NULL; + } +} + +// When the server thread serving clients is in the INITIAL state, +// try to connect to the pipe asynchronously. If the connection +// finishes synchronously, directly go into the CONNECTED state; +// otherwise go into the CONNECTING state. For any problems, go +// into the ERROR state. +void CrashGenerationServer::HandleInitialState() { + assert(server_state_ == IPC_SERVER_STATE_INITIAL); + + if (!ResetEvent(overlapped_.hEvent)) { + server_state_ = IPC_SERVER_STATE_ERROR; + return; + } + + bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE; + + // From MSDN, it is not clear that when ConnectNamedPipe is used + // in an overlapped mode, will it ever return non-zero value, and + // if so, in what cases. + assert(!success); + + DWORD error_code = GetLastError(); + switch (error_code) { + case ERROR_IO_PENDING: + server_state_ = IPC_SERVER_STATE_CONNECTING; + break; + + case ERROR_PIPE_CONNECTED: + if (SetEvent(overlapped_.hEvent)) { + server_state_ = IPC_SERVER_STATE_CONNECTED; + } else { + server_state_ = IPC_SERVER_STATE_ERROR; + } + break; + + default: + server_state_ = IPC_SERVER_STATE_ERROR; + break; + } +} + +// When the server thread serving the clients is in the CONNECTING state, +// try to get the result of the asynchronous connection request using +// the OVERLAPPED object. If the result indicates the connection is done, +// go into the CONNECTED state. If the result indicates I/O is still +// INCOMPLETE, remain in the CONNECTING state. For any problems, +// go into the DISCONNECTING state. +void CrashGenerationServer::HandleConnectingState() { + assert(server_state_ == IPC_SERVER_STATE_CONNECTING); + + DWORD bytes_count = 0; + bool success = GetOverlappedResult(pipe_, + &overlapped_, + &bytes_count, + FALSE) != FALSE; + + if (success) { + server_state_ = IPC_SERVER_STATE_CONNECTED; + return; + } + + if (GetLastError() != ERROR_IO_INCOMPLETE) { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + } +} + +// When the server thread serving the clients is in the CONNECTED state, +// try to issue an asynchronous read from the pipe. If read completes +// synchronously or if I/O is pending then go into the READING state. +// For any problems, go into the DISCONNECTING state. +void CrashGenerationServer::HandleConnectedState() { + assert(server_state_ == IPC_SERVER_STATE_CONNECTED); + + DWORD bytes_count = 0; + memset(&msg_, 0, sizeof(msg_)); + bool success = ReadFile(pipe_, + &msg_, + sizeof(msg_), + &bytes_count, + &overlapped_) != FALSE; + + // Note that the asynchronous read issued above can finish before the + // code below executes. But, it is okay to change state after issuing + // the asynchronous read. This is because even if the asynchronous read + // is done, the callback for it would not be executed until the current + // thread finishes its execution. + if (success || GetLastError() == ERROR_IO_PENDING) { + server_state_ = IPC_SERVER_STATE_READING; + } else { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + } +} + +// When the server thread serving the clients is in the READING state, +// try to get the result of the async read. If async read is done, +// go into the READ_DONE state. For any problems, go into the +// DISCONNECTING state. +void CrashGenerationServer::HandleReadingState() { + assert(server_state_ == IPC_SERVER_STATE_READING); + + DWORD bytes_count = 0; + bool success = GetOverlappedResult(pipe_, + &overlapped_, + &bytes_count, + FALSE) != FALSE; + + if (success && bytes_count == sizeof(ProtocolMessage)) { + server_state_ = IPC_SERVER_STATE_READ_DONE; + return; + } + + DWORD error_code; + error_code = GetLastError(); + + // We should never get an I/O incomplete since we should not execute this + // unless the Read has finished and the overlapped event is signaled. If + // we do get INCOMPLETE, we have a bug in our code. + assert(error_code != ERROR_IO_INCOMPLETE); + + server_state_ = IPC_SERVER_STATE_DISCONNECTING; +} + +// When the server thread serving the client is in the READ_DONE state, +// validate the client's request message, register the client by +// creating appropriate objects and prepare the response. Then try to +// write the response to the pipe asynchronously. If that succeeds, +// go into the WRITING state. For any problems, go into the DISCONNECTING +// state. +void CrashGenerationServer::HandleReadDoneState() { + assert(server_state_ == IPC_SERVER_STATE_READ_DONE); + + if (!IsClientRequestValid(msg_)) { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + return; + } + + scoped_ptr client_info( + new ClientInfo(this, + msg_.pid, + msg_.dump_type, + msg_.thread_id, + msg_.exception_pointers, + msg_.assert_info, + msg_.custom_client_info)); + + if (!client_info->Initialize()) { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + return; + } + + if (!RespondToClient(client_info.get())) { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + return; + } + + // Note that the asynchronous write issued by RespondToClient function + // can finish before the code below executes. But it is okay to change + // state after issuing the asynchronous write. This is because even if + // the asynchronous write is done, the callback for it would not be + // executed until the current thread finishes its execution. + server_state_ = IPC_SERVER_STATE_WRITING; + client_info_ = client_info.release(); +} + +// When the server thread serving the clients is in the WRITING state, +// try to get the result of the async write. If the async write is done, +// go into the WRITE_DONE state. For any problems, go into the +// DISONNECTING state. +void CrashGenerationServer::HandleWritingState() { + assert(server_state_ == IPC_SERVER_STATE_WRITING); + + DWORD bytes_count = 0; + bool success = GetOverlappedResult(pipe_, + &overlapped_, + &bytes_count, + FALSE) != FALSE; + + if (success) { + server_state_ = IPC_SERVER_STATE_WRITE_DONE; + return; + } + + DWORD error_code; + error_code = GetLastError(); + + // We should never get an I/O incomplete since we should not execute this + // unless the Write has finished and the overlapped event is signaled. If + // we do get INCOMPLETE, we have a bug in our code. + assert(error_code != ERROR_IO_INCOMPLETE); + + server_state_ = IPC_SERVER_STATE_DISCONNECTING; +} + +// When the server thread serving the clients is in the WRITE_DONE state, +// try to issue an async read on the pipe. If the read completes synchronously +// or if I/O is still pending then go into the READING_ACK state. For any +// issues, go into the DISCONNECTING state. +void CrashGenerationServer::HandleWriteDoneState() { + assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE); + + server_state_ = IPC_SERVER_STATE_READING_ACK; + + DWORD bytes_count = 0; + bool success = ReadFile(pipe_, + &msg_, + sizeof(msg_), + &bytes_count, + &overlapped_) != FALSE; + + if (success) { + return; + } + + DWORD error_code = GetLastError(); + + if (error_code != ERROR_IO_PENDING) { + server_state_ = IPC_SERVER_STATE_DISCONNECTING; + } +} + +// When the server thread serving the clients is in the READING_ACK state, +// try to get result of async read. Go into the DISCONNECTING state. +void CrashGenerationServer::HandleReadingAckState() { + assert(server_state_ == IPC_SERVER_STATE_READING_ACK); + + DWORD bytes_count = 0; + bool success = GetOverlappedResult(pipe_, + &overlapped_, + &bytes_count, + FALSE) != FALSE; + + if (success) { + // The connection handshake with the client is now complete; perform + // the callback. + if (connect_callback_) { + connect_callback_(connect_context_, client_info_); + } + } else { + DWORD error_code = GetLastError(); + + // We should never get an I/O incomplete since we should not execute this + // unless the Read has finished and the overlapped event is signaled. If + // we do get INCOMPLETE, we have a bug in our code. + assert(error_code != ERROR_IO_INCOMPLETE); + } + + server_state_ = IPC_SERVER_STATE_DISCONNECTING; +} + +// When the server thread serving the client is in the DISCONNECTING state, +// disconnect from the pipe and reset the event. If anything fails, go into +// the ERROR state. If it goes well, go into the INITIAL state and set the +// event to start all over again. +void CrashGenerationServer::HandleDisconnectingState() { + assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING); + + // Done serving the client. + client_info_ = NULL; + + overlapped_.Internal = NULL; + overlapped_.InternalHigh = NULL; + overlapped_.Offset = 0; + overlapped_.OffsetHigh = 0; + overlapped_.Pointer = NULL; + + if (!ResetEvent(overlapped_.hEvent)) { + server_state_ = IPC_SERVER_STATE_ERROR; + return; + } + + if (!DisconnectNamedPipe(pipe_)) { + server_state_ = IPC_SERVER_STATE_ERROR; + return; + } + + // If the server is shutting down do not connect to the + // next client. + if (shutting_down_) { + return; + } + + server_state_ = IPC_SERVER_STATE_INITIAL; + if (!SetEvent(overlapped_.hEvent)) { + server_state_ = IPC_SERVER_STATE_ERROR; + } +} + +bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info, + ProtocolMessage* reply) const { + reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE; + reply->pid = GetCurrentProcessId(); + + if (CreateClientHandles(client_info, reply)) { + return true; + } + + if (reply->dump_request_handle) { + CloseHandle(reply->dump_request_handle); + } + + if (reply->dump_generated_handle) { + CloseHandle(reply->dump_generated_handle); + } + + if (reply->server_alive_handle) { + CloseHandle(reply->server_alive_handle); + } + + return false; +} + +bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info, + ProtocolMessage* reply) const { + HANDLE current_process = GetCurrentProcess(); + if (!DuplicateHandle(current_process, + client_info.dump_requested_handle(), + client_info.process_handle(), + &reply->dump_request_handle, + kDumpRequestEventAccess, + FALSE, + 0)) { + return false; + } + + if (!DuplicateHandle(current_process, + client_info.dump_generated_handle(), + client_info.process_handle(), + &reply->dump_generated_handle, + kDumpGeneratedEventAccess, + FALSE, + 0)) { + return false; + } + + if (!DuplicateHandle(current_process, + server_alive_handle_, + client_info.process_handle(), + &reply->server_alive_handle, + kMutexAccess, + FALSE, + 0)) { + return false; + } + + return true; +} + +bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) { + ProtocolMessage reply; + if (!PrepareReply(*client_info, &reply)) { + return false; + } + + if (!AddClient(client_info)) { + return false; + } + + DWORD bytes_count = 0; + bool success = WriteFile(pipe_, + &reply, + sizeof(reply), + &bytes_count, + &overlapped_) != FALSE; + + return success || GetLastError() == ERROR_IO_PENDING; +} + +// The server thread servicing the clients runs this method. The method +// implements the state machine described in ReadMe.txt along with the +// helper methods HandleXXXState. +void CrashGenerationServer::HandleConnectionRequest() { + // If we are shutting doen then get into ERROR state, reset the event so more + // workers don't run and return immediately. + if (shutting_down_) { + server_state_ = IPC_SERVER_STATE_ERROR; + ResetEvent(overlapped_.hEvent); + return; + } + + switch (server_state_) { + case IPC_SERVER_STATE_ERROR: + HandleErrorState(); + break; + + case IPC_SERVER_STATE_INITIAL: + HandleInitialState(); + break; + + case IPC_SERVER_STATE_CONNECTING: + HandleConnectingState(); + break; + + case IPC_SERVER_STATE_CONNECTED: + HandleConnectedState(); + break; + + case IPC_SERVER_STATE_READING: + HandleReadingState(); + break; + + case IPC_SERVER_STATE_READ_DONE: + HandleReadDoneState(); + break; + + case IPC_SERVER_STATE_WRITING: + HandleWritingState(); + break; + + case IPC_SERVER_STATE_WRITE_DONE: + HandleWriteDoneState(); + break; + + case IPC_SERVER_STATE_READING_ACK: + HandleReadingAckState(); + break; + + case IPC_SERVER_STATE_DISCONNECTING: + HandleDisconnectingState(); + break; + + default: + assert(false); + // This indicates that we added one more state without + // adding handling code. + server_state_ = IPC_SERVER_STATE_ERROR; + break; + } +} + +bool CrashGenerationServer::AddClient(ClientInfo* client_info) { + HANDLE request_wait_handle = NULL; + if (!RegisterWaitForSingleObject(&request_wait_handle, + client_info->dump_requested_handle(), + OnDumpRequest, + client_info, + INFINITE, + kDumpRequestThreadFlags)) { + return false; + } + + client_info->set_dump_request_wait_handle(request_wait_handle); + + // OnClientEnd will be called when the client process terminates. + HANDLE process_wait_handle = NULL; + if (!RegisterWaitForSingleObject(&process_wait_handle, + client_info->process_handle(), + OnClientEnd, + client_info, + INFINITE, + WT_EXECUTEONLYONCE)) { + return false; + } + + client_info->set_process_exit_wait_handle(process_wait_handle); + + // New scope to hold the lock for the shortest time. + { + AutoCriticalSection lock(&clients_sync_); + clients_.push_back(client_info); + } + + return true; +} + +// static +void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) { + assert (context); + + CrashGenerationServer* obj = + reinterpret_cast(context); + obj->HandleConnectionRequest(); +} + +// static +void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) { + assert(context); + ClientInfo* client_info = reinterpret_cast(context); + client_info->PopulateCustomInfo(); + + CrashGenerationServer* crash_server = client_info->crash_server(); + assert(crash_server); + crash_server->HandleDumpRequest(*client_info); + + ResetEvent(client_info->dump_requested_handle()); +} + +// static +void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) { + assert(context); + ClientInfo* client_info = reinterpret_cast(context); + + CrashGenerationServer* crash_server = client_info->crash_server(); + assert(crash_server); + + InterlockedIncrement(&crash_server->cleanup_item_count_); + + if (!QueueUserWorkItem(CleanupClient, context, WT_EXECUTEDEFAULT)) { + InterlockedDecrement(&crash_server->cleanup_item_count_); + } +} + +// static +DWORD WINAPI CrashGenerationServer::CleanupClient(void* context) { + assert(context); + ClientInfo* client_info = reinterpret_cast(context); + + CrashGenerationServer* crash_server = client_info->crash_server(); + assert(crash_server); + + if (crash_server->exit_callback_) { + crash_server->exit_callback_(crash_server->exit_context_, client_info); + } + + crash_server->DoCleanup(client_info); + + InterlockedDecrement(&crash_server->cleanup_item_count_); + return 0; +} + +void CrashGenerationServer::DoCleanup(ClientInfo* client_info) { + assert(client_info); + + // Start a new scope to release lock automatically. + { + AutoCriticalSection lock(&clients_sync_); + clients_.remove(client_info); + } + + delete client_info; +} + +void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) { + // Generate the dump only if it's explicitly requested by the + // server application; otherwise the server might want to generate + // dump in the callback. + std::wstring dump_path; + if (generate_dumps_) { + if (!GenerateDump(client_info, &dump_path)) { + return; + } + } + + if (dump_callback_) { + std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path; + dump_callback_(dump_context_, &client_info, ptr_dump_path); + } + + SetEvent(client_info.dump_generated_handle()); +} + +bool CrashGenerationServer::GenerateDump(const ClientInfo& client, + std::wstring* dump_path) { + assert(client.pid() != 0); + assert(client.process_handle()); + + // We have to get the address of EXCEPTION_INFORMATION from + // the client process address space. + EXCEPTION_POINTERS* client_ex_info = NULL; + if (!client.GetClientExceptionInfo(&client_ex_info)) { + return false; + } + + DWORD client_thread_id = 0; + if (!client.GetClientThreadId(&client_thread_id)) { + return false; + } + + return dump_generator_->WriteMinidump(client.process_handle(), + client.pid(), + client_thread_id, + GetCurrentThreadId(), + client_ex_info, + client.assert_info(), + client.dump_type(), + true, + dump_path); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.h b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.h new file mode 100644 index 00000000..cacb639a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/crash_generation_server.h @@ -0,0 +1,269 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ + +#include +#include +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/crash_generation/client_info.h" +#include "client/windows/crash_generation/minidump_generator.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +// Abstraction for server side implementation of out-of-process crash +// generation protocol for Windows platform only. It generates Windows +// minidump files for client processes that request dump generation. When +// the server is requested to start listening for clients (by calling the +// Start method), it creates a named pipe and waits for the clients to +// register. In response, it hands them event handles that the client can +// signal to request dump generation. When the clients request dump +// generation in this way, the server generates Windows minidump files. +class CrashGenerationServer { + public: + typedef void (*OnClientConnectedCallback)(void* context, + const ClientInfo* client_info); + + typedef void (*OnClientDumpRequestCallback)(void* context, + const ClientInfo* client_info, + const std::wstring* file_path); + + typedef void (*OnClientExitedCallback)(void* context, + const ClientInfo* client_info); + + // Creates an instance with the given parameters. + // + // Parameter pipe_name: Name of the Windows named pipe + // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass + // NULL to use default security on the pipe. By default, the pipe created + // allows Local System, Administrators and the Creator full control and + // the Everyone group read access on the pipe. + // Parameter connect_callback: Callback for a new client connection. + // Parameter connect_context: Context for client connection callback. + // Parameter crash_callback: Callback for a client crash dump request. + // Parameter crash_context: Context for client crash dump request callback. + // Parameter exit_callback: Callback for client process exit. + // Parameter exit_context: Context for client exit callback. + // Parameter generate_dumps: Whether to automatically generate dumps. + // Client code of this class might want to generate dumps explicitly in the + // crash dump request callback. In that case, false can be passed for this + // parameter. + // Parameter dump_path: Path for generating dumps; required only if true is + // passed for generateDumps parameter; NULL can be passed otherwise. + CrashGenerationServer(const std::wstring& pipe_name, + SECURITY_ATTRIBUTES* pipe_sec_attrs, + OnClientConnectedCallback connect_callback, + void* connect_context, + OnClientDumpRequestCallback dump_callback, + void* dump_context, + OnClientExitedCallback exit_callback, + void* exit_context, + bool generate_dumps, + const std::wstring* dump_path); + + ~CrashGenerationServer(); + + // Performs initialization steps needed to start listening to clients. + // + // Returns true if initialization is successful; false otherwise. + bool Start(); + + private: + // Various states the client can be in during the handshake with + // the server. + enum IPCServerState { + // Server is in error state and it cannot serve any clients. + IPC_SERVER_STATE_ERROR, + + // Server starts in this state. + IPC_SERVER_STATE_INITIAL, + + // Server has issued an async connect to the pipe and it is waiting + // for the connection to be established. + IPC_SERVER_STATE_CONNECTING, + + // Server is connected successfully. + IPC_SERVER_STATE_CONNECTED, + + // Server has issued an async read from the pipe and it is waiting for + // the read to finish. + IPC_SERVER_STATE_READING, + + // Server is done reading from the pipe. + IPC_SERVER_STATE_READ_DONE, + + // Server has issued an async write to the pipe and it is waiting for + // the write to finish. + IPC_SERVER_STATE_WRITING, + + // Server is done writing to the pipe. + IPC_SERVER_STATE_WRITE_DONE, + + // Server has issued an async read from the pipe for an ack and it + // is waiting for the read to finish. + IPC_SERVER_STATE_READING_ACK, + + // Server is done writing to the pipe and it is now ready to disconnect + // and reconnect. + IPC_SERVER_STATE_DISCONNECTING + }; + + // + // Helper methods to handle various server IPC states. + // + void HandleErrorState(); + void HandleInitialState(); + void HandleConnectingState(); + void HandleConnectedState(); + void HandleReadingState(); + void HandleReadDoneState(); + void HandleWritingState(); + void HandleWriteDoneState(); + void HandleReadingAckState(); + void HandleDisconnectingState(); + + // Prepares reply for a client from the given parameters. + bool PrepareReply(const ClientInfo& client_info, + ProtocolMessage* reply) const; + + // Duplicates various handles in the ClientInfo object for the client + // process and stores them in the given ProtocolMessage instance. If + // creating any handle fails, ProtocolMessage will contain the handles + // already created successfully, which should be closed by the caller. + bool CreateClientHandles(const ClientInfo& client_info, + ProtocolMessage* reply) const; + + // Response to the given client. Return true if all steps of + // responding to the client succeed, false otherwise. + bool RespondToClient(ClientInfo* client_info); + + // Handles a connection request from the client. + void HandleConnectionRequest(); + + // Handles a dump request from the client. + void HandleDumpRequest(const ClientInfo& client_info); + + // Callback for pipe connected event. + static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait); + + // Callback for a dump request. + static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait); + + // Callback for client process exit event. + static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait); + + // Releases resources for a client. + static DWORD WINAPI CleanupClient(void* context); + + // Cleans up for the given client. + void DoCleanup(ClientInfo* client_info); + + // Adds the given client to the list of registered clients. + bool AddClient(ClientInfo* client_info); + + // Generates dump for the given client. + bool GenerateDump(const ClientInfo& client, std::wstring* dump_path); + + // Sync object for thread-safe access to the shared list of clients. + CRITICAL_SECTION clients_sync_; + + // List of clients. + std::list clients_; + + // Pipe name. + std::wstring pipe_name_; + + // Pipe security attributes + SECURITY_ATTRIBUTES* pipe_sec_attrs_; + + // Handle to the pipe used for handshake with clients. + HANDLE pipe_; + + // Pipe wait handle. + HANDLE pipe_wait_handle_; + + // Handle to server-alive mutex. + HANDLE server_alive_handle_; + + // Callback for a successful client connection. + OnClientConnectedCallback connect_callback_; + + // Context for client connected callback. + void* connect_context_; + + // Callback for a client dump request. + OnClientDumpRequestCallback dump_callback_; + + // Context for client dump request callback. + void* dump_context_; + + // Callback for client process exit. + OnClientExitedCallback exit_callback_; + + // Context for client process exit callback. + void* exit_context_; + + // Whether to generate dumps. + bool generate_dumps_; + + // Instance of a mini dump generator. + scoped_ptr dump_generator_; + + // State of the server in performing the IPC with the client. + // Note that since we restrict the pipe to one instance, we + // only need to keep one state of the server. Otherwise, server + // would have one state per client it is talking to. + volatile IPCServerState server_state_; + + // Whether the server is shutting down. + volatile bool shutting_down_; + + // Overlapped instance for async I/O on the pipe. + OVERLAPPED overlapped_; + + // Message object used in IPC with the client. + ProtocolMessage msg_; + + // Client Info for the client that's connecting to the server. + ClientInfo* client_info_; + + // Count of clean-up work items that are currently running or are + // already queued to run. + volatile LONG cleanup_item_count_; + + // Disable copy ctor and operator=. + CrashGenerationServer(const CrashGenerationServer& crash_server); + CrashGenerationServer& operator=(const CrashGenerationServer& crash_server); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.cc b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.cc new file mode 100644 index 00000000..c03b191a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.cc @@ -0,0 +1,289 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "client/windows/crash_generation/minidump_generator.h" +#include +#include "client/windows/common/auto_critical_section.h" +#include "common/windows/guid_string.h" + +using std::wstring; + +namespace google_breakpad { + +MinidumpGenerator::MinidumpGenerator(const wstring& dump_path) + : dbghelp_module_(NULL), + rpcrt4_module_(NULL), + dump_path_(dump_path), + write_dump_(NULL), + create_uuid_(NULL) { + InitializeCriticalSection(&module_load_sync_); + InitializeCriticalSection(&get_proc_address_sync_); +} + +MinidumpGenerator::~MinidumpGenerator() { + if (dbghelp_module_) { + FreeLibrary(dbghelp_module_); + } + + if (rpcrt4_module_) { + FreeLibrary(rpcrt4_module_); + } + + DeleteCriticalSection(&get_proc_address_sync_); + DeleteCriticalSection(&module_load_sync_); +} + +bool MinidumpGenerator::WriteMinidump(HANDLE process_handle, + DWORD process_id, + DWORD thread_id, + DWORD requesting_thread_id, + EXCEPTION_POINTERS* exception_pointers, + MDRawAssertionInfo* assert_info, + MINIDUMP_TYPE dump_type, + bool is_client_pointers, + wstring* dump_path) { + MiniDumpWriteDumpType write_dump = GetWriteDump(); + if (!write_dump) { + return false; + } + + wstring dump_file_path; + if (!GenerateDumpFilePath(&dump_file_path)) { + return false; + } + + // If the client requests a full memory dump, we will write a normal mini + // dump and a full memory dump. Both dump files use the same uuid as file + // name prefix. + bool full_memory_dump = (dump_type & MiniDumpWithFullMemory) != 0; + wstring full_dump_file_path; + if (full_memory_dump) { + full_dump_file_path.assign(dump_file_path); + full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp + full_dump_file_path.append(TEXT("-full.dmp")); + } + + HANDLE dump_file = CreateFile(dump_file_path.c_str(), + GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (dump_file == INVALID_HANDLE_VALUE) { + return false; + } + + HANDLE full_dump_file = INVALID_HANDLE_VALUE; + if (full_memory_dump) { + full_dump_file = CreateFile(full_dump_file_path.c_str(), + GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (full_dump_file == INVALID_HANDLE_VALUE) { + CloseHandle(dump_file); + return false; + } + } + + MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL; + MINIDUMP_EXCEPTION_INFORMATION dump_exception_info; + + // Setup the exception information object only if it's a dump + // due to an exception. + if (exception_pointers) { + dump_exception_pointers = &dump_exception_info; + dump_exception_info.ThreadId = thread_id; + dump_exception_info.ExceptionPointers = exception_pointers; + dump_exception_info.ClientPointers = is_client_pointers; + } + + // Add an MDRawBreakpadInfo stream to the minidump, to provide additional + // information about the exception handler to the Breakpad processor. + // The information will help the processor determine which threads are + // relevant. The Breakpad processor does not require this information but + // can function better with Breakpad-generated dumps when it is present. + // The native debugger is not harmed by the presence of this information. + MDRawBreakpadInfo breakpad_info = {0}; + if (!is_client_pointers) { + // Set the dump thread id and requesting thread id only in case of + // in-process dump generation. + breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; + breakpad_info.dump_thread_id = thread_id; + breakpad_info.requesting_thread_id = requesting_thread_id; + } + + // Leave room in user_stream_array for a possible assertion info stream. + MINIDUMP_USER_STREAM user_stream_array[2]; + user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; + user_stream_array[0].BufferSize = sizeof(breakpad_info); + user_stream_array[0].Buffer = &breakpad_info; + + MINIDUMP_USER_STREAM_INFORMATION user_streams; + user_streams.UserStreamCount = 1; + user_streams.UserStreamArray = user_stream_array; + + MDRawAssertionInfo* actual_assert_info = assert_info; + MDRawAssertionInfo client_assert_info = {0}; + + if (assert_info) { + // If the assertion info object lives in the client process, + // read the memory of the client process. + if (is_client_pointers) { + SIZE_T bytes_read = 0; + if (!ReadProcessMemory(process_handle, + assert_info, + &client_assert_info, + sizeof(client_assert_info), + &bytes_read)) { + CloseHandle(dump_file); + if (full_dump_file != INVALID_HANDLE_VALUE) + CloseHandle(full_dump_file); + return false; + } + + if (bytes_read != sizeof(client_assert_info)) { + CloseHandle(dump_file); + if (full_dump_file != INVALID_HANDLE_VALUE) + CloseHandle(full_dump_file); + return false; + } + + actual_assert_info = &client_assert_info; + } + + user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM; + user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo); + user_stream_array[1].Buffer = actual_assert_info; + ++user_streams.UserStreamCount; + } + + bool result_minidump = write_dump( + process_handle, + process_id, + dump_file, + static_cast((dump_type & (~MiniDumpWithFullMemory)) + | MiniDumpNormal), + exception_pointers ? &dump_exception_info : NULL, + &user_streams, + NULL) != FALSE; + + bool result_full_memory = true; + if (full_memory_dump) { + result_full_memory = write_dump( + process_handle, + process_id, + full_dump_file, + static_cast(dump_type & (~MiniDumpNormal)), + exception_pointers ? &dump_exception_info : NULL, + &user_streams, + NULL) != FALSE; + } + + bool result = result_minidump && result_full_memory; + + CloseHandle(dump_file); + if (full_dump_file != INVALID_HANDLE_VALUE) + CloseHandle(full_dump_file); + + // Store the path of the dump file in the out parameter if dump generation + // succeeded. + if (result && dump_path) { + *dump_path = dump_file_path; + } + + return result; +} + +HMODULE MinidumpGenerator::GetDbghelpModule() { + AutoCriticalSection lock(&module_load_sync_); + if (!dbghelp_module_) { + dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll")); + } + + return dbghelp_module_; +} + +MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() { + AutoCriticalSection lock(&get_proc_address_sync_); + if (!write_dump_) { + HMODULE module = GetDbghelpModule(); + if (module) { + FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump"); + write_dump_ = reinterpret_cast(proc); + } + } + + return write_dump_; +} + +HMODULE MinidumpGenerator::GetRpcrt4Module() { + AutoCriticalSection lock(&module_load_sync_); + if (!rpcrt4_module_) { + rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll")); + } + + return rpcrt4_module_; +} + +MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() { + AutoCriticalSection lock(&module_load_sync_); + if (!create_uuid_) { + HMODULE module = GetRpcrt4Module(); + if (module) { + FARPROC proc = GetProcAddress(module, "UuidCreate"); + create_uuid_ = reinterpret_cast(proc); + } + } + + return create_uuid_; +} + +bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) { + UUID id = {0}; + + UuidCreateType create_uuid = GetCreateUuid(); + if(!create_uuid) { + return false; + } + + create_uuid(&id); + wstring id_str = GUIDString::GUIDToWString(&id); + + *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp"); + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.h b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.h new file mode 100644 index 00000000..8ab6a8f6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/crash_generation/minidump_generator.h @@ -0,0 +1,121 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ +#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ + +#include +#include +#include +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +// Abstraction for various objects and operations needed to generate +// minidump on Windows. This abstraction is useful to hide all the gory +// details for minidump generation and provide a clean interface to +// the clients to generate minidumps. +class MinidumpGenerator { + public: + // Creates an instance with the given dump path. + explicit MinidumpGenerator(const std::wstring& dump_path); + + ~MinidumpGenerator(); + + // Writes the minidump with the given parameters. Stores the + // dump file path in the dump_path parameter if dump generation + // succeeds. + bool WriteMinidump(HANDLE process_handle, + DWORD process_id, + DWORD thread_id, + DWORD requesting_thread_id, + EXCEPTION_POINTERS* exception_pointers, + MDRawAssertionInfo* assert_info, + MINIDUMP_TYPE dump_type, + bool is_client_pointers, + std::wstring* dump_path); + + private: + // Function pointer type for MiniDumpWriteDump, which is looked up + // dynamically. + typedef BOOL (WINAPI* MiniDumpWriteDumpType)( + HANDLE hProcess, + DWORD ProcessId, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + + // Function pointer type for UuidCreate, which is looked up dynamically. + typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid); + + // Loads the appropriate DLL lazily in a thread safe way. + HMODULE GetDbghelpModule(); + + // Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump + // function lazily and in a thread-safe manner. + MiniDumpWriteDumpType GetWriteDump(); + + // Loads the appropriate DLL lazily in a thread safe way. + HMODULE GetRpcrt4Module(); + + // Loads the appropriate DLL and gets a pointer to the UuidCreate + // function lazily and in a thread-safe manner. + UuidCreateType GetCreateUuid(); + + // Returns the path for the file to write dump to. + bool GenerateDumpFilePath(std::wstring* file_path); + + // Handle to dynamically loaded DbgHelp.dll. + HMODULE dbghelp_module_; + + // Pointer to the MiniDumpWriteDump function. + MiniDumpWriteDumpType write_dump_; + + // Handle to dynamically loaded rpcrt4.dll. + HMODULE rpcrt4_module_; + + // Pointer to the UuidCreate function. + UuidCreateType create_uuid_; + + // Folder path to store dump files. + std::wstring dump_path_; + + // Critical section to sychronize action of loading modules dynamically. + CRITICAL_SECTION module_load_sync_; + + // Critical section to synchronize action of dynamically getting function + // addresses from modules. + CRITICAL_SECTION get_proc_address_sync_; +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATION_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.cc b/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.cc new file mode 100644 index 00000000..f3bb5a61 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.cc @@ -0,0 +1,746 @@ +// 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 + +#include +#include + +#include "common/windows/string_utils-inl.h" + +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/handler/exception_handler.h" +#include "common/windows/guid_string.h" + +namespace google_breakpad { + +static const int kWaitForHandlerThreadMs = 60000; +static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024; + +vector* ExceptionHandler::handler_stack_ = NULL; +LONG ExceptionHandler::handler_stack_index_ = 0; +CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_; +volatile LONG ExceptionHandler::instance_count_ = 0; + +ExceptionHandler::ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info) { + Initialize(dump_path, + filter, + callback, + callback_context, + handler_types, + dump_type, + pipe_name, + custom_info); +} + +ExceptionHandler::ExceptionHandler(const wstring &dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types) { + Initialize(dump_path, + filter, + callback, + callback_context, + handler_types, + MiniDumpNormal, + NULL, + NULL); +} + +void ExceptionHandler::Initialize(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info) { + LONG instance_count = InterlockedIncrement(&instance_count_); + filter_ = filter; + callback_ = callback; + callback_context_ = callback_context; + dump_path_c_ = NULL; + next_minidump_id_c_ = NULL; + next_minidump_path_c_ = NULL; + dbghelp_module_ = NULL; + minidump_write_dump_ = NULL; + dump_type_ = dump_type; + rpcrt4_module_ = NULL; + uuid_create_ = NULL; + handler_types_ = handler_types; + previous_filter_ = NULL; +#if _MSC_VER >= 1400 // MSVC 2005/8 + previous_iph_ = NULL; +#endif // _MSC_VER >= 1400 + previous_pch_ = NULL; + handler_thread_ = NULL; + is_shutdown_ = false; + handler_start_semaphore_ = NULL; + handler_finish_semaphore_ = NULL; + requesting_thread_id_ = 0; + exception_info_ = NULL; + assertion_ = NULL; + handler_return_value_ = false; + handle_debug_exceptions_ = false; + + // Attempt to use out-of-process if user has specified pipe name. + if (pipe_name != NULL) { + scoped_ptr client( + new CrashGenerationClient(pipe_name, + dump_type_, + custom_info)); + + // If successful in registering with the monitoring process, + // there is no need to setup in-process crash generation. + if (client->Register()) { + crash_generation_client_.reset(client.release()); + } + } + + if (!IsOutOfProcess()) { + // Either client did not ask for out-of-process crash generation + // or registration with the server process failed. In either case, + // setup to do in-process crash generation. + + // Set synchronization primitives and the handler thread. Each + // ExceptionHandler object gets its own handler thread because that's the + // only way to reliably guarantee sufficient stack space in an exception, + // and it allows an easy way to get a snapshot of the requesting thread's + // context outside of an exception. + InitializeCriticalSection(&handler_critical_section_); + handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); + assert(handler_start_semaphore_ != NULL); + + handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); + assert(handler_finish_semaphore_ != NULL); + + // Don't attempt to create the thread if we could not create the semaphores. + if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) { + DWORD thread_id; + handler_thread_ = CreateThread(NULL, // lpThreadAttributes + kExceptionHandlerThreadInitialStackSize, + ExceptionHandlerThreadMain, + this, // lpParameter + 0, // dwCreationFlags + &thread_id); + assert(handler_thread_ != NULL); + } + + dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); + if (dbghelp_module_) { + minidump_write_dump_ = reinterpret_cast( + GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); + } + + // Load this library dynamically to not affect existing projects. Most + // projects don't link against this directly, it's usually dynamically + // loaded by dependent code. + rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll"); + if (rpcrt4_module_) { + uuid_create_ = reinterpret_cast( + GetProcAddress(rpcrt4_module_, "UuidCreate")); + } + + // set_dump_path calls UpdateNextID. This sets up all of the path and id + // strings, and their equivalent c_str pointers. + set_dump_path(dump_path); + } + + // There is a race condition here. If the first instance has not yet + // initialized the critical section, the second (and later) instances may + // try to use uninitialized critical section object. The feature of multiple + // instances in one module is not used much, so leave it as is for now. + // One way to solve this in the current design (that is, keeping the static + // handler stack) is to use spin locks with volatile bools to synchronize + // the handler stack. This works only if the compiler guarantees to generate + // cache coherent code for volatile. + // TODO(munjal): Fix this in a better way by changing the design if possible. + + // Lazy initialization of the handler_stack_critical_section_ + if (instance_count == 1) { + InitializeCriticalSection(&handler_stack_critical_section_); + } + + if (handler_types != HANDLER_NONE) { + EnterCriticalSection(&handler_stack_critical_section_); + + // The first time an ExceptionHandler that installs a handler is + // created, set up the handler stack. + if (!handler_stack_) { + handler_stack_ = new vector(); + } + handler_stack_->push_back(this); + + if (handler_types & HANDLER_EXCEPTION) + previous_filter_ = SetUnhandledExceptionFilter(HandleException); + +#if _MSC_VER >= 1400 // MSVC 2005/8 + if (handler_types & HANDLER_INVALID_PARAMETER) + previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter); +#endif // _MSC_VER >= 1400 + + if (handler_types & HANDLER_PURECALL) + previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); + + LeaveCriticalSection(&handler_stack_critical_section_); + } +} + +ExceptionHandler::~ExceptionHandler() { + if (dbghelp_module_) { + FreeLibrary(dbghelp_module_); + } + + if (rpcrt4_module_) { + FreeLibrary(rpcrt4_module_); + } + + if (handler_types_ != HANDLER_NONE) { + EnterCriticalSection(&handler_stack_critical_section_); + + if (handler_types_ & HANDLER_EXCEPTION) + SetUnhandledExceptionFilter(previous_filter_); + +#if _MSC_VER >= 1400 // MSVC 2005/8 + if (handler_types_ & HANDLER_INVALID_PARAMETER) + _set_invalid_parameter_handler(previous_iph_); +#endif // _MSC_VER >= 1400 + + if (handler_types_ & HANDLER_PURECALL) + _set_purecall_handler(previous_pch_); + + if (handler_stack_->back() == this) { + handler_stack_->pop_back(); + } else { + // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the + // system's application event log. + fprintf(stderr, "warning: removing Breakpad handler out of order\n"); + for (vector::iterator iterator = + handler_stack_->begin(); + iterator != handler_stack_->end(); + ++iterator) { + if (*iterator == this) { + handler_stack_->erase(iterator); + } + } + } + + if (handler_stack_->empty()) { + // When destroying the last ExceptionHandler that installed a handler, + // clean up the handler stack. + delete handler_stack_; + handler_stack_ = NULL; + } + + LeaveCriticalSection(&handler_stack_critical_section_); + } + + // Some of the objects were only initialized if out of process + // registration was not done. + if (!IsOutOfProcess()) { +#ifdef BREAKPAD_NO_TERMINATE_THREAD + // Clean up the handler thread and synchronization primitives. The handler + // thread is either waiting on the semaphore to handle a crash or it is + // handling a crash. Coming out of the wait is fast but wait more in the + // eventuality a crash is handled. This compilation option results in a + // deadlock if the exception handler is destroyed while executing code + // inside DllMain. + is_shutdown_ = true; + ReleaseSemaphore(handler_start_semaphore_, 1, NULL); + WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs); +#else + TerminateThread(handler_thread_, 1); +#endif // BREAKPAD_NO_TERMINATE_THREAD + + DeleteCriticalSection(&handler_critical_section_); + CloseHandle(handler_start_semaphore_); + CloseHandle(handler_finish_semaphore_); + } + + // There is a race condition in the code below: if this instance is + // deleting the static critical section and a new instance of the class + // is created, then there is a possibility that the critical section be + // initialized while the same critical section is being deleted. Given the + // usage pattern for the code, this race condition is unlikely to hit, but it + // is a race condition nonetheless. + if (InterlockedDecrement(&instance_count_) == 0) { + DeleteCriticalSection(&handler_stack_critical_section_); + } +} + +// static +DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { + ExceptionHandler* self = reinterpret_cast(lpParameter); + assert(self); + assert(self->handler_start_semaphore_ != NULL); + assert(self->handler_finish_semaphore_ != NULL); + + while (true) { + if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == + WAIT_OBJECT_0) { + // Perform the requested action. + if (self->is_shutdown_) { + // The instance of the exception handler is being destroyed. + break; + } else { + self->handler_return_value_ = + self->WriteMinidumpWithException(self->requesting_thread_id_, + self->exception_info_, + self->assertion_); + } + + // Allow the requesting thread to proceed. + ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); + } + } + + // This statement is not reached when the thread is unconditionally + // terminated by the ExceptionHandler destructor. + return 0; +} + +// HandleException and HandleInvalidParameter must create an +// AutoExceptionHandler object to maintain static state and to determine which +// ExceptionHandler instance to use. The constructor locates the correct +// instance, and makes it available through get_handler(). The destructor +// restores the state in effect prior to allocating the AutoExceptionHandler. +class AutoExceptionHandler { + public: + AutoExceptionHandler() { + // Increment handler_stack_index_ so that if another Breakpad handler is + // registered using this same HandleException function, and it needs to be + // called while this handler is running (either becaause this handler + // declines to handle the exception, or an exception occurs during + // handling), HandleException will find the appropriate ExceptionHandler + // object in handler_stack_ to deliver the exception to. + // + // Because handler_stack_ is addressed in reverse (as |size - index|), + // preincrementing handler_stack_index_ avoids needing to subtract 1 from + // the argument to |at|. + // + // The index is maintained instead of popping elements off of the handler + // stack and pushing them at the end of this method. This avoids ruining + // the order of elements in the stack in the event that some other thread + // decides to manipulate the handler stack (such as creating a new + // ExceptionHandler object) while an exception is being handled. + EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_); + handler_ = ExceptionHandler::handler_stack_->at( + ExceptionHandler::handler_stack_->size() - + ++ExceptionHandler::handler_stack_index_); + LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); + + // In case another exception occurs while this handler is doing its thing, + // it should be delivered to the previous filter. + SetUnhandledExceptionFilter(handler_->previous_filter_); +#if _MSC_VER >= 1400 // MSVC 2005/8 + _set_invalid_parameter_handler(handler_->previous_iph_); +#endif // _MSC_VER >= 1400 + _set_purecall_handler(handler_->previous_pch_); + } + + ~AutoExceptionHandler() { + // Put things back the way they were before entering this handler. + SetUnhandledExceptionFilter(ExceptionHandler::HandleException); +#if _MSC_VER >= 1400 // MSVC 2005/8 + _set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter); +#endif // _MSC_VER >= 1400 + _set_purecall_handler(ExceptionHandler::HandlePureVirtualCall); + + EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_); + --ExceptionHandler::handler_stack_index_; + LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); + } + + ExceptionHandler* get_handler() const { return handler_; } + + private: + ExceptionHandler* handler_; +}; + +// static +LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) { + AutoExceptionHandler auto_exception_handler; + ExceptionHandler* current_handler = auto_exception_handler.get_handler(); + + // Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions. This + // logic will short-circuit before calling WriteMinidumpOnHandlerThread, + // allowing something else to handle the breakpoint without incurring the + // overhead transitioning to and from the handler thread. This behavior + // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions. + DWORD code = exinfo->ExceptionRecord->ExceptionCode; + LONG action; + bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) || + (code == EXCEPTION_SINGLE_STEP); + + bool success = false; + + if (!is_debug_exception || + current_handler->get_handle_debug_exceptions()) { + // If out-of-proc crash handler client is available, we have to use that + // to generate dump and we cannot fall back on in-proc dump generation + // because we never prepared for an in-proc dump generation + + // In case of out-of-process dump generation, directly call + // WriteMinidumpWithException since there is no separate thread running. + if (current_handler->IsOutOfProcess()) { + success = current_handler->WriteMinidumpWithException( + GetCurrentThreadId(), + exinfo, + NULL); + } else { + success = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL); + } + } + + // The handler fully handled the exception. Returning + // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually + // results in the application being terminated. + // + // Note: If the application was launched from within the Cygwin + // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the + // application to be restarted. + if (success) { + action = EXCEPTION_EXECUTE_HANDLER; + } else { + // There was an exception, it was a breakpoint or something else ignored + // above, or it was passed to the handler, which decided not to handle it. + // This could be because the filter callback didn't want it, because + // minidump writing failed for some reason, or because the post-minidump + // callback function indicated failure. Give the previous handler a + // chance to do something with the exception. If there is no previous + // handler, return EXCEPTION_CONTINUE_SEARCH, which will allow a debugger + // or native "crashed" dialog to handle the exception. + if (current_handler->previous_filter_) { + action = current_handler->previous_filter_(exinfo); + } else { + action = EXCEPTION_CONTINUE_SEARCH; + } + } + + return action; +} + +#if _MSC_VER >= 1400 // MSVC 2005/8 +// static +void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression, + const wchar_t* function, + const wchar_t* file, + unsigned int line, + uintptr_t reserved) { + // This is an invalid parameter, not an exception. It's safe to play with + // sprintf here. + AutoExceptionHandler auto_exception_handler; + ExceptionHandler* current_handler = auto_exception_handler.get_handler(); + + MDRawAssertionInfo assertion; + memset(&assertion, 0, sizeof(assertion)); + _snwprintf_s(reinterpret_cast(assertion.expression), + sizeof(assertion.expression) / sizeof(assertion.expression[0]), + _TRUNCATE, L"%s", expression); + _snwprintf_s(reinterpret_cast(assertion.function), + sizeof(assertion.function) / sizeof(assertion.function[0]), + _TRUNCATE, L"%s", function); + _snwprintf_s(reinterpret_cast(assertion.file), + sizeof(assertion.file) / sizeof(assertion.file[0]), + _TRUNCATE, L"%s", file); + assertion.line = line; + assertion.type = MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER; + + bool success = false; + // In case of out-of-process dump generation, directly call + // WriteMinidumpWithException since there is no separate thread running. + if (current_handler->IsOutOfProcess()) { + success = current_handler->WriteMinidumpWithException( + GetCurrentThreadId(), + NULL, + &assertion); + } else { + success = current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion); + } + + if (!success) { + if (current_handler->previous_iph_) { + // The handler didn't fully handle the exception. Give it to the + // previous invalid parameter handler. + current_handler->previous_iph_(expression, + function, + file, + line, + reserved); + } else { + // If there's no previous handler, pass the exception back in to the + // invalid parameter handler's core. That's the routine that called this + // function, but now, since this function is no longer registered (and in + // fact, no function at all is registered), this will result in the + // default code path being taken: _CRT_DEBUGGER_HOOK and _invoke_watson. + // Use _invalid_parameter where it exists (in _DEBUG builds) as it passes + // more information through. In non-debug builds, it is not available, + // so fall back to using _invalid_parameter_noinfo. See invarg.c in the + // CRT source. +#ifdef _DEBUG + _invalid_parameter(expression, function, file, line, reserved); +#else // _DEBUG + _invalid_parameter_noinfo(); +#endif // _DEBUG + } + } + + // The handler either took care of the invalid parameter problem itself, + // or passed it on to another handler. "Swallow" it by exiting, paralleling + // the behavior of "swallowing" exceptions. + exit(0); +} +#endif // _MSC_VER >= 1400 + +// static +void ExceptionHandler::HandlePureVirtualCall() { + AutoExceptionHandler auto_exception_handler; + ExceptionHandler* current_handler = auto_exception_handler.get_handler(); + + MDRawAssertionInfo assertion; + memset(&assertion, 0, sizeof(assertion)); + assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL; + + bool success = false; + // In case of out-of-process dump generation, directly call + // WriteMinidumpWithException since there is no separate thread running. + + if (current_handler->IsOutOfProcess()) { + success = current_handler->WriteMinidumpWithException( + GetCurrentThreadId(), + NULL, + &assertion); + } else { + success = current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion); + } + + if (!success) { + if (current_handler->previous_pch_) { + // The handler didn't fully handle the exception. Give it to the + // previous purecall handler. + current_handler->previous_pch_(); + } else { + // If there's no previous handler, return and let _purecall handle it. + // This will just put up an assertion dialog. + return; + } + } + + // The handler either took care of the invalid parameter problem itself, + // or passed it on to another handler. "Swallow" it by exiting, paralleling + // the behavior of "swallowing" exceptions. + exit(0); +} + +bool ExceptionHandler::WriteMinidumpOnHandlerThread( + EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { + EnterCriticalSection(&handler_critical_section_); + + // There isn't much we can do if the handler thread + // was not successfully created. + if (handler_thread_ == NULL) { + LeaveCriticalSection(&handler_critical_section_); + return false; + } + + // The handler thread should only be created when the semaphores are valid. + assert(handler_start_semaphore_ != NULL); + assert(handler_finish_semaphore_ != NULL); + + // Set up data to be passed in to the handler thread. + requesting_thread_id_ = GetCurrentThreadId(); + exception_info_ = exinfo; + assertion_ = assertion; + + // This causes the handler thread to call WriteMinidumpWithException. + ReleaseSemaphore(handler_start_semaphore_, 1, NULL); + + // Wait until WriteMinidumpWithException is done and collect its return value. + WaitForSingleObject(handler_finish_semaphore_, INFINITE); + bool status = handler_return_value_; + + // Clean up. + requesting_thread_id_ = 0; + exception_info_ = NULL; + assertion_ = NULL; + + LeaveCriticalSection(&handler_critical_section_); + + return status; +} + +bool ExceptionHandler::WriteMinidump() { + return WriteMinidumpForException(NULL); +} + +bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) { + // In case of out-of-process dump generation, directly call + // WriteMinidumpWithException since there is no separate thread running. + if (IsOutOfProcess()) { + return WriteMinidumpWithException(GetCurrentThreadId(), + exinfo, + NULL); + } + + bool success = WriteMinidumpOnHandlerThread(exinfo, NULL); + UpdateNextID(); + return success; +} + +// static +bool ExceptionHandler::WriteMinidump(const wstring &dump_path, + MinidumpCallback callback, + void* callback_context) { + ExceptionHandler handler(dump_path, NULL, callback, callback_context, + HANDLER_NONE); + return handler.WriteMinidump(); +} + +bool ExceptionHandler::WriteMinidumpWithException( + DWORD requesting_thread_id, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion) { + // Give user code a chance to approve or prevent writing a minidump. If the + // filter returns false, don't handle the exception at all. If this method + // was called as a result of an exception, returning false will cause + // HandleException to call any previous handler or return + // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear + // as though this handler were not present at all. + if (filter_ && !filter_(callback_context_, exinfo, assertion)) { + return false; + } + + bool success = false; + if (IsOutOfProcess()) { + // Use the EXCEPTION_POINTERS overload for RequestDump if + // both exinfo and assertion are NULL. + if (!assertion) { + success = crash_generation_client_->RequestDump(exinfo); + } else { + success = crash_generation_client_->RequestDump(assertion); + } + } else { + if (minidump_write_dump_) { + HANDLE dump_file = CreateFile(next_minidump_path_c_, + GENERIC_WRITE, + 0, // no sharing + NULL, + CREATE_NEW, // fail if exists + FILE_ATTRIBUTE_NORMAL, + NULL); + if (dump_file != INVALID_HANDLE_VALUE) { + MINIDUMP_EXCEPTION_INFORMATION except_info; + except_info.ThreadId = requesting_thread_id; + except_info.ExceptionPointers = exinfo; + except_info.ClientPointers = FALSE; + + // Add an MDRawBreakpadInfo stream to the minidump, to provide additional + // information about the exception handler to the Breakpad processor. The + // information will help the processor determine which threads are + // relevant. The Breakpad processor does not require this information but + // can function better with Breakpad-generated dumps when it is present. + // The native debugger is not harmed by the presence of this information. + MDRawBreakpadInfo breakpad_info; + breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; + breakpad_info.dump_thread_id = GetCurrentThreadId(); + breakpad_info.requesting_thread_id = requesting_thread_id; + + // Leave room in user_stream_array for a possible assertion info stream. + MINIDUMP_USER_STREAM user_stream_array[2]; + user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; + user_stream_array[0].BufferSize = sizeof(breakpad_info); + user_stream_array[0].Buffer = &breakpad_info; + + MINIDUMP_USER_STREAM_INFORMATION user_streams; + user_streams.UserStreamCount = 1; + user_streams.UserStreamArray = user_stream_array; + + if (assertion) { + user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM; + user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo); + user_stream_array[1].Buffer = assertion; + ++user_streams.UserStreamCount; + } + + // The explicit comparison to TRUE avoids a warning (C4800). + success = (minidump_write_dump_(GetCurrentProcess(), + GetCurrentProcessId(), + dump_file, + dump_type_, + exinfo ? &except_info : NULL, + &user_streams, + NULL) == TRUE); + + CloseHandle(dump_file); + } + } + } + + if (callback_) { + // TODO(munjal): In case of out-of-process dump generation, both + // dump_path_c_ and next_minidump_id_ will be NULL. For out-of-process + // scenario, the server process ends up creating the dump path and dump + // id so they are not known to the client. + success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_, + exinfo, assertion, success); + } + + return success; +} + +void ExceptionHandler::UpdateNextID() { + assert(uuid_create_); + UUID id = {0}; + if (uuid_create_) { + uuid_create_(&id); + } + next_minidump_id_ = GUIDString::GUIDToWString(&id); + next_minidump_id_c_ = next_minidump_id_.c_str(); + + wchar_t minidump_path[MAX_PATH]; + swprintf(minidump_path, MAX_PATH, L"%s\\%s.dmp", + dump_path_c_, next_minidump_id_c_); + + // remove when VC++7.1 is no longer supported + minidump_path[MAX_PATH - 1] = L'\0'; + + next_minidump_path_ = minidump_path; + next_minidump_path_c_ = next_minidump_path_.c_str(); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.h b/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.h new file mode 100644 index 00000000..2cacdc38 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/handler/exception_handler.h @@ -0,0 +1,415 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ExceptionHandler can write a minidump file when an exception occurs, +// or when WriteMinidump() is called explicitly by your program. +// +// To have the exception handler write minidumps when an uncaught exception +// (crash) occurs, you should create an instance early in the execution +// of your program, and keep it around for the entire time you want to +// have crash handling active (typically, until shutdown). +// +// If you want to write minidumps without installing the exception handler, +// you can create an ExceptionHandler with install_handler set to false, +// then call WriteMinidump. You can also use this technique if you want to +// use different minidump callbacks for different call sites. +// +// In either case, a callback function is called when a minidump is written, +// which receives the unqiue id of the minidump. The caller can use this +// id to collect and write additional application state, and to launch an +// external crash-reporting application. +// +// It is important that creation and destruction of ExceptionHandler objects +// be nested cleanly, when using install_handler = true. +// Avoid the following pattern: +// ExceptionHandler *e = new ExceptionHandler(...); +// ExceptionHandler *f = new ExceptionHandler(...); +// delete e; +// This will put the exception filter stack into an inconsistent state. + +#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ +#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ + +#include +#include +#include +#include + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/crash_generation/crash_generation_client.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/scoped_ptr.h" + +namespace google_breakpad { + +using std::vector; +using std::wstring; + +class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. exinfo points to the + // exception record, if any; assertion points to assertion information, + // if any. + // + // If a FilterCallback returns true, Breakpad will continue processing, + // attempting to write a minidump. If a FilterCallback returns false, Breakpad + // will immediately report the exception as unhandled without writing a + // minidump, allowing another handler the opportunity to handle it. + typedef bool (*FilterCallback)(void* context, EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // A callback function to run after the minidump has been written. + // minidump_id is a unique id for the dump, so the minidump + // file is \.dmp. context is the parameter supplied + // by the user as callback_context when the handler was created. exinfo + // points to the exception record, or NULL if no exception occurred. + // succeeded indicates whether a minidump file was successfully written. + // assertion points to information about an assertion if the handler was + // invoked by an assertion. + // + // If an exception occurred and the callback returns true, Breakpad will treat + // the exception as fully-handled, suppressing any other handlers from being + // notified of the exception. If the callback returns false, Breakpad will + // treat the exception as unhandled, and allow another handler to handle it. + // If there are no other handlers, Breakpad will report the exception to the + // system as unhandled, allowing a debugger or native crash dialog the + // opportunity to handle the exception. Most callback implementations + // should normally return the value of |succeeded|, or when they wish to + // not report an exception of handled, false. Callbacks will rarely want to + // return true directly (unless |succeeded| is true). + // + // For out-of-process dump generation, dump path and minidump ID will always + // be NULL. In case of out-of-process dump generation, the dump path and + // minidump id are controlled by the server process and are not communicated + // back to the crashing process. + typedef bool (*MinidumpCallback)(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded); + + // HandlerType specifies which types of handlers should be installed, if + // any. Use HANDLER_NONE for an ExceptionHandler that remains idle, + // without catching any failures on its own. This type of handler may + // still be triggered by calling WriteMinidump. Otherwise, use a + // combination of the other HANDLER_ values, or HANDLER_ALL to install + // all handlers. + enum HandlerType { + HANDLER_NONE = 0, + HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter + HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler + HANDLER_PURECALL = 1 << 2, // _set_purecall_handler + HANDLER_ALL = HANDLER_EXCEPTION | + HANDLER_INVALID_PARAMETER | + HANDLER_PURECALL + }; + + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Before writing a minidump, the optional filter callback will be called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // handler_types specifies the types of handlers that should be installed. + ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types); + + // Creates a new ExcetpionHandler instance that can attempt to perform + // out-of-process dump generation if pipe_name is not NULL. If pipe_name is + // NULL, or if out-of-process dump generation registration step fails, + // in-process dump generation will be used. This also allows specifying + // the dump type to generate. + ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info); + + ~ExceptionHandler(); + + // Get and set the minidump path. + wstring dump_path() const { return dump_path_; } + void set_dump_path(const wstring &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. + } + + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Writes a minidump immediately, with the user-supplied exception + // information. + bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. + static bool WriteMinidump(const wstring &dump_path, + MinidumpCallback callback, void* callback_context); + + // Get the thread ID of the thread requesting the dump (either the exception + // thread or any other thread that called WriteMinidump directly). This + // may be useful if you want to include additional thread state in your + // dumps. + DWORD get_requesting_thread_id() const { return requesting_thread_id_; } + + // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP. + bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; } + void set_handle_debug_exceptions(bool handle_debug_exceptions) { + handle_debug_exceptions_ = handle_debug_exceptions; + } + + // Returns whether out-of-process dump generation is used or not. + bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; } + + private: + friend class AutoExceptionHandler; + + // Initializes the instance with given values. + void Initialize(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info); + + // Function pointer type for MiniDumpWriteDump, which is looked up + // dynamically. + typedef BOOL (WINAPI *MiniDumpWriteDump_type)( + HANDLE hProcess, + DWORD dwPid, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + + // Function pointer type for UuidCreate, which is looked up dynamically. + typedef RPC_STATUS (RPC_ENTRY *UuidCreate_type)(UUID* Uuid); + + // Runs the main loop for the exception handler thread. + static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter); + + // Called on the exception thread when an unhandled exception occurs. + // Signals the exception handler thread to handle the exception. + static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); + +#if _MSC_VER >= 1400 // MSVC 2005/8 + // This function will be called by some CRT functions when they detect + // that they were passed an invalid parameter. Note that in _DEBUG builds, + // the CRT may display an assertion dialog before calling this function, + // and the function will not be called unless the assertion dialog is + // dismissed by clicking "Ignore." + static void HandleInvalidParameter(const wchar_t* expression, + const wchar_t* function, + const wchar_t* file, + unsigned int line, + uintptr_t reserved); +#endif // _MSC_VER >= 1400 + + // This function will be called by the CRT when a pure virtual + // function is called. + static void HandlePureVirtualCall(); + + // This is called on the exception thread or on another thread that + // the user wishes to produce a dump from. It calls + // WriteMinidumpWithException on the handler thread, avoiding stack + // overflows and inconsistent dumps due to writing the dump from + // the exception thread. If the dump is requested as a result of an + // exception, exinfo contains exception information, otherwise, it + // is NULL. If the dump is requested as a result of an assertion + // (such as an invalid parameter being passed to a CRT function), + // assertion contains data about the assertion, otherwise, it is NULL. + bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // This function does the actual writing of a minidump. It is called + // on the handler thread. requesting_thread_id is the ID of the thread + // that requested the dump. If the dump is requested as a result of + // an exception, exinfo contains exception information, otherwise, + // it is NULL. + bool WriteMinidumpWithException(DWORD requesting_thread_id, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion); + + // Generates a new ID and stores it in next_minidump_id_, and stores the + // path of the next minidump to be written in next_minidump_path_. + void UpdateNextID(); + + FilterCallback filter_; + MinidumpCallback callback_; + void* callback_context_; + + scoped_ptr crash_generation_client_; + + // The directory in which a minidump will be written, set by the dump_path + // argument to the constructor, or set_dump_path. + wstring dump_path_; + + // The basename of the next minidump to be written, without the extension. + wstring next_minidump_id_; + + // The full pathname of the next minidump to be written, including the file + // extension. + wstring next_minidump_path_; + + // Pointers to C-string representations of the above. These are set when + // the above wstring versions are set in order to avoid calling c_str during + // an exception, as c_str may attempt to allocate heap memory. These + // pointers are not owned by the ExceptionHandler object, but their lifetimes + // should be equivalent to the lifetimes of the associated wstring, provided + // that the wstrings are not altered. + const wchar_t* dump_path_c_; + const wchar_t* next_minidump_id_c_; + const wchar_t* next_minidump_path_c_; + + HMODULE dbghelp_module_; + MiniDumpWriteDump_type minidump_write_dump_; + MINIDUMP_TYPE dump_type_; + + HMODULE rpcrt4_module_; + UuidCreate_type uuid_create_; + + // Tracks the handler types that were installed according to the + // handler_types constructor argument. + int handler_types_; + + // When installed_handler_ is true, previous_filter_ is the unhandled + // exception filter that was set prior to installing ExceptionHandler as + // the unhandled exception filter and pointing it to |this|. NULL indicates + // that there is no previous unhandled exception filter. + LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_; + +#if _MSC_VER >= 1400 // MSVC 2005/8 + // Beginning in VC 8, the CRT provides an invalid parameter handler that will + // be called when some CRT functions are passed invalid parameters. In + // earlier CRTs, the same conditions would cause unexpected behavior or + // crashes. + _invalid_parameter_handler previous_iph_; +#endif // _MSC_VER >= 1400 + + // The CRT allows you to override the default handler for pure + // virtual function calls. + _purecall_handler previous_pch_; + + // The exception handler thread. + HANDLE handler_thread_; + + // True if the exception handler is being destroyed. + // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars. + // It has release semantics on write and acquire semantics on reads. + // See the msdn documentation. + volatile bool is_shutdown_; + + // The critical section enforcing the requirement that only one exception be + // handled by a handler at a time. + CRITICAL_SECTION handler_critical_section_; + + // Semaphores used to move exception handling between the exception thread + // and the handler thread. handler_start_semaphore_ is signalled by the + // exception thread to wake up the handler thread when an exception occurs. + // handler_finish_semaphore_ is signalled by the handler thread to wake up + // the exception thread when handling is complete. + HANDLE handler_start_semaphore_; + HANDLE handler_finish_semaphore_; + + // The next 2 fields contain data passed from the requesting thread to + // the handler thread. + + // The thread ID of the thread requesting the dump (either the exception + // thread or any other thread that called WriteMinidump directly). + DWORD requesting_thread_id_; + + // The exception info passed to the exception handler on the exception + // thread, if an exception occurred. NULL for user-requested dumps. + EXCEPTION_POINTERS* exception_info_; + + // If the handler is invoked due to an assertion, this will contain a + // pointer to the assertion information. It is NULL at other times. + MDRawAssertionInfo* assertion_; + + // The return value of the handler, passed from the handler thread back to + // the requesting thread. + bool handler_return_value_; + + // If true, the handler will intercept EXCEPTION_BREAKPOINT and + // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default) + // to not interfere with debuggers. + bool handle_debug_exceptions_; + + // A stack of ExceptionHandler objects that have installed unhandled + // exception filters. This vector is used by HandleException to determine + // which ExceptionHandler object to route an exception to. When an + // ExceptionHandler is created with install_handler true, it will append + // itself to this list. + static vector* handler_stack_; + + // The index of the ExceptionHandler in handler_stack_ that will handle the + // next exception. Note that 0 means the last entry in handler_stack_, 1 + // means the next-to-last entry, and so on. This is used by HandleException + // to support multiple stacked Breakpad handlers. + static LONG handler_stack_index_; + + // handler_stack_critical_section_ guards operations on handler_stack_ and + // handler_stack_index_. The critical section is initialized by the + // first instance of the class and destroyed by the last instance of it. + static CRITICAL_SECTION handler_stack_critical_section_; + + // The number of instances of this class. + volatile static LONG instance_count_; + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.cc b/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.cc new file mode 100644 index 00000000..7672acfd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.cc @@ -0,0 +1,143 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include + +#include "client/windows/sender/crash_report_sender.h" +#include "common/windows/http_upload.h" + +#if _MSC_VER < 1400 // MSVC 2005/8 +// Older MSVC doesn't have fscanf_s, but they are compatible as long as +// we don't use the string conversions (%s/%c/%S/%C). +#define fscanf_s fscanf +#endif + +namespace google_breakpad { + +static const char kCheckpointSignature[] = "GBP1\n"; + +CrashReportSender::CrashReportSender(const wstring &checkpoint_file) + : checkpoint_file_(checkpoint_file), + max_reports_per_day_(-1), + last_sent_date_(-1), + reports_sent_(0) { + FILE *fd; + if (OpenCheckpointFile(L"r", &fd) == 0) { + ReadCheckpoint(fd); + fclose(fd); + } +} + +ReportResult CrashReportSender::SendCrashReport( + const wstring &url, const map ¶meters, + const wstring &dump_file_name, wstring *report_code) { + int today = GetCurrentDate(); + if (today == last_sent_date_ && + max_reports_per_day_ != -1 && + reports_sent_ >= max_reports_per_day_) { + return RESULT_THROTTLED; + } + + int http_response = 0; + bool result = HTTPUpload::SendRequest( + url, parameters, dump_file_name, L"upload_file_minidump", report_code, + &http_response); + + if (result) { + ReportSent(today); + return RESULT_SUCCEEDED; + } else if (http_response == 400) { // TODO: update if/when the server + // switches to a different code + return RESULT_REJECTED; + } else { + return RESULT_FAILED; + } +} + +void CrashReportSender::ReadCheckpoint(FILE *fd) { + char buf[128]; + if (!fgets(buf, sizeof(buf), fd) || + strcmp(buf, kCheckpointSignature) != 0) { + return; + } + + if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) { + last_sent_date_ = -1; + return; + } + if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) { + reports_sent_ = 0; + return; + } +} + +void CrashReportSender::ReportSent(int today) { + // Update the report stats + if (today != last_sent_date_) { + last_sent_date_ = today; + reports_sent_ = 0; + } + ++reports_sent_; + + // Update the checkpoint file + FILE *fd; + if (OpenCheckpointFile(L"w", &fd) == 0) { + fputs(kCheckpointSignature, fd); + fprintf(fd, "%d\n", last_sent_date_); + fprintf(fd, "%d\n", reports_sent_); + fclose(fd); + } +} + +int CrashReportSender::GetCurrentDate() const { + SYSTEMTIME system_time; + GetSystemTime(&system_time); + return (system_time.wYear * 10000) + (system_time.wMonth * 100) + + system_time.wDay; +} + +int CrashReportSender::OpenCheckpointFile(const wchar_t *mode, FILE **fd) { + if (checkpoint_file_.empty()) { + return ENOENT; + } +#if _MSC_VER >= 1400 // MSVC 2005/8 + return _wfopen_s(fd, checkpoint_file_.c_str(), mode); +#else + *fd = _wfopen(checkpoint_file_.c_str(), mode); + if (*fd == NULL) { + return errno; + } + return 0; +#endif +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.h b/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.h new file mode 100644 index 00000000..da1ed0af --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/sender/crash_report_sender.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ +#define CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ + +// CrashReportSender is a "static" class which provides an API to upload +// crash reports via HTTP(S). A crash report is formatted as a multipart POST +// request, which contains a set of caller-supplied string key/value pairs, +// and a minidump file to upload. +// +// To use this library in your project, you will need to link against +// wininet.lib. + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +namespace google_breakpad { + +using std::wstring; +using std::map; + +typedef enum { + RESULT_FAILED = 0, // Failed to communicate with the server; try later. + RESULT_REJECTED, // Successfully sent the crash report, but the + // server rejected it; don't resend this report. + RESULT_SUCCEEDED, // The server accepted the crash report. + RESULT_THROTTLED // No attempt was made to send the crash report, because + // we exceeded the maximum reports per day. +} ReportResult; + +class CrashReportSender { + public: + // Initializes a CrashReportSender instance. + // If checkpoint_file is non-empty, breakpad will persist crash report + // state to this file. A checkpoint file is required for + // set_max_reports_per_day() to function properly. + explicit CrashReportSender(const wstring &checkpoint_file); + ~CrashReportSender() {} + + // Sets the maximum number of crash reports that will be sent in a 24-hour + // period. This uses the state persisted to the checkpoint file. + // The default value of -1 means that there is no limit on reports sent. + void set_max_reports_per_day(int reports) { + max_reports_per_day_ = reports; + } + + int max_reports_per_day() const { return max_reports_per_day_; } + + // Sends the specified minidump file, along with the map of + // name value pairs, as a multipart POST request to the given URL. + // Parameter names must contain only printable ASCII characters, + // and may not contain a quote (") character. + // Only HTTP(S) URLs are currently supported. The return value indicates + // the result of the operation (see above for possible results). + // If report_code is non-NULL and the report is sent successfully (that is, + // the return value is RESULT_SUCCEEDED), a code uniquely identifying the + // report will be returned in report_code. + // (Otherwise, report_code will be unchanged.) + ReportResult SendCrashReport(const wstring &url, + const map ¶meters, + const wstring &dump_file_name, + wstring *report_code); + + private: + // Reads persistent state from a checkpoint file. + void ReadCheckpoint(FILE *fd); + + // Called when a new report has been sent, to update the checkpoint state. + void ReportSent(int today); + + // Returns today's date (UTC) formatted as YYYYMMDD. + int GetCurrentDate() const; + + // Opens the checkpoint file with the specified mode. + // Returns zero on success, or an error code on failure. + int OpenCheckpointFile(const wchar_t *mode, FILE **fd); + + wstring checkpoint_file_; + int max_reports_per_day_; + // The last date on which we sent a report, expressed as YYYYMMDD. + int last_sent_date_; + // Number of reports sent on last_sent_date_ + int reports_sent_; + + // Disallow copy constructor and operator= + explicit CrashReportSender(const CrashReportSender &); + void operator=(const CrashReportSender &); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.cc b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.cc new file mode 100644 index 00000000..f71addfb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.cc @@ -0,0 +1,53 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "precompile.h" + +namespace google_breakpad { + +Base::Base(Derived* derived) + : derived_(derived) { +} + +Base::~Base() { + derived_->DoSomething(); +} + +#pragma warning(push) +#pragma warning(disable:4355) +// Disable warning C4355: 'this' : used in base member initializer list. +Derived::Derived() + : Base(this) { // C4355 +} +#pragma warning(pop) + +void Derived::DoSomething() { +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.h b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.h new file mode 100644 index 00000000..e3f2a4f3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/abstract_class.h @@ -0,0 +1,57 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__ +#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__ + +namespace google_breakpad { + +// Dummy classes to help generate a pure call violation. + +class Derived; + +class Base { + public: + Base(Derived* derived); + virtual ~Base(); + virtual void DoSomething() = 0; + + private: + Derived* derived_; +}; + +class Derived : public Base { + public: + Derived(); + virtual void DoSomething(); +}; + +} // namespace google_breakpad + +#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.cc new file mode 100644 index 00000000..a3c560bd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.cc @@ -0,0 +1,510 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// crash_generation_app.cpp : Defines the entry point for the application. +// + +#include "precompile.h" + +namespace google_breakpad { + +const int kMaxLoadString = 100; +const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashServices\\TestServer"; + +const DWORD kEditBoxStyles = WS_CHILD | + WS_VISIBLE | + WS_VSCROLL | + ES_LEFT | + ES_MULTILINE | + ES_AUTOVSCROLL | + ES_READONLY; + +// Maximum length of a line in the edit box. +const size_t kMaximumLineLength = 256; + +// CS to access edit control in a thread safe way. +static CRITICAL_SECTION* cs_edit = NULL; + +// Edit control. +static HWND client_status_edit_box; + +HINSTANCE current_instance; // Current instance. +TCHAR title[kMaxLoadString]; // Title bar text. +TCHAR window_class[kMaxLoadString]; // Main window class name. + +ATOM MyRegisterClass(HINSTANCE instance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +static int kCustomInfoCount = 2; +static CustomInfoEntry kCustomInfoEntries[] = { + CustomInfoEntry(L"prod", L"CrashTestApp"), + CustomInfoEntry(L"ver", L"1.0"), +}; + +static ExceptionHandler* handler = NULL; +static CrashGenerationServer* crash_server = NULL; + +// Registers the window class. +// +// This function and its usage are only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this +// function so that the application will get 'well formed' small icons +// associated with it. +ATOM MyRegisterClass(HINSTANCE instance) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = instance; + wcex.hIcon = LoadIcon(instance, + MAKEINTRESOURCE(IDI_CRASHGENERATIONAPP)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP); + wcex.lpszClassName = window_class; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +// Saves instance handle and creates main window +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +BOOL InitInstance(HINSTANCE instance, int command_show) { + current_instance = instance; + HWND wnd = CreateWindow(window_class, + title, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + 0, + CW_USEDEFAULT, + 0, + NULL, + NULL, + instance, + NULL); + + if (!wnd) { + return FALSE; + } + + ShowWindow(wnd, command_show); + UpdateWindow(wnd); + + return TRUE; +} + +static void AppendTextToEditBox(TCHAR* text) { + EnterCriticalSection(cs_edit); + SYSTEMTIME current_time; + GetLocalTime(¤t_time); + TCHAR line[kMaximumLineLength]; + int result = swprintf_s(line, + kMaximumLineLength, + L"[%.2d-%.2d-%.4d %.2d:%.2d:%.2d] %s", + current_time.wMonth, + current_time.wDay, + current_time.wYear, + current_time.wHour, + current_time.wMinute, + current_time.wSecond, + text); + + if (result == -1) { + return; + } + + int length = GetWindowTextLength(client_status_edit_box); + SendMessage(client_status_edit_box, + EM_SETSEL, + (WPARAM)length, + (LPARAM)length); + SendMessage(client_status_edit_box, + EM_REPLACESEL, + (WPARAM)FALSE, + (LPARAM)line); + LeaveCriticalSection(cs_edit); +} + +static DWORD WINAPI AppendTextWorker(void* context) { + TCHAR* text = reinterpret_cast(context); + + AppendTextToEditBox(text); + delete[] text; + + return 0; +} + +bool ShowDumpResults(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded) { + TCHAR* text = new TCHAR[kMaximumLineLength]; + text[0] = _T('\0'); + int result = swprintf_s(text, + kMaximumLineLength, + TEXT("Dump generation request %s\r\n"), + succeeded ? TEXT("succeeded") : TEXT("failed")); + if (result == -1) { + delete [] text; + } + + AppendTextWorker(text); + return succeeded; +} + +static void _cdecl ShowClientConnected(void* context, + const ClientInfo* client_info) { + TCHAR* line = new TCHAR[kMaximumLineLength]; + line[0] = _T('\0'); + int result = swprintf_s(line, + kMaximumLineLength, + L"Client connected:\t\t%d\r\n", + client_info->pid()); + + if (result == -1) { + delete[] line; + return; + } + + QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); +} + +static void _cdecl ShowClientCrashed(void* context, + const ClientInfo* client_info, + const wstring* dump_path) { + TCHAR* line = new TCHAR[kMaximumLineLength]; + line[0] = _T('\0'); + int result = swprintf_s(line, + kMaximumLineLength, + TEXT("Client requested dump:\t%d\r\n"), + client_info->pid()); + + if (result == -1) { + delete[] line; + return; + } + + QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); + + CustomClientInfo custom_info = client_info->GetCustomInfo(); + if (custom_info.count <= 0) { + return; + } + + wstring str_line; + for (int i = 0; i < custom_info.count; ++i) { + if (i > 0) { + str_line += L", "; + } + str_line += custom_info.entries[i].name; + str_line += L": "; + str_line += custom_info.entries[i].value; + } + + line = new TCHAR[kMaximumLineLength]; + line[0] = _T('\0'); + result = swprintf_s(line, + kMaximumLineLength, + L"%s\n", + str_line.c_str()); + if (result == -1) { + delete[] line; + return; + } + QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); +} + +static void _cdecl ShowClientExited(void* context, + const ClientInfo* client_info) { + TCHAR* line = new TCHAR[kMaximumLineLength]; + line[0] = _T('\0'); + int result = swprintf_s(line, + kMaximumLineLength, + TEXT("Client exited:\t\t%d\r\n"), + client_info->pid()); + + if (result == -1) { + delete[] line; + return; + } + + QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); +} + +void CrashServerStart() { + // Do not create another instance of the server. + if (crash_server) { + return; + } + + std::wstring dump_path = L"C:\\Dumps\\"; + crash_server = new CrashGenerationServer(kPipeName, + NULL, + ShowClientConnected, + NULL, + ShowClientCrashed, + NULL, + ShowClientExited, + NULL, + true, + &dump_path); + + if (!crash_server->Start()) { + MessageBoxW(NULL, L"Unable to start server", L"Dumper", MB_OK); + delete crash_server; + crash_server = NULL; + } +} + +void CrashServerStop() { + delete crash_server; + crash_server = NULL; +} + +void DerefZeroCrash() { + int* x = 0; + *x = 1; +} + +void InvalidParamCrash() { + printf(NULL); +} + +void PureCallCrash() { + Derived derived; +} + +void RequestDump() { + if (!handler->WriteMinidump()) { + MessageBoxW(NULL, L"Dump request failed", L"Dumper", MB_OK); + } + kCustomInfoEntries[1].set_value(L"1.1"); +} + +void CleanUp() { + if (cs_edit) { + DeleteCriticalSection(cs_edit); + delete cs_edit; + } + + if (handler) { + delete handler; + } + + if (crash_server) { + delete crash_server; + } +} + +// Processes messages for the main window. +// +// WM_COMMAND - process the application menu. +// WM_PAINT - Paint the main window. +// WM_DESTROY - post a quit message and return. +LRESULT CALLBACK WndProc(HWND wnd, + UINT message, + WPARAM w_param, + LPARAM l_param) { + int message_id; + int message_event; + PAINTSTRUCT ps; + HDC hdc; + +#pragma warning(push) +#pragma warning(disable:4312) + // Disable warning C4312: 'type cast' : conversion from 'LONG' to + // 'HINSTANCE' of greater size. + // The value returned by GetwindowLong in the case below returns unsigned. + HINSTANCE instance = (HINSTANCE)GetWindowLong(wnd, GWL_HINSTANCE); +#pragma warning(pop) + + switch (message) { + case WM_COMMAND: + // Parse the menu selections. + message_id = LOWORD(w_param); + message_event = HIWORD(w_param); + switch (message_id) { + case IDM_ABOUT: + DialogBox(current_instance, + MAKEINTRESOURCE(IDD_ABOUTBOX), + wnd, + About); + break; + case IDM_EXIT: + DestroyWindow(wnd); + break; + case ID_SERVER_START: + CrashServerStart(); + break; + case ID_SERVER_STOP: + CrashServerStop(); + break; + case ID_CLIENT_DEREFZERO: + DerefZeroCrash(); + break; + case ID_CLIENT_INVALIDPARAM: + InvalidParamCrash(); + break; + case ID_CLIENT_PURECALL: + PureCallCrash(); + break; + case ID_CLIENT_REQUESTEXPLICITDUMP: + RequestDump(); + break; + default: + return DefWindowProc(wnd, message, w_param, l_param); + } + break; + case WM_CREATE: + client_status_edit_box = CreateWindow(TEXT("EDIT"), + NULL, + kEditBoxStyles, + 0, + 0, + 0, + 0, + wnd, + NULL, + instance, + NULL); + break; + case WM_SIZE: + // Make the edit control the size of the window's client area. + MoveWindow(client_status_edit_box, + 0, + 0, + LOWORD(l_param), // width of client area. + HIWORD(l_param), // height of client area. + TRUE); // repaint window. + break; + case WM_SETFOCUS: + SetFocus(client_status_edit_box); + break; + case WM_PAINT: + hdc = BeginPaint(wnd, &ps); + EndPaint(wnd, &ps); + break; + case WM_DESTROY: + CleanUp(); + PostQuitMessage(0); + break; + default: + return DefWindowProc(wnd, message, w_param, l_param); + } + + return 0; +} + +// Message handler for about box. +INT_PTR CALLBACK About(HWND dlg, + UINT message, + WPARAM w_param, + LPARAM l_param) { + UNREFERENCED_PARAMETER(l_param); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(w_param) == IDOK || LOWORD(w_param) == IDCANCEL) { + EndDialog(dlg, LOWORD(w_param)); + return (INT_PTR)TRUE; + } + break; + } + + return (INT_PTR)FALSE; +} + +} // namespace google_breakpad + +int APIENTRY _tWinMain(HINSTANCE instance, + HINSTANCE previous_instance, + LPTSTR command_line, + int command_show) { + using namespace google_breakpad; + + UNREFERENCED_PARAMETER(previous_instance); + UNREFERENCED_PARAMETER(command_line); + + cs_edit = new CRITICAL_SECTION(); + InitializeCriticalSection(cs_edit); + + CustomClientInfo custom_info = {kCustomInfoEntries, kCustomInfoCount}; + + // This is needed for CRT to not show dialog for invalid param + // failures and instead let the code handle it. + _CrtSetReportMode(_CRT_ASSERT, 0); + handler = new ExceptionHandler(L"C:\\dumps\\", + NULL, + google_breakpad::ShowDumpResults, + NULL, + ExceptionHandler::HANDLER_ALL, + MiniDumpNormal, + kPipeName, + &custom_info); + + // Initialize global strings. + LoadString(instance, IDS_APP_TITLE, title, kMaxLoadString); + LoadString(instance, + IDC_CRASHGENERATIONAPP, + window_class, + kMaxLoadString); + MyRegisterClass(instance); + + // Perform application initialization. + if (!InitInstance (instance, command_show)) { + return FALSE; + } + + HACCEL accel_table = LoadAccelerators( + instance, + MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP)); + + // Main message loop. + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator(msg.hwnd, accel_table, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int)msg.wParam; +} + diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.h b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.h new file mode 100644 index 00000000..4d3bb6eb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.h @@ -0,0 +1,35 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ +#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ + +#include "resource.h" + +#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.ico b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.ico new file mode 100644 index 00000000..d551aa3a Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.ico differ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.rc b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.rc new file mode 100644 index 00000000..a362562b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/crash_generation_app.rc @@ -0,0 +1,144 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CRASHGENERATIONAPP ICON "crash_generation_app.ico" +IDI_SMALL ICON "small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_CRASHGENERATIONAPP MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Server" + BEGIN + MENUITEM "&Start", ID_SERVER_START + MENUITEM "S&top", ID_SERVER_STOP + END + POPUP "&Client" + BEGIN + MENUITEM "&Deref Zero", ID_CLIENT_DEREFZERO + MENUITEM "&Invalid Param", ID_CLIENT_INVALIDPARAM + MENUITEM "&Pure Call", ID_CLIENT_PURECALL + MENUITEM "&Request Dump", ID_CLIENT_REQUESTEXPLICITDUMP + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_CRASHGENERATIONAPP ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 22, 17, 230, 75 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_CRASHGENERATIONAPP,IDC_MYICON,14,9,16,16 + LTEXT "CrashGenerationApp Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2008",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "CrashGenerationApp" + IDC_CRASHGENERATIONAPP "CRASHGENERATIONAPP" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.cc b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.cc new file mode 100644 index 00000000..9d2173cc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// precompile.cpp : source file that includes just the standard includes +// CrashGenerationApp.pch will be the pre-compiled header +// precompile.obj will contain the pre-compiled type information + +#include "precompile.h" + +// Reference any additional headers you need in PRECOMPILE.H +// and not in this file. diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.h b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.h new file mode 100644 index 00000000..1ade4451 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/precompile.h @@ -0,0 +1,90 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// PreCompile.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__ +#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__ + +// Modify the following defines if you have to target a platform prior to +// the ones specified below. Refer to MSDN for the latest info on +// corresponding values for different platforms. + +// Allow use of features specific to Windows XP or later. +#ifndef WINVER +// Change this to the appropriate value to target other versions of Windows. +#define WINVER 0x0501 +#endif + +// Allow use of features specific to Windows XP or later. +#ifndef _WIN32_WINNT +// Change this to the appropriate value to target other versions of Windows. +#define _WIN32_WINNT 0x0501 +#endif + +// Allow use of features specific to Windows 98 or later. +#ifndef _WIN32_WINDOWS +// Change this to the appropriate value to target Windows Me or later. +#define _WIN32_WINDOWS 0x0410 +#endif + +// Allow use of features specific to IE 6.0 or later. +#ifndef _WIN32_IE +// Change this to the appropriate value to target other versions of IE. +#define _WIN32_IE 0x0600 +#endif + +// Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "client/windows/common/ipc_protocol.h" +#include "client/windows/crash_generation/client_info.h" +#include "client/windows/crash_generation/crash_generation_client.h" +#include "client/windows/crash_generation/crash_generation_server.h" +#include "client/windows/crash_generation/minidump_generator.h" +#include "client/windows/handler/exception_handler.h" +#include "client/windows/tests/crash_generation_app/abstract_class.h" +#include "client/windows/tests/crash_generation_app/crash_generation_app.h" +#include "google_breakpad/common/minidump_format.h" + +#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_PRECOMPILE_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/resource.h b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/resource.h new file mode 100644 index 00000000..8c7f6570 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/resource.h @@ -0,0 +1,73 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// PreCompile.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ +#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by crash_generation_app.rc +// +#define IDC_MYICON 2 +#define IDD_CRASHGENERATIONAPP_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_CRASHGENERATIONAPP 107 +#define IDI_SMALL 108 +#define IDC_CRASHGENERATIONAPP 109 +#define IDR_MAINFRAME 128 +#define ID_SERVER_START 32771 +#define ID_SERVER_STOP 32772 +#define ID_CLIENT_INVALIDPARAM 32773 +#define ID_CLIENT_ASSERTFAILURE 32774 +#define ID_CLIENT_DEREFZERO 32775 +#define ID_CLIENT_PURECALL 32777 +#define ID_CLIENT_REQUESTEXPLICITDUMP 32778 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32780 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif + +#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ diff --git a/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/small.ico b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/small.ico new file mode 100644 index 00000000..d551aa3a Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/client/windows/tests/crash_generation_app/small.ico differ diff --git a/thirdparty/google-breakpad/r318/src/common/convert_UTF.c b/thirdparty/google-breakpad/r318/src/common/convert_UTF.c new file mode 100644 index 00000000..80178d35 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/convert_UTF.c @@ -0,0 +1,533 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + +Conversions between UTF32, UTF-16, and UTF-8. Source code file. +Author: Mark E. Davis, 1994. +Rev History: Rick McGowan, fixes & updates May 2001. +Sept 2001: fixed const & error conditions per +mods suggested by S. Parent & A. Lillich. +June 2002: Tim Dodd added detection and handling of incomplete +source sequences, enhanced error detection, added casts +to eliminate compiler warnings. +July 2003: slight mods to back out aggressive FFFE detection. +Jan 2004: updated switches in from-UTF8 conversions. +Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + +See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "convert_UTF.h" +#ifdef CVTUTF_DEBUG +#include +#endif + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } +*sourceStart = source; +*targetStart = target; +return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF32* target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG + if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); + } +#endif + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. +* Constants have been gathered. Loops & conditionals have been removed as +* much as possible for efficiency, in favor of drop-through switches. +* (See "Note A" at the bottom of the file for equivalent code.) +* If your compiler supports it, the "isLegalUTF8" call can be turned +* into an inline function. +*/ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } +*sourceStart = source; +*targetStart = target; +return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (source+length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } +*sourceStart = source; +*targetStart = target; +return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } +*sourceStart = source; +*targetStart = target; +return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF32* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up the source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + +Note A. +The fall-through switches in UTF-8 reading code save a +temp variable, some decrements & conditionals. The switches +are equivalent to the following loop: +{ + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); +} +In UTF-8 writing code, the switches on "bytesToWrite" are +similarly unrolled loops. + +--------------------------------------------------------------------- */ diff --git a/thirdparty/google-breakpad/r318/src/common/convert_UTF.h b/thirdparty/google-breakpad/r318/src/common/convert_UTF.h new file mode 100644 index 00000000..b1556de8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/convert_UTF.h @@ -0,0 +1,143 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + +Conversions between UTF32, UTF-16, and UTF-8. Header file. + +Several funtions are included here, forming a complete set of +conversions between the three formats. UTF-7 is not included +here, but is handled in a separate source file. + +Each of these routines takes pointers to input buffers and output +buffers. The input buffers are const. + +Each routine converts the text between *sourceStart and sourceEnd, +putting the result into the buffer between *targetStart and +targetEnd. Note: the end pointers are *after* the last item: e.g. +*(sourceEnd - 1) is the last item. + +The return result indicates whether the conversion was successful, +and if not, whether the problem was in the source or target buffers. +(Only the first encountered problem is indicated.) + +After the conversion, *sourceStart and *targetStart are both +updated to point to the end of last text successfully converted in +the respective buffers. + +Input parameters: +sourceStart - pointer to a pointer to the source buffer. +The contents of this are modified on return so that +it points at the next thing to be converted. +targetStart - similarly, pointer to pointer to the target buffer. +sourceEnd, targetEnd - respectively pointers to the ends of the +two buffers, for overflow checking only. + +These conversion functions take a ConversionFlags argument. When this +flag is set to strict, both irregular sequences and isolated surrogates +will cause an error. When the flag is set to lenient, both irregular +sequences and isolated surrogates are converted. + +Whether the flag is strict or lenient, all illegal sequences will cause +an error return. This includes sequences such as: , , +or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code +must check for illegal sequences. + +When the flag is set to lenient, characters over 0x10FFFF are converted +to the replacement character; otherwise (when the flag is set to strict) +they constitute an error. + +Output parameters: +The value "sourceIllegal" is returned from some routines if the input +sequence is malformed. When "sourceIllegal" is returned, the source +value will point to the illegal value that caused the problem. E.g., +in UTF-8 when a sequence is malformed, it points to the start of the +malformed sequence. + +Author: Mark E. Davis, 1994. +Rev History: Rick McGowan, fixes & updates May 2001. +Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- +The following 4 definitions are compiler-specific. +The C standard does not guarantee that wchar_t has at least +16 bits, so wchar_t is no less portable than unsigned short! +All should be unsigned values to avoid sign extension during +bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.cc b/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.cc new file mode 100644 index 00000000..aff0d792 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.cc @@ -0,0 +1,781 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "common/linux/dump_symbols.h" +#include "common/linux/file_id.h" +#include "common/linux/guid_creator.h" +#include "processor/scoped_ptr.h" + +// This namespace contains helper functions. +namespace { + +// Infomation of a line. +struct LineInfo { + // The index into string table for the name of the source file which + // this line belongs to. + // Load from stab symbol. + uint32_t source_name_index; + // Offset from start of the function. + // Load from stab symbol. + ElfW(Off) rva_to_func; + // Offset from base of the loading binary. + ElfW(Off) rva_to_base; + // Size of the line. + // It is the difference of the starting address of the line and starting + // address of the next N_SLINE, N_FUN or N_SO. + uint32_t size; + // Line number. + uint32_t line_num; + // Id of the source file for this line. + int source_id; +}; + +typedef std::list LineInfoList; + +// Information of a function. +struct FuncInfo { + // Name of the function. + const char *name; + // Offset from the base of the loading address. + ElfW(Off) rva_to_base; + // Virtual address of the function. + // Load from stab symbol. + ElfW(Addr) addr; + // Size of the function. + // It is the difference of the starting address of the function and starting + // address of the next N_FUN or N_SO. + uint32_t size; + // Total size of stack parameters. + uint32_t stack_param_size; + // Is there any lines included from other files? + bool has_sol; + // Line information array. + LineInfoList line_info; +}; + +typedef std::list FuncInfoList; + +// Information of a source file. +struct SourceFileInfo { + // Name string index into the string table. + uint32_t name_index; + // Name of the source file. + const char *name; + // Starting address of the source file. + ElfW(Addr) addr; + // Id of the source file. + int source_id; + // Functions information. + FuncInfoList func_info; +}; + +typedef std::list SourceFileInfoList; + +// Information of a symbol table. +// This is the root of all types of symbol. +struct SymbolInfo { + SourceFileInfoList source_file_info; + + // The next source id for newly found source file. + int next_source_id; +}; + +// Stab section name. +static const char *kStabName = ".stab"; + +// Demangle using abi call. +// Older GCC may not support it. +static std::string Demangle(const char *mangled) { + int status = 0; + char *demangled = abi::__cxa_demangle(mangled, NULL, NULL, &status); + if (status == 0 && demangled != NULL) { + std::string str(demangled); + free(demangled); + return str; + } + return std::string(mangled); +} + +// Fix offset into virtual address by adding the mapped base into offsets. +// Make life easier when want to find something by offset. +static void FixAddress(void *obj_base) { + ElfW(Word) base = reinterpret_cast(obj_base); + ElfW(Ehdr) *elf_header = static_cast(obj_base); + elf_header->e_phoff += base; + elf_header->e_shoff += base; + ElfW(Shdr) *sections = reinterpret_cast(elf_header->e_shoff); + for (int i = 0; i < elf_header->e_shnum; ++i) + sections[i].sh_offset += base; +} + +// Find the prefered loading address of the binary. +static ElfW(Addr) GetLoadingAddress(const ElfW(Phdr) *program_headers, + int nheader) { + for (int i = 0; i < nheader; ++i) { + const ElfW(Phdr) &header = program_headers[i]; + // For executable, it is the PT_LOAD segment with offset to zero. + if (header.p_type == PT_LOAD && + header.p_offset == 0) + return header.p_vaddr; + } + // For other types of ELF, return 0. + return 0; +} + +static bool WriteFormat(int fd, const char *fmt, ...) { + va_list list; + char buffer[4096]; + ssize_t expected, written; + va_start(list, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, list); + expected = strlen(buffer); + written = write(fd, buffer, strlen(buffer)); + va_end(list); + return expected == written; +} + +static bool IsValidElf(const ElfW(Ehdr) *elf_header) { + return memcmp(elf_header, ELFMAG, SELFMAG) == 0; +} + +static const ElfW(Shdr) *FindSectionByName(const char *name, + const ElfW(Shdr) *sections, + const ElfW(Shdr) *strtab, + int nsection) { + assert(name != NULL); + assert(sections != NULL); + assert(nsection > 0); + + int name_len = strlen(name); + if (name_len == 0) + return NULL; + + for (int i = 0; i < nsection; ++i) { + const char *section_name = + (char*)(strtab->sh_offset + sections[i].sh_name); + if (!strncmp(name, section_name, name_len)) + return sections + i; + } + return NULL; +} + +// TODO(liuli): Computer the stack parameter size. +// Expect parameter variables are immediately following the N_FUN symbol. +// Will need to parse the type information to get a correct size. +static int LoadStackParamSize(struct nlist *list, + struct nlist *list_end, + struct FuncInfo *func_info) { + struct nlist *cur_list = list; + assert(cur_list->n_type == N_FUN); + ++cur_list; + int step = 1; + while (cur_list < list_end && cur_list->n_type == N_PSYM) { + ++cur_list; + ++step; + } + func_info->stack_param_size = 0; + return step; +} + +static int LoadLineInfo(struct nlist *list, + struct nlist *list_end, + const struct SourceFileInfo &source_file_info, + struct FuncInfo *func_info) { + struct nlist *cur_list = list; + func_info->has_sol = false; + // Records which source file the following lines belongs. Default + // to the file we are handling. This helps us handling inlined source. + // When encountering N_SOL, we will change this to the source file + // specified by N_SOL. + int current_source_name_index = source_file_info.name_index; + do { + // Skip non line information. + while (cur_list < list_end && cur_list->n_type != N_SLINE) { + // Only exit when got another function, or source file. + if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO) + return cur_list - list; + // N_SOL means source lines following it will be from + // another source file. + if (cur_list->n_type == N_SOL) { + func_info->has_sol = true; + + if (cur_list->n_un.n_strx > 0 && + cur_list->n_un.n_strx != current_source_name_index) { + // The following lines will be from this source file. + current_source_name_index = cur_list->n_un.n_strx; + } + } + ++cur_list; + } + struct LineInfo line; + while (cur_list < list_end && cur_list->n_type == N_SLINE) { + line.source_name_index = current_source_name_index; + line.rva_to_func = cur_list->n_value; + // n_desc is a signed short + line.line_num = (unsigned short)cur_list->n_desc; + // Don't set it here. + // Will be processed in later pass. + line.source_id = -1; + func_info->line_info.push_back(line); + ++cur_list; + } + } while (list < list_end); + + return cur_list - list; +} + +static int LoadFuncSymbols(struct nlist *list, + struct nlist *list_end, + const ElfW(Shdr) *stabstr_section, + struct SourceFileInfo *source_file_info) { + struct nlist *cur_list = list; + assert(cur_list->n_type == N_SO); + ++cur_list; + source_file_info->func_info.clear(); + while (cur_list < list_end) { + // Go until the function symbol. + while (cur_list < list_end && cur_list->n_type != N_FUN) { + if (cur_list->n_type == N_SO) { + return cur_list - list; + } + ++cur_list; + continue; + } + if (cur_list->n_type == N_FUN) { + struct FuncInfo func_info; + func_info.name = + reinterpret_cast(cur_list->n_un.n_strx + + stabstr_section->sh_offset); + func_info.addr = cur_list->n_value; + func_info.rva_to_base = 0; + func_info.size = 0; + func_info.stack_param_size = 0; + func_info.has_sol = 0; + + // Stack parameter size. + cur_list += LoadStackParamSize(cur_list, list_end, &func_info); + // Line info. + cur_list += LoadLineInfo(cur_list, + list_end, + *source_file_info, + &func_info); + + // Functions in this module should have address bigger than the module + // startring address. + // There maybe a lot of duplicated entry for a function in the symbol, + // only one of them can met this. + if (func_info.addr >= source_file_info->addr) { + source_file_info->func_info.push_back(func_info); + } + } + } + return cur_list - list; +} + +// Comapre the address. +// The argument should have a memeber named "addr" +template +static bool CompareAddress(T1 *a, T2 *b) { + return a->addr < b->addr; +} + +// Sort the array into increasing ordered array based on the virtual address. +// Return vector of pointers to the elements in the incoming array. So caller +// should make sure the returned vector lives longer than the incoming vector. +template +static std::vector SortByAddress( + Container *container) { + typedef typename Container::iterator It; + typedef typename Container::value_type T; + std::vector sorted_array_ptr; + sorted_array_ptr.reserve(container->size()); + for (It it = container->begin(); it != container->end(); it++) + sorted_array_ptr.push_back(&(*it)); + std::sort(sorted_array_ptr.begin(), + sorted_array_ptr.end(), + std::ptr_fun(CompareAddress)); + + return sorted_array_ptr; +} + +// Find the address of the next function or source file symbol in the symbol +// table. The address should be bigger than the current function's address. +static ElfW(Addr) NextAddress( + std::vector *sorted_functions, + std::vector *sorted_files, + const struct FuncInfo &func_info) { + std::vector::iterator next_func_iter = + std::find_if(sorted_functions->begin(), + sorted_functions->end(), + std::bind1st( + std::ptr_fun( + CompareAddress + ), + &func_info) + ); + if (next_func_iter != sorted_functions->end()) + return (*next_func_iter)->addr; + + std::vector::iterator next_file_iter = + std::find_if(sorted_files->begin(), + sorted_files->end(), + std::bind1st( + std::ptr_fun( + CompareAddress + ), + &func_info) + ); + if (next_file_iter != sorted_files->end()) { + return (*next_file_iter)->addr; + } + return 0; +} + +static int FindFileByNameIdx(uint32_t name_index, + SourceFileInfoList &files) { + for (SourceFileInfoList::iterator it = files.begin(); + it != files.end(); it++) { + if (it->name_index == name_index) + return it->source_id; + } + + return -1; +} + +// Add included file information. +// Also fix the source id for the line info. +static void AddIncludedFiles(struct SymbolInfo *symbols, + const ElfW(Shdr) *stabstr_section) { + for (SourceFileInfoList::iterator source_file_it = + symbols->source_file_info.begin(); + source_file_it != symbols->source_file_info.end(); + ++source_file_it) { + struct SourceFileInfo &source_file = *source_file_it; + + for (FuncInfoList::iterator func_info_it = source_file.func_info.begin(); + func_info_it != source_file.func_info.end(); + ++func_info_it) { + struct FuncInfo &func_info = *func_info_it; + + for (LineInfoList::iterator line_info_it = func_info.line_info.begin(); + line_info_it != func_info.line_info.end(); ++line_info_it) { + struct LineInfo &line_info = *line_info_it; + + assert(line_info.source_name_index > 0); + assert(source_file.name_index > 0); + + // Check if the line belongs to the source file by comparing the + // name index into string table. + if (line_info.source_name_index != source_file.name_index) { + // This line is not from the current source file, check if this + // source file has been added before. + int found_source_id = FindFileByNameIdx(line_info.source_name_index, + symbols->source_file_info); + if (found_source_id < 0) { + // Got a new included file. + // Those included files don't have address or line information. + SourceFileInfo new_file; + new_file.name_index = line_info.source_name_index; + new_file.name = reinterpret_cast(new_file.name_index + + stabstr_section->sh_offset); + new_file.addr = 0; + new_file.source_id = symbols->next_source_id++; + line_info.source_id = new_file.source_id; + symbols->source_file_info.push_back(new_file); + } else { + // The file has been added. + line_info.source_id = found_source_id; + } + } else { + // The line belongs to the file. + line_info.source_id = source_file.source_id; + } + } // for each line. + } // for each function. + } // for each source file. + +} + +// Compute size and rva information based on symbols loaded from stab section. +static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr, + struct SymbolInfo *symbols) { + std::vector sorted_files = + SortByAddress(&(symbols->source_file_info)); + for (size_t i = 0; i < sorted_files.size(); ++i) { + struct SourceFileInfo &source_file = *sorted_files[i]; + std::vector sorted_functions = + SortByAddress(&(source_file.func_info)); + for (size_t j = 0; j < sorted_functions.size(); ++j) { + struct FuncInfo &func_info = *sorted_functions[j]; + assert(func_info.addr >= loading_addr); + func_info.rva_to_base = func_info.addr - loading_addr; + func_info.size = 0; + ElfW(Addr) next_addr = NextAddress(&sorted_functions, + &sorted_files, + func_info); + // I've noticed functions with an address bigger than any other functions + // and source files modules, this is probably the last function in the + // module, due to limitions of Linux stab symbol, it is impossible to get + // the exact size of this kind of function, thus we give it a default + // very big value. This should be safe since this is the last function. + // But it is a ugly hack..... + // The following code can reproduce the case: + // template + // void Foo(T value) { + // } + // + // int main(void) { + // Foo(10); + // Foo(std::string("hello")); + // return 0; + // } + // TODO(liuli): Find a better solution. + static const int kDefaultSize = 0x10000000; + static int no_next_addr_count = 0; + if (next_addr != 0) { + func_info.size = next_addr - func_info.addr; + } else { + if (no_next_addr_count > 1) { + fprintf(stderr, "Got more than one funtion without the \ + following symbol. Igore this function.\n"); + fprintf(stderr, "The dumped symbol may not correct.\n"); + assert(!"This should not happen!\n"); + func_info.size = 0; + continue; + } + + no_next_addr_count++; + func_info.size = kDefaultSize; + } + // Compute line size. + for (LineInfoList::iterator line_info_it = func_info.line_info.begin(); + line_info_it != func_info.line_info.end(); line_info_it++) { + struct LineInfo &line_info = *line_info_it; + LineInfoList::iterator next_line_info_it = line_info_it; + next_line_info_it++; + line_info.size = 0; + if (next_line_info_it != func_info.line_info.end()) { + line_info.size = + next_line_info_it->rva_to_func - line_info.rva_to_func; + } else { + // The last line in the function. + // If we can find a function or source file symbol immediately + // following the line, we can get the size of the line by computing + // the difference of the next address to the starting address of this + // line. + // Otherwise, we need to set a default big enough value. This occurs + // mostly because the this function is the last one in the module. + if (next_addr != 0) { + ElfW(Off) next_addr_offset = next_addr - func_info.addr; + line_info.size = next_addr_offset - line_info.rva_to_func; + } else { + line_info.size = kDefaultSize; + } + } + line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base; + } // for each line. + } // for each function. + } // for each source file. + return true; +} + +static bool LoadSymbols(const ElfW(Shdr) *stab_section, + const ElfW(Shdr) *stabstr_section, + ElfW(Addr) loading_addr, + struct SymbolInfo *symbols) { + if (stab_section == NULL || stabstr_section == NULL) + return false; + + struct nlist *lists = + reinterpret_cast(stab_section->sh_offset); + int nstab = stab_section->sh_size / sizeof(struct nlist); + // First pass, load all symbols from the object file. + for (int i = 0; i < nstab; ) { + int step = 1; + struct nlist *cur_list = lists + i; + if (cur_list->n_type == N_SO) { + // FUNC
+ struct SourceFileInfo source_file_info; + source_file_info.name_index = cur_list->n_un.n_strx; + source_file_info.name = reinterpret_cast(cur_list->n_un.n_strx + + stabstr_section->sh_offset); + source_file_info.addr = cur_list->n_value; + if (strchr(source_file_info.name, '.')) + source_file_info.source_id = symbols->next_source_id++; + else + source_file_info.source_id = -1; + step = LoadFuncSymbols(cur_list, lists + nstab, + stabstr_section, &source_file_info); + symbols->source_file_info.push_back(source_file_info); + } + i += step; + } + + // Second pass, compute the size of functions and lines. + if (ComputeSizeAndRVA(loading_addr, symbols)) { + // Third pass, check for included source code, especially for header files. + // Until now, we only have compiling unit information, but they can + // have code from include files, add them here. + AddIncludedFiles(symbols, stabstr_section); + return true; + } + return false; +} + +static bool LoadSymbols(ElfW(Ehdr) *elf_header, struct SymbolInfo *symbols) { + // Translate all offsets in section headers into address. + FixAddress(elf_header); + ElfW(Addr) loading_addr = GetLoadingAddress( + reinterpret_cast(elf_header->e_phoff), + elf_header->e_phnum); + + const ElfW(Shdr) *sections = + reinterpret_cast(elf_header->e_shoff); + const ElfW(Shdr) *strtab = sections + elf_header->e_shstrndx; + const ElfW(Shdr) *stab_section = + FindSectionByName(kStabName, sections, strtab, elf_header->e_shnum); + if (stab_section == NULL) { + fprintf(stderr, "Stab section not found.\n"); + return false; + } + const ElfW(Shdr) *stabstr_section = stab_section->sh_link + sections; + + // Load symbols. + return LoadSymbols(stab_section, stabstr_section, loading_addr, symbols); +} + +static bool WriteModuleInfo(int fd, + ElfW(Half) arch, + const std::string &obj_file) { + const char *arch_name = NULL; + if (arch == EM_386) + arch_name = "x86"; + else if (arch == EM_X86_64) + arch_name = "x86_64"; + else + return false; + + unsigned char identifier[16]; + google_breakpad::FileID file_id(obj_file.c_str()); + if (file_id.ElfFileIdentifier(identifier)) { + char identifier_str[40]; + file_id.ConvertIdentifierToString(identifier, + identifier_str, sizeof(identifier_str)); + char id_no_dash[40]; + int id_no_dash_len = 0; + memset(id_no_dash, 0, sizeof(id_no_dash)); + for (int i = 0; identifier_str[i] != '\0'; ++i) + if (identifier_str[i] != '-') + id_no_dash[id_no_dash_len++] = identifier_str[i]; + // Add an extra "0" by the end. + id_no_dash[id_no_dash_len++] = '0'; + std::string filename = obj_file; + size_t slash_pos = obj_file.find_last_of("/"); + if (slash_pos != std::string::npos) + filename = obj_file.substr(slash_pos + 1); + return WriteFormat(fd, "MODULE Linux %s %s %s\n", arch_name, + id_no_dash, filename.c_str()); + } + return false; +} + +static bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) { + for (SourceFileInfoList::const_iterator it = + symbols.source_file_info.begin(); + it != symbols.source_file_info.end(); it++) { + if (it->source_id != -1) { + const char *name = it->name; + if (!WriteFormat(fd, "FILE %d %s\n", it->source_id, name)) + return false; + } + } + return true; +} + +static bool WriteOneFunction(int fd, + const struct FuncInfo &func_info){ + // Discard the ending part of the name. + std::string func_name(func_info.name); + std::string::size_type last_colon = func_name.find_last_of(':'); + if (last_colon != std::string::npos) + func_name = func_name.substr(0, last_colon); + func_name = Demangle(func_name.c_str()); + + if (func_info.size <= 0) + return true; + + if (WriteFormat(fd, "FUNC %lx %lx %d %s\n", + func_info.rva_to_base, + func_info.size, + func_info.stack_param_size, + func_name.c_str())) { + for (LineInfoList::const_iterator it = func_info.line_info.begin(); + it != func_info.line_info.end(); it++) { + const struct LineInfo &line_info = *it; + if (!WriteFormat(fd, "%lx %lx %d %d\n", + line_info.rva_to_base, + line_info.size, + line_info.line_num, + line_info.source_id)) + return false; + } + return true; + } + return false; +} + +static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) { + for (SourceFileInfoList::const_iterator it = + symbols.source_file_info.begin(); + it != symbols.source_file_info.end(); it++) { + const struct SourceFileInfo &file_info = *it; + for (FuncInfoList::const_iterator fiIt = file_info.func_info.begin(); + fiIt != file_info.func_info.end(); fiIt++) { + const struct FuncInfo &func_info = *fiIt; + if (!WriteOneFunction(fd, func_info)) + return false; + } + } + return true; +} + +static bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) { + return WriteSourceFileInfo(fd, symbols) && + WriteFunctionInfo(fd, symbols); +} + +// +// FDWrapper +// +// Wrapper class to make sure opened file is closed. +// +class FDWrapper { + public: + explicit FDWrapper(int fd) : + fd_(fd) { + } + ~FDWrapper() { + if (fd_ != -1) + close(fd_); + } + int get() { + return fd_; + } + int release() { + int fd = fd_; + fd_ = -1; + return fd; + } + private: + int fd_; +}; + +// +// MmapWrapper +// +// Wrapper class to make sure mapped regions are unmapped. +// +class MmapWrapper { + public: + MmapWrapper(void *mapped_address, size_t mapped_size) : + base_(mapped_address), size_(mapped_size) { + } + ~MmapWrapper() { + if (base_ != NULL) { + assert(size_ > 0); + munmap(base_, size_); + } + } + void release() { + base_ = NULL; + size_ = 0; + } + + private: + void *base_; + size_t size_; +}; + +} // namespace + +namespace google_breakpad { + +bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, + int sym_fd) { + int obj_fd = open(obj_file.c_str(), O_RDONLY); + if (obj_fd < 0) + return false; + FDWrapper obj_fd_wrapper(obj_fd); + struct stat st; + if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) + return false; + void *obj_base = mmap(NULL, st.st_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); + if (obj_base == MAP_FAILED) + return false; + MmapWrapper map_wrapper(obj_base, st.st_size); + ElfW(Ehdr) *elf_header = reinterpret_cast(obj_base); + if (!IsValidElf(elf_header)) + return false; + struct SymbolInfo symbols; + symbols.next_source_id = 0; + + if (!LoadSymbols(elf_header, &symbols)) + return false; + // Write to symbol file. + if (WriteModuleInfo(sym_fd, elf_header->e_machine, obj_file) && + DumpStabSymbols(sym_fd, symbols)) + return true; + + return false; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.h b/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.h new file mode 100644 index 00000000..64f4c9e6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/dump_symbols.h @@ -0,0 +1,48 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// dump_symbols.cc: Implements a linux stab debugging format dumper. +// + +#ifndef COMMON_LINUX_DUMP_SYMBOLS_H__ +#define COMMON_LINUX_DUMP_SYMBOLS_H__ + +#include + +namespace google_breakpad { + +class DumpSymbols { + public: + bool WriteSymbolFile(const std::string &obj_file, + int sym_fd); +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_DUMP_SYMBOLS_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/linux/file_id.cc b/thirdparty/google-breakpad/r318/src/common/linux/file_id.cc new file mode 100644 index 00000000..1adf2a13 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/file_id.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// file_id.cc: Return a unique identifier for a file +// +// See file_id.h for documentation +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/linux/file_id.h" +#include "common/md5.h" + +namespace google_breakpad { + +static bool FindElfTextSection(const void *elf_mapped_base, + const void **text_start, + int *text_size) { + assert(elf_mapped_base); + assert(text_start); + assert(text_size); + + const unsigned char *elf_base = + static_cast(elf_mapped_base); + const ElfW(Ehdr) *elf_header = + reinterpret_cast(elf_base); + if (memcmp(elf_header, ELFMAG, SELFMAG) != 0) + return false; + *text_start = NULL; + *text_size = 0; + const ElfW(Shdr) *sections = + reinterpret_cast(elf_base + elf_header->e_shoff); + const char *text_section_name = ".text"; + int name_len = strlen(text_section_name); + const ElfW(Shdr) *string_section = sections + elf_header->e_shstrndx; + const ElfW(Shdr) *text_section = NULL; + for (int i = 0; i < elf_header->e_shnum; ++i) { + if (sections[i].sh_type == SHT_PROGBITS) { + const char *section_name = (char*)(elf_base + + string_section->sh_offset + + sections[i].sh_name); + if (!strncmp(section_name, text_section_name, name_len)) { + text_section = §ions[i]; + break; + } + } + } + if (text_section != NULL && text_section->sh_size > 0) { + int text_section_size = text_section->sh_size; + *text_start = elf_base + text_section->sh_offset; + *text_size = text_section_size; + } + return true; +} + +FileID::FileID(const char *path) { + strncpy(path_, path, sizeof(path_)); +} + +bool FileID::ElfFileIdentifier(unsigned char identifier[16]) { + int fd = open(path_, O_RDONLY); + if (fd < 0) + return false; + struct stat st; + if (fstat(fd, &st) != 0 && st.st_size <= 0) { + close(fd); + return false; + } + void *base = mmap(NULL, st.st_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (base == MAP_FAILED) { + close(fd); + return false; + } + bool success = false; + const void *text_section = NULL; + int text_size = 0; + if (FindElfTextSection(base, &text_section, &text_size) && (text_size > 0)) { + struct MD5Context md5; + MD5Init(&md5); + MD5Update(&md5, + static_cast(text_section), + text_size); + MD5Final(identifier, &md5); + success = true; + } + + close(fd); + munmap(base, st.st_size); + return success; +} + +// static +void FileID::ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length) { + int buffer_idx = 0; + for (int idx = 0; (buffer_idx < buffer_length) && (idx < 16); ++idx) { + int hi = (identifier[idx] >> 4) & 0x0F; + int lo = (identifier[idx]) & 0x0F; + + if (idx == 4 || idx == 6 || idx == 8 || idx == 10) + buffer[buffer_idx++] = '-'; + + buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; + buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; + } + + // NULL terminate + buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/linux/file_id.h b/thirdparty/google-breakpad/r318/src/common/linux/file_id.h new file mode 100644 index 00000000..5e1cd6e1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/file_id.h @@ -0,0 +1,66 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// file_id.h: Return a unique identifier for a file +// + +#ifndef COMMON_LINUX_FILE_ID_H__ +#define COMMON_LINUX_FILE_ID_H__ + +#include + +namespace google_breakpad { + +class FileID { + public: + FileID(const char *path); + ~FileID() {}; + + // Load the identifier for the elf file path specified in the constructor into + // |identifier|. Return false if the identifier could not be created for the + // file. + // The current implementation will return the MD5 hash of the file's bytes. + bool ElfFileIdentifier(unsigned char identifier[16]); + + // Convert the |identifier| data to a NULL terminated string. The string will + // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE). + // The |buffer| should be at least 37 bytes long to receive all of the data + // and termination. Shorter buffers will contain truncated data. + static void ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length); + + private: + // Storage for the path specified + char path_[PATH_MAX]; +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_FILE_ID_H__ + diff --git a/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.cc b/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.cc new file mode 100644 index 00000000..d133c6b0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.cc @@ -0,0 +1,82 @@ +// 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 +#include +#include +#include +#include + +#include "common/linux/guid_creator.h" + +// +// GUIDGenerator +// +// This class is used to generate random GUID. +// Currently use random number to generate a GUID since Linux has +// no native GUID generator. This should be OK since we don't expect +// crash to happen very offen. +// +class GUIDGenerator { + public: + GUIDGenerator() { + srandom(time(NULL)); + } + + bool CreateGUID(GUID *guid) const { + guid->data1 = random(); + guid->data2 = (u_int16_t)(random()); + guid->data3 = (u_int16_t)(random()); + *reinterpret_cast(&guid->data4[0]) = random(); + *reinterpret_cast(&guid->data4[4]) = random(); + return true; + } +}; + +// Guid generator. +const GUIDGenerator kGuidGenerator; + +bool CreateGUID(GUID *guid) { + return kGuidGenerator.CreateGUID(guid); +} + +// Parse guid to string. +bool GUIDToString(const GUID *guid, char *buf, int buf_len) { + // Should allow more space the the max length of GUID. + assert(buf_len > kGUIDStringLength); + int num = snprintf(buf, buf_len, kGUIDFormatString, + guid->data1, guid->data2, guid->data3, + *reinterpret_cast(&(guid->data4[0])), + *reinterpret_cast(&(guid->data4[4]))); + if (num != kGUIDStringLength) + return false; + + buf[num] = '\0'; + return true; +} diff --git a/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.h b/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.h new file mode 100644 index 00000000..c86d856c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/guid_creator.h @@ -0,0 +1,48 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef COMMON_LINUX_GUID_CREATOR_H__ +#define COMMON_LINUX_GUID_CREATOR_H__ + +#include "google_breakpad/common/minidump_format.h" + +typedef MDGUID GUID; + +// Format string for parsing GUID. +#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x" +// Length of GUID string. Don't count the ending '\0'. +#define kGUIDStringLength 36 + +// Create a guid. +bool CreateGUID(GUID *guid); + +// Get the string from guid. +bool GUIDToString(const GUID *guid, char *buf, int buf_len); + +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/linux/http_upload.cc b/thirdparty/google-breakpad/r318/src/common/linux/http_upload.cc new file mode 100644 index 00000000..8748d117 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/http_upload.cc @@ -0,0 +1,185 @@ +// 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 +#include +#include +#include +#include + +#include "common/linux/http_upload.h" + +namespace { + +// Callback to get the response data from server. +static size_t WriteCallback(void *ptr, size_t size, + size_t nmemb, void *userp) { + if (!userp) + return 0; + + std::string *response = reinterpret_cast(userp); + size_t real_size = size * nmemb; + response->append(reinterpret_cast(ptr), real_size); + return real_size; +} + +} // namespace + +namespace google_breakpad { + +static const char kUserAgent[] = "Breakpad/1.0 (Linux)"; + +// static +bool HTTPUpload::SendRequest(const string &url, + const map ¶meters, + const string &upload_file, + const string &file_part_name, + const string &proxy, + const string &proxy_user_pwd, + string *response_body, + string *error_description) { + if (!CheckParameters(parameters)) + return false; + + void *curl_lib = dlopen("libcurl.so", RTLD_NOW); + if (!curl_lib) { + curl_lib = dlopen("libcurl.so.4", RTLD_NOW); + } + if (!curl_lib) { + curl_lib = dlopen("libcurl.so.3", RTLD_NOW); + } + if (!curl_lib) { + return false; + } + + CURL* (*curl_easy_init)(void); + *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init"); + CURL *curl = (*curl_easy_init)(); + if (error_description != NULL) + *error_description = "No Error"; + + if (!curl) { + dlclose(curl_lib); + return false; + } + + CURLcode err_code = CURLE_OK; + CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...); + *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt"); + (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str()); + (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent); + // Set proxy information if necessary. + if (!proxy.empty()) + (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str()); + if (!proxy_user_pwd.empty()) + (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str()); + + struct curl_httppost *formpost = NULL; + struct curl_httppost *lastptr = NULL; + // Add form data. + CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...); + *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd"); + map::const_iterator iter = parameters.begin(); + for (; iter != parameters.end(); ++iter) + (*curl_formadd)(&formpost, &lastptr, + CURLFORM_COPYNAME, iter->first.c_str(), + CURLFORM_COPYCONTENTS, iter->second.c_str(), + CURLFORM_END); + + // Add form file. + (*curl_formadd)(&formpost, &lastptr, + CURLFORM_COPYNAME, file_part_name.c_str(), + CURLFORM_FILE, upload_file.c_str(), + CURLFORM_END); + + (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost); + + // Disable 100-continue header. + struct curl_slist *headerlist = NULL; + char buf[] = "Expect:"; + struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *); + *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append"); + headerlist = (*curl_slist_append)(headerlist, buf); + (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist); + + if (response_body != NULL) { + (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA, + reinterpret_cast(response_body)); + } + + CURLcode (*curl_easy_perform)(CURL *); + *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform"); + err_code = (*curl_easy_perform)(curl); + const char* (*curl_easy_strerror)(CURLcode); + *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror"); +#ifndef NDEBUG + if (err_code != CURLE_OK) + fprintf(stderr, "Failed to send http request to %s, error: %s\n", + url.c_str(), + (*curl_easy_strerror)(err_code)); +#endif + if (error_description != NULL) + *error_description = (*curl_easy_strerror)(err_code); + + void (*curl_easy_cleanup)(CURL *); + *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup"); + (*curl_easy_cleanup)(curl); + if (formpost != NULL) { + void (*curl_formfree)(struct curl_httppost *); + *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree"); + (*curl_formfree)(formpost); + } + if (headerlist != NULL) { + void (*curl_slist_free_all)(struct curl_slist *); + *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all"); + (*curl_slist_free_all)(headerlist); + } + dlclose(curl_lib); + return err_code == CURLE_OK; +} + +// static +bool HTTPUpload::CheckParameters(const map ¶meters) { + for (map::const_iterator pos = parameters.begin(); + pos != parameters.end(); ++pos) { + const string &str = pos->first; + if (str.size() == 0) + return false; // disallow empty parameter names + for (unsigned int i = 0; i < str.size(); ++i) { + int c = str[i]; + if (c < 32 || c == '"' || c > 127) { + return false; + } + } + } + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/linux/http_upload.h b/thirdparty/google-breakpad/r318/src/common/linux/http_upload.h new file mode 100644 index 00000000..fa6ad12c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/linux/http_upload.h @@ -0,0 +1,83 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST +// request using libcurl. It currently supports requests that contain +// a set of string parameters (key/value pairs), and a file to upload. + +#ifndef COMMON_LINUX_HTTP_UPLOAD_H__ +#define COMMON_LINUX_HTTP_UPLOAD_H__ + +#include +#include + +namespace google_breakpad { + +using std::string; +using std::map; + +class HTTPUpload { + public: + // Sends the given set of parameters, along with the contents of + // upload_file, as a multipart POST request to the given URL. + // file_part_name contains the name of the file part of the request + // (i.e. it corresponds to the name= attribute on an . + // Parameter names must contain only printable ASCII characters, + // and may not contain a quote (") character. + // Only HTTP(S) URLs are currently supported. Returns true on success. + // If the request is successful and response_body is non-NULL, + // the response body will be returned in response_body. + // If the send fails, a description of the error will be + // returned in error_description. + static bool SendRequest(const string &url, + const map ¶meters, + const string &upload_file, + const string &file_part_name, + const string &proxy, + const string &proxy_user_pwd, + string *response_body, + string *error_description); + + private: + // Checks that the given list of parameters has only printable + // ASCII characters in the parameter name, and does not contain + // any quote (") characters. Returns true if so. + static bool CheckParameters(const map ¶meters); + + // No instances of this class should be created. + // Disallow all constructors, destructors, and operator=. + HTTPUpload(); + explicit HTTPUpload(const HTTPUpload &); + void operator=(const HTTPUpload &); + ~HTTPUpload(); +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_HTTP_UPLOAD_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.h b/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.h new file mode 100644 index 00000000..95f259b9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.h @@ -0,0 +1,61 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// HTTPMultipartUpload: A multipart/form-data HTTP uploader. +// Each parameter pair is sent as a boundary +// Each file is sent with a name field in addition to the filename and data +// The data will be sent synchronously. + +#import + +@interface HTTPMultipartUpload : NSObject { + @protected + NSURL *url_; // The destination URL (STRONG) + NSDictionary *parameters_; // The key/value pairs for sending data (STRONG) + NSMutableDictionary *files_; // Dictionary of name/file-path (STRONG) + NSString *boundary_; // The boundary string (STRONG) + NSHTTPURLResponse *response_; // The response from the send (STRONG) +} + +- (id)initWithURL:(NSURL *)url; + +- (NSURL *)URL; + +- (void)setParameters:(NSDictionary *)parameters; +- (NSDictionary *)parameters; + +- (void)addFileAtPath:(NSString *)path name:(NSString *)name; +- (void)addFileContents:(NSData *)data name:(NSString *)name; +- (NSDictionary *)files; + +// Set the data and return the response +- (NSData *)send:(NSError **)error; +- (NSHTTPURLResponse *)response; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.m b/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.m new file mode 100644 index 00000000..dd3612d8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/HTTPMultipartUpload.m @@ -0,0 +1,205 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "HTTPMultipartUpload.h" + +@interface HTTPMultipartUpload(PrivateMethods) +- (NSString *)multipartBoundary; +- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value; +- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name; +- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name; +@end + +@implementation HTTPMultipartUpload +//============================================================================= +#pragma mark - +#pragma mark || Private || +//============================================================================= +- (NSString *)multipartBoundary { + // The boundary has 27 '-' characters followed by 16 hex digits + return [NSString stringWithFormat:@"---------------------------%08X%08X", + rand(), rand()]; +} + +//============================================================================= +- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value { + NSString *escaped = + [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSString *fmt = + @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n"; + NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value]; + + return [form dataUsingEncoding:NSUTF8StringEncoding]; +} + +//============================================================================= +- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name { + NSMutableData *data = [NSMutableData data]; + NSString *escaped = + [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; " + "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n"; + NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped]; + NSString *post = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_]; + + [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]]; + [data appendData:contents]; + [data appendData:[post dataUsingEncoding:NSUTF8StringEncoding]]; + + return data; +} + +//============================================================================= +- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name { + NSData *contents = [NSData dataWithContentsOfFile:file]; + + return [self formDataForFileContents:contents name:name]; +} + +//============================================================================= +#pragma mark - +#pragma mark || Public || +//============================================================================= +- (id)initWithURL:(NSURL *)url { + if ((self = [super init])) { + url_ = [url copy]; + boundary_ = [[self multipartBoundary] retain]; + files_ = [[NSMutableDictionary alloc] init]; + } + + return self; +} + +//============================================================================= +- (void)dealloc { + [url_ release]; + [parameters_ release]; + [files_ release]; + [boundary_ release]; + [response_ release]; + + [super dealloc]; +} + +//============================================================================= +- (NSURL *)URL { + return url_; +} + +//============================================================================= +- (void)setParameters:(NSDictionary *)parameters { + if (parameters != parameters_) { + [parameters_ release]; + parameters_ = [parameters copy]; + } +} + +//============================================================================= +- (NSDictionary *)parameters { + return parameters_; +} + +//============================================================================= +- (void)addFileAtPath:(NSString *)path name:(NSString *)name { + [files_ setObject:path forKey:name]; +} + +//============================================================================= +- (void)addFileContents:(NSData *)data name:(NSString *)name { + [files_ setObject:data forKey:name]; +} + +//============================================================================= +- (NSDictionary *)files { + return files_; +} + +//============================================================================= +- (NSData *)send:(NSError **)error { + NSMutableURLRequest *req = + [[NSMutableURLRequest alloc] + initWithURL:url_ cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:10.0 ]; + + NSMutableData *postBody = [NSMutableData data]; + int i, count; + + [req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", + boundary_] forHTTPHeaderField:@"Content-type"]; + + // Add any parameters to the message + NSArray *parameterKeys = [parameters_ allKeys]; + NSString *key; + + count = [parameterKeys count]; + for (i = 0; i < count; ++i) { + key = [parameterKeys objectAtIndex:i]; + [postBody appendData:[self formDataForKey:key + value:[parameters_ objectForKey:key]]]; + } + + // Add any files to the message + NSArray *fileNames = [files_ allKeys]; + count = [fileNames count]; + for (i = 0; i < count; ++i) { + NSString *name = [fileNames objectAtIndex:i]; + id fileOrData = [files_ objectForKey:name]; + NSData *fileData; + + // The object can be either the path to a file (NSString) or the contents + // of the file (NSData). + if ([fileOrData isKindOfClass:[NSData class]]) + fileData = [self formDataForFileContents:fileOrData name:name]; + else + fileData = [self formDataForFile:fileOrData name:name]; + + [postBody appendData:fileData]; + } + + [req setHTTPBody:postBody]; + [req setHTTPMethod:@"POST"]; + + [response_ release]; + response_ = nil; + + NSData *data = [NSURLConnection sendSynchronousRequest:req + returningResponse:&response_ + error:error]; + + [response_ retain]; + + return data; +} + +//============================================================================= +- (NSHTTPURLResponse *)response { + return response_; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.h b/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.h new file mode 100644 index 00000000..12d8f7d6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.h @@ -0,0 +1,79 @@ +// 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. + +// dump_syms.h: Interface for DumpSymbols. This class will take a mach-o file +// and extract the symbol information and write it to a file using the +// breakpad symbol file format. + +#import +#include +#include "common/mac/dwarf/dwarf2reader.h" + +// This will map from an architecture string to a SectionMap, which +// will contain the offsets for all the sections in the dictionary +typedef hash_map ArchSectionMap; + +@interface DumpSymbols : NSObject { + @protected + NSString *sourcePath_; // Source of symbols (STRONG) + NSString *architecture_; // Architecture to extract (STRONG) + NSMutableDictionary *addresses_; // Addresses and symbols (STRONG) + NSMutableSet *functionAddresses_; // Function addresses (STRONG) + NSMutableDictionary *sources_; // Address and Source file paths (STRONG) + NSMutableDictionary *headers_; // Mach-o header information (STRONG) + NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG) + uint32_t lastStartAddress_; + ArchSectionMap *sectionsForArch_; +} + +- (id)initWithContentsOfFile:(NSString *)machoFile; + +- (NSArray *)availableArchitectures; + +// One of ppc, x86, i386, ppc64, x86_64 +// If the architecture is not available, it will return NO +// If not set, the native architecture will be used +- (BOOL)setArchitecture:(NSString *)architecture; +- (NSString *)architecture; + +// Write the symbols to |symbolFilePath|. Return YES if successful. +- (BOOL)writeSymbolFile:(NSString *)symbolFilePath; + +@end + +@interface MachSection : NSObject { + @protected + struct section *sect_; + uint32_t sectionNumber_; +} +- (id)initWithMachSection:(struct section *)sect andNumber:(uint32_t)sectionNumber; +- (struct section*)sectionPointer; +- (uint32_t)sectionNumber; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.mm b/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.mm new file mode 100644 index 00000000..88f1f4f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dump_syms.mm @@ -0,0 +1,1224 @@ +// 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. + +// dump_syms.mm: Create a symbol file for use with minidumps + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#import + +#import "dump_syms.h" +#import "common/mac/file_id.h" +#import "common/mac/macho_utilities.h" +#import "common/mac/dwarf/dwarf2reader.h" +#import "common/mac/dwarf/functioninfo.h" +#import "common/mac/dwarf/bytereader.h" + +using google_breakpad::FileID; + +static NSString *kAddressSymbolKey = @"symbol"; +static NSString *kAddressConvertedSymbolKey = @"converted_symbol"; +static NSString *kAddressSourceLineKey = @"line"; +static NSString *kFunctionSizeKey = @"size"; +static NSString *kFunctionFileKey = @"source_file"; +static NSString *kHeaderBaseAddressKey = @"baseAddr"; +static NSString *kHeaderSizeKey = @"size"; +static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header +static NSString *kHeaderIs64BitKey = @"is64"; +static NSString *kHeaderCPUTypeKey = @"cpuType"; + +// The section for __TEXT, __text seems to be always 1. This is useful +// for pruning out extraneous non-function symbols. +static const int kTextSection = 1; + +namespace __gnu_cxx { +template<> + struct hash { + size_t operator()(const std::string& k) const { + return hash< const char* >()( k.c_str() ); + } +}; +} + +// Dump FunctionMap to stdout. Print address, function name, file +// name, line number, lowpc, and highpc if available. +void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) { + for (dwarf2reader::FunctionMap::const_iterator iter = function_map.begin(); + iter != function_map.end(); ++iter) { + if (iter->second->name.empty()) { + continue; + } + printf("%08llx: %s", iter->first, + iter->second->name.data()); + if (!iter->second->file.empty()) { + printf(" - %s", iter->second->file.data()); + if (iter->second->line != 0) { + printf(":%u", iter->second->line); + } + } + if (iter->second->lowpc != 0 && iter->second->highpc != 0) { + printf(" (%08llx - %08llx)\n", + iter->second->lowpc, + iter->second->highpc); + } + } +} + + +@interface DumpSymbols(PrivateMethods) +- (NSString *)convertCPlusPlusSymbol:(NSString *)symbol; +- (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section; +- (BOOL)processSymbolItem:(struct nlist_64 *)list stringTable:(char *)table; +- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset; +- (BOOL)loadSymbolInfo64:(void *)base offset:(uint32_t)offset; +- (BOOL)loadSymbolInfoForArchitecture; +- (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset; +- (BOOL)loadSTABSSymbolInfo:(void *)base offset:(uint32_t)offset; +- (void)generateSectionDictionary:(struct mach_header*)header; +- (BOOL)loadHeader:(void *)base offset:(uint32_t)offset; +- (BOOL)loadHeader64:(void *)base offset:(uint32_t)offset; +- (BOOL)loadModuleInfo; +- (void)processDWARFLineNumberInfo:(dwarf2reader::LineMap*)line_map; +- (void)processDWARFFunctionInfo:(dwarf2reader::FunctionMap*)address_to_funcinfo; +- (void)processDWARFSourceFileInfo:(vector*) files; +- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset; +- (dwarf2reader::SectionMap*)getSectionMapForArchitecture:(NSString*)architecture; +@end + +@implementation DumpSymbols +//============================================================================= +- (NSString *)convertCPlusPlusSymbol:(NSString *)symbol { + // __cxa_demangle will realloc this if needed + char *buffer = (char *)malloc(1024); + size_t buffer_size = 1024; + int result; + + const char *sym = [symbol UTF8String]; + NSString *demangled = nil; + buffer = abi::__cxa_demangle(sym, buffer, &buffer_size, &result); + if (result == 0) { + demangled = [NSString stringWithUTF8String:buffer]; + } + free(buffer); + return demangled; +} + +//============================================================================= +- (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section { + NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:address]; + + if (!address) + return; + + // If the function starts with "_Z" or "__Z" then demangle it. + BOOL isCPP = NO; + + if ([name hasPrefix:@"__Z"]) { + // Remove the leading underscore + name = [name substringFromIndex:1]; + isCPP = YES; + } else if ([name hasPrefix:@"_Z"]) { + isCPP = YES; + } + + // Filter out non-functions + if ([name hasSuffix:@".eh"]) + return; + + if ([name hasSuffix:@"__func__"]) + return; + + if ([name hasSuffix:@"GCC_except_table"]) + return; + + if (isCPP) { + // OBJCPP_MANGLING_HACK + // There are cases where ObjC++ mangles up an ObjC name using quasi-C++ + // mangling: + // @implementation Foozles + (void)barzles { + // static int Baz = 0; + // } @end + // gives you _ZZ18+[Foozles barzles]E3Baz + // c++filt won't parse this properly, and will crash in certain cases. + // Logged as radar: + // 5129938: c++filt does not deal with ObjC++ symbols + // If 5129938 ever gets fixed, we can remove this, but for now this prevents + // c++filt from attempting to demangle names it doesn't know how to handle. + // This is with c++filt 2.16 + NSCharacterSet *objcppCharSet = [NSCharacterSet characterSetWithCharactersInString:@"-+[]: "]; + NSRange emptyRange = { NSNotFound, 0 }; + NSRange objcppRange = [name rangeOfCharacterFromSet:objcppCharSet]; + isCPP = NSEqualRanges(objcppRange, emptyRange); + } else if ([name characterAtIndex:0] == '_') { + // Remove the leading underscore + name = [name substringFromIndex:1]; + } + + // If there's already an entry for this address, check and see if we can add + // either the symbol, or a missing line # + NSMutableDictionary *dict = [addresses_ objectForKey:addressNum]; + + if (!dict) { + dict = [[NSMutableDictionary alloc] init]; + [addresses_ setObject:dict forKey:addressNum]; + [dict release]; + } + + if (name && ![dict objectForKey:kAddressSymbolKey]) { + [dict setObject:name forKey:kAddressSymbolKey]; + + // only functions, not line number addresses + [functionAddresses_ addObject:addressNum]; + } + + if (isCPP) { + // try demangling + NSString *demangled = [self convertCPlusPlusSymbol:name]; + if (demangled != nil) + [dict setObject:demangled forKey:kAddressConvertedSymbolKey]; + } + + if (line && ![dict objectForKey:kAddressSourceLineKey]) + [dict setObject:[NSNumber numberWithUnsignedInt:line] + forKey:kAddressSourceLineKey]; + +} + +//============================================================================= +- (BOOL)processSymbolItem:(struct nlist_64 *)list stringTable:(char *)table { + uint32_t n_strx = list->n_un.n_strx; + BOOL result = NO; + + // We don't care about non-section specific information except function length + if (list->n_sect == 0 && list->n_type != N_FUN ) + return NO; + + if (list->n_type == N_FUN) { + if (list->n_sect != 0) { + // we get the function address from the first N_FUN + lastStartAddress_ = list->n_value; + } + else { + // an N_FUN from section 0 may follow the initial N_FUN + // giving us function length information + NSMutableDictionary *dict = [addresses_ objectForKey: + [NSNumber numberWithUnsignedLong:lastStartAddress_]]; + + assert(dict); + + // only set the function size the first time + // (sometimes multiple section 0 N_FUN entries appear!) + if (![dict objectForKey:kFunctionSizeKey]) { + [dict setObject:[NSNumber numberWithUnsignedLongLong:list->n_value] + forKey:kFunctionSizeKey]; + } + } + } + + int line = list->n_desc; + + // __TEXT __text section + NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_]; + + uint32_t mainSection = [[archSections objectForKey:@"__TEXT__text" ] sectionNumber]; + + // Extract debugging information: + // Doc: http://developer.apple.com/documentation/DeveloperTools/gdb/stabs/stabs_toc.html + // Header: /usr/include/mach-o/stab.h: + if (list->n_type == N_SO) { + NSString *src = [NSString stringWithUTF8String:&table[n_strx]]; + NSString *ext = [src pathExtension]; + NSNumber *address = [NSNumber numberWithUnsignedLongLong:list->n_value]; + + // Leopard puts .c files with no code as an offset of 0, but a + // crash can't happen here and it throws off our code that matches + // symbols to line numbers so we ignore them.. + // Return YES because this isn't an error, just something we don't + // care to handle. + if ([address unsignedLongValue] == 0) { + return YES; + } + // TODO(waylonis):Ensure that we get the full path for the source file + // from the first N_SO record + // If there is an extension, we'll consider it source code + if ([ext length]) { + if (!sources_) + sources_ = [[NSMutableDictionary alloc] init]; + // Save the source associated with an address + [sources_ setObject:src forKey:address]; + result = YES; + } + } else if (list->n_type == N_FUN) { + NSString *fn = [NSString stringWithUTF8String:&table[n_strx]]; + NSRange range = [fn rangeOfString:@":" options:NSBackwardsSearch]; + + if (![fn length]) + return NO; + + if (range.length > 0) { + // The function has a ":" followed by some stuff, so strip it off + fn = [fn substringToIndex:range.location]; + } + + [self addFunction:fn line:line address:list->n_value section:list->n_sect ]; + + result = YES; + } else if (list->n_type == N_SLINE && list->n_sect == mainSection) { + [self addFunction:nil line:line address:list->n_value section:list->n_sect ]; + result = YES; + } else if (((list->n_type & N_TYPE) == N_SECT) && !(list->n_type & N_STAB)) { + // Regular symbols or ones that are external + NSString *fn = [NSString stringWithUTF8String:&table[n_strx]]; + + [self addFunction:fn line:0 address:list->n_value section:list->n_sect ]; + result = YES; + } + + return result; +} + +#define SwapLongLongIfNeeded(a) (swap ? NXSwapLongLong(a) : (a)) +#define SwapLongIfNeeded(a) (swap ? NXSwapLong(a) : (a)) +#define SwapIntIfNeeded(a) (swap ? NXSwapInt(a) : (a)) +#define SwapShortIfNeeded(a) (swap ? NXSwapShort(a) : (a)) + +//============================================================================= +- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset { + NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_]; + if ([archSections objectForKey:@"__DWARF__debug_info"]) { + // Treat this this as debug information + return [self loadDWARFSymbolInfo:base offset:offset]; + } + + return [self loadSTABSSymbolInfo:base offset:offset]; +} + +//============================================================================= +- (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset { + + struct mach_header *header = (struct mach_header *) + ((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM); + + NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_]; + assert (archSections != nil); + section *dbgInfoSection = [[archSections objectForKey:@"__DWARF__debug_info"] sectionPointer]; + uint32_t debugInfoSize = SwapLongIfNeeded(dbgInfoSection->size); + + // i think this will break if run on a big-endian machine + dwarf2reader::ByteReader byte_reader(swap ? + dwarf2reader::ENDIANNESS_BIG : + dwarf2reader::ENDIANNESS_LITTLE); + + uint64_t dbgOffset = 0; + + dwarf2reader::SectionMap* oneArchitectureSectionMap = [self getSectionMapForArchitecture:architecture_]; + + while (dbgOffset < debugInfoSize) { + // Prepare necessary objects. + dwarf2reader::FunctionMap off_to_funcinfo; + dwarf2reader::FunctionMap address_to_funcinfo; + dwarf2reader::LineMap line_map; + vector files; + vector dirs; + + dwarf2reader::CULineInfoHandler line_info_handler(&files, &dirs, + &line_map); + + dwarf2reader::CUFunctionInfoHandler function_info_handler(&files, &dirs, + &line_map, + &off_to_funcinfo, + &address_to_funcinfo, + &line_info_handler, + *oneArchitectureSectionMap, + &byte_reader); + + dwarf2reader::CompilationUnit compilation_unit(*oneArchitectureSectionMap, + dbgOffset, + &byte_reader, + &function_info_handler); + + dbgOffset += compilation_unit.Start(); + + // The next 3 functions take the info that the dwarf reader + // gives and massages them into the data structures that + // dump_syms uses + [self processDWARFSourceFileInfo:&files]; + [self processDWARFFunctionInfo:&address_to_funcinfo]; + [self processDWARFLineNumberInfo:&line_map]; + } + + return YES; +} + +- (void)processDWARFSourceFileInfo:(vector*) files { + if (!sources_) + sources_ = [[NSMutableDictionary alloc] init]; + // Save the source associated with an address + vector::const_iterator iter = files->begin(); + for (; iter != files->end(); iter++) { + NSString *sourceFile = [NSString stringWithUTF8String:(*iter).name.c_str()]; + if ((*iter).lowpc != ULLONG_MAX) { + NSNumber *address = [NSNumber numberWithUnsignedLongLong:(*iter).lowpc]; + if ([address unsignedLongLongValue] == 0) { + continue; + } + [sources_ setObject:sourceFile forKey:address]; + } + } +} + +- (void)processDWARFFunctionInfo:(dwarf2reader::FunctionMap*)address_to_funcinfo { + for (dwarf2reader::FunctionMap::const_iterator iter = address_to_funcinfo->begin(); + iter != address_to_funcinfo->end(); ++iter) { + if (iter->second->name.empty()) { + continue; + } + + if (!addresses_) + addresses_ = [[NSMutableDictionary alloc] init]; + + NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:(*iter).second->lowpc]; + + [functionAddresses_ addObject:addressNum]; + + NSMutableDictionary *dict = [addresses_ objectForKey:addressNum]; + + if (!dict) { + dict = [[NSMutableDictionary alloc] init]; + [addresses_ setObject:dict forKey:addressNum]; + [dict release]; + } + + // set name of function if it isn't already set + if (![dict objectForKey:kAddressSymbolKey]) { + NSString *symbolName = [NSString stringWithUTF8String:iter->second->name.c_str()]; + [dict setObject:symbolName forKey:kAddressSymbolKey]; + } + + // try demangling function name if we have a mangled name + if (![dict objectForKey:kAddressConvertedSymbolKey] && + !iter->second->mangled_name.empty()) { + NSString *mangled = [NSString stringWithUTF8String:iter->second->mangled_name.c_str()]; + NSString *demangled = [self convertCPlusPlusSymbol:mangled]; + if (demangled != nil) + [dict setObject:demangled forKey:kAddressConvertedSymbolKey]; + } + + // set line number for beginning of function + if (iter->second->line && ![dict objectForKey:kAddressSourceLineKey]) + [dict setObject:[NSNumber numberWithUnsignedInt:iter->second->line] + forKey:kAddressSourceLineKey]; + + // set function size by subtracting low PC from high PC + if (![dict objectForKey:kFunctionSizeKey]) { + [dict setObject:[NSNumber numberWithUnsignedLongLong:iter->second->highpc - iter->second->lowpc] + forKey:kFunctionSizeKey]; + } + + // Set the file that the function is in + if (![dict objectForKey:kFunctionFileKey]) { + [dict setObject:[NSString stringWithUTF8String:iter->second->file.c_str()] + forKey:kFunctionFileKey]; + } + } +} + +- (void)processDWARFLineNumberInfo:(dwarf2reader::LineMap*)line_map { + for (dwarf2reader::LineMap::const_iterator iter = line_map->begin(); + iter != line_map->end(); + ++iter) { + + NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:iter->first]; + NSMutableDictionary *dict = [addresses_ objectForKey:addressNum]; + + if (!dict) { + dict = [[NSMutableDictionary alloc] init]; + [addresses_ setObject:dict forKey:addressNum]; + [dict release]; + } + + if (iter->second.second && ![dict objectForKey:kAddressSourceLineKey]) { + [dict setObject:[NSNumber numberWithUnsignedInt:iter->second.second] + forKey:kAddressSourceLineKey]; + } + + // Set the file that the function's address is in + if (![dict objectForKey:kFunctionFileKey]) { + [dict setObject:[NSString stringWithUTF8String:iter->second.first.c_str()] + forKey:kFunctionFileKey]; + } + } +} + +//============================================================================= +- (BOOL)loadSTABSSymbolInfo:(void *)base offset:(uint32_t)offset { + struct mach_header *header = (struct mach_header *)((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM); + uint32_t count = SwapLongIfNeeded(header->ncmds); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); + uint32_t symbolTableCommand = SwapLongIfNeeded(LC_SYMTAB); + BOOL result = NO; + + if (!addresses_) + addresses_ = [[NSMutableDictionary alloc] init]; + + for (uint32_t i = 0; cmd && (i < count); ++i) { + if (cmd->cmd == symbolTableCommand) { + struct symtab_command *symtab = (struct symtab_command *)cmd; + uint32_t ncmds = SwapLongIfNeeded(symtab->nsyms); + uint32_t symoff = SwapLongIfNeeded(symtab->symoff); + uint32_t stroff = SwapLongIfNeeded(symtab->stroff); + struct nlist *list = (struct nlist *)((uint32_t)base + symoff + offset); + char *strtab = ((char *)header + stroff); + + // Process each command, looking for debugging stuff + for (uint32_t j = 0; j < ncmds; ++j, ++list) { + // Fill in an nlist_64 structure and process with that + struct nlist_64 nlist64; + nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx); + nlist64.n_type = list->n_type; + nlist64.n_sect = list->n_sect; + nlist64.n_desc = SwapShortIfNeeded(list->n_desc); + nlist64.n_value = (uint64_t)SwapLongIfNeeded(list->n_value); + + // TODO(nealsid): is this broken? we get NO if one symbol fails + // but then we lose that information if another suceeeds + if ([self processSymbolItem:&nlist64 stringTable:strtab]) + result = YES; + } + } + + uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); + } + + return result; +} + +//============================================================================= +- (BOOL)loadSymbolInfo64:(void *)base offset:(uint32_t)offset { + struct mach_header_64 *header = (struct mach_header_64 *) + ((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM_64); + uint32_t count = SwapLongIfNeeded(header->ncmds); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); + uint32_t symbolTableCommand = SwapLongIfNeeded(LC_SYMTAB); + BOOL result = NO; + + for (uint32_t i = 0; cmd && (i < count); i++) { + if (cmd->cmd == symbolTableCommand) { + struct symtab_command *symtab = (struct symtab_command *)cmd; + uint32_t ncmds = SwapLongIfNeeded(symtab->nsyms); + uint32_t symoff = SwapLongIfNeeded(symtab->symoff); + uint32_t stroff = SwapLongIfNeeded(symtab->stroff); + struct nlist_64 *list = (struct nlist_64 *)((uint32_t)base + symoff); + char *strtab = ((char *)header + stroff); + + // Process each command, looking for debugging stuff + for (uint32_t j = 0; j < ncmds; ++j, ++list) { + if (!(list->n_type & (N_STAB | N_TYPE))) + continue; + + // Fill in an nlist_64 structure and process with that + struct nlist_64 nlist64; + nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx); + nlist64.n_type = list->n_type; + nlist64.n_sect = list->n_sect; + nlist64.n_desc = SwapShortIfNeeded(list->n_desc); + nlist64.n_value = SwapLongLongIfNeeded(list->n_value); + + if ([self processSymbolItem:&nlist64 stringTable:strtab]) + result = YES; + } + } + + uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); + } + + return result; +} + +//============================================================================= +- (BOOL)loadSymbolInfoForArchitecture { + NSMutableData *data = [[NSMutableData alloc] + initWithContentsOfMappedFile:sourcePath_]; + + NSDictionary *headerInfo = [headers_ objectForKey:architecture_]; + void *base = [data mutableBytes]; + uint32_t offset = + [[headerInfo objectForKey:kHeaderOffsetKey] unsignedLongValue]; + BOOL is64 = [[headerInfo objectForKey:kHeaderIs64BitKey] boolValue]; + BOOL result = is64 ? [self loadSymbolInfo64:base offset:offset] : + [self loadSymbolInfo:base offset:offset]; + + [data release]; + return result; +} + +- (dwarf2reader::SectionMap*)getSectionMapForArchitecture:(NSString*)architecture { + + string currentArch([architecture UTF8String]); + dwarf2reader::SectionMap *oneArchitectureSectionMap; + + ArchSectionMap::const_iterator iter = sectionsForArch_->find(currentArch); + + if (iter == sectionsForArch_->end()) { + oneArchitectureSectionMap = new dwarf2reader::SectionMap(); + sectionsForArch_->insert(make_pair(currentArch, oneArchitectureSectionMap)); + } else { + oneArchitectureSectionMap = iter->second; + } + + return oneArchitectureSectionMap; +} + +//============================================================================= +// build a dictionary of section numbers keyed off a string +// which is the concatenation of the segment name and the section name +- (void)generateSectionDictionary:(struct mach_header*)header { + + BOOL swap = (header->magic == MH_CIGAM); + uint32_t count = SwapLongIfNeeded(header->ncmds); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); + uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT); + uint32_t sectionNumber = 1; // section numbers are counted from 1 + + cpu_type_t cpu = SwapIntIfNeeded(header->cputype); + + NSString *arch; + + if (cpu & CPU_ARCH_ABI64) + arch = ((cpu & ~CPU_ARCH_ABI64) == CPU_TYPE_X86) ? + @"x86_64" : @"ppc64"; + else + arch = (cpu == CPU_TYPE_X86) ? @"x86" : @"ppc"; + + NSMutableDictionary *archSections; + + if (!sectionData_) { + sectionData_ = [[NSMutableDictionary alloc] init]; + } + + if (![sectionData_ objectForKey:architecture_]) { + [sectionData_ setObject:[[NSMutableDictionary alloc] init] forKey:arch]; + } + + archSections = [sectionData_ objectForKey:arch]; + + dwarf2reader::SectionMap* oneArchitectureSectionMap = [self getSectionMapForArchitecture:arch]; + + // loop through every segment command, then through every section + // contained inside each of them + for (uint32_t i = 0; cmd && (i < count); ++i) { + if (cmd->cmd == segmentCommand) { + struct segment_command *seg = (struct segment_command *)cmd; + section *sect = (section *)((uint32_t)cmd + sizeof(segment_command)); + uint32_t nsects = SwapLongIfNeeded(seg->nsects); + + for (uint32_t j = 0; j < nsects; ++j) { + NSString *segSectName = [NSString stringWithFormat:@"%s%s", + seg->segname, sect->sectname]; + + [archSections setObject:[[MachSection alloc] initWithMachSection:sect andNumber:sectionNumber] + forKey:segSectName]; + + // filter out sections with size 0, offset 0 + if (sect->offset != 0 && sect->size != 0) { + // fill sectionmap for dwarf reader + oneArchitectureSectionMap->insert(make_pair(sect->sectname,make_pair(((const char*)header) + SwapLongIfNeeded(sect->offset), (size_t)SwapLongIfNeeded(sect->size)))); + } + + ++sect; + ++sectionNumber; + } + } + + uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); + } +} + +//============================================================================= +- (BOOL)loadHeader:(void *)base offset:(uint32_t)offset { + struct mach_header *header = (struct mach_header *)((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM); + uint32_t count = SwapLongIfNeeded(header->ncmds); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); + uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT); + + [self generateSectionDictionary:header]; + + for (uint32_t i = 0; cmd && (i < count); ++i) { + if (cmd->cmd == segmentCommand) { + struct segment_command *seg = (struct segment_command *)cmd; + + if (!strcmp(seg->segname, "__TEXT")) { + uint32_t addr = SwapLongIfNeeded(seg->vmaddr); + uint32_t size = SwapLongIfNeeded(seg->vmsize); + cpu_type_t cpu = SwapIntIfNeeded(header->cputype); + NSString *cpuStr = (cpu == CPU_TYPE_I386) ? @"x86" : @"ppc"; + + [headers_ setObject:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedLongLong:(uint64_t)addr], + kHeaderBaseAddressKey, + [NSNumber numberWithUnsignedLongLong:(uint64_t)size], kHeaderSizeKey, + [NSNumber numberWithUnsignedLong:offset], kHeaderOffsetKey, + [NSNumber numberWithBool:NO], kHeaderIs64BitKey, + [NSNumber numberWithUnsignedLong:cpu], kHeaderCPUTypeKey, + nil] forKey:cpuStr]; + + return YES; + } + } + + uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); + } + + return NO; +} + +//============================================================================= +- (BOOL)loadHeader64:(void *)base offset:(uint32_t)offset { + struct mach_header_64 *header = + (struct mach_header_64 *)((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM_64); + uint32_t count = SwapLongIfNeeded(header->ncmds); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header_64)); + + for (uint32_t i = 0; cmd && (i < count); ++i) { + uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT_64); + if (cmd->cmd == segmentCommand) { + struct segment_command_64 *seg = (struct segment_command_64 *)cmd; + if (!strcmp(seg->segname, "__TEXT")) { + uint64_t addr = SwapLongLongIfNeeded(seg->vmaddr); + uint64_t size = SwapLongLongIfNeeded(seg->vmsize); + cpu_type_t cpu = SwapIntIfNeeded(header->cputype); + cpu &= (~CPU_ARCH_ABI64); + NSString *cpuStr = (cpu == CPU_TYPE_I386) ? @"x86_64" : @"ppc64"; + + [headers_ setObject:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedLongLong:addr], kHeaderBaseAddressKey, + [NSNumber numberWithUnsignedLongLong:size], kHeaderSizeKey, + [NSNumber numberWithUnsignedLong:offset], kHeaderOffsetKey, + [NSNumber numberWithBool:YES], kHeaderIs64BitKey, + [NSNumber numberWithUnsignedLong:cpu], kHeaderCPUTypeKey, + nil] forKey:cpuStr]; + return YES; + } + } + + uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); + } + + return NO; +} + +//============================================================================= +- (BOOL)loadModuleInfo { + uint64_t result = 0; + NSMutableData *data = [[NSMutableData alloc] + initWithContentsOfMappedFile:sourcePath_]; + void *bytes = [data mutableBytes]; + struct fat_header *fat = (struct fat_header *)bytes; + + if (!fat) { + [data release]; + return 0; + } + + // Gather some information based on the header + BOOL isFat = fat->magic == FAT_MAGIC || fat->magic == FAT_CIGAM; + BOOL is64 = fat->magic == MH_MAGIC_64 || fat->magic == MH_CIGAM_64; + BOOL is32 = fat->magic == MH_MAGIC || fat->magic == MH_CIGAM; + BOOL swap = fat->magic == FAT_CIGAM || fat->magic == MH_CIGAM_64 || + fat->magic == MH_CIGAM; + + if (!is64 && !is32 && !isFat) { + [data release]; + return 0; + } + + // Load any available architectures and save the information + headers_ = [[NSMutableDictionary alloc] init]; + + if (isFat) { + struct fat_arch *archs = + (struct fat_arch *)((uint32_t)fat + sizeof(struct fat_header)); + uint32_t count = SwapLongIfNeeded(fat->nfat_arch); + + for (uint32_t i = 0; i < count; ++i) { + archs[i].cputype = SwapIntIfNeeded(archs[i].cputype); + archs[i].cpusubtype = SwapIntIfNeeded(archs[i].cpusubtype); + archs[i].offset = SwapLongIfNeeded(archs[i].offset); + archs[i].size = SwapLongIfNeeded(archs[i].size); + archs[i].align = SwapLongIfNeeded(archs[i].align); + + if (archs[i].cputype & CPU_ARCH_ABI64) + result = [self loadHeader64:bytes offset:archs[i].offset]; + else + result = [self loadHeader:bytes offset:archs[i].offset]; + } + } else if (is32) { + result = [self loadHeader:bytes offset:0]; + } else { + result = [self loadHeader64:bytes offset:0]; + } + + [data release]; + return result; +} + +//============================================================================= +static BOOL WriteFormat(int fd, const char *fmt, ...) { + va_list list; + char buffer[4096]; + ssize_t expected, written; + + va_start(list, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, list); + expected = strlen(buffer); + written = write(fd, buffer, strlen(buffer)); + va_end(list); + + return expected == written; +} + +//============================================================================= +- (BOOL)outputSymbolFile:(int)fd { + // Get the baseAddress for this architecture + NSDictionary *archDict = [headers_ objectForKey:architecture_]; + NSNumber *baseAddressNum = [archDict objectForKey:kHeaderBaseAddressKey]; + uint64_t baseAddress = + baseAddressNum ? [baseAddressNum unsignedLongLongValue] : 0; + NSNumber *moduleSizeNum = [archDict objectForKey:kHeaderSizeKey]; + uint64_t moduleSize = + moduleSizeNum ? [moduleSizeNum unsignedLongLongValue] : 0; + + // UUID + FileID file_id([sourcePath_ fileSystemRepresentation]); + unsigned char identifier[16]; + char identifierStr[40]; + const char *moduleName = [[sourcePath_ lastPathComponent] UTF8String]; + int cpu_type = [[archDict objectForKey:kHeaderCPUTypeKey] unsignedLongValue]; + if (file_id.MachoIdentifier(cpu_type, identifier)) { + FileID::ConvertIdentifierToString(identifier, identifierStr, + sizeof(identifierStr)); + } + else { + fprintf(stderr, "Unable to calculate UUID of mach-o binary!\n"); + return NO; + } + + // keep track exclusively of function addresses + // for sanity checking function lengths + functionAddresses_ = [[NSMutableSet alloc] init]; + + // Gather the information + [self loadSymbolInfoForArchitecture]; + + NSArray *sortedAddresses = [[addresses_ allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + + NSArray *sortedFunctionAddresses = [[functionAddresses_ allObjects] + sortedArrayUsingSelector:@selector(compare:)]; + + // position ourselves at the 2nd function + unsigned int funcIndex = 1; + + // Remove the dashes from the string + NSMutableString *compactedStr = + [NSMutableString stringWithCString:identifierStr encoding:NSASCIIStringEncoding]; + [compactedStr replaceOccurrencesOfString:@"-" withString:@"" options:0 + range:NSMakeRange(0, [compactedStr length])]; + + if (!WriteFormat(fd, "MODULE mac %s %s0 %s\n", [architecture_ UTF8String], + [compactedStr UTF8String], moduleName)) { + return NO; + } + + // Sources ordered by address + NSArray *sources = [[sources_ allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + NSMutableDictionary *fileNameToFileIndex = [[NSMutableDictionary alloc] init]; + unsigned int sourceCount = [sources count]; + for (unsigned int i = 0; i < sourceCount; ++i) { + NSString *file = [sources_ objectForKey:[sources objectAtIndex:i]]; + if (!WriteFormat(fd, "FILE %d %s\n", i + 1, [file UTF8String])) + return NO; + + [fileNameToFileIndex setObject:[NSNumber numberWithUnsignedInt:i+1] + forKey:file]; + } + + // Symbols + char terminatingChar = '\n'; + uint32_t fileIdx = 0, nextFileIdx = 0; + uint64_t nextSourceFileAddress = 0; + NSNumber *nextAddress; + uint64_t nextAddressVal; + unsigned int addressCount = [sortedAddresses count]; + + bool insideFunction = false; + + for (unsigned int i = 0; i < addressCount; ++i) { + NSNumber *address = [sortedAddresses objectAtIndex:i]; + // skip sources that have a starting address of 0 + if ([address unsignedLongValue] == 0) { + continue; + } + + uint64_t addressVal = [address unsignedLongLongValue] - baseAddress; + + // Get the next address to calculate the length + if (i + 1 < addressCount) { + nextAddress = [sortedAddresses objectAtIndex:i + 1]; + nextAddressVal = [nextAddress unsignedLongLongValue] - baseAddress; + } else { + nextAddressVal = baseAddress + moduleSize; + // The symbol reader doesn't want a trailing newline + terminatingChar = '\0'; + } + + NSDictionary *dict = [addresses_ objectForKey:address]; + NSNumber *line = [dict objectForKey:kAddressSourceLineKey]; + NSString *symbol = [dict objectForKey:kAddressConvertedSymbolKey]; + + if (!symbol) + symbol = [dict objectForKey:kAddressSymbolKey]; + + // sanity check the function length by making sure it doesn't + // run beyond the next function entry + uint64_t nextFunctionAddress = 0; + if (symbol && funcIndex < [sortedFunctionAddresses count]) { + nextFunctionAddress = [[sortedFunctionAddresses objectAtIndex:funcIndex] + unsignedLongLongValue] - baseAddress; + ++funcIndex; + } + + // Skip some symbols + if ([symbol hasPrefix:@"vtable for"]) + continue; + + if ([symbol hasPrefix:@"__static_initialization_and_destruction_0"]) + continue; + + if ([symbol hasPrefix:@"_GLOBAL__I_"]) + continue; + + if ([symbol hasPrefix:@"__func__."]) + continue; + + if ([symbol hasPrefix:@"__gnu"]) + continue; + + if ([symbol hasPrefix:@"typeinfo "]) + continue; + + if ([symbol hasPrefix:@"EH_frame"]) + continue; + + if ([symbol hasPrefix:@"GCC_except_table"]) + continue; + + if ([symbol hasPrefix:@"__tcf"]) + continue; + + if ([symbol hasPrefix:@"non-virtual thunk"]) + continue; + + // Find the source file (if any) that contains this address + while (sourceCount && (addressVal >= nextSourceFileAddress)) { + fileIdx = nextFileIdx; + + if (nextFileIdx < sourceCount) { + NSNumber *addr = [sources objectAtIndex:nextFileIdx]; + ++nextFileIdx; + nextSourceFileAddress = [addr unsignedLongLongValue] - baseAddress; + } else { + nextSourceFileAddress = baseAddress + moduleSize; + break; + } + } + + NSNumber *functionLength = [dict objectForKey:kFunctionSizeKey]; + + if (line) { + if (symbol && functionLength) { + + uint64_t functionLengthVal = [functionLength unsignedLongLongValue]; + + insideFunction = true; + // sanity check to make sure the length we were told does not exceed + // the space between this function and the next + if (nextFunctionAddress != 0) { + uint64_t functionLengthVal2 = nextFunctionAddress - addressVal; + + if(functionLengthVal > functionLengthVal2 ) { + functionLengthVal = functionLengthVal2; + } + } + + // Function + if (!WriteFormat(fd, "FUNC %llx %llx 0 %s\n", addressVal, + functionLengthVal, [symbol UTF8String])) + return NO; + } + + // Throw out line number information that doesn't correspond to + // any function + if (insideFunction) { + // Source line + uint64_t length = nextAddressVal - addressVal; + + // if fileNameToFileIndex/dict has an entry for the + // file/kFunctionFileKey, we're processing DWARF and have stored + // files for each program counter. If there is no entry, we're + // processing STABS and can use the old method of mapping + // addresses to files(which was basically iterating over a set + // of addresses until we reached one that was greater than the + // high PC of the current file, then moving on to the next file) + NSNumber *fileIndex = [fileNameToFileIndex objectForKey:[dict objectForKey:kFunctionFileKey]]; + if (!WriteFormat(fd, "%llx %llx %d %d\n", addressVal, length, + [line unsignedIntValue], fileIndex ? [fileIndex unsignedIntValue] : fileIdx)) + return NO; + } + } else { + // PUBLIC
+ if (!WriteFormat(fd, "PUBLIC %llx 0 %s\n", addressVal, + [symbol UTF8String])) + return NO; + insideFunction = false; + } + } + + return YES; +} + +//============================================================================= +- (id)initWithContentsOfFile:(NSString *)path { + if ((self = [super init])) { + + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + [self autorelease]; + return nil; + } + + sourcePath_ = [path copy]; + + // Test for .DSYM bundle + NSBundle *dsymBundle = [NSBundle bundleWithPath:sourcePath_]; + + if (dsymBundle) { + + // we need to take the DSYM bundle path and remove it's + // extension to get the name of the file inside the resources + // directory of the bundle that actually has the DWARF + // information + // But, Xcode supports something called "Wrapper extension"(see + // build settings), which would make the bundle name + // /tmp/foo/test.kext.dSYM, but the dwarf binary name would + // still be "test". so, now we loop through until deleting the + // extension doesn't change the string + + // e.g. suppose sourcepath_ is /tmp/foo/test.dSYM + + NSString *dwarfBinName = [sourcePath_ lastPathComponent]; + NSString *dwarfBinPath; + + // We use a do/while loop so we can handle files without an extension + do { + dwarfBinName = [dwarfBinName stringByDeletingPathExtension]; + // now, dwarfBinName is "test" + dwarfBinPath = [dsymBundle pathForResource:dwarfBinName ofType:nil inDirectory:@"DWARF"]; + if (dwarfBinPath != nil) + break; + } while (![[dwarfBinName stringByDeletingPathExtension] isEqualToString:dwarfBinName]); + + if (dwarfBinPath == nil) { + NSLog(@"The bundle passed on the command line does not appear to be a DWARF dSYM bundle"); + [self autorelease]; + return nil; + } + + // otherwise we're good to go + [sourcePath_ release]; + + sourcePath_ = [dwarfBinPath copy]; + NSLog(@"Loading DWARF dSYM file from %@", sourcePath_); + } + + sectionsForArch_ = new ArchSectionMap(); + + if (![self loadModuleInfo]) { + [self autorelease]; + return nil; + } + + // If there's more than one, use the native one + if ([headers_ count] > 1) { + const NXArchInfo *localArchInfo = NXGetLocalArchInfo(); + + if (localArchInfo) { + cpu_type_t cpu = localArchInfo->cputype; + NSString *arch; + + if (cpu & CPU_ARCH_ABI64) + arch = ((cpu & ~CPU_ARCH_ABI64) == CPU_TYPE_X86) ? + @"x86_64" : @"ppc64"; + else + arch = (cpu == CPU_TYPE_X86) ? @"x86" : @"ppc"; + + [self setArchitecture:arch]; + } + } else { + // Specify the default architecture + [self setArchitecture:[[headers_ allKeys] objectAtIndex:0]]; + } + } + + return self; +} + +//============================================================================= +- (NSArray *)availableArchitectures { + return [headers_ allKeys]; +} + +//============================================================================= +- (void)dealloc { + [sourcePath_ release]; + [architecture_ release]; + [addresses_ release]; + [functionAddresses_ release]; + [sources_ release]; + [headers_ release]; + delete sectionsForArch_; + + [super dealloc]; +} + +//============================================================================= +- (BOOL)setArchitecture:(NSString *)architecture { + NSString *normalized = [architecture lowercaseString]; + BOOL isValid = NO; + + if ([normalized isEqualToString:@"ppc"]) { + isValid = YES; + } + else if ([normalized isEqualToString:@"i386"]) { + normalized = @"x86"; + isValid = YES; + } + else if ([normalized isEqualToString:@"x86"]) { + isValid = YES; + } + else if ([normalized isEqualToString:@"ppc64"]) { + isValid = YES; + } + else if ([normalized isEqualToString:@"x86_64"]) { + isValid = YES; + } + + if (isValid) { + if (![headers_ objectForKey:normalized]) + return NO; + + [architecture_ autorelease]; + architecture_ = [normalized copy]; + } + + return isValid; +} + +//============================================================================= +- (NSString *)architecture { + return architecture_; +} + +//============================================================================= +- (BOOL)writeSymbolFile:(NSString *)destinationPath { + const char *dest = [destinationPath fileSystemRepresentation]; + int fd; + + if ([[destinationPath substringToIndex:1] isEqualToString:@"-"]) + fd = STDOUT_FILENO; + else + fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666); + + if (fd == -1) + return NO; + + BOOL result = [self outputSymbolFile:fd]; + + close(fd); + + return result; +} + +@end + +@implementation MachSection + +- (id)initWithMachSection:(section *)sect andNumber:(uint32_t)sectionNumber { + if ((self = [super init])) { + sect_ = sect; + sectionNumber_ = sectionNumber; + } + + return self; +} + +- (section*)sectionPointer { + return sect_; +} + +- (uint32_t)sectionNumber { + return sectionNumber_; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader-inl.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader-inl.h new file mode 100644 index 00000000..7ccd0fe6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader-inl.h @@ -0,0 +1,141 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__ +#define UTIL_DEBUGINFO_BYTEREADER_INL_H__ + +#include "common/mac/dwarf/bytereader.h" + +namespace dwarf2reader { + +inline uint8 ByteReader::ReadOneByte(const char* buffer) const { + return buffer[0]; +} + +inline uint16 ByteReader::ReadTwoBytes(const char* buffer) const { + const uint16 buffer0 = static_cast(buffer[0]); + const uint16 buffer1 = static_cast(buffer[1]); + if (endian_ == ENDIANNESS_LITTLE) { + return buffer0 | buffer1 << 8; + } else { + return buffer1 | buffer0 << 8; + } +} + +inline uint64 ByteReader::ReadFourBytes(const char* buffer) const { + const uint32 buffer0 = static_cast(buffer[0]); + const uint32 buffer1 = static_cast(buffer[1]); + const uint32 buffer2 = static_cast(buffer[2]); + const uint32 buffer3 = static_cast(buffer[3]); + if (endian_ == ENDIANNESS_LITTLE) { + return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24; + } else { + return buffer3 | buffer2 << 8 | buffer1 << 16 | buffer0 << 24; + } +} + +inline uint64 ByteReader::ReadEightBytes(const char* buffer) const { + const uint64 buffer0 = static_cast(buffer[0]); + const uint64 buffer1 = static_cast(buffer[1]); + const uint64 buffer2 = static_cast(buffer[2]); + const uint64 buffer3 = static_cast(buffer[3]); + const uint64 buffer4 = static_cast(buffer[4]); + const uint64 buffer5 = static_cast(buffer[5]); + const uint64 buffer6 = static_cast(buffer[6]); + const uint64 buffer7 = static_cast(buffer[7]); + if (endian_ == ENDIANNESS_LITTLE) { + return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 | + buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56; + } else { + return buffer7 | buffer6 << 8 | buffer5 << 16 | buffer4 << 24 | + buffer3 << 32 | buffer2 << 40 | buffer1 << 48 | buffer0 << 56; + } +} + +// Read an unsigned LEB128 number. Each byte contains 7 bits of +// information, plus one bit saying whether the number continues or +// not. + +inline uint64 ByteReader::ReadUnsignedLEB128(const char* buffer, + size_t* len) const { + uint64 result = 0; + size_t num_read = 0; + unsigned int shift = 0; + unsigned char byte; + + do { + byte = *buffer++; + num_read++; + + result |= (static_cast(byte & 0x7f)) << shift; + + shift += 7; + + } while (byte & 0x80); + + *len = num_read; + + return result; +} + +// Read a signed LEB128 number. These are like regular LEB128 +// numbers, except the last byte may have a sign bit set. + +inline int64 ByteReader::ReadSignedLEB128(const char* buffer, + size_t* len) const { + int64 result = 0; + unsigned int shift = 0; + size_t num_read = 0; + unsigned char byte; + + do { + byte = *buffer++; + num_read++; + result |= (static_cast(byte & 0x7f) << shift); + shift += 7; + } while (byte & 0x80); + + if ((shift < 8 * sizeof (result)) && (byte & 0x40)) + result |= -((static_cast(1)) << shift); + *len = num_read; + return result; +} + +inline uint64 ByteReader::ReadOffset(const char* buffer) const { + assert(this->offset_reader_); + return (this->*offset_reader_)(buffer); +} + +inline uint64 ByteReader::ReadAddress(const char* buffer) const { + assert(this->address_reader_); + return (this->*address_reader_)(buffer); +} + +} // namespace dwarf2reader + +#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.cc b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.cc new file mode 100644 index 00000000..823cf2b6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.cc @@ -0,0 +1,62 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "common/mac/dwarf/bytereader-inl.h" + +#include "common/mac/dwarf/bytereader.h" + +namespace dwarf2reader { + +ByteReader::ByteReader(enum Endianness endian) + :offset_reader_(NULL), address_reader_(NULL), endian_(endian), + address_size_(0), offset_size_(0) +{ } + +ByteReader::~ByteReader() { } + +void ByteReader::SetOffsetSize(uint8 size) { + offset_size_ = size; + assert(size == 4 || size == 8); + if (size == 4) { + this->offset_reader_ = &ByteReader::ReadFourBytes; + } else { + this->offset_reader_ = &ByteReader::ReadEightBytes; + } +} + +void ByteReader::SetAddressSize(uint8 size) { + address_size_ = size; + assert(size == 4 || size == 8); + if (size == 4) { + this->address_reader_ = &ByteReader::ReadFourBytes; + } else { + this->address_reader_ = &ByteReader::ReadEightBytes; + } +} + +} // namespace dwarf2reader diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.h new file mode 100644 index 00000000..299dd9ac --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/bytereader.h @@ -0,0 +1,132 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef COMMON_MAC_DWARF_BYTEREADER_H__ +#define COMMON_MAC_DWARF_BYTEREADER_H__ + +#include +#include "common/mac/dwarf/types.h" + +namespace dwarf2reader { + +// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN +// because it conflicts with a macro +enum Endianness { + ENDIANNESS_BIG, + ENDIANNESS_LITTLE +}; + +// Class that knows how to read both big endian and little endian +// numbers, for use in DWARF2/3 reader. +// Takes an endianness argument. +// To read addresses and offsets, SetAddressSize and SetOffsetSize +// must be called first. +class ByteReader { + public: + explicit ByteReader(enum Endianness endian); + virtual ~ByteReader(); + + // Set the address size to SIZE, which sets up the ReadAddress member + // so that it works. + void SetAddressSize(uint8 size); + + // Set the offset size to SIZE, which sets up the ReadOffset member + // so that it works. + void SetOffsetSize(uint8 size); + + // Return the current offset size + uint8 OffsetSize() const { return offset_size_; } + + // Return the current address size + uint8 AddressSize() const { return address_size_; } + + // Read a single byte from BUFFER and return it as an unsigned 8 bit + // number. + uint8 ReadOneByte(const char* buffer) const; + + // Read two bytes from BUFFER and return it as an unsigned 16 bit + // number. + uint16 ReadTwoBytes(const char* buffer) const; + + // Read four bytes from BUFFER and return it as an unsigned 32 bit + // number. This function returns a uint64 so that it is compatible + // with ReadAddress and ReadOffset. The number it returns will + // never be outside the range of an unsigned 32 bit integer. + uint64 ReadFourBytes(const char* buffer) const; + + // Read eight bytes from BUFFER and return it as an unsigned 64 bit + // number + uint64 ReadEightBytes(const char* buffer) const; + + // Read an unsigned LEB128 (Little Endian Base 128) number from + // BUFFER and return it as an unsigned 64 bit integer. LEN is set + // to the length read. Everybody seems to reinvent LEB128 as a + // variable size integer encoding, DWARF has had it for a long time. + uint64 ReadUnsignedLEB128(const char* buffer, size_t* len) const; + + // Read a signed LEB128 number from BUFFER and return it as an + // signed 64 bit integer. LEN is set to the length read. + int64 ReadSignedLEB128(const char* buffer, size_t* len) const; + + // Read an offset from BUFFER and return it as an unsigned 64 bit + // integer. DWARF2/3 define offsets as either 4 or 8 bytes, + // generally depending on the amount of DWARF2/3 info present. + uint64 ReadOffset(const char* buffer) const; + + // Read an address from BUFFER and return it as an unsigned 64 bit + // integer. DWARF2/3 allow addresses to be any size from 0-255 + // bytes currently. Internally we support 4 and 8 byte addresses, + // and will CHECK on anything else. + uint64 ReadAddress(const char* buffer) const; + + private: + + // Function pointer type for our address and offset readers. + typedef uint64 (ByteReader::*AddressReader)(const char*) const; + + // Read an offset from BUFFER and return it as an unsigned 64 bit + // integer. DWARF2/3 define offsets as either 4 or 8 bytes, + // generally depending on the amount of DWARF2/3 info present. + // This function pointer gets set by SetOffsetSize. + AddressReader offset_reader_; + + // Read an address from BUFFER and return it as an unsigned 64 bit + // integer. DWARF2/3 allow addresses to be any size from 0-255 + // bytes currently. Internally we support 4 and 8 byte addresses, + // and will CHECK on anything else. + // This function pointer gets set by SetAddressSize. + AddressReader address_reader_; + + Endianness endian_; + uint8 address_size_; + uint8 offset_size_; +}; + +} // namespace dwarf2reader + +#endif // COMMON_MAC_DWARF_BYTEREADER_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2enums.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2enums.h new file mode 100644 index 00000000..c52e2b47 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2enums.h @@ -0,0 +1,490 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef COMMON_MAC_DWARF_DWARF2ENUMS_H__ +#define COMMON_MAC_DWARF_DWARF2ENUMS_H__ + +namespace dwarf2reader { + +// These enums do not follow the google3 style only because they are +// known universally (specs, other implementations) by the names in +// exactly this capitalization. +// Tag names and codes. +enum DwarfTag { + DW_TAG_padding = 0x00, + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_param = 0x2f, + DW_TAG_template_value_param = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + // DWARF 3. + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + // SGI/MIPS Extensions. + DW_TAG_MIPS_loop = 0x4081, + // HP extensions. See: + // ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz + DW_TAG_HP_array_descriptor = 0x4090, + // GNU extensions. + DW_TAG_format_label = 0x4101, // For FORTRAN 77 and Fortran 90. + DW_TAG_function_template = 0x4102, // For C++. + DW_TAG_class_template = 0x4103, // For C++. + DW_TAG_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105, + // Extensions for UPC. See: http://upc.gwu.edu/~upc. + DW_TAG_upc_shared_type = 0x8765, + DW_TAG_upc_strict_type = 0x8766, + DW_TAG_upc_relaxed_type = 0x8767, + // PGI (STMicroelectronics) extensions. No documentation available. + DW_TAG_PGI_kanji_type = 0xA000, + DW_TAG_PGI_interface_block = 0xA020 +}; + + +enum DwarfHasChild { + DW_children_no = 0, + DW_children_yes = 1 +}; + +// Form names and codes. +enum DwarfForm { + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16 +}; + +// Attribute names and codes +enum DwarfAttribute { + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_subscr_data = 0x0a, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_element_list = 0x0f, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_member = 0x14, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_stride_size = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_items = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + // DWARF 3 values. + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + // SGI/MIPS extensions. + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + // HP extensions. + DW_AT_HP_block_index = 0x2000, + DW_AT_HP_unmodifiable = 0x2001, // Same as DW_AT_MIPS_fde. + DW_AT_HP_actuals_stmt_list = 0x2010, + DW_AT_HP_proc_per_section = 0x2011, + DW_AT_HP_raw_data_ptr = 0x2012, + DW_AT_HP_pass_by_reference = 0x2013, + DW_AT_HP_opt_level = 0x2014, + DW_AT_HP_prof_version_id = 0x2015, + DW_AT_HP_opt_flags = 0x2016, + DW_AT_HP_cold_region_low_pc = 0x2017, + DW_AT_HP_cold_region_high_pc = 0x2018, + DW_AT_HP_all_variables_modifiable = 0x2019, + DW_AT_HP_linkage_name = 0x201a, + DW_AT_HP_prof_flags = 0x201b, // In comp unit of procs_info for -g. + // GNU extensions. + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + // VMS extensions. + DW_AT_VMS_rtnbeg_pd_address = 0x2201, + // UPC extension. + DW_AT_upc_threads_scaled = 0x3210, + // PGI (STMicroelectronics) extensions. + DW_AT_PGI_lbase = 0x3a00, + DW_AT_PGI_soffset = 0x3a01, + DW_AT_PGI_lstride = 0x3a02 +}; + + +// Line number opcodes. +enum DwarfLineNumberOps { + DW_LNS_extended_op = 0, + DW_LNS_copy = 1, + DW_LNS_advance_pc = 2, + DW_LNS_advance_line = 3, + DW_LNS_set_file = 4, + DW_LNS_set_column = 5, + DW_LNS_negate_stmt = 6, + DW_LNS_set_basic_block = 7, + DW_LNS_const_add_pc = 8, + DW_LNS_fixed_advance_pc = 9, + // DWARF 3. + DW_LNS_set_prologue_end = 10, + DW_LNS_set_epilogue_begin = 11, + DW_LNS_set_isa = 12 +}; + +// Line number extended opcodes. +enum DwarfLineNumberExtendedOps { + DW_LNE_end_sequence = 1, + DW_LNE_set_address = 2, + DW_LNE_define_file = 3, + // HP extensions. + DW_LNE_HP_negate_is_UV_update = 0x11, + DW_LNE_HP_push_context = 0x12, + DW_LNE_HP_pop_context = 0x13, + DW_LNE_HP_set_file_line_column = 0x14, + DW_LNE_HP_set_routine_name = 0x15, + DW_LNE_HP_set_sequence = 0x16, + DW_LNE_HP_negate_post_semantics = 0x17, + DW_LNE_HP_negate_function_exit = 0x18, + DW_LNE_HP_negate_front_end_logical = 0x19, + DW_LNE_HP_define_proc = 0x20 +}; + +// Type encoding names and codes +enum DwarfEncoding { + DW_ATE_address =0x1, + DW_ATE_boolean =0x2, + DW_ATE_complex_float =0x3, + DW_ATE_float =0x4, + DW_ATE_signed =0x5, + DW_ATE_signed_char =0x6, + DW_ATE_unsigned =0x7, + DW_ATE_unsigned_char =0x8, + // DWARF3/DWARF3f + DW_ATE_imaginary_float =0x9, + DW_ATE_packed_decimal =0xa, + DW_ATE_numeric_string =0xb, + DW_ATE_edited =0xc, + DW_ATE_signed_fixed =0xd, + DW_ATE_unsigned_fixed =0xe, + DW_ATE_decimal_float =0xf, + DW_ATE_lo_user =0x80, + DW_ATE_hi_user =0xff +}; + +// Location virtual machine opcodes +enum DwarfOpcode { + DW_OP_addr =0x03, + DW_OP_deref =0x06, + DW_OP_const1u =0x08, + DW_OP_const1s =0x09, + DW_OP_const2u =0x0a, + DW_OP_const2s =0x0b, + DW_OP_const4u =0x0c, + DW_OP_const4s =0x0d, + DW_OP_const8u =0x0e, + DW_OP_const8s =0x0f, + DW_OP_constu =0x10, + DW_OP_consts =0x11, + DW_OP_dup =0x12, + DW_OP_drop =0x13, + DW_OP_over =0x14, + DW_OP_pick =0x15, + DW_OP_swap =0x16, + DW_OP_rot =0x17, + DW_OP_xderef =0x18, + DW_OP_abs =0x19, + DW_OP_and =0x1a, + DW_OP_div =0x1b, + DW_OP_minus =0x1c, + DW_OP_mod =0x1d, + DW_OP_mul =0x1e, + DW_OP_neg =0x1f, + DW_OP_not =0x20, + DW_OP_or =0x21, + DW_OP_plus =0x22, + DW_OP_plus_uconst =0x23, + DW_OP_shl =0x24, + DW_OP_shr =0x25, + DW_OP_shra =0x26, + DW_OP_xor =0x27, + DW_OP_bra =0x28, + DW_OP_eq =0x29, + DW_OP_ge =0x2a, + DW_OP_gt =0x2b, + DW_OP_le =0x2c, + DW_OP_lt =0x2d, + DW_OP_ne =0x2e, + DW_OP_skip =0x2f, + DW_OP_lit0 =0x30, + DW_OP_lit1 =0x31, + DW_OP_lit2 =0x32, + DW_OP_lit3 =0x33, + DW_OP_lit4 =0x34, + DW_OP_lit5 =0x35, + DW_OP_lit6 =0x36, + DW_OP_lit7 =0x37, + DW_OP_lit8 =0x38, + DW_OP_lit9 =0x39, + DW_OP_lit10 =0x3a, + DW_OP_lit11 =0x3b, + DW_OP_lit12 =0x3c, + DW_OP_lit13 =0x3d, + DW_OP_lit14 =0x3e, + DW_OP_lit15 =0x3f, + DW_OP_lit16 =0x40, + DW_OP_lit17 =0x41, + DW_OP_lit18 =0x42, + DW_OP_lit19 =0x43, + DW_OP_lit20 =0x44, + DW_OP_lit21 =0x45, + DW_OP_lit22 =0x46, + DW_OP_lit23 =0x47, + DW_OP_lit24 =0x48, + DW_OP_lit25 =0x49, + DW_OP_lit26 =0x4a, + DW_OP_lit27 =0x4b, + DW_OP_lit28 =0x4c, + DW_OP_lit29 =0x4d, + DW_OP_lit30 =0x4e, + DW_OP_lit31 =0x4f, + DW_OP_reg0 =0x50, + DW_OP_reg1 =0x51, + DW_OP_reg2 =0x52, + DW_OP_reg3 =0x53, + DW_OP_reg4 =0x54, + DW_OP_reg5 =0x55, + DW_OP_reg6 =0x56, + DW_OP_reg7 =0x57, + DW_OP_reg8 =0x58, + DW_OP_reg9 =0x59, + DW_OP_reg10 =0x5a, + DW_OP_reg11 =0x5b, + DW_OP_reg12 =0x5c, + DW_OP_reg13 =0x5d, + DW_OP_reg14 =0x5e, + DW_OP_reg15 =0x5f, + DW_OP_reg16 =0x60, + DW_OP_reg17 =0x61, + DW_OP_reg18 =0x62, + DW_OP_reg19 =0x63, + DW_OP_reg20 =0x64, + DW_OP_reg21 =0x65, + DW_OP_reg22 =0x66, + DW_OP_reg23 =0x67, + DW_OP_reg24 =0x68, + DW_OP_reg25 =0x69, + DW_OP_reg26 =0x6a, + DW_OP_reg27 =0x6b, + DW_OP_reg28 =0x6c, + DW_OP_reg29 =0x6d, + DW_OP_reg30 =0x6e, + DW_OP_reg31 =0x6f, + DW_OP_breg0 =0x70, + DW_OP_breg1 =0x71, + DW_OP_breg2 =0x72, + DW_OP_breg3 =0x73, + DW_OP_breg4 =0x74, + DW_OP_breg5 =0x75, + DW_OP_breg6 =0x76, + DW_OP_breg7 =0x77, + DW_OP_breg8 =0x78, + DW_OP_breg9 =0x79, + DW_OP_breg10 =0x7a, + DW_OP_breg11 =0x7b, + DW_OP_breg12 =0x7c, + DW_OP_breg13 =0x7d, + DW_OP_breg14 =0x7e, + DW_OP_breg15 =0x7f, + DW_OP_breg16 =0x80, + DW_OP_breg17 =0x81, + DW_OP_breg18 =0x82, + DW_OP_breg19 =0x83, + DW_OP_breg20 =0x84, + DW_OP_breg21 =0x85, + DW_OP_breg22 =0x86, + DW_OP_breg23 =0x87, + DW_OP_breg24 =0x88, + DW_OP_breg25 =0x89, + DW_OP_breg26 =0x8a, + DW_OP_breg27 =0x8b, + DW_OP_breg28 =0x8c, + DW_OP_breg29 =0x8d, + DW_OP_breg30 =0x8e, + DW_OP_breg31 =0x8f, + DW_OP_regX =0x90, + DW_OP_fbreg =0x91, + DW_OP_bregX =0x92, + DW_OP_piece =0x93, + DW_OP_deref_size =0x94, + DW_OP_xderef_size =0x95, + DW_OP_nop =0x96, + // DWARF3/DWARF3f + DW_OP_push_object_address =0x97, + DW_OP_call2 =0x98, + DW_OP_call4 =0x99, + DW_OP_call_ref =0x9a, + DW_OP_form_tls_address =0x9b, + DW_OP_call_frame_cfa =0x9c, + DW_OP_bit_piece =0x9d, + DW_OP_lo_user =0xe0, + DW_OP_hi_user =0xff, + // GNU extensions + DW_OP_GNU_push_tls_address =0xe0 +}; + +} // namespace dwarf2reader +#endif // COMMON_MAC_DWARF_DWARF2ENUMS_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.cc b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.cc new file mode 100644 index 00000000..6e7a2f1d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.cc @@ -0,0 +1,830 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include + +#include "common/mac/dwarf/bytereader-inl.h" +#include "common/mac/dwarf/dwarf2reader.h" +#include "common/mac/dwarf/bytereader.h" +#include "common/mac/dwarf/line_state_machine.h" + +namespace __gnu_cxx +{ + template<> struct hash< std::string > + { + size_t operator()( const std::string& x ) const + { + return hash< const char* >()( x.c_str() ); + } + }; +} + +namespace dwarf2reader { + +// Read a DWARF2/3 initial length field from START, using READER, and +// report the length in LEN. Return the actual initial length. + +static uint64 ReadInitialLength(const char* start, + ByteReader* reader, size_t* len) { + const uint64 initial_length = reader->ReadFourBytes(start); + start += 4; + + // In DWARF2/3, if the initial length is all 1 bits, then the offset + // size is 8 and we need to read the next 8 bytes for the real length. + if (initial_length == 0xffffffff) { + reader->SetOffsetSize(8); + *len = 12; + return reader->ReadOffset(start); + } else { + reader->SetOffsetSize(4); + *len = 4; + } + return initial_length; +} + +CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset, + ByteReader* reader, Dwarf2Handler* handler) + : offset_from_section_start_(offset), reader_(reader), + sections_(sections), handler_(handler), abbrevs_(NULL), + string_buffer_(NULL), string_buffer_length_(0) {} + +// Read a DWARF2/3 abbreviation section. +// Each abbrev consists of a abbreviation number, a tag, a byte +// specifying whether the tag has children, and a list of +// attribute/form pairs. +// The list of forms is terminated by a 0 for the attribute, and a +// zero for the form. The entire abbreviation section is terminated +// by a zero for the code. + +void CompilationUnit::ReadAbbrevs() { + if (abbrevs_) + return; + + // First get the debug_abbrev section + SectionMap::const_iterator iter = sections_.find("__debug_abbrev"); + assert(iter != sections_.end()); + + abbrevs_ = new vector; + abbrevs_->resize(1); + + // The only way to check whether we are reading over the end of the + // buffer would be to first compute the size of the leb128 data by + // reading it, then go back and read it again. + const char* abbrev_start = iter->second.first + + header_.abbrev_offset; + const char* abbrevptr = abbrev_start; + const uint64 abbrev_length = iter->second.second - header_.abbrev_offset; + + while (1) { + CompilationUnit::Abbrev abbrev; + size_t len; + const uint32 number = reader_->ReadUnsignedLEB128(abbrevptr, &len); + + if (number == 0) + break; + abbrev.number = number; + abbrevptr += len; + + assert(abbrevptr < abbrev_start + abbrev_length); + const uint32 tag = reader_->ReadUnsignedLEB128(abbrevptr, &len); + abbrevptr += len; + abbrev.tag = static_cast(tag); + + assert(abbrevptr < abbrev_start + abbrev_length); + abbrev.has_children = reader_->ReadOneByte(abbrevptr); + abbrevptr += 1; + + assert(abbrevptr < abbrev_start + abbrev_length); + + while (1) { + const uint32 nametemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); + abbrevptr += len; + + assert(abbrevptr < abbrev_start + abbrev_length); + const uint32 formtemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); + abbrevptr += len; + if (nametemp == 0 && formtemp == 0) + break; + + const enum DwarfAttribute name = + static_cast(nametemp); + const enum DwarfForm form = static_cast(formtemp); + abbrev.attributes.push_back(make_pair(name, form)); + } + assert(abbrev.number == abbrevs_->size()); + abbrevs_->push_back(abbrev); + } +} + +// Skips a single DIE's attributes. +const char* CompilationUnit::SkipDIE(const char* start, + const Abbrev& abbrev) { + for (AttributeList::const_iterator i = abbrev.attributes.begin(); + i != abbrev.attributes.end(); + i++) { + start = SkipAttribute(start, i->second); + } + return start; +} + +// Skips a single attribute form's data. +const char* CompilationUnit::SkipAttribute(const char* start, + enum DwarfForm form) { + size_t len; + + switch (form) { + case DW_FORM_indirect: + form = static_cast(reader_->ReadUnsignedLEB128(start, + &len)); + start += len; + return SkipAttribute(start, form); + break; + + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + return start + 1; + break; + case DW_FORM_ref2: + case DW_FORM_data2: + return start + 2; + break; + case DW_FORM_ref4: + case DW_FORM_data4: + return start + 4; + break; + case DW_FORM_ref8: + case DW_FORM_data8: + return start + 8; + break; + case DW_FORM_string: + return start + strlen(start) + 1; + break; + case DW_FORM_udata: + case DW_FORM_ref_udata: + reader_->ReadUnsignedLEB128(start, &len); + return start + len; + break; + + case DW_FORM_sdata: + reader_->ReadSignedLEB128(start, &len); + return start + len; + break; + case DW_FORM_addr: + return start + reader_->AddressSize(); + break; + case DW_FORM_ref_addr: + // DWARF2 and 3 differ on whether ref_addr is address size or + // offset size. + assert(header_.version == 2 || header_.version == 3); + if (header_.version == 2) { + return start + reader_->AddressSize(); + } else if (header_.version == 3) { + return start + reader_->OffsetSize(); + } + break; + + case DW_FORM_block1: + return start + 1 + reader_->ReadOneByte(start); + break; + case DW_FORM_block2: + return start + 2 + reader_->ReadTwoBytes(start); + break; + case DW_FORM_block4: + return start + 4 + reader_->ReadFourBytes(start); + break; + case DW_FORM_block: { + uint64 size = reader_->ReadUnsignedLEB128(start, &len); + return start + size + len; + } + break; + case DW_FORM_strp: + return start + reader_->OffsetSize(); + break; + default: + fprintf(stderr,"Unhandled form type"); + } + fprintf(stderr,"Unhandled form type"); + return NULL; +} + +// Read a DWARF2/3 header. +// The header is variable length in DWARF3 (and DWARF2 as extended by +// most compilers), and consists of an length field, a version number, +// the offset in the .debug_abbrev section for our abbrevs, and an +// address size. +void CompilationUnit::ReadHeader() { + const char* headerptr = buffer_; + size_t initial_length_size; + + assert(headerptr + 4 < buffer_ + buffer_length_); + const uint64 initial_length = ReadInitialLength(headerptr, reader_, + &initial_length_size); + headerptr += initial_length_size; + header_.length = initial_length; + + assert(headerptr + 2 < buffer_ + buffer_length_); + header_.version = reader_->ReadTwoBytes(headerptr); + headerptr += 2; + + assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_); + header_.abbrev_offset = reader_->ReadOffset(headerptr); + headerptr += reader_->OffsetSize(); + + assert(headerptr + 1 < buffer_ + buffer_length_); + header_.address_size = reader_->ReadOneByte(headerptr); + reader_->SetAddressSize(header_.address_size); + headerptr += 1; + + after_header_ = headerptr; + + // This check ensures that we don't have to do checking during the + // reading of DIEs. header_.length does not include the size of the + // initial length. + assert(buffer_ + initial_length_size + header_.length <= + buffer_ + buffer_length_); +} + +uint64 CompilationUnit::Start() { + // First get the debug_info section + SectionMap::const_iterator iter = sections_.find("__debug_info"); + assert(iter != sections_.end()); + + // Set up our buffer + buffer_ = iter->second.first + offset_from_section_start_; + buffer_length_ = iter->second.second - offset_from_section_start_; + + // Read the header + ReadHeader(); + + // Figure out the real length from the end of the initial length to + // the end of the compilation unit, since that is the value we + // return. + uint64 ourlength = header_.length; + if (reader_->OffsetSize() == 8) + ourlength += 12; + else + ourlength += 4; + + // See if the user wants this compilation unit, and if not, just return. + if (!handler_->StartCompilationUnit(offset_from_section_start_, + reader_->AddressSize(), + reader_->OffsetSize(), + header_.length, + header_.version)) + return ourlength; + + // Otherwise, continue by reading our abbreviation entries. + ReadAbbrevs(); + + // Set the string section if we have one. + iter = sections_.find("__debug_str"); + if (iter != sections_.end()) { + string_buffer_ = iter->second.first; + string_buffer_length_ = iter->second.second; + } + + // Now that we have our abbreviations, start processing DIE's. + ProcessDIEs(); + + return ourlength; +} + +// If one really wanted, you could merge SkipAttribute and +// ProcessAttribute +// This is all boring data manipulation and calling of the handler. +const char* CompilationUnit::ProcessAttribute( + uint64 dieoffset, const char* start, enum DwarfAttribute attr, + enum DwarfForm form) { + size_t len; + + switch (form) { + // DW_FORM_indirect is never used because it is such a space + // waster. + case DW_FORM_indirect: + form = static_cast(reader_->ReadUnsignedLEB128(start, + &len)); + start += len; + return ProcessAttribute(dieoffset, start, attr, form); + break; + + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadOneByte(start)); + return start + 1; + break; + case DW_FORM_ref2: + case DW_FORM_data2: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadTwoBytes(start)); + return start + 2; + break; + case DW_FORM_ref4: + case DW_FORM_data4: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadFourBytes(start)); + return start + 4; + break; + case DW_FORM_ref8: + case DW_FORM_data8: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadEightBytes(start)); + return start + 8; + break; + case DW_FORM_string: { + const char* str = start; + handler_->ProcessAttributeString(dieoffset, attr, form, + str); + return start + strlen(str) + 1; + } + break; + case DW_FORM_udata: + case DW_FORM_ref_udata: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadUnsignedLEB128(start, + &len)); + return start + len; + break; + + case DW_FORM_sdata: + handler_->ProcessAttributeSigned(dieoffset, attr, form, + reader_->ReadSignedLEB128(start, &len)); + return start + len; + break; + case DW_FORM_addr: + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadAddress(start)); + return start + reader_->AddressSize(); + break; + case DW_FORM_ref_addr: + // DWARF2 and 3 differ on whether ref_addr is address size or + // offset size. + assert(header_.version == 2 || header_.version == 3); + if (header_.version == 2) { + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadAddress(start)); + return start + reader_->AddressSize(); + } else if (header_.version == 3) { + handler_->ProcessAttributeUnsigned(dieoffset, attr, form, + reader_->ReadOffset(start)); + return start + reader_->OffsetSize(); + } + break; + + case DW_FORM_block1: { + uint64 datalen = reader_->ReadOneByte(start); + handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1, + datalen); + return start + 1 + datalen; + } + break; + case DW_FORM_block2: { + uint64 datalen = reader_->ReadTwoBytes(start); + handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 2, + datalen); + return start + 2 + datalen; + } + break; + case DW_FORM_block4: { + uint64 datalen = reader_->ReadFourBytes(start); + handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 4, + datalen); + return start + 4 + datalen; + } + break; + case DW_FORM_block: { + uint64 datalen = reader_->ReadUnsignedLEB128(start, &len); + handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len, + datalen); + return start + datalen + len; + } + break; + case DW_FORM_strp: { + assert(string_buffer_ != NULL); + + const uint64 offset = reader_->ReadOffset(start); + assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); + + const char* str = string_buffer_ + offset; + handler_->ProcessAttributeString(dieoffset, attr, form, + str); + return start + reader_->OffsetSize(); + } + break; + default: + fprintf(stderr, "Unhandled form type"); + } + fprintf(stderr, "Unhandled form type"); + return NULL; +} + +const char* CompilationUnit::ProcessDIE(uint64 dieoffset, + const char* start, + const Abbrev& abbrev) { + for (AttributeList::const_iterator i = abbrev.attributes.begin(); + i != abbrev.attributes.end(); + i++) { + start = ProcessAttribute(dieoffset, start, i->first, i->second); + } + return start; +} + +void CompilationUnit::ProcessDIEs() { + const char* dieptr = after_header_; + size_t len; + + // lengthstart is the place the length field is based on. + // It is the point in the header after the initial length field + const char* lengthstart = buffer_; + + // In 64 bit dwarf, the initial length is 12 bytes, because of the + // 0xffffffff at the start. + if (reader_->OffsetSize() == 8) + lengthstart += 12; + else + lengthstart += 4; + + // we need semantics of boost scoped_ptr here - no intention of trasnferring + // ownership of the stack. use const, but then we limit ourselves to not + // ever being able to call .reset() on the smart pointer. + auto_ptr > const die_stack(new stack); + + while (dieptr < (lengthstart + header_.length)) { + // We give the user the absolute offset from the beginning of + // debug_info, since they need it to deal with ref_addr forms. + uint64 absolute_offset = (dieptr - buffer_) + offset_from_section_start_; + + uint64 abbrev_num = reader_->ReadUnsignedLEB128(dieptr, &len); + + dieptr += len; + + // Abbrev == 0 represents the end of a list of children. + if (abbrev_num == 0) { + const uint64 offset = die_stack->top(); + die_stack->pop(); + handler_->EndDIE(offset); + continue; + } + + const Abbrev& abbrev = abbrevs_->at(abbrev_num); + const enum DwarfTag tag = abbrev.tag; + if (!handler_->StartDIE(absolute_offset, tag, abbrev.attributes)) { + dieptr = SkipDIE(dieptr, abbrev); + } else { + dieptr = ProcessDIE(absolute_offset, dieptr, abbrev); + } + + if (abbrev.has_children) { + die_stack->push(absolute_offset); + } else { + handler_->EndDIE(absolute_offset); + } + } +} + +LineInfo::LineInfo(const char* buffer, uint64 buffer_length, + ByteReader* reader, LineInfoHandler* handler): + handler_(handler), reader_(reader), buffer_(buffer), + buffer_length_(buffer_length) { + header_.std_opcode_lengths = NULL; +} + +uint64 LineInfo::Start() { + ReadHeader(); + ReadLines(); + return after_header_ - buffer_; +} + +// The header for a debug_line section is mildly complicated, because +// the line info is very tightly encoded. +void LineInfo::ReadHeader() { + const char* lineptr = buffer_; + size_t initial_length_size; + + const uint64 initial_length = ReadInitialLength(lineptr, reader_, + &initial_length_size); + + lineptr += initial_length_size; + header_.total_length = initial_length; + assert(buffer_ + initial_length_size + header_.total_length <= + buffer_ + buffer_length_); + + // Address size *must* be set by CU ahead of time. + assert(reader_->AddressSize() != 0); + + header_.version = reader_->ReadTwoBytes(lineptr); + lineptr += 2; + + header_.prologue_length = reader_->ReadOffset(lineptr); + lineptr += reader_->OffsetSize(); + + header_.min_insn_length = reader_->ReadOneByte(lineptr); + lineptr += 1; + + header_.default_is_stmt = reader_->ReadOneByte(lineptr); + lineptr += 1; + + header_.line_base = *reinterpret_cast(lineptr); + lineptr += 1; + + header_.line_range = reader_->ReadOneByte(lineptr); + lineptr += 1; + + header_.opcode_base = reader_->ReadOneByte(lineptr); + lineptr += 1; + + header_.std_opcode_lengths = new vector; + header_.std_opcode_lengths->resize(header_.opcode_base + 1); + (*header_.std_opcode_lengths)[0] = 0; + for (int i = 1; i < header_.opcode_base; i++) { + (*header_.std_opcode_lengths)[i] = reader_->ReadOneByte(lineptr); + lineptr += 1; + } + + // It is legal for the directory entry table to be empty. + if (*lineptr) { + uint32 dirindex = 1; + while (*lineptr) { + const char* dirname = lineptr; + handler_->DefineDir(dirname, dirindex); + lineptr += strlen(dirname) + 1; + dirindex++; + } + } + lineptr++; + + // It is also legal for the file entry table to be empty. + if (*lineptr) { + uint32 fileindex = 1; + size_t len; + while (*lineptr) { + const char* filename = lineptr; + lineptr += strlen(filename) + 1; + + uint64 dirindex = reader_->ReadUnsignedLEB128(lineptr, &len); + lineptr += len; + + uint64 mod_time = reader_->ReadUnsignedLEB128(lineptr, &len); + lineptr += len; + + uint64 filelength = reader_->ReadUnsignedLEB128(lineptr, &len); + lineptr += len; + handler_->DefineFile(filename, fileindex, dirindex, mod_time, + filelength); + fileindex++; + } + } + lineptr++; + + after_header_ = lineptr; +} + +/* static */ +bool LineInfo::ProcessOneOpcode(ByteReader* reader, + LineInfoHandler* handler, + const struct LineInfoHeader &header, + const char* start, + struct LineStateMachine* lsm, + size_t* len, + uintptr_t pc, + bool *lsm_passes_pc) { + size_t oplen = 0; + size_t templen; + uint8 opcode = reader->ReadOneByte(start); + oplen++; + start++; + + // If the opcode is great than the opcode_base, it is a special + // opcode. Most line programs consist mainly of special opcodes. + if (opcode >= header.opcode_base) { + opcode -= header.opcode_base; + const int64 advance_address = (opcode / header.line_range) + * header.min_insn_length; + const int64 advance_line = (opcode % header.line_range) + + header.line_base; + + // Check if the lsm passes "pc". If so, mark it as passed. + if (lsm_passes_pc && + lsm->address <= pc && pc < lsm->address + advance_address) { + *lsm_passes_pc = true; + } + + lsm->address += advance_address; + lsm->line_num += advance_line; + lsm->basic_block = true; + *len = oplen; + return true; + } + + // Otherwise, we have the regular opcodes + switch (opcode) { + case DW_LNS_copy: { + lsm->basic_block = false; + *len = oplen; + return true; + } + + case DW_LNS_advance_pc: { + uint64 advance_address = reader->ReadUnsignedLEB128(start, &templen); + oplen += templen; + + // Check if the lsm passes "pc". If so, mark it as passed. + if (lsm_passes_pc && lsm->address <= pc && + pc < lsm->address + header.min_insn_length * advance_address) { + *lsm_passes_pc = true; + } + + lsm->address += header.min_insn_length * advance_address; + } + break; + case DW_LNS_advance_line: { + const int64 advance_line = reader->ReadSignedLEB128(start, &templen); + oplen += templen; + lsm->line_num += advance_line; + + // With gcc 4.2.1, we can get the line_no here for the first time + // since DW_LNS_advance_line is called after DW_LNE_set_address is + // called. So we check if the lsm passes "pc" here, not in + // DW_LNE_set_address. + if (lsm_passes_pc && lsm->address == pc) { + *lsm_passes_pc = true; + } + } + break; + case DW_LNS_set_file: { + const uint64 fileno = reader->ReadUnsignedLEB128(start, &templen); + oplen += templen; + lsm->file_num = fileno; + } + break; + case DW_LNS_set_column: { + const uint64 colno = reader->ReadUnsignedLEB128(start, &templen); + oplen += templen; + lsm->column_num = colno; + } + break; + case DW_LNS_negate_stmt: { + lsm->is_stmt = !lsm->is_stmt; + } + break; + case DW_LNS_set_basic_block: { + lsm->basic_block = true; + } + break; + case DW_LNS_fixed_advance_pc: { + const uint16 advance_address = reader->ReadTwoBytes(start); + oplen += 2; + + // Check if the lsm passes "pc". If so, mark it as passed. + if (lsm_passes_pc && + lsm->address <= pc && pc < lsm->address + advance_address) { + *lsm_passes_pc = true; + } + + lsm->address += advance_address; + } + break; + case DW_LNS_const_add_pc: { + const int64 advance_address = header.min_insn_length + * ((255 - header.opcode_base) + / header.line_range); + + // Check if the lsm passes "pc". If so, mark it as passed. + if (lsm_passes_pc && + lsm->address <= pc && pc < lsm->address + advance_address) { + *lsm_passes_pc = true; + } + + lsm->address += advance_address; + } + break; + case DW_LNS_extended_op: { + const size_t extended_op_len = reader->ReadUnsignedLEB128(start, + &templen); + start += templen; + oplen += templen + extended_op_len; + + const uint64 extended_op = reader->ReadOneByte(start); + start++; + + switch (extended_op) { + case DW_LNE_end_sequence: { + lsm->end_sequence = true; + *len = oplen; + return true; + } + break; + case DW_LNE_set_address: { + // With gcc 4.2.1, we cannot tell the line_no here since + // DW_LNE_set_address is called before DW_LNS_advance_line is + // called. So we do not check if the lsm passes "pc" here. See + // also the comment in DW_LNS_advance_line. + uint64 address = reader->ReadAddress(start); + lsm->address = address; + } + break; + case DW_LNE_define_file: { + const char* filename = start; + + templen = strlen(filename) + 1; + start += templen; + + uint64 dirindex = reader->ReadUnsignedLEB128(start, &templen); + oplen += templen; + + const uint64 mod_time = reader->ReadUnsignedLEB128(start, + &templen); + oplen += templen; + + const uint64 filelength = reader->ReadUnsignedLEB128(start, + &templen); + oplen += templen; + + if (handler) { + handler->DefineFile(filename, -1, dirindex, mod_time, + filelength); + } + } + break; + } + } + break; + + default: { + // Ignore unknown opcode silently + if (header.std_opcode_lengths) { + for (int i = 0; i < (*header.std_opcode_lengths)[opcode]; i++) { + size_t templen; + reader->ReadUnsignedLEB128(start, &templen); + start += templen; + oplen += templen; + } + } + } + break; + } + *len = oplen; + return false; +} + +void LineInfo::ReadLines() { + struct LineStateMachine lsm; + + // lengthstart is the place the length field is based on. + // It is the point in the header after the initial length field + const char* lengthstart = buffer_; + + // In 64 bit dwarf, the initial length is 12 bytes, because of the + // 0xffffffff at the start. + if (reader_->OffsetSize() == 8) + lengthstart += 12; + else + lengthstart += 4; + + const char* lineptr = after_header_; + while (lineptr < lengthstart + header_.total_length) { + lsm.Reset(header_.default_is_stmt); + while (!lsm.end_sequence) { + size_t oplength; + bool add_line = ProcessOneOpcode(reader_, handler_, header_, + lineptr, &lsm, &oplength, (uintptr_t)-1, NULL); + if (add_line) + handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num, + lsm.column_num); + lineptr += oplength; + } + } + + after_header_ = lengthstart + header_.total_length; +} + +} // namespace dwarf2reader diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.h new file mode 100644 index 00000000..f27cdac7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/dwarf2reader.h @@ -0,0 +1,393 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file contains definitions related to the DWARF2/3 reader and +// it's handler interfaces. +// The DWARF2/3 specification can be found at +// http://dwarf.freestandards.org and should be considered required +// reading if you wish to modify the implementation. +// Only a cursory attempt is made to explain terminology that is +// used here, as it is much better explained in the standard documents +#ifndef COMMON_MAC_DWARF_DWARF2READER_H__ +#define COMMON_MAC_DWARF_DWARF2READER_H__ + +#include +#include +#include +#include +#include + +#include "common/mac/dwarf/dwarf2enums.h" +#include "common/mac/dwarf/types.h" + +using namespace std; +using namespace __gnu_cxx; + +namespace dwarf2reader { +struct LineStateMachine; +class ByteReader; +class Dwarf2Handler; +class LineInfoHandler; + +// This maps from a string naming a section to a pair containing a +// the data for the section, and the size of the section. +typedef hash_map > SectionMap; +typedef list > AttributeList; +typedef AttributeList::iterator AttributeIterator; +typedef AttributeList::const_iterator ConstAttributeIterator; + +struct LineInfoHeader { + uint64 total_length; + uint16 version; + uint64 prologue_length; + uint8 min_insn_length; // insn stands for instructin + bool default_is_stmt; // stmt stands for statement + int8 line_base; + uint8 line_range; + uint8 opcode_base; + // Use a pointer so that signalsafe_addr2line is able to use this structure + // without heap allocation problem. + vector *std_opcode_lengths; +}; + +class LineInfo { + public: + + // Initializes a .debug_line reader. Buffer and buffer length point + // to the beginning and length of the line information to read. + // Reader is a ByteReader class that has the endianness set + // properly. + LineInfo(const char* buffer_, uint64 buffer_length, + ByteReader* reader, LineInfoHandler* handler); + + virtual ~LineInfo() { + if (header_.std_opcode_lengths) { + delete header_.std_opcode_lengths; + } + } + + // Start processing line info, and calling callbacks in the handler. + // Consumes the line number information for a single compilation unit. + // Returns the number of bytes processed. + uint64 Start(); + + // Process a single line info opcode at START using the state + // machine at LSM. Return true if we should define a line using the + // current state of the line state machine. Place the length of the + // opcode in LEN. + // If LSM_PASSES_PC is non-NULL, this function also checks if the lsm + // passes the address of PC. In other words, LSM_PASSES_PC will be + // set to true, if the following condition is met. + // + // lsm's old address < PC <= lsm's new address + static bool ProcessOneOpcode(ByteReader* reader, + LineInfoHandler* handler, + const struct LineInfoHeader &header, + const char* start, + struct LineStateMachine* lsm, + size_t* len, + uintptr_t pc, + bool *lsm_passes_pc); + + private: + // Reads the DWARF2/3 header for this line info. + void ReadHeader(); + + // Reads the DWARF2/3 line information + void ReadLines(); + + // The associated handler to call processing functions in + LineInfoHandler* handler_; + + // The associated ByteReader that handles endianness issues for us + ByteReader* reader_; + + // A DWARF2/3 line info header. This is not the same size as + // in the actual file, as the one in the file may have a 32 bit or + // 64 bit lengths + + struct LineInfoHeader header_; + + // buffer is the buffer for our line info, starting at exactly where + // the line info to read is. after_header is the place right after + // the end of the line information header. + const char* buffer_; + uint64 buffer_length_; + const char* after_header_; +}; + +// This class is the main interface between the line info reader and +// the client. The virtual functions inside this get called for +// interesting events that happen during line info reading. The +// default implementation does nothing + +class LineInfoHandler { + public: + LineInfoHandler() { } + + virtual ~LineInfoHandler() { } + + // Called when we define a directory. NAME is the directory name, + // DIR_NUM is the directory number + virtual void DefineDir(const string& name, uint32 dir_num) { } + + // Called when we define a filename. NAME is the filename, FILE_NUM + // is the file number which is -1 if the file index is the next + // index after the last numbered index (this happens when files are + // dynamically defined by the line program), DIR_NUM is the + // directory index for the directory name of this file, MOD_TIME is + // the modification time of the file, and LENGTH is the length of + // the file + virtual void DefineFile(const string& name, int32 file_num, + uint32 dir_num, uint64 mod_time, + uint64 length) { } + + // Called when the line info reader has a new line, address pair + // ready for us. ADDRESS is the address of the code, FILE_NUM is + // the file number containing the code, LINE_NUM is the line number in + // that file for the code, and COLUMN_NUM is the column number the code + // starts at, if we know it (0 otherwise). + virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, + uint32 column_num) { } +}; + +// The base of DWARF2/3 debug info is a DIE (Debugging Information +// Entry. +// DWARF groups DIE's into a tree and calls the root of this tree a +// "compilation unit". Most of the time, their is one compilation +// unit in the .debug_info section for each file that had debug info +// generated. +// Each DIE consists of + +// 1. a tag specifying a thing that is being described (ie +// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc +// 2. attributes (such as DW_AT_location for location in memory, +// DW_AT_name for name), and data for each attribute. +// 3. A flag saying whether the DIE has children or not + +// In order to gain some amount of compression, the format of +// each DIE (tag name, attributes and data forms for the attributes) +// are stored in a separate table called the "abbreviation table". +// This is done because a large number of DIEs have the exact same tag +// and list of attributes, but different data for those attributes. +// As a result, the .debug_info section is just a stream of data, and +// requires reading of the .debug_abbrev section to say what the data +// means. + +// As a warning to the user, it should be noted that the reason for +// using absolute offsets from the beginning of .debug_info is that +// DWARF2/3 support referencing DIE's from other DIE's by their offset +// from either the current compilation unit start, *or* the beginning +// of the .debug_info section. This means it is possible to reference +// a DIE in one compilation unit from a DIE in another compilation +// unit. This style of reference is usually used to eliminate +// duplicated information that occurs across compilation +// units, such as base types, etc. GCC 3.4+ support this with +// -feliminate-dwarf2-dups. Other toolchains will sometimes do +// duplicate elimination in the linker. + +class CompilationUnit { + public: + + // Initialize a compilation unit. This requires a map of sections, + // the offset of this compilation unit in the debug_info section, a + // ByteReader, and a Dwarf2Handler class to call callbacks in. + CompilationUnit(const SectionMap& sections, uint64 offset, + ByteReader* reader, Dwarf2Handler* handler); + virtual ~CompilationUnit() { + if (abbrevs_) delete abbrevs_; + } + + // Begin reading a Dwarf2 compilation unit, and calling the + // callbacks in the Dwarf2Handler + // Return the offset of the end of the compilation unit - the passed + // in offset. + uint64 Start(); + + private: + + // This struct represents a single DWARF2/3 abbreviation + // The abbreviation tells how to read a DWARF2/3 DIE, and consist of a + // tag and a list of attributes, as well as the data form of each attribute. + struct Abbrev { + uint32 number; + enum DwarfTag tag; + bool has_children; + AttributeList attributes; + }; + + // A DWARF2/3 compilation unit header. This is not the same size as + // in the actual file, as the one in the file may have a 32 bit or + // 64 bit length. + struct CompilationUnitHeader { + uint64 length; + uint16 version; + uint64 abbrev_offset; + uint8 address_size; + } header_; + + // Reads the DWARF2/3 header for this compilation unit. + void ReadHeader(); + + // Reads the DWARF2/3 abbreviations for this compilation unit + void ReadAbbrevs(); + + // Processes a single DIE for this compilation unit and return a new + // pointer just past the end of it + const char* ProcessDIE(uint64 dieoffset, + const char* start, + const Abbrev& abbrev); + + // Processes a single attribute and return a new pointer just past the + // end of it + const char* ProcessAttribute(uint64 dieoffset, + const char* start, + enum DwarfAttribute attr, + enum DwarfForm form); + + // Processes all DIEs for this compilation unit + void ProcessDIEs(); + + // Skips the die with attributes specified in ABBREV starting at + // START, and return the new place to position the stream to. + const char* SkipDIE(const char* start, + const Abbrev& abbrev); + + // Skips the attribute starting at START, with FORM, and return the + // new place to position the stream to. + const char* SkipAttribute(const char* start, + enum DwarfForm form); + + // Offset from section start is the offset of this compilation unit + // from the beginning of the .debug_info section. + uint64 offset_from_section_start_; + + // buffer is the buffer for our CU, starting at .debug_info + offset + // passed in from constructor. + // after_header points to right after the compilation unit header. + const char* buffer_; + uint64 buffer_length_; + const char* after_header_; + + // The associated ByteReader that handles endianness issues for us + ByteReader* reader_; + + // The map of sections in our file to buffers containing their data + const SectionMap& sections_; + + // The associated handler to call processing functions in + Dwarf2Handler* handler_; + + // Set of DWARF2/3 abbreviations for this compilation unit. Indexed + // by abbreviation number, which means that abbrevs_[0] is not + // valid. + vector* abbrevs_; + + // String section buffer and length, if we have a string section. + // This is here to avoid doing a section lookup for strings in + // ProcessAttribute, which is in the hot path for DWARF2 reading. + const char* string_buffer_; + uint64 string_buffer_length_; +}; + +// This class is the main interface between the reader and the +// client. The virtual functions inside this get called for +// interesting events that happen during DWARF2 reading. +// The default implementation skips everything. + +class Dwarf2Handler { + public: + Dwarf2Handler() { } + + virtual ~Dwarf2Handler() { } + + // Start to process a compilation unit at OFFSET from the beginning of the + // debug_info section. Return false if you would like + // to skip this compilation unit. + virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, + uint8 offset_size, uint64 cu_length, + uint8 dwarf_version) { return false; } + + // Start to process a DIE at OFFSET from the beginning of the + // debug_info section. Return false if you would like to skip this + // DIE. + virtual bool StartDIE(uint64 offset, enum DwarfTag tag, + const AttributeList& attrs) { return false; } + + // Called when we have an attribute with unsigned data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA. + virtual void ProcessAttributeUnsigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 data) { } + + // Called when we have an attribute with signed data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA. + virtual void ProcessAttributeSigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + int64 data) { } + + // Called when we have an attribute with a buffer of data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA, and the + // length of the buffer is LENGTH. The buffer is owned by the + // caller, not the callee, and may not persist for very long. If + // you want the data to be available later, it needs to be copied. + virtual void ProcessAttributeBuffer(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const char* data, + uint64 len) { } + + // Called when we have an attribute with string data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA. + virtual void ProcessAttributeString(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const string& data) { } + + // Called when finished processing the DIE at OFFSET. + // Because DWARF2/3 specifies a tree of DIEs, you may get starts + // before ends of the previous DIE, as we process children before + // ending the parent. + virtual void EndDIE(uint64 offset) { } + +}; + + +} // namespace dwarf2reader + +#endif // UTIL_DEBUGINFO_DWARF2READER_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.cc b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.cc new file mode 100644 index 00000000..b6d3f0fe --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.cc @@ -0,0 +1,240 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a client for the dwarf2reader to extract function and line +// information from the debug info. + +#include +#include +#include + + +#include "common/mac/dwarf/functioninfo.h" + +#include "common/mac/dwarf/bytereader.h" + + +namespace __gnu_cxx +{ + template<> + struct hash + { + size_t operator()(const std::string& k) const; + }; +} + + +namespace dwarf2reader { + +// Given an offset value, its form, and the base offset of the +// compilation unit containing this value, return an absolute offset +// within the .debug_info section. +uint64 GetAbsoluteOffset(uint64 offset, + enum DwarfForm form, + uint64 compilation_unit_base) { + switch (form) { + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + return offset + compilation_unit_base; + case DW_FORM_ref_addr: + default: + return offset; + } +} + +CULineInfoHandler::CULineInfoHandler(vector* files, + vector* dirs, + LineMap* linemap):linemap_(linemap), + files_(files), + dirs_(dirs) { + // The dirs and files are 1 indexed, so just make sure we put + // nothing in the 0 vector. + assert(dirs->size() == 0); + assert(files->size() == 0); + dirs->push_back(""); + SourceFileInfo s; + s.name = ""; + s.lowpc = ULLONG_MAX; + files->push_back(s); +} + +void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) { + // These should never come out of order, actually + assert(dir_num == dirs_->size()); + dirs_->push_back(name); +} + +void CULineInfoHandler::DefineFile(const string& name, + int32 file_num, uint32 dir_num, + uint64 mod_time, uint64 length) { + assert(dir_num >= 0); + assert(dir_num < dirs_->size()); + + // These should never come out of order, actually. + if (file_num == (int32)files_->size() || file_num == -1) { + string dir = dirs_->at(dir_num); + + SourceFileInfo s; + s.lowpc = ULLONG_MAX; + + if (dir == "") { + s.name = name; + } else { + s.name = dir + "/" + name; + } + + files_->push_back(s); + } else { + fprintf(stderr, "error in DefineFile"); + } +} + +void CULineInfoHandler::AddLine(uint64 address, uint32 file_num, + uint32 line_num, uint32 column_num) { + if (file_num < files_->size()) { + linemap_->insert(make_pair(address, make_pair(files_->at(file_num).name.c_str(), + line_num))); + + if(address < files_->at(file_num).lowpc) { + files_->at(file_num).lowpc = address; + } + } else { + fprintf(stderr,"error in AddLine"); + } +} + +bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset, + uint8 address_size, + uint8 offset_size, + uint64 cu_length, + uint8 dwarf_version) { + current_compilation_unit_offset_ = offset; + return true; +} + + +// For function info, we only care about subprograms and inlined +// subroutines. For line info, the DW_AT_stmt_list lives in the +// compile unit tag. + +bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag, + const AttributeList& attrs) { + switch (tag) { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: { + current_function_info_ = new FunctionInfo; + current_function_info_->lowpc = current_function_info_->highpc = 0; + current_function_info_->name = ""; + current_function_info_->line = 0; + current_function_info_->file = ""; + offset_to_funcinfo_->insert(make_pair(offset, current_function_info_)); + }; + // FALLTHROUGH + case DW_TAG_compile_unit: + return true; + default: + return false; + } + return false; +} + +// Only care about the name attribute for functions + +void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const string &data) { + if (current_function_info_) { + if (attr == DW_AT_name) + current_function_info_->name = data; + else if(attr == DW_AT_MIPS_linkage_name) + current_function_info_->mangled_name = data; + } +} + +void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 data) { + if (attr == DW_AT_stmt_list) { + SectionMap::const_iterator iter = sections_.find("__debug_line"); + assert(iter != sections_.end()); + + // this should be a scoped_ptr but we dont' use boost :-( + auto_ptr lireader(new LineInfo(iter->second.first + data, + iter->second.second - data, + reader_, linehandler_)); + lireader->Start(); + } else if (current_function_info_) { + switch (attr) { + case DW_AT_low_pc: + current_function_info_->lowpc = data; + break; + case DW_AT_high_pc: + current_function_info_->highpc = data; + break; + case DW_AT_decl_line: + current_function_info_->line = data; + break; + case DW_AT_decl_file: + current_function_info_->file = files_->at(data).name; + break; + case DW_AT_specification: { + // Some functions have a "specification" attribute + // which means they were defined elsewhere. The name + // attribute is not repeated, and must be taken from + // the specification DIE. Here we'll assume that + // any DIE referenced in this manner will already have + // been seen, but that's not really required by the spec. + uint64 abs_offset = GetAbsoluteOffset(data, form, current_compilation_unit_offset_); + FunctionMap::iterator iter = offset_to_funcinfo_->find(abs_offset); + if (iter != offset_to_funcinfo_->end()) { + current_function_info_->name = iter->second->name; + current_function_info_->mangled_name = iter->second->mangled_name; + } else { + // If you hit this, this code probably needs to be rewritten. + fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", abs_offset, offset); + } + break; + } + default: + break; + } + } +} + +void CUFunctionInfoHandler::EndDIE(uint64 offset) { + if (current_function_info_ && current_function_info_->lowpc) + address_to_funcinfo_->insert(make_pair(current_function_info_->lowpc, + current_function_info_)); +} + +} // namespace dwarf2reader diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.h new file mode 100644 index 00000000..130f182e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/functioninfo.h @@ -0,0 +1,178 @@ +// Copyright 2006 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This file contains the definitions for a DWARF2/3 information +// collector that uses the DWARF2/3 reader interface to build a mapping +// of addresses to files, lines, and functions. + +#ifndef COMMON_MAC_DWARF_FUNCTIONINFO_H__ +#define COMMON_MAC_DWARF_FUNCTIONINFO_H__ + +#include +#include +#include +#include + +#include "common/mac/dwarf/dwarf2reader.h" + + +namespace dwarf2reader { + +struct FunctionInfo { + // Name of the function + string name; + // Mangled name of the function + string mangled_name; + // File containing this function + string file; + // Line number for start of function. + uint32 line; + // Beginning address for this function + uint64 lowpc; + // End address for this function. + uint64 highpc; +}; + +struct SourceFileInfo { + // Name of the source file name + string name; + // Low address of source file name + uint64 lowpc; +}; + +typedef map FunctionMap; +typedef map > LineMap; + +// This class is a basic line info handler that fills in the dirs, +// file, and linemap passed into it with the data produced from the +// LineInfoHandler. +class CULineInfoHandler: public LineInfoHandler { + public: + + // + CULineInfoHandler(vector* files, + vector* dirs, + LineMap* linemap); + virtual ~CULineInfoHandler() { } + + // Called when we define a directory. We just place NAME into dirs_ + // at position DIR_NUM. + virtual void DefineDir(const string& name, uint32 dir_num); + + // Called when we define a filename. We just place + // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM. + virtual void DefineFile(const string& name, int32 file_num, + uint32 dir_num, uint64 mod_time, uint64 length); + + + // Called when the line info reader has a new line, address pair + // ready for us. ADDRESS is the address of the code, FILE_NUM is + // the file number containing the code, LINE_NUM is the line number + // in that file for the code, and COLUMN_NUM is the column number + // the code starts at, if we know it (0 otherwise). + virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, + uint32 column_num); + + + private: + LineMap* linemap_; + vector* files_; + vector* dirs_; +}; + +class CUFunctionInfoHandler: public Dwarf2Handler { + public: + CUFunctionInfoHandler(vector* files, + vector* dirs, + LineMap* linemap, + FunctionMap* offset_to_funcinfo, + FunctionMap* address_to_funcinfo, + CULineInfoHandler* linehandler, + const SectionMap& sections, + ByteReader* reader) + : files_(files), dirs_(dirs), linemap_(linemap), + offset_to_funcinfo_(offset_to_funcinfo), + address_to_funcinfo_(address_to_funcinfo), + linehandler_(linehandler), sections_(sections), + reader_(reader), current_function_info_(NULL) { } + + virtual ~CUFunctionInfoHandler() { } + + // Start to process a compilation unit at OFFSET from the beginning of the + // debug_info section. We want to see all compilation units, so we + // always return true. + + virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, + uint8 offset_size, uint64 cu_length, + uint8 dwarf_version); + + // Start to process a DIE at OFFSET from the beginning of the + // debug_info section. We only care about function related DIE's. + virtual bool StartDIE(uint64 offset, enum DwarfTag tag, + const AttributeList& attrs); + + // Called when we have an attribute with unsigned data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA. + virtual void ProcessAttributeUnsigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 data); + + // Called when we have an attribute with string data to give to + // our handler. The attribute is for the DIE at OFFSET from the + // beginning of compilation unit, has a name of ATTR, a form of + // FORM, and the actual data of the attribute is in DATA. + virtual void ProcessAttributeString(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const string& data); + + // Called when finished processing the DIE at OFFSET. + // Because DWARF2/3 specifies a tree of DIEs, you may get starts + // before ends of the previous DIE, as we process children before + // ending the parent. + virtual void EndDIE(uint64 offset); + + private: + vector* files_; + vector* dirs_; + LineMap* linemap_; + FunctionMap* offset_to_funcinfo_; + FunctionMap* address_to_funcinfo_; + CULineInfoHandler* linehandler_; + const SectionMap& sections_; + ByteReader* reader_; + FunctionInfo* current_function_info_; + uint64 current_compilation_unit_offset_; +}; + +} // namespace dwarf2reader +#endif // COMMON_MAC_DWARF_FUNCTIONINFO_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/line_state_machine.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/line_state_machine.h new file mode 100644 index 00000000..4ba98f74 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/line_state_machine.h @@ -0,0 +1,61 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#ifndef COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ +#define COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ + +namespace dwarf2reader { + +// This is the format of a DWARF2/3 line state machine that we process +// opcodes using. There is no need for anything outside the lineinfo +// processor to know how this works. +struct LineStateMachine { + void Reset(bool default_is_stmt) { + file_num = 1; + address = 0; + line_num = 1; + column_num = 0; + is_stmt = default_is_stmt; + basic_block = false; + end_sequence = false; + } + + uint32 file_num; + uint64 address; + uint64 line_num; + uint32 column_num; + bool is_stmt; // stmt means statement. + bool basic_block; + bool end_sequence; +}; + +} // namespace dwarf2reader + + +#endif // COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/dwarf/types.h b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/types.h new file mode 100644 index 00000000..76541597 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/dwarf/types.h @@ -0,0 +1,46 @@ +// Copyright 2008 Google, Inc. All Rights reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This file contains some typedefs for basic types + + +#ifndef _COMMON_MAC_DWARF_TYPES_H__ +#define _COMMON_MAC_DWARF_TYPES_H__ + +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef long long int64; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +#endif // _COMMON_MAC_DWARF_TYPES_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.h new file mode 100644 index 00000000..83482e92 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.h @@ -0,0 +1,380 @@ +// +// GTMCarbonEvent.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import + +#import "GTMDefines.h" + +@class GTMCarbonEventHandler; + +// Objective C wrapper for a Carbon Event +@interface GTMCarbonEvent : NSObject { + @private + EventRef event_; //Event we are wrapping. STRONG +} + + +// Create an event of class |inClass| and kind |inKind| +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)eventWithClass:(UInt32)inClass kind:(UInt32)kind; + +// Create an event based on |event|. Retains |event|. +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)eventWithEvent:(EventRef)event; + +// Create an event based on the event currently being handled. +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)currentEvent; + +// Create an event of class |inClass| and kind |inKind| +// +// Returns: +// GTMCarbonEvent +// +- (id)initWithClass:(UInt32)inClass kind:(UInt32)kind; + +// Create an event based on |event|. Retains |event|. +// +// Returns: +// GTMCarbonEvent +// +- (id)initWithEvent:(EventRef)event; + +// Get the event's class. +// +// Returns: +// event class +// +- (UInt32)eventClass; + +// Get the event's kind. +// +// Returns: +// event kind +// +- (UInt32)eventKind; + +// Set the event's time. +// +// Arguments: +// time - the time you want associated with the event +// +- (void)setTime:(EventTime)eventTime; + +// Get the event's time. +// +// Returns: +// the time associated with the event +// +- (EventTime)time; + +// Get the event's eventref for passing to other carbon functions. +// +// Returns: +// the event ref associated with the event +// +- (EventRef)event; + +// Sets (or adds) a parameter to an event. Try not to use this function +// directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// size - the size of the data that |data| points to. +// data - pointer to the data you want to set the parameter to. +// +- (void)setParameterNamed:(EventParamName)name + type:(EventParamType)type + size:(ByteCount)size + data:(const void *)data; + + +// Gets a parameter from an event. Try not to use this function +// directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// size - the size of the data that |data| points to. +// data - pointer to the buffer that you want to fill with your data. +// +// Returns: +// YES is parameter is retrieved successfully. NO if parameter doesn't exist. +// +- (BOOL)getParameterNamed:(EventParamName)name + type:(EventParamType)type + size:(ByteCount)size + data:(void *)data; + +// Gets a the size of a parameter from an event. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// +// Returns: +// The size of the buffer required to hold the parameter. 0 if parameter +// doesn't exist. +// +- (ByteCount)sizeOfParameterNamed:(EventParamName)name + type:(EventParamType)type; + +// Sends event to an event target with options +// +// Arguments: +// target - target to send event to. +// options - options to send event. See SendEventToEventTargetWithOptions +// for details. +// +// Returns: +// OSStatus value. +// +- (OSStatus)sendToTarget:(GTMCarbonEventHandler *)target + options:(OptionBits)options; + +// Post event to an event queue. +// +// Arguments: +// queue - queue to post it to. +// priority - priority to post it with +// +// Returns: +// OSStatus value. +// +- (OSStatus)postToQueue:(EventQueueRef)queue priority:(EventPriority)priority; + +// Post event to current queue with standard priority. +// +- (void)postToCurrentQueue; + +// Post event to main queue with standard priority. +// +- (void)postToMainQueue; + +@end + +// Macros for defining simple set/get parameter methods for GTMCarbonEvent. See +// the category GTMCarbonEvent (GTMCarbonEventGettersAndSetters) for an example +// of their use. GTM_PARAM_TEMPLATE_DECL2/DEFN2 is for the case where the +// parameter name is different than the parameter type (rare, but it does +// occur...e.g. for a Rect, the name is typeQDRectangle, and the type is Rect, +// so it would be GTM_PARAM_TEMPLATE_DECL2(QDRectangle, Rect) ). In most cases +// you will just use GTM_PARAM_TEMPLATE_DECL/DEFN. +#define GTM_PARAM_TEMPLATE_DECL2(paramName, paramType) \ +- (void)set##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data; \ +- (BOOL)get##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data; + +#define GTM_PARAM_TEMPLATE_DEFN2(paramName, paramType) \ +- (void)set##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data { \ +[self setParameterNamed:name type:type##paramName size:sizeof(paramType) data:data]; \ +} \ +- (BOOL)get##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data { \ +return [self getParameterNamed:name type:type##paramName size:sizeof(paramType) data:data]; \ +} + +#define GTM_PARAM_TEMPLATE_DECL(paramType) GTM_PARAM_TEMPLATE_DECL2(paramType, paramType) +#define GTM_PARAM_TEMPLATE_DEFN(paramType) GTM_PARAM_TEMPLATE_DEFN2(paramType, paramType) + + +// Category defining some basic types that we want to be able to easily set and +// get from GTMCarbonEvents +@interface GTMCarbonEvent (GTMCarbonEventGettersAndSetters) +GTM_PARAM_TEMPLATE_DECL(UInt32) +GTM_PARAM_TEMPLATE_DECL(EventHotKeyID) +@end + +// Utility function for converting between modifier types +// Arguments: +// inCocoaModifiers - keyboard modifiers in carbon form +// (NSCommandKeyMask etc) +// Returns: +// Carbon modifiers equivalent to |inCocoaModifiers| (cmdKey etc) +GTM_EXTERN UInt32 GTMCocoaToCarbonKeyModifiers(NSUInteger inCocoaModifiers); + +// Utility function for converting between modifier types +// Arguments: +// inCarbonModifiers - keyboard modifiers in carbon form (cmdKey etc) +// Returns: +// cocoa modifiers equivalent to |inCocoaModifiers| (NSCommandKeyMask etc) +GTM_EXTERN NSUInteger GTMCarbonToCocoaKeyModifiers(UInt32 inCarbonModifiers); + +// An "abstract" superclass for objects that handle events such as +// menus, HIObjects, etc. +// +// Subclasses are expected to override the eventTarget and +// handleEvent:handler: methods to customize them. +@interface GTMCarbonEventHandler : NSObject { + @private + // handler we are wrapping + // lazily created in the eventHandler method + EventHandlerRef eventHandler_; + __weak id delegate_; // Our delegate + // Does our delegate respond to the gtm_eventHandler:receivedEvent:handler: + // selector? Cached for performance reasons. + BOOL delegateRespondsToHandleEvent_; +} + +// Registers the event handler to listen for |events|. +// +// Arguments: +// events - an array of EventTypeSpec. The events to register for. +// count - the number of EventTypeSpecs in events. +// +- (void)registerForEvents:(const EventTypeSpec *)events count:(size_t)count; + +// Causes the event handler to stop listening for |events|. +// +// Arguments: +// events - an array of EventTypeSpec. The events to register for. +// count - the number of EventTypeSpecs in events. +// +- (void)unregisterForEvents:(const EventTypeSpec *)events count:(size_t)count; + +// To be overridden by subclasses to respond to events. +// +// All subclasses should call [super handleEvent:handler:] if they +// don't handle the event themselves. +// +// Arguments: +// event - the event to be handled +// handler - the call ref in case you want to call CallNextEventHandler +// in your method +// Returns: +// OSStatus - usually either noErr or eventNotHandledErr +// +- (OSStatus)handleEvent:(GTMCarbonEvent *)event + handler:(EventHandlerCallRef)handler; + +// To be overridden by subclasses to return the event target for the class. +// GTMCarbonEventHandler's implementation returns NULL. +// +// Returns: +// The event target ref. +// +- (EventTargetRef)eventTarget; + +// Gets the underlying EventHandlerRef for that this class wraps. +// +// Returns: +// The EventHandlerRef this class wraps. +// +- (EventHandlerRef)eventHandler; + +// Gets the delegate for the handler +// +// Returns: +// the delegate +- (id)delegate; + +// Sets the delegate for the handler +// +// Arguments: +// delegate - the delegate to set to +- (void)setDelegate:(id)delegate; + +@end + +// Category for methods that a delegate of GTMCarbonEventHandlerDelegate may +// want to implement. +@interface NSObject (GTMCarbonEventHandlerDelegate) + +// If a delegate implements this method it gets called before every event +// that the handler gets sent. If it returns anything but eventNotHandledErr, +// the handlers handlerEvent:handler: method will not be called, and +// the return value returned by the delegate will be returned back to the +// carbon event dispatch system. This allows you to override any method +// that a handler may implement. +// +// Arguments: +// delegate - the delegate to set to +// +- (OSStatus)gtm_eventHandler:(GTMCarbonEventHandler *)sender + receivedEvent:(GTMCarbonEvent *)event + handler:(EventHandlerCallRef)handler; + +@end + +// A general OSType for use when setting properties on GTMCarbonEvent objects. +// This is the "signature" as part of commandIDs, controlsIDs, and properties. +// 'GooG' +GTM_EXTERN const OSType kGTMCarbonFrameworkSignature; + +// An event handler class representing the event monitor event handler +// +// there is only one of these per application. This way you can put +// event handlers directly on the dispatcher if necessary. +@interface GTMCarbonEventMonitorHandler : GTMCarbonEventHandler +// Accessor to get the GTMCarbonEventMonitorHandler singleton. +// +// Returns: +// pointer to the GTMCarbonEventMonitorHandler singleton. ++ (GTMCarbonEventMonitorHandler *)sharedEventMonitorHandler; +@end + +// An event handler class representing the toolbox dispatcher event handler +// +// there is only one of these per application. This way you can put +// event handlers directly on the dispatcher if necessary. +@interface GTMCarbonEventDispatcherHandler : GTMCarbonEventHandler { + @private + NSMutableDictionary *hotkeys_; // Collection of registered hotkeys +} + +// Accessor to get the GTMCarbonEventDispatcherHandler singleton. +// +// Returns: +// pointer to the GTMCarbonEventDispatcherHandler singleton. ++ (GTMCarbonEventDispatcherHandler *)sharedEventDispatcherHandler; + +// Registers a hotkey. When the hotkey is executed by the user, target will be +// called with selector. +// Arguments: +// keyCode - the virtual keycode of the hotkey +// cocoaModifiers - the modifiers that need to be used with |keyCode|. NB +// that these are cocoa modifiers, so NSCommandKeyMask etc. +// target - instance that will get |action| called when the hotkey fires +// action - the method to call on |target| when the hotkey fires +// onPress - is YES, the hotkey fires on the keydown (usual) otherwise +// it fires on the key up. +// Returns: +// a EventHotKeyRef that you can use with other Carbon functions, or for +// unregistering the hotkey. Note that all hotkeys are unregistered +// automatically when an app quits. Will be NULL on failure. +- (EventHotKeyRef)registerHotKey:(NSUInteger)keyCode + modifiers:(NSUInteger)cocoaModifiers + target:(id)target + action:(SEL)action + whenPressed:(BOOL)onPress; + +// Unregisters a hotkey previously registered with registerHotKey. +// Arguments: +// keyRef - the EventHotKeyRef to unregister +- (void)unregisterHotKey:(EventHotKeyRef)keyRef; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.m new file mode 100644 index 00000000..16c46c83 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEvent.m @@ -0,0 +1,710 @@ +// +// GTMCarbonEvent.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMCarbonEvent.h" +#import "GTMObjectSingleton.h" +#import "GTMDebugSelectorValidation.h" + +// Wrapper for all the info we need about a hotkey that we can store in a +// Foundation storage class. We expecct selector to have this signature: +// - (void)hitHotKey:sender; +@interface GTMCarbonHotKey : NSObject { + @private + EventHotKeyID id_; // EventHotKeyID for this hotkey. + id target_; // Object we are going to call when the hotkey is hit + SEL selector_; // Selector we are going to call on target_ + BOOL onKeyDown_; // Do we do it on key down or on key up? +} + +// Create a HotKey record +// Arguments: +// keyID - id of the hotkey +// target - object we are going to call when the hotkey is hit +// action - selector we are going to call on target +// whenPressed - do we do it on key down or key up? +// Returns: +// a hotkey record, or nil on failure +- (id)initWithHotKey:(EventHotKeyID)keyID + target:(id)target + action:(SEL)selector + whenPressed:(BOOL)onKeyDown; + +// Does this record match key |keyID| +// Arguments: +// keyID - the id to match against +// Returns: +// Yes if we match this key id +- (BOOL)matchesHotKeyID:(EventHotKeyID)keyID; + +// Make target perform selector +// Returns: +// Yes if handled +- (BOOL)sendAction:(id)sender; + +// Do we do it on key down or key up? +// Returns: +// Yes if on keydown +- (BOOL)onKeyDown; + +@end + +@implementation GTMCarbonEvent + +// Create an event of class |inClass| and kind |inKind| +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)eventWithClass:(UInt32)inClass kind:(UInt32)kind { + return [[[[self class] alloc] initWithClass:inClass kind:kind] autorelease]; +} + + +// Create an event based on |event|. Retains |event|. +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)eventWithEvent:(EventRef)event { + return [[[[self class] alloc] initWithEvent:event] autorelease]; +} + + +// Create an event based on the event currently being handled. +// +// Returns: +// Autoreleased GTMCarbonEvent +// ++ (id)currentEvent { + return [[self class] eventWithEvent:GetCurrentEvent()]; +} + + +// Create an event of class |inClass| and kind |inKind| +// +// Returns: +// GTMCarbonEvent +// +- (id)initWithClass:(UInt32)inClass kind:(UInt32)kind { + if ((self = [super init])) { + verify_noerr(CreateEvent(kCFAllocatorDefault, inClass, kind, + 0, kEventAttributeNone, &event_)); + } + return self; +} + + +// Create an event based on |event|. Retains |event|. +// +// Returns: +// GTMCarbonEvent +// +- (id)initWithEvent:(EventRef)event { + if ((self = [super init])) { + if (event) { + event_ = RetainEvent(event); + } + } + return self; +} + + +// This does a proper event copy, but ignores the |zone|. No way to do a copy +// of an event into a specific zone. +// +// Arguments: +// zone - the zone to copy to +// Returns: +// the copied event. nil on failure +- (id)copyWithZone:(NSZone *)zone { + GTMCarbonEvent *carbonEvent = nil; + EventRef newEvent = CopyEvent([self event]); + if (newEvent) { + carbonEvent = [[[self class] allocWithZone:zone] initWithEvent:newEvent]; + ReleaseEvent(newEvent); + } + return carbonEvent; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + if (event_) { + ReleaseEvent(event_); + event_ = NULL; + } + [super finalize]; +} +#endif + +// releases our retained event +// +- (void)dealloc { + if (event_) { + ReleaseEvent(event_); + event_ = NULL; + } + [super dealloc]; +} + +// description utliity for debugging +// +- (NSString *)description { + char cls[5]; + UInt32 kind; + + // Need everything bigendian if we are printing out the class as a "string" + *((UInt32 *)cls) = CFSwapInt32HostToBig([self eventClass]); + kind = [self eventKind]; + cls[4] = 0; + return [NSString stringWithFormat:@"GTMCarbonEvent '%s' %d", cls, kind]; +} + + +// Get the event's class. +// +// Returns: +// event class +// +- (UInt32)eventClass { + return GetEventClass(event_); +} + + +// Get the event's kind. +// +// Returns: +// event kind +// +- (UInt32)eventKind { + return GetEventKind(event_); +} + + +// Set the event's time. +// +// Arguments: +// time - the time you want associated with the event +// +- (void)setTime:(EventTime)eventTime { + verify_noerr(SetEventTime(event_, eventTime)); +} + + +// Get the event's time. +// +// Returns: +// the time associated with the event +// +- (EventTime)time { + return GetEventTime(event_); +} + + +// Get the event's eventref for passing to other carbon functions. +// +// Returns: +// the event ref associated with the event +// +- (EventRef)event { + return event_; +} + + +// Sends event to an event target with options +// +// Arguments: +// target - target to send event to. +// options - options to send event. See SendEventToEventTargetWithOptions +// for details. +// +// Returns: +// OSStatus value. +// +- (OSStatus)sendToTarget:(GTMCarbonEventHandler *)target + options:(OptionBits)options { + return SendEventToEventTargetWithOptions(event_, + [target eventTarget], options); +} + +// Post event to an event queue. +// +// Arguments: +// queue - queue to post it to. +// priority - priority to post it with +// +// Returns: +// OSStatus value. +// +- (OSStatus)postToQueue:(EventQueueRef)queue priority:(EventPriority)priority { + return PostEventToQueue(queue, event_, priority); +} + + +// Post event to current queue with standard priority. +// +- (void)postToCurrentQueue { + verify_noerr([self postToQueue:GetCurrentEventQueue() + priority:kEventPriorityStandard]); +} + + +// Post event to main queue with standard priority. +// +- (void)postToMainQueue { + verify_noerr([self postToQueue:GetMainEventQueue() + priority:kEventPriorityStandard]); +} + + +// Sets (or adds) a parameter to an event. Try not to use this function +// directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// size - the size of the data that |data| points to. +// data - pointer to the data you want to set the parameter to. +// +- (void)setParameterNamed:(EventParamName)name + type:(EventParamType)type + size:(ByteCount)size + data:(const void *)data { + verify_noerr(SetEventParameter(event_, name, type, size, data)); +} + + +// Gets a parameter from an event. Try not to use this function +// directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// size - the size of the data that |data| points to. +// data - pointer to the buffer that you want to fill with your data. +// +// Returns: +// YES is parameter is retrieved successfully. NO if parameter doesn't exist. +// +- (BOOL)getParameterNamed:(EventParamName)name + type:(EventParamType)type + size:(ByteCount)size + data:(void *)data { + OSStatus status = GetEventParameter(event_, name, type, + NULL, size, NULL, data); + return status == noErr; +} + + +// Gets a the size of a parameter from an event. +// +// Arguments: +// name - the parameter name. +// type - the parameter type. +// +// Returns: +// The size of the buffer required to hold the parameter. 0 if parameter +// doesn't exist. +// +- (ByteCount)sizeOfParameterNamed:(EventParamName)name + type:(EventParamType)type { + ByteCount size = 0; + verify_noerr(GetEventParameter(event_, name, type, NULL, 0, &size, NULL)); + return size; +} + +@end + +@implementation GTMCarbonEvent (GTMCarbonEventGettersAndSetters) +GTM_PARAM_TEMPLATE_DEFN(UInt32) +GTM_PARAM_TEMPLATE_DEFN(EventHotKeyID) +@end + +UInt32 GTMCocoaToCarbonKeyModifiers(NSUInteger inCocoaModifiers) { + UInt32 carbModifiers = 0; + if (inCocoaModifiers & NSAlphaShiftKeyMask) carbModifiers |= alphaLock; + if (inCocoaModifiers & NSShiftKeyMask) carbModifiers |= shiftKey; + if (inCocoaModifiers & NSControlKeyMask) carbModifiers |= controlKey; + if (inCocoaModifiers & NSAlternateKeyMask) carbModifiers |= optionKey; + if (inCocoaModifiers & NSCommandKeyMask) carbModifiers |= cmdKey; + return carbModifiers; +} + +NSUInteger GTMCarbonToCocoaKeyModifiers(UInt32 inCarbonModifiers) { + NSUInteger nsModifiers = 0; + if (inCarbonModifiers & alphaLock) nsModifiers |= NSAlphaShiftKeyMask; + if (inCarbonModifiers & shiftKey) nsModifiers |= NSShiftKeyMask; + if (inCarbonModifiers & controlKey) nsModifiers |= NSControlKeyMask; + if (inCarbonModifiers & optionKey) nsModifiers |= NSAlternateKeyMask; + if (inCarbonModifiers & cmdKey) nsModifiers |= NSCommandKeyMask; + return nsModifiers; +} + +const OSType kGTMCarbonFrameworkSignature = 'GTM '; + +@implementation GTMCarbonEventHandler + +// Does our delegate respond to eventHandler:receivedEvent:handler: +// +// Returns: +// YES if delegate responds to eventHandler:receivedEvent:handler: +- (BOOL) delegateRespondsToHandleEvent { + return delegateRespondsToHandleEvent_; +} + +// Registers the event handler to listen for |events|. +// +// Arguments: +// events - an array of EventTypeSpec. The events to register for. +// count - the number of EventTypeSpecs in events. +// +- (void)registerForEvents:(const EventTypeSpec *)events count:(size_t)count { + verify_noerr(AddEventTypesToHandler([self eventHandler], count, events)); +} + +// Causes the event handler to stop listening for |events|. +// +// Arguments: +// events - an array of EventTypeSpec. The events to register for. +// count - the number of EventTypeSpecs in events. +// +- (void)unregisterForEvents:(const EventTypeSpec *)events count:(size_t)count { + verify_noerr(RemoveEventTypesFromHandler([self eventHandler], count, events)); +} + +// To be overridden by subclasses to respond to events. All subclasses should +// call [super handleEvent:handler:] if they don't handle the event themselves. +// +// Arguments: +// event - the event to be handled +// handler - the call ref in case you want to call CallNextEventHandler +// in your method +// Returns: +// OSStatus - usually either noErr or eventNotHandledErr +// +- (OSStatus)handleEvent:(GTMCarbonEvent *)event + handler:(EventHandlerCallRef)handler { + OSStatus status = eventNotHandledErr; + require(event, CantUseParams); + require(handler, CantUseParams); + require([event event], CantUseParams); + status = CallNextEventHandler(handler, [event event]); +CantUseParams: + return status; +} + +// To be overridden by subclasses to return the event target for the class. +// GTMCarbonEventHandler's implementation returns NULL. +// +// Returns: +// The event target ref. +// +- (EventTargetRef)eventTarget { + // Defaults implementation needs to be overridden + return NULL; +} + +// C callback for our registered EventHandlerUPP. +// +// Arguments: +// inHandler - handler given to us from Carbon Event system +// inEvent - the event we are handling +// inUserData - refcon that we gave to the carbon event system. Is a +// GTMCarbonEventHandler in disguise. +// Returns: +// status of event handler +// +static OSStatus EventHandler(EventHandlerCallRef inHandler, + EventRef inEvent, + void *inUserData) { + GTMCarbonEvent *event = [GTMCarbonEvent eventWithEvent:inEvent]; + GTMCarbonEventHandler *handler= (GTMCarbonEventHandler *)inUserData; + check([handler isKindOfClass:[GTMCarbonEventHandler class]]); + + // First check to see if our delegate cares about this event. If the delegate + // handles it (i.e responds to it and does not return eventNotHandledErr) we + // do not pass it on to default handling. + OSStatus status = eventNotHandledErr; + if ([handler delegateRespondsToHandleEvent]) { + status = [[handler delegate] gtm_eventHandler:handler + receivedEvent:event + handler:inHandler]; + } + if (status == eventNotHandledErr) { + status = [handler handleEvent:event handler:inHandler]; + } + return status; +} + +// Gets the underlying EventHandlerRef for that this class wraps. +// +// Returns: +// The EventHandlerRef this class wraps. +// +- (EventHandlerRef)eventHandler { + if (!eventHandler_) { + static EventHandlerUPP sHandlerProc = NULL; + if ( sHandlerProc == NULL ) { + sHandlerProc = NewEventHandlerUPP(EventHandler); + } + verify_noerr(InstallEventHandler([self eventTarget], + sHandlerProc, 0, + NULL, self, &eventHandler_)); + } + return eventHandler_; +} + +// Gets the delegate for the handler +// +// Returns: +// the delegate +- (id)delegate { + return delegate_; +} + +// Sets the delegate for the handler and caches whether it responds to +// the eventHandler:receivedEvent:handler: selector for performance purposes. +// +// Arguments: +// delegate - the delegate for the handler +- (void)setDelegate:(id)delegate { + delegate_ = delegate; + SEL selector = @selector(gtm_eventHandler:receivedEvent:handler:); + delegateRespondsToHandleEvent_ = [delegate respondsToSelector:selector]; +} + +@end + +@implementation GTMCarbonEventMonitorHandler + +GTMOBJECT_SINGLETON_BOILERPLATE(GTMCarbonEventMonitorHandler, + sharedEventMonitorHandler); + +- (EventTargetRef)eventTarget { + return GetEventMonitorTarget(); +} + +@end + +@implementation GTMCarbonEventDispatcherHandler + +GTMOBJECT_SINGLETON_BOILERPLATE(GTMCarbonEventDispatcherHandler, + sharedEventDispatcherHandler); + +// Register for the events we handle, and set up the dictionaries we need +// to keep track of the hotkeys and commands that we handle. +// Returns: +// GTMCarbonApplication or nil on failure +- (id)init { + if ((self = [super init])) { + static EventTypeSpec events[] = { + { kEventClassKeyboard, kEventHotKeyPressed }, + { kEventClassKeyboard, kEventHotKeyReleased }, + }; + [self registerForEvents:events count:GetEventTypeCount(events)]; + hotkeys_ = [[NSMutableDictionary alloc] initWithCapacity:0]; + } + return self; +} + +// COV_NF_START +// Singleton, we never get released. Just here for completeness. +- (void)dealloc { + [hotkeys_ release]; + [super dealloc]; +} +// COV_NF_END + +- (EventTargetRef)eventTarget { + return GetEventDispatcherTarget(); +} + +// Registers a hotkey. When the hotkey is executed by the user, target will be +// called with selector. +// Arguments: +// keyCode - the virtual keycode of the hotkey +// cocoaModifiers - the modifiers that need to be used with |keyCode|. NB +// that these are cocoa modifiers, so NSCommandKeyMask etc. +// target - instance that will get |action| called when the hotkey fires +// action - the method to call on |target| when the hotkey fires +// onKeyDown - is YES, the hotkey fires on the keydown (usual) otherwise +// it fires on the key up. +// Returns: +// a EventHotKeyRef that you can use with other Carbon functions, or for +// unregistering the hotkey. Note that all hotkeys are unregistered +// automatically when an app quits. Will be NULL on failure. +- (EventHotKeyRef)registerHotKey:(NSUInteger)keyCode + modifiers:(NSUInteger)cocoaModifiers + target:(id)target + action:(SEL)selector + whenPressed:(BOOL)onKeyDown { + static UInt32 sCurrentID = 0; + + EventHotKeyRef theRef = NULL; + EventHotKeyID keyID; + keyID.signature = kGTMCarbonFrameworkSignature; + keyID.id = ++sCurrentID; + GTMCarbonHotKey *newKey = [[[GTMCarbonHotKey alloc] initWithHotKey:keyID + target:target + action:selector + whenPressed:onKeyDown] + autorelease]; + require(newKey, CantCreateKey); + require_noerr(RegisterEventHotKey((UInt32)keyCode, + GTMCocoaToCarbonKeyModifiers(cocoaModifiers), + keyID, + [self eventTarget], + 0, + &theRef), CantRegisterHotkey); + + + [hotkeys_ setObject:newKey forKey:[NSValue valueWithPointer:theRef]]; +CantCreateKey: +CantRegisterHotkey: + return theRef; +} + +// Unregisters a hotkey previously registered with registerHotKey. +// Arguments: +// keyRef - the EventHotKeyRef to unregister +- (void)unregisterHotKey:(EventHotKeyRef)keyRef { + NSValue *key = [NSValue valueWithPointer:keyRef]; + check([hotkeys_ objectForKey:key] != nil); + [hotkeys_ removeObjectForKey:key]; + verify_noerr(UnregisterEventHotKey(keyRef)); +} + +// A hotkey has been hit. See if it is one of ours, and if so fire it. +// Arguments: +// event - the hotkey even that was received +// Returns: +// Yes if handled. +- (BOOL)handleHotKeyEvent:(GTMCarbonEvent *)event { + EventHotKeyID keyID; + BOOL handled = [event getEventHotKeyIDParameterNamed:kEventParamDirectObject + data:&keyID]; + if (handled) { + GTMCarbonHotKey *hotkey; + GTM_FOREACH_OBJECT(hotkey, [hotkeys_ allValues]) { + if ([hotkey matchesHotKeyID:keyID]) { + EventKind kind = [event eventKind]; + BOOL onKeyDown = [hotkey onKeyDown]; + if ((kind == kEventHotKeyPressed && onKeyDown) || + (kind == kEventHotKeyReleased && !onKeyDown)) { + handled = [hotkey sendAction:self]; + } + break; + } + } + } + return handled; +} + +// Currently we handle hotkey and command events here. If we get one of them +// we dispatch them off to the handlers above. Otherwise we just call up to +// super. +// Arguments: +// event - the event to check +// handler - the handler call ref +// Returns: +// OSStatus +- (OSStatus)handleEvent:(GTMCarbonEvent *)event + handler:(EventHandlerCallRef)handler { + OSStatus theStatus = eventNotHandledErr; + if ([event eventClass] == kEventClassKeyboard) { + EventKind kind = [event eventKind]; + if (kind == kEventHotKeyPressed || kind == kEventHotKeyReleased) { + theStatus = [self handleHotKeyEvent:event] ? noErr : eventNotHandledErr; + } + } + // We didn't handle it, maybe somebody upstairs will. + if (theStatus == eventNotHandledErr) { + theStatus = [super handleEvent:event handler:handler]; + } + return theStatus; +} + +@end + +@implementation GTMCarbonHotKey + +// Init a HotKey record. In debug version make sure that the selector we are +// passed matches what we expect. ( +// Arguments: +// keyID - id of the hotkey +// target - object we are going to call when the hotkey is hit +// action - selector we are going to call on target +// whenPressed - do we do it on key down or key up? +// Returns: +// a hotkey record, or nil on failure +- (id)initWithHotKey:(EventHotKeyID)keyID + target:(id)target + action:(SEL)selector + whenPressed:(BOOL)onKeyDown { + if ((self = [super init])) { + if(!target || !selector) { + [self release]; + return nil; + } + id_ = keyID; + target_ = [target retain]; + selector_ = selector; + onKeyDown_ = onKeyDown; + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target, + selector, + @encode(void), + @encode(id), + NULL); + } + return self; +} + +- (void)dealloc { + [target_ release]; + [super dealloc]; +} + +// Does this record match key |keyID| +// Arguments: +// keyID - the id to match against +// Returns: +// Yes if we match this key id +- (BOOL)matchesHotKeyID:(EventHotKeyID)keyID { + return (id_.signature == keyID.signature) && (id_.id == keyID.id); +} + +- (BOOL)sendAction:(id)sender { + BOOL handled = NO; + @try { + [target_ performSelector:selector_ withObject:sender]; + handled = YES; + } + @catch (NSException * e) { + handled = NO; + _GTMDevLog(@"Exception fired in hotkey: %@ (%@)", [e name], [e reason]); + } // COV_NF_LINE + return handled; +} + +- (BOOL)onKeyDown { + return onKeyDown_; +} + +@end + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEventTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEventTest.m new file mode 100644 index 00000000..f7b4d54f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMCarbonEventTest.m @@ -0,0 +1,367 @@ +// +// GTMCarbonEventTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMCarbonEvent.h" +#import "GTMUnitTestingUtilities.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMCarbonEventTest : GTMTestCase { + @private + GTMCarbonEvent *event_; +} +@end + +@interface GTMCarbonEventHandlerTest : GTMTestCase { + @private + GTMCarbonEventHandler *handler_; +} +@end + +@interface GTMCarbonEventMonitorHandlerTest : GTMTestCase +@end + +@interface GTMCarbonEventDispatcherHandlerTest : GTMTestCase { + @private + BOOL hotKeyHit_; +} +@end + +static const UInt32 kTestClass = 'foo '; +static const UInt32 kTestKind = 'bar '; +static const UInt32 kTestParameterName = 'baz '; +static const UInt32 kTestBadParameterName = 'bom '; +static const UInt32 kTestParameterValue = 'bam '; + +@implementation GTMCarbonEventTest +- (void)setUp { + event_ = [[GTMCarbonEvent eventWithClass:kTestClass kind:kTestKind] retain]; +} + +- (void)tearDown { + [event_ release]; +} + +- (void)testCopy { + GTMCarbonEvent *event2 = [[event_ copy] autorelease]; + STAssertNotNil(event2, nil); +} + +- (void)testEventWithClassAndKind { + STAssertEquals([event_ eventClass], kTestClass, nil); + STAssertEquals([event_ eventKind], kTestKind, nil); +} + +- (void)testEventWithEvent { + GTMCarbonEvent *event2 = [GTMCarbonEvent eventWithEvent:[event_ event]]; + STAssertEquals([event2 event], [event_ event], nil); +} + +- (void)testCurrentEvent { + EventRef eventRef = GetCurrentEvent(); + GTMCarbonEvent *event = [GTMCarbonEvent currentEvent]; + STAssertEquals([event event], eventRef, nil); +} + +- (void)testEventClass { + [self testEventWithClassAndKind]; +} + +- (void)testEventKind { + [self testEventWithClassAndKind]; +} + +- (void)testSetTime { + EventTime eventTime = [event_ time]; + STAssertNotEquals(eventTime, kEventDurationNoWait, nil); + STAssertNotEquals(eventTime, kEventDurationForever, nil); + [event_ setTime:kEventDurationForever]; + EventTime testTime = [event_ time]; + STAssertEquals(testTime, kEventDurationForever, nil); + [event_ setTime:eventTime]; + STAssertEquals([event_ time], eventTime, nil); +} + +- (void)testTime { + [self testSetTime]; +} + +- (void)testEvent { + [self testEventWithEvent]; +} + +- (void)testSetParameterNamed { + UInt32 theData = kTestParameterValue; + [event_ setUInt32ParameterNamed:kTestParameterName data:&theData]; + theData = 0; + STAssertEquals([event_ sizeOfParameterNamed:kTestParameterName + type:typeUInt32], + sizeof(UInt32), nil); + STAssertTrue([event_ getUInt32ParameterNamed:kTestParameterName + data:&theData], nil); + STAssertEquals(theData, kTestParameterValue, nil); +} + +- (void)testGetParameterNamed { + [self testSetParameterNamed]; + UInt32 theData = kTestParameterValue; + STAssertFalse([event_ getUInt32ParameterNamed:kTestBadParameterName + data:&theData], nil); + STAssertFalse([event_ getUInt32ParameterNamed:kTestBadParameterName + data:NULL], nil); + +} + +- (void)testSizeOfParameterNamed { + [self testSetParameterNamed]; +} + +- (void)testHasParameterNamed { + [self testSetParameterNamed]; +} + +- (OSStatus)gtm_eventHandler:(GTMCarbonEventHandler *)sender + receivedEvent:(GTMCarbonEvent *)event + handler:(EventHandlerCallRef)handler { + OSStatus status = eventNotHandledErr; + if ([event eventClass] == kTestClass && [event eventKind] == kTestKind) { + status = noErr; + } + return status; +} + +- (void)testSendToTarget { + EventTypeSpec types = { kTestClass, kTestKind }; + GTMCarbonEventDispatcherHandler *handler + = [[GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler] + autorelease]; + [handler registerForEvents:&types count:1]; + OSStatus status = [event_ sendToTarget:handler options:0]; + STAssertErr(status, eventNotHandledErr, @"status: %ld", status); + [handler setDelegate:self]; + status = [event_ sendToTarget:handler options:0]; + STAssertNoErr(status, @"status: %ld", status); + [handler unregisterForEvents:&types count:1]; +} + +- (void)testPostToQueue { + EventQueueRef eventQueue = GetMainEventQueue(); + [event_ postToMainQueue]; + OSStatus status = [event_ postToQueue:eventQueue + priority:kEventPriorityStandard]; + STAssertErr(status, eventAlreadyPostedErr, @"status: %ld", status); + EventTypeSpec types = { kTestClass, kTestKind }; + status = FlushEventsMatchingListFromQueue(eventQueue, 1, &types); + STAssertNoErr(status, @"status: %ld", status); + + eventQueue = GetCurrentEventQueue(); + [event_ postToCurrentQueue]; + status = [event_ postToQueue:eventQueue priority:kEventPriorityStandard]; + STAssertErr(status, eventAlreadyPostedErr, @"status: %ld", status); + status = FlushEventsMatchingListFromQueue(eventQueue, 1, &types); + STAssertNoErr(status, @"status: %ld", status); +} + +- (void)testPostToMainQueue { + [self testPostToQueue]; +} + +- (void)testPostToCurrentQueue { + STAssertEquals(GetCurrentEventQueue(), GetMainEventQueue(), nil); + [self testPostToMainQueue]; +} + +- (void)testDescription { + NSString *descString + = [NSString stringWithFormat:@"GTMCarbonEvent 'foo ' %d", kTestKind]; + STAssertEqualObjects([event_ description], descString, nil); +} +@end + +@implementation GTMCarbonEventHandlerTest + +- (void)setUp { + handler_ = [[GTMCarbonEventHandler alloc] init]; +} + +- (void)tearDown { + [handler_ release]; +} + +- (void)testEventTarget { + STAssertNULL([handler_ eventTarget], nil); +} + +- (void)testEventHandler { + [GTMUnitTestDevLogDebug expectPattern: + @"DebugAssert: GoogleToolboxForMac: event CantUseParams .*"]; + STAssertErr([handler_ handleEvent:nil handler:nil], eventNotHandledErr, nil); +} + +- (void)testDelegate { + [handler_ setDelegate:self]; + STAssertEqualObjects([handler_ delegate], self, nil); + [handler_ setDelegate:nil]; + STAssertNil([handler_ delegate], nil); +} + + +- (void)testSetDelegate { + [self testDelegate]; +} + +@end + +@implementation GTMCarbonEventMonitorHandlerTest + +- (void)testEventHandler { + GTMCarbonEventMonitorHandler *monitor + = [GTMCarbonEventMonitorHandler sharedEventMonitorHandler]; + STAssertEquals([monitor eventTarget], GetEventMonitorTarget(), nil); +} + +@end + +@implementation GTMCarbonEventDispatcherHandlerTest + +- (void)testEventHandler { + GTMCarbonEventDispatcherHandler *dispatcher + = [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; + STAssertEquals([dispatcher eventTarget], GetEventDispatcherTarget(), nil); +} + +- (void)hitHotKey:(id)sender { + hotKeyHit_ = YES; + [NSApp stop:self]; +} + +- (void)hitExceptionalHotKey:(id)sender { + [NSException raise:@"foo" format:@"bar"]; +} + +- (void)testRegisterHotKeyModifiersTargetActionWhenPressed { + + // This test can't be run if the screen saver is active because the security + // agent blocks us from sending events via remote operations + if (![GTMUnitTestingUtilities isScreenSaverActive]) { + GTMCarbonEventDispatcherHandler *dispatcher + = [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; + STAssertNotNil(dispatcher, @"Unable to acquire singleton"); + UInt32 keyMods = (NSShiftKeyMask | NSControlKeyMask + | NSAlternateKeyMask | NSCommandKeyMask); + EventHotKeyRef hotKey; + [GTMUnitTestDevLogDebug expectPattern:@"DebugAssert: GoogleToolboxForMac: " + @"newKey CantCreateKey .*"]; + STAssertNULL([dispatcher registerHotKey:0x5 + modifiers:keyMods + target:nil + action:nil + whenPressed:YES], + @"Shouldn't have created hotkey"); +#if DEBUG + // This tests debug selector validation, so we only can do it in debug. + [GTMUnitTestDevLogDebug expectPattern:@"RecordedNSAssert in " + @"GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments - " + @"\"GTMCarbonEventDispatcherHandlerTest\" selector \"badSelector:\" is " + @"unimplemented or misnamed \\(.*/GTMDebugSelectorValidation.h:[0-9]*\\)"]; + STAssertThrowsSpecificNamed([dispatcher registerHotKey:0x5 + modifiers:keyMods + target:self + action:@selector(badSelector:) + whenPressed:YES], + NSException, NSInternalInconsistencyException, + @"Shouldn't have created hotkey"); +#endif + hotKey = [dispatcher registerHotKey:0x5 + modifiers:keyMods + target:self + action:@selector(hitHotKey:) + whenPressed:YES]; + STAssertNotNULL(hotKey, @"Unable to create hotkey"); + + hotKeyHit_ = NO; + + // Post the hotkey combo to the event queue. If everything is working + // correctly hitHotKey: should get called, and hotKeyHit_ will be set for + // us. We run the event loop for a set amount of time waiting for this to + // happen. + [GTMUnitTestingUtilities postTypeCharacterEvent:'g' modifiers:keyMods]; + NSDate* future = [NSDate dateWithTimeIntervalSinceNow:1.0f]; + [GTMUnitTestingUtilities runUntilDate:future]; + STAssertTrue(hotKeyHit_, @"Hot key never got fired."); + [dispatcher unregisterHotKey:hotKey]; + } +} + +- (void)testRegisterHotKeyModifiersTargetActionWhenPressedException { + + // This test can't be run if the screen saver is active because the security + // agent blocks us from sending events via remote operations + if (![GTMUnitTestingUtilities isScreenSaverActive]) { + GTMCarbonEventDispatcherHandler *dispatcher + = [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; + STAssertNotNil(dispatcher, @"Unable to acquire singleton"); + UInt32 keyMods = (NSShiftKeyMask | NSControlKeyMask + | NSAlternateKeyMask | NSCommandKeyMask); + EventHotKeyRef hotKey = [dispatcher registerHotKey:0x5 + modifiers:keyMods + target:self + action:@selector(hitExceptionalHotKey:) + whenPressed:YES]; + STAssertTrue(hotKey != nil, @"Unable to create hotkey"); + + // Post the hotkey combo to the event queue. If everything is working correctly + // hitHotKey: should get called, and hotKeyHit_ will be set for us. + // We run the event loop for a set amount of time waiting for this to happen. + [GTMUnitTestingUtilities postTypeCharacterEvent:'g' modifiers:keyMods]; + NSDate* future = [NSDate dateWithTimeIntervalSinceNow:1.0f]; + [GTMUnitTestDevLog expectString:@"Exception fired in hotkey: foo (bar)"]; + [GTMUnitTestingUtilities runUntilDate:future]; + [dispatcher unregisterHotKey:hotKey]; + } +} + +- (void)testKeyModifiers { + struct { + NSUInteger cocoaKey_; + UInt32 carbonKey_; + } keyMap[] = { + { NSAlphaShiftKeyMask, alphaLock}, + { NSShiftKeyMask, shiftKey}, + { NSControlKeyMask, controlKey}, + { NSAlternateKeyMask, optionKey}, + { NSCommandKeyMask, cmdKey}, + }; + size_t combos = pow(2, sizeof(keyMap) / sizeof(keyMap[0])); + for (size_t i = 0; i < combos; i++) { + NSUInteger cocoaMods = 0; + UInt32 carbonMods = 0; + for (size_t j = 0; j < 32 && j < sizeof(keyMap) / sizeof(keyMap[0]); j++) { + if (i & 1 << j) { + cocoaMods |= keyMap[j].cocoaKey_; + carbonMods |= keyMap[j].carbonKey_; + } + } + STAssertEquals(GTMCocoaToCarbonKeyModifiers(cocoaMods), carbonMods, nil); + STAssertEquals(GTMCarbonToCocoaKeyModifiers(carbonMods), cocoaMods, nil); + } +} + + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.h new file mode 100644 index 00000000..63abf203 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.h @@ -0,0 +1,35 @@ +// +// GTMDelegatingTableColumn.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// NOTE: If you're using the 10.5 SDK, just use the new delegate method: +// tableView:dataCellForTableColumn:row: + +@interface GTMDelegatingTableColumn : NSTableColumn +// no instance state or new method, it will just invoke the tableview's delegate +// w/ the method below. +@end + +// the method delegated to +@interface NSObject (GTMDelegatingTableColumnDelegate) +- (id)gtm_tableView:(NSTableView *)tableView + dataCellForTableColumn:(NSTableColumn *)tableColumn + row:(NSInteger)row; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.m new file mode 100644 index 00000000..0bd23714 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMDelegatingTableColumn.m @@ -0,0 +1,42 @@ +// +// GTMDelegatingTableColumn.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDelegatingTableColumn.h" + +@implementation GTMDelegatingTableColumn +- (id)dataCellForRow:(NSInteger)row { + id dataCell = nil; + id delegate = [[self tableView] delegate]; + BOOL sendSuper = YES; + if (delegate) { + if ([delegate respondsToSelector:@selector(gtm_tableView:dataCellForTableColumn:row:)]) { + + dataCell = [delegate gtm_tableView:[self tableView] + dataCellForTableColumn:self + row:row]; + sendSuper = NO; + } else { + _GTMDevLog(@"tableView delegate didn't implement gtm_tableView:dataCellForTableColumn:row:"); + } + } + if (sendSuper) { + dataCell = [super dataCellForRow:row]; + } + return dataCell; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandler.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandler.m new file mode 100644 index 00000000..dcac2922 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandler.m @@ -0,0 +1,310 @@ +// +// GTMGetURLHandler.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Add this class to your app to have get URL handled almost automatically for +// you. For each entry in your CFBundleURLTypes dictionaries, add a new +// key/object pair of GTMBundleURLClass/the name of the class you want +// to have handle the scheme(s). +// Then have that class respond to the class method: +// + (BOOL)gtm_openURL:(NSURL*)url +// and voila, it will just work. +// Note that in Debug mode we will do extensive testing to make sure that this +// is all hooked up correctly, and will spew out to the console if we +// find anything amiss. +// +// Example plist entry +// ... +// +// CFBundleURLTypes +// +// +// CFBundleURLName +// Google Suggestion URL +// GTMBundleURLClass +// GoogleSuggestURLHandler +// CFBundleURLSchemes +// +// googlesuggest +// googlesuggestextreme +// +// +// +// +// +// Example implementation +// @interface GoogleSuggestURLHandler +// @end +// @implementation GoogleSuggestURLHandler +// + (BOOL)gtm_openURL:(NSURL*)url { +// NSLog(@"%@", url); +// } +// @end + +#import +#import "GTMGarbageCollection.h" +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMMethodCheck.h" + +static NSString *const kGTMBundleURLClassKey = @"GTMBundleURLClass"; +// A variety of constants Apple really should have defined somewhere to +// allow the compiler to find your typos. +static NSString *const kGTMCFBundleURLSchemesKey = @"CFBundleURLSchemes"; +static NSString *const kGTMCFBundleURLNameKey = @"CFBundleURLName"; +static NSString *const kGTMCFBundleTypeRoleKey = @"CFBundleTypeRole"; +static NSString *const kGTMCFBundleURLTypesKey = @"CFBundleURLTypes"; +static NSString *const kGTMCFBundleViewerRole = @"Viewer"; +static NSString *const kGTMCFBundleEditorRole = @"Editor"; + +// Set this macro elsewhere is you want to force the +// bundle checks on/off. They are nice for debugging +// problems, but shouldn't be required in a release version +// unless you are paranoid about your users messing with your +// Info.plist +#ifndef GTM_CHECK_BUNDLE_URL_CLASSES +#define GTM_CHECK_BUNDLE_URL_CLASSES DEBUG +#endif // GTM_CHECK_BUNDLE_URL_CLASSES + +@protocol GTMGetURLHandlerProtocol ++ (BOOL)gtm_openURL:(NSURL*)url; +@end + +@interface GTMGetURLHandler : NSObject { + NSArray *urlTypes_; +} +- (id)initWithTypes:(NSArray*)urlTypes; +- (void)getUrl:(NSAppleEventDescriptor *)event +withReplyEvent:(NSAppleEventDescriptor *)replyEvent; +- (void)addError:(OSStatus)error + withDescription:(NSString*)string + toDescriptor:(NSAppleEventDescriptor *)desc; ++ (id)handlerForBundle:(NSBundle *)bundle; ++ (void)getUrl:(NSAppleEventDescriptor *)event +withReplyEvent:(NSAppleEventDescriptor *)replyEvent; +@end + +@implementation GTMGetURLHandler +GTM_METHOD_CHECK(NSNumber, gtm_appleEventDescriptor); +GTM_METHOD_CHECK(NSString, gtm_appleEventDescriptor); + ++ (void)load { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAppleEventManager *man = [NSAppleEventManager sharedAppleEventManager]; + [man setEventHandler:self + andSelector:@selector(getUrl:withReplyEvent:) + forEventClass:kInternetEventClass + andEventID:kAEGetURL]; + [pool release]; +} + ++ (void)getUrl:(NSAppleEventDescriptor *)event +withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + static GTMGetURLHandler *sHandler = nil; + if (!sHandler) { + NSBundle *bundle = [NSBundle mainBundle]; + sHandler = [GTMGetURLHandler handlerForBundle:bundle]; + if (sHandler) { + [sHandler retain]; + GTMNSMakeUncollectable(sHandler); + } + } + [sHandler getUrl:event withReplyEvent:replyEvent]; +} + ++ (id)handlerForBundle:(NSBundle *)bundle { + GTMGetURLHandler *handler = nil; + NSArray *urlTypes + = [bundle objectForInfoDictionaryKey:kGTMCFBundleURLTypesKey]; + if (urlTypes) { + handler = [[[GTMGetURLHandler alloc] initWithTypes:urlTypes] autorelease]; + } else { + // COV_NF_START + // Hard to test it if we don't have it. + _GTMDevLog(@"If you don't have CFBundleURLTypes in your plist, you may want" + @" to remove GTMGetURLHandler.m from your project"); + // COV_NF_END + } + return handler; +} + +- (id)initWithTypes:(NSArray*)urlTypes { + if ((self = [super init])) { + urlTypes_ = [urlTypes retain]; +#if GTM_CHECK_BUNDLE_URL_CLASSES + // Some debug handling to check to make sure we can handle the + // classes properly. We check here instead of at init in case some of the + // handlers are being handled by plugins or other imported code that are + // loaded after we have been initialized. + NSDictionary *urlType; + GTM_FOREACH_OBJECT(urlType, urlTypes_) { + NSString *className = [urlType objectForKey:kGTMBundleURLClassKey]; + if ([className length]) { + Class cls = NSClassFromString(className); + if (cls) { + if (![cls respondsToSelector:@selector(gtm_openURL:)]) { + _GTMDevLog(@"Class %@ for URL handler %@ " + @"(URL schemes: %@) doesn't respond to openURL:", + className, + [urlType objectForKey:kGTMCFBundleURLNameKey], + [urlType objectForKey:kGTMCFBundleURLSchemesKey]); + } + } else { + _GTMDevLog(@"Unable to get class %@ for URL handler %@ " + @"(URL schemes: %@)", + className, + [urlType objectForKey:kGTMCFBundleURLNameKey], + [urlType objectForKey:kGTMCFBundleURLSchemesKey]); + } + } else { + NSString *role = [urlType objectForKey:kGTMCFBundleTypeRoleKey]; + if ([role caseInsensitiveCompare:kGTMCFBundleViewerRole] == NSOrderedSame || + [role caseInsensitiveCompare:kGTMCFBundleEditorRole] == NSOrderedSame) { + _GTMDevLog(@"Missing %@ for URL handler %@ " + @"(URL schemes: %@)", + kGTMBundleURLClassKey, + [urlType objectForKey:kGTMCFBundleURLNameKey], + [urlType objectForKey:kGTMCFBundleURLSchemesKey]); + } + } + } +#endif // GTM_CHECK_BUNDLE_URL_CLASSES + } + return self; +} + +// COV_NF_START +// Singleton is never dealloc'd +- (void)dealloc { + [urlTypes_ release]; + [super dealloc]; +} +// COV_NF_END + + +- (NSURL*)extractURLFromEvent:(NSAppleEventDescriptor*)event + withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + NSAppleEventDescriptor *desc + = [event paramDescriptorForKeyword:keyDirectObject]; + NSString *urlstring = [desc stringValue]; + NSURL *url = [NSURL URLWithString:urlstring]; + if (!url) { + // COV_NF_START + // Can't convince the OS to give me a bad URL + [self addError:errAECoercionFail + withDescription:@"Unable to extract url from key direct object." + toDescriptor:replyEvent]; + // COV_NF_END + } + return url; +} + +- (Class)getClassForScheme:(NSString *)scheme + withReplyEvent:(NSAppleEventDescriptor*)replyEvent { + NSDictionary *urlType; + Class cls = nil; + NSString *typeScheme = nil; + GTM_FOREACH_OBJECT(urlType, urlTypes_) { + NSArray *schemes = [urlType objectForKey:kGTMCFBundleURLSchemesKey]; + NSString *aScheme; + GTM_FOREACH_OBJECT(aScheme, schemes) { + if ([aScheme caseInsensitiveCompare:scheme] == NSOrderedSame) { + typeScheme = aScheme; + break; + } + } + if (typeScheme) { + break; + } + } + if (typeScheme) { + NSString *class = [urlType objectForKey:kGTMBundleURLClassKey]; + if (class) { + cls = NSClassFromString(class); + } + if (!cls) { + NSString *errorString + = [NSString stringWithFormat:@"Unable to instantiate class for " + @"%@:%@ for scheme:%@.", + kGTMBundleURLClassKey, class, typeScheme]; + [self addError:errAECorruptData + withDescription:errorString + toDescriptor:replyEvent]; + } else { + if (![cls respondsToSelector:@selector(gtm_openURL:)]) { + NSString *errorString + = [NSString stringWithFormat:@"Class %@:%@ for scheme:%@ does not" + @"respond to gtm_openURL:", + kGTMBundleURLClassKey, class, typeScheme]; + [self addError:errAECorruptData + withDescription:errorString + toDescriptor:replyEvent]; + cls = Nil; + } + } + } else { + // COV_NF_START + // Don't know how to force an URL that we don't respond to upon ourselves. + NSString *errorString + = [NSString stringWithFormat:@"Unable to find handler for scheme %@.", + scheme]; + [self addError:errAECorruptData + withDescription:errorString + toDescriptor:replyEvent]; + // COV_NF_END + + } + return cls; +} + +- (void)getUrl:(NSAppleEventDescriptor *)event +withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + NSURL *url = [self extractURLFromEvent:event withReplyEvent:replyEvent]; + if (!url) { + return; + } + NSString *scheme = [url scheme]; + Class cls = [self getClassForScheme:scheme withReplyEvent:replyEvent]; + if (!cls) { + return; + } + BOOL wasGood = [cls gtm_openURL:url]; + if (!wasGood) { + NSString *errorString + = [NSString stringWithFormat:@"[%@ gtm_openURL:] failed to handle %@", + NSStringFromClass(cls), url]; + [self addError:errAEEventNotHandled + withDescription:errorString + toDescriptor:replyEvent]; + } +} + +- (void)addError:(OSStatus)error + withDescription:(NSString*)string + toDescriptor:(NSAppleEventDescriptor *)desc { + NSAppleEventDescriptor *errorDesc = nil; + if (error != noErr) { + NSNumber *errNum = [NSNumber numberWithLong:error]; + errorDesc = [errNum gtm_appleEventDescriptor]; + [desc setParamDescriptor:errorDesc forKeyword:keyErrorNumber]; + } + if (string) { + errorDesc = [string gtm_appleEventDescriptor]; + [desc setParamDescriptor:errorDesc forKeyword:keyErrorString]; + } +} +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandlerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandlerTest.m new file mode 100644 index 00000000..ba0be7d6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMGetURLHandlerTest.m @@ -0,0 +1,84 @@ +// GTMGetURLHandlerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMUnitTestingUtilities.h" +#import "GTMUnitTestDevLog.h" + +static BOOL sURLHandlerWasHit; + +@interface GTMGetURLHandlerBadClassWarning : NSObject +@end + +@implementation GTMGetURLHandlerBadClassWarning : NSObject +@end + +@interface GTMGetURLHandlerTest : GTMTestCase +@end + +@implementation GTMGetURLHandlerTest +- (BOOL)openURLString:(NSString *)url { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + NSAppleEventDescriptor *currentProcess + = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber + bytes:&psn + length:sizeof(ProcessSerialNumber)]; + NSAppleEventDescriptor *event + = [NSAppleEventDescriptor appleEventWithEventClass:kInternetEventClass + eventID:kAEGetURL + targetDescriptor:currentProcess + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID]; + NSAppleEventDescriptor *keyDesc + = [NSAppleEventDescriptor descriptorWithString:url]; + [event setParamDescriptor:keyDesc forKeyword:keyDirectObject]; + OSStatus err = AESendMessage([event aeDesc], NULL, kAEWaitReply, 60); + return err == noErr ? YES : NO; +} + ++ (BOOL)gtm_openURL:(NSURL*)url { + sURLHandlerWasHit = !sURLHandlerWasHit; + return sURLHandlerWasHit; +} + +- (void)testURLCall { + sURLHandlerWasHit = NO; + + [GTMUnitTestDevLogDebug expectPattern:@"Class GTMGetURLHandlerBadClassWarning " + @"for URL handler GTMGetURLHandlerBadClassURL .*"]; + [GTMUnitTestDevLogDebug expectPattern:@"Unable to get class " + @"GTMGetURLHandlerMissingClassWarning for URL handler " + @"GTMGetURLHandlerMissingClassURL .*"]; + [GTMUnitTestDevLogDebug expectPattern:@"Missing GTMBundleURLClass for URL handler " + @"GTMGetURLHandlerMissingHandlerURL .*"]; + STAssertTrue([self openURLString:@"gtmgeturlhandlertest://test.foo"], nil); + STAssertTrue(sURLHandlerWasHit, @"URL handler not called"); + + STAssertTrue([self openURLString:@"gtmgeturlhandlertest://test.foo"], nil); + STAssertFalse(sURLHandlerWasHit, @"URL handler not called 2"); + + // test the two URL schemes with bad entries + STAssertTrue([self openURLString:@"gtmgeturlhandlerbadclasstest://test.foo"], + nil); + + STAssertTrue([self openURLString:@"gtmgeturlhandlermissingclasstest://test.foo"], + nil); + + STAssertTrue([self openURLString:@"gtmgeturlhandlermissinghandlerurl://test.foo"], + nil); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.h new file mode 100644 index 00000000..4177f496 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.h @@ -0,0 +1,127 @@ +// +// GTMHotKeyTextField.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Text field for capturing hot key entry. This is intended to be similar to the +// Apple key editor in their Keyboard pref pane. + +// NOTE: There are strings that need to be localized to use this field. See the +// code in stringForKeycode the the keys. The keys are all the English versions +// so you'll get reasonable things if you don't have a strings file. + +#import +#import "GTMDefines.h" + +// Dictionary key for hot key configuration information modifier flags. +// NSNumber of a unsigned int. Modifier flags are stored using Cocoa constants +// (same as NSEvent) you will need to translate them to Carbon modifier flags +// for use with RegisterEventHotKey() +#define kGTMHotKeyModifierFlagsKey @"Modifiers" + +// Dictionary key for hot key configuration of virtual key code. NSNumber of +// unsigned int. For double-modifier hotkeys (see below) this value is ignored. +#define kGTMHotKeyKeyCodeKey @"KeyCode" + +// Dictionary key for hot key configuration of double-modifier tap. NSNumber +// BOOL value. Double-tap modifier keys cannot be used with +// RegisterEventHotKey(), you must implement your own Carbon event handler. +#define kGTMHotKeyDoubledModifierKey @"DoubleModifier" + +// Custom text field class used for hot key entry. In order to use this class +// you will need to configure your window's delegate, to return the related +// field editor. +// +// Sample window delegate method: +// +// -(id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject { +// +// if ([anObject isKindOfClass:[GTMHotKeyTextField class]]) { +// return [GTMHotKeyFieldEditor sharedHotKeyFieldEditor]; +// } else { +// return nil; // Window will use the AppKit shared editor +// } +// +// } +// +// +// Other notes: +// - Though you are free to implement control:textShouldEndEditing: in your +// delegate its return is always ignored. The field always accepts only +// one hotkey keystroke before editing ends. +// - The "value" binding of this control is to the dictionary describing the +// hotkey. At this time binding options are not supported. +// - The field does not attempt to consume all hotkeys. Hotkeys which are +// already bound in Apple prefs or other applications will have their +// normal effect. +// + +@interface GTMHotKeyTextField : NSTextField { + @private + NSDictionary *hotKeyDict_; + // Bindings + NSObject *boundObject_; + NSString *boundKeyPath_; +} + +// Set/Get the hot key dictionary for the field. See above for key names. +- (void)setHotKeyValue:(NSDictionary *)hotKey; +- (NSDictionary *)hotKeyValue; + +// Convert Cocoa modifier flags (-[NSEvent modifierFlags]) into a string for +// display. Modifiers are represented in the string in the same order they would +// appear in the Menu Manager. +// +// Args: +// flags: -[NSEvent modifierFlags] +// +// Returns: +// Autoreleased NSString +// ++ (NSString *)stringForModifierFlags:(unsigned int)flags; + +// Convert a keycode into a string that would result from typing the keycode in +// the current keyboard layout. This may be one or more characters. +// +// Args: +// keycode: Virtual keycode such as one obtained from NSEvent +// useGlyph: In many cases the glyphs are confusing, and a string is clearer. +// However, if you want to display in a menu item, use must +// have a glyph. Set useGlyph to FALSE to get localized strings +// which are better for UI display in places other than menus. +// bundle: Localization bundle to use for localizable key names +// +// Returns: +// Autoreleased NSString +// ++ (NSString *)stringForKeycode:(UInt16)keycode + useGlyph:(BOOL)useGlyph + resourceBundle:(NSBundle *)bundle; + +@end + +// Custom field editor for use with hotkey entry fields (GTMHotKeyTextField). +// See the GTMHotKeyTextField for instructions on using from the window +// delegate. +@interface GTMHotKeyFieldEditor : NSTextView { + @private + NSDictionary *hotKeyDict_; // strong +} + +// Get the shared field editor for all hot key fields ++ (GTMHotKeyFieldEditor *)sharedHotKeyFieldEditor; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.m new file mode 100644 index 00000000..65737434 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextField.m @@ -0,0 +1,1024 @@ +// GTMHotKeyTextField.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMHotKeyTextField.h" + +#import +#import "GTMSystemVersion.h" +#import "GTMObjectSingleton.h" +#import "GTMNSObject+KeyValueObserving.h" + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +typedef struct __TISInputSource* TISInputSourceRef; +static TISInputSourceRef(*GTM_TISCopyCurrentKeyboardLayoutInputSource)(void) = NULL; +static void * (*GTM_TISGetInputSourceProperty)(TISInputSourceRef inputSource, + CFStringRef propertyKey) = NULL; +static CFStringRef kGTM_TISPropertyUnicodeKeyLayoutData = NULL; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + + +@interface GTMHotKeyTextField (PrivateMethods) +- (void)setupBinding:(id)bound withPath:(NSString *)path; +- (void)updateDisplayedPrettyString; ++ (BOOL)isValidHotKey:(NSDictionary *)hotKey; ++ (NSString *)displayStringForHotKey:(NSDictionary *)hotKey; +@end + +@interface GTMHotKeyFieldEditor (PrivateMethods) +- (NSDictionary *)hotKeyDictionary; +- (void)setHotKeyDictionary:(NSDictionary *)hotKey; +- (BOOL)shouldBypassEvent:(NSEvent *)theEvent; +- (void)processEventToHotKeyAndString:(NSEvent *)theEvent; +- (void)windowResigned:(NSNotification *)notification; +- (NSDictionary *)hotKeyDictionaryForEvent:(NSEvent *)event; +@end + +@implementation GTMHotKeyTextField + +#if GTM_SUPPORT_GC +- (void)finalize { + if (boundObject_ && boundKeyPath_) { + [boundObject_ gtm_removeObserver:self + forKeyPath:boundKeyPath_ + selector:@selector(hotKeyValueChanged:)]; + } + [super finalize]; +} +#endif + +- (void)dealloc { + + if (boundObject_ && boundKeyPath_) { + [boundObject_ gtm_removeObserver:self + forKeyPath:boundKeyPath_ + selector:@selector(hotKeyValueChanged:)]; + } + [boundObject_ release]; + [boundKeyPath_ release]; + [hotKeyDict_ release]; + [super dealloc]; + +} + +#pragma mark Bindings + + +- (void)bind:(NSString *)binding toObject:(id)observableController + withKeyPath:(NSString *)keyPath + options:(NSDictionary *)options { + + if ([binding isEqualToString:NSValueBinding]) { + // Update to our new binding + [self setupBinding:observableController withPath:keyPath]; + // TODO: Should deal with the bind options + } + [super bind:binding + toObject:observableController + withKeyPath:keyPath + options:options]; + +} + +- (void)unbind:(NSString *)binding { + + // Clean up value on unbind + if ([binding isEqualToString:NSValueBinding]) { + if (boundObject_ && boundKeyPath_) { + [boundObject_ gtm_removeObserver:self + forKeyPath:boundKeyPath_ + selector:@selector(hotKeyValueChanged:)]; + } + [boundObject_ release]; + boundObject_ = nil; + [boundKeyPath_ release]; + boundKeyPath_ = nil; + } + [super unbind:binding]; + +} + +- (void)hotKeyValueChanged:(GTMKeyValueChangeNotification *)note { + NSDictionary *change = [note change]; + // Our binding has changed, update + id changedValue = [change objectForKey:NSKeyValueChangeNewKey]; + // NSUserDefaultsController does not appear to pass on the new object and, + // perhaps other controllers may not, so if we get a nil or NSNull back + // here let's directly retrieve the hotKeyDict_ from the object. + if (!changedValue || changedValue == [NSNull null]) { + id object = [note object]; + NSString *keyPath = [note keyPath]; + changedValue = [object valueForKeyPath:keyPath]; + } + [hotKeyDict_ autorelease]; + hotKeyDict_ = [changedValue copy]; + [self updateDisplayedPrettyString]; +} + + +// Private convenience method for attaching to a new binding +- (void)setupBinding:(id)bound withPath:(NSString *)path { + + // Release previous + if (boundObject_ && boundKeyPath_) { + [boundObject_ gtm_removeObserver:self + forKeyPath:boundKeyPath_ + selector:@selector(hotKeyValueChanged:)]; + } + [boundObject_ release]; + [boundKeyPath_ release]; + // Set new + boundObject_ = [bound retain]; + boundKeyPath_ = [path copy]; + // Make ourself an observer + [boundObject_ gtm_addObserver:self + forKeyPath:boundKeyPath_ + selector:@selector(hotKeyValueChanged:) + userInfo:nil + options:NSKeyValueObservingOptionNew]; + // Pull in any current value + [hotKeyDict_ autorelease]; + hotKeyDict_ = [[boundObject_ valueForKeyPath:boundKeyPath_] copy]; + // Update the display string + [self updateDisplayedPrettyString]; + +} + +#pragma mark Defeating NSControl + +- (double)doubleValue { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return 0.0; + +} + +- (void)setDoubleValue:(double)value { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +- (float)floatValue { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return 0.0f; + +} + +- (void)setFloatValue:(float)value { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +- (int)intValue { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return 0; + +} + +- (void)setIntValue:(int)value { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +- (NSInteger)integerValue { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return 0; + +} + +- (void)setIntegerValue:(NSInteger)value { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +- (id)objectValue { + + return [self hotKeyValue]; + +} + +- (void)setObjectValue:(id)object { + + [self setHotKeyValue:object]; + +} + +- (NSString *)stringValue { + + return [[self class] displayStringForHotKey:hotKeyDict_]; + +} + +- (void)setStringValue:(NSString *)string { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields want dictionaries, not strings."); + return; + +} + +- (NSAttributedString *)attributedStringValue { + + NSString *prettyString = [self stringValue]; + if (!prettyString) return nil; + return [[[NSAttributedString alloc] initWithString:prettyString] autorelease]; + +} + +- (void)setAttributedStringValue:(NSAttributedString *)string { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields want dictionaries, not strings."); + return; + +} + +- (void)takeDoubleValueFrom:(id)sender { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +- (void)takeFloatValueFrom:(id)sender { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +- (void)takeIntValueFrom:(id)sender { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't take numbers."); + return; + +} + +- (void)takeObjectValueFrom:(id)sender { + + // Defeating NSControl + _GTMDevAssert(NO, + @"Hot key fields want dictionaries via bindings, not from controls."); + return; + +} + +- (void)takeStringValueFrom:(id)sender { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields want dictionaries, not strings."); + return; + +} + +- (id)formatter { + + return nil; + +} + +- (void)setFormatter:(NSFormatter *)newFormatter { + + // Defeating NSControl + _GTMDevAssert(NO, @"Hot key fields don't accept formatters."); + return; + +} + +#pragma mark Hot Key Support + ++ (BOOL)isValidHotKey:(NSDictionary *)hotKeyDict { + if (!hotKeyDict || + ![hotKeyDict isKindOfClass:[NSDictionary class]] || + ![hotKeyDict objectForKey:kGTMHotKeyModifierFlagsKey] || + ![hotKeyDict objectForKey:kGTMHotKeyKeyCodeKey] || + ![hotKeyDict objectForKey:kGTMHotKeyDoubledModifierKey]) { + return NO; + } + return YES; +} + +- (void)setHotKeyValue:(NSDictionary *)hotKey { + + // Sanity only if set, nil is OK + if (hotKey && ![[self class] isValidHotKey:hotKey]) { + return; + } + + // If we are bound we want to round trip through that interface + if (boundObject_ && boundKeyPath_) { + // If the change is accepted this will call us back as an observer + [boundObject_ setValue:hotKey forKeyPath:boundKeyPath_]; + return; + } + + // Otherwise we directly update ourself + [hotKeyDict_ autorelease]; + hotKeyDict_ = [hotKey copy]; + [self updateDisplayedPrettyString]; + +} + +- (NSDictionary *)hotKeyValue { + + return hotKeyDict_; + +} + +// Private method to update the displayed text of the field with the +// user-readable representation. +- (void)updateDisplayedPrettyString { + + // Basic validation + if (![[self class] isValidHotKey:hotKeyDict_]) { + [super setStringValue:@""]; + return; + } + + // Pretty string + NSString *prettyString = [[self class] displayStringForHotKey:hotKeyDict_]; + if (!prettyString) { + prettyString = @""; + } + [super setStringValue:prettyString]; + +} + ++ (NSString *)displayStringForHotKey:(NSDictionary *)hotKeyDict { + + if (!hotKeyDict) return nil; + + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + + // Modifiers + unsigned int flags + = [[hotKeyDict objectForKey:kGTMHotKeyModifierFlagsKey] unsignedIntValue]; + NSString *mods = [GTMHotKeyTextField stringForModifierFlags:flags]; + if (!mods || ![mods length]) return nil; + // Handle double modifier case + if ([[hotKeyDict objectForKey:kGTMHotKeyDoubledModifierKey] boolValue]) { + return [NSString stringWithFormat:@"%@ + %@", mods, mods]; + } + // Keycode + unsigned int keycode + = [[hotKeyDict objectForKey:kGTMHotKeyKeyCodeKey] unsignedIntValue]; + NSString *keystroke = [GTMHotKeyTextField stringForKeycode:keycode + useGlyph:NO + resourceBundle:bundle]; + if (!keystroke || ![keystroke length]) return nil; + return [NSString stringWithFormat:@"%@%@", mods, keystroke]; + +} + + +#pragma mark Field Editor Callbacks + +- (BOOL)textShouldBeginEditing:(GTMHotKeyFieldEditor *)fieldEditor { + + // Sanity + if (![fieldEditor isKindOfClass:[GTMHotKeyFieldEditor class]]) { + _GTMDevLog(@"Field editor not appropriate for field, check window delegate"); + return NO; + } + + // We don't call super from here, because we are defeating default behavior + // as a result we have to call the delegate ourself. + id myDelegate = [self delegate]; + SEL selector = @selector(control:textShouldBeginEditing:); + if ([myDelegate respondsToSelector:selector]) { + if (![myDelegate control:self textShouldBeginEditing:fieldEditor]) return NO; + } + + // Update the field editor internal hotkey representation + [fieldEditor setHotKeyDictionary:hotKeyDict_]; // OK if its nil + return YES; + +} + +- (void)textDidChange:(NSNotification *)notification { + + // Sanity + GTMHotKeyFieldEditor *fieldEditor = [notification object]; + if (![fieldEditor isKindOfClass:[GTMHotKeyFieldEditor class]]) { + _GTMDevLog(@"Field editor not appropriate for field, check window delegate"); + return; + } + + // When the field changes we want to read in the current hotkey value so + // bindings can validate + [self setHotKeyValue:[fieldEditor hotKeyDictionary]]; + + // Let super handle the notifications + [super textDidChange:notification]; + +} + +- (BOOL)textShouldEndEditing:(GTMHotKeyFieldEditor *)fieldEditor { + + // Sanity + if (![fieldEditor isKindOfClass:[GTMHotKeyFieldEditor class]]) { + _GTMDevLog(@"Field editor not appropriate for field, check window delegate"); + return NO; + } + + // Again we are defeating default behavior so we have to do delegate handling + // ourself. In this case our goal is simply to prevent the superclass from + // doing its own KVO, but we can also skip [[self cell] isEntryAcceptable:]. + // We'll also ignore the delegate control:textShouldEndEditing:. The field + // editor is done whether they like it or not. + id myDelegate = [self delegate]; + SEL selector = @selector(control:textShouldEndEditing:); + if ([myDelegate respondsToSelector:selector]) { + [myDelegate control:self textShouldEndEditing:fieldEditor]; + } + + // The end is always allowed, so set new value + [self setHotKeyValue:[fieldEditor hotKeyDictionary]]; + + return YES; + +} + +#pragma mark Class methods building strings for use w/in the UI. + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 ++ (void)initialize { + if (!GTM_TISCopyCurrentKeyboardLayoutInputSource + && [GTMSystemVersion isLeopardOrGreater]) { + CFBundleRef hiToolbox + = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox")); + if (hiToolbox) { + kGTM_TISPropertyUnicodeKeyLayoutData + = *(CFStringRef*)CFBundleGetDataPointerForName(hiToolbox, + CFSTR("kTISPropertyUnicodeKeyLayoutData")); + GTM_TISCopyCurrentKeyboardLayoutInputSource + = CFBundleGetFunctionPointerForName(hiToolbox, + CFSTR("TISCopyCurrentKeyboardLayoutInputSource")); + GTM_TISGetInputSourceProperty + = CFBundleGetFunctionPointerForName(hiToolbox, + CFSTR("TISGetInputSourceProperty")); + } + } +} +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +#pragma mark Useful String Class Methods + +// These are not in a category on NSString because this class could be used +// within multiple preference panes at the same time. If we put it in a category +// it would require setting up some magic so that the categories didn't conflict +// between the multiple pref panes. By putting it in the class, you can just +// #define the class name to something else, and then you won't have any +// conflicts. + ++ (NSString *)stringForModifierFlags:(unsigned int)flags { + + UniChar modChars[4]; // We only look for 4 flags + unsigned int charCount = 0; + // These are in the same order as the menu manager shows them + if (flags & NSControlKeyMask) modChars[charCount++] = kControlUnicode; + if (flags & NSAlternateKeyMask) modChars[charCount++] = kOptionUnicode; + if (flags & NSShiftKeyMask) modChars[charCount++] = kShiftUnicode; + if (flags & NSCommandKeyMask) modChars[charCount++] = kCommandUnicode; + if (charCount == 0) return nil; + return [NSString stringWithCharacters:modChars length:charCount]; + +} + ++ (NSString *)stringForKeycode:(UInt16)keycode + useGlyph:(BOOL)useGlyph + resourceBundle:(NSBundle *)bundle { + + // Some keys never move in any layout (to the best of our knowledge at least) + // so we can hard map them. + UniChar key = 0; + NSString *localizedKey = nil; + + switch (keycode) { + + // Of the hard mapped keys some can be represented with pretty and obvioous + // Unicode or simple strings without localization. + + // Arrow keys + case 123: key = NSLeftArrowFunctionKey; break; + case 124: key = NSRightArrowFunctionKey; break; + case 125: key = NSDownArrowFunctionKey; break; + case 126: key = NSUpArrowFunctionKey; break; + case 122: key = NSF1FunctionKey; break; + case 120: key = NSF2FunctionKey; break; + case 99: key = NSF3FunctionKey; break; + case 118: key = NSF4FunctionKey; break; + case 96: key = NSF5FunctionKey; break; + case 97: key = NSF6FunctionKey; break; + case 98: key = NSF7FunctionKey; break; + case 100: key = NSF8FunctionKey; break; + case 101: key = NSF9FunctionKey; break; + case 109: key = NSF10FunctionKey; break; + case 103: key = NSF11FunctionKey; break; + case 111: key = NSF12FunctionKey; break; + case 105: key = NSF13FunctionKey; break; + case 107: key = NSF14FunctionKey; break; + case 113: key = NSF15FunctionKey; break; + case 106: key = NSF16FunctionKey; break; + // Forward delete is a terrible name so we'll use the glyph Apple puts on + // their current keyboards + case 117: key = 0x2326; break; + + // Now we have keys that can be hard coded but don't have good glyph + // representations. Sure, the Apple menu manager has glyphs for them, but + // an informal poll of Google developers shows no one really knows what + // they mean, so its probably a good idea to use strings. Unfortunately + // this also means localization (*sigh*). We'll use the real English + // strings here as keys so that even if localization is missed we'll do OK + // in output. + + // Whitespace + case 36: key = '\r'; localizedKey = @"Return"; break; + case 76: key = 0x3; localizedKey = @"Enter"; break; + case 48: key = 0x9; localizedKey = @"Tab"; break; + case 49: key = 0xA0; localizedKey = @"Space"; break; + // Control keys + case 51: key = 0x8; localizedKey = @"Delete"; break; + case 71: key = NSClearDisplayFunctionKey; localizedKey = @"Clear"; break; + case 53: key = 0x1B; localizedKey = @"Esc"; break; + case 115: key = NSHomeFunctionKey; localizedKey = @"Home"; break; + case 116: key = NSPageUpFunctionKey; localizedKey = @"Page Up"; break; + case 119: key = NSEndFunctionKey; localizedKey = @"End"; break; + case 121: key = NSPageDownFunctionKey; localizedKey = @"Page Down"; break; + case 114: key = NSHelpFunctionKey; localizedKey = @"Help"; break; + // Keypad keys + // There is no good way we could find to glyph these. We tried a variety + // of Unicode glyphs, and the menu manager wouldn't take them. We tried + // subscript numbers, circled numbers and superscript numbers with no + // luck. It may be a bit confusing to the user, but we're happy to hear + // any suggestions. + case 65: key = '.'; localizedKey = @"Keypad ."; break; + case 67: key = '*'; localizedKey = @"Keypad *"; break; + case 69: key = '+'; localizedKey = @"Keypad +"; break; + case 75: key = '/'; localizedKey = @"Keypad /"; break; + case 78: key = '-'; localizedKey = @"Keypad -"; break; + case 81: key = '='; localizedKey = @"Keypad ="; break; + case 82: key = '0'; localizedKey = @"Keypad 0"; break; + case 83: key = '1'; localizedKey = @"Keypad 1"; break; + case 84: key = '2'; localizedKey = @"Keypad 2"; break; + case 85: key = '3'; localizedKey = @"Keypad 3"; break; + case 86: key = '4'; localizedKey = @"Keypad 4"; break; + case 87: key = '5'; localizedKey = @"Keypad 5"; break; + case 88: key = '6'; localizedKey = @"Keypad 6"; break; + case 89: key = '7'; localizedKey = @"Keypad 7"; break; + case 91: key = '8'; localizedKey = @"Keypad 8"; break; + case 92: key = '9'; localizedKey = @"Keypad 9"; break; + + } + + // If they asked for strings, and we have one return it. Otherwise, return + // any key we've picked. + if (!useGlyph && localizedKey) { + return NSLocalizedStringFromTableInBundle(localizedKey, @"KeyCode", + bundle, @""); + } else if (key != 0) { + return [NSString stringWithFormat:@"%C", key]; + } + + // Everything else should be printable so look it up in the current keyboard + UCKeyboardLayout *uchrData = NULL; + + OSStatus err = noErr; +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + // layout + KeyboardLayoutRef currentLayout = NULL; + // Get the layout kind + SInt32 currentLayoutKind = -1; + if ([GTMSystemVersion isLeopardOrGreater] + && kGTM_TISPropertyUnicodeKeyLayoutData + && GTM_TISGetInputSourceProperty + && GTM_TISCopyCurrentKeyboardLayoutInputSource) { + // On Leopard we use the new improved TIS interfaces which work for input + // sources as well as keyboard layouts. + TISInputSourceRef inputSource + = GTM_TISCopyCurrentKeyboardLayoutInputSource(); + if (inputSource) { + CFDataRef uchrDataRef + = GTM_TISGetInputSourceProperty(inputSource, + kGTM_TISPropertyUnicodeKeyLayoutData); + if(uchrDataRef) { + uchrData = (UCKeyboardLayout*)CFDataGetBytePtr(uchrDataRef); + } + CFRelease(inputSource); + } + } else { + // Tiger we use keyboard layouts as it's the best we can officially do. + err = KLGetCurrentKeyboardLayout(¤tLayout); + if (err != noErr) { // COV_NF_START + _GTMDevLog(@"failed to fetch the keyboard layout, err=%d", err); + return nil; + } // COV_NF_END + + err = KLGetKeyboardLayoutProperty(currentLayout, + kKLKind, + (const void **)¤tLayoutKind); + if (err != noErr) { // COV_NF_START + _GTMDevLog(@"failed to fetch the keyboard layout kind property, err=%d", + err); + return nil; + } // COV_NF_END + + if (currentLayoutKind != kKLKCHRKind) { + err = KLGetKeyboardLayoutProperty(currentLayout, + kKLuchrData, + (const void **)&uchrData); + if (err != noErr) { // COV_NF_START + _GTMDevLog(@"failed to fetch the keyboard layout uchar data, err=%d", + err); + return nil; + } // COV_NF_END + } + } +#else + TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource(); + if (inputSource) { + CFDataRef uchrDataRef + = TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData); + if(uchrDataRef) { + uchrData = (UCKeyboardLayout*)CFDataGetBytePtr(uchrDataRef); + } + CFRelease(inputSource); + } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + + NSString *keystrokeString = nil; + if (uchrData) { + // uchr layout data is available, this is our preference + UniCharCount uchrCharLength = 0; + UniChar uchrChars[256] = { 0 }; + UInt32 uchrDeadKeyState = 0; + err = UCKeyTranslate(uchrData, + keycode, + kUCKeyActionDisplay, + 0, // No modifiers + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysMask, + &uchrDeadKeyState, + sizeof(uchrChars) / sizeof(UniChar), + &uchrCharLength, + uchrChars); + if (err != noErr) { + // COV_NF_START + _GTMDevLog(@"failed to translate the keycode, err=%d", err); + return nil; + // COV_NF_END + } + if (uchrCharLength < 1) return nil; + keystrokeString = [NSString stringWithCharacters:uchrChars + length:uchrCharLength]; + } +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + else if (currentLayoutKind == kKLKCHRKind) { + // Only KCHR layout data is available, go old school + void *KCHRData = NULL; + err = KLGetKeyboardLayoutProperty(currentLayout, kKLKCHRData, + (const void **)&KCHRData); + if (err != noErr) { // COV_NF_START + _GTMDevLog(@"failed to fetch the keyboard layout uchar data, err=%d", + err); + return nil; + } // COV_NF_END + // Turn into character code + UInt32 keyTranslateState = 0; + UInt32 twoKCHRChars = KeyTranslate(KCHRData, keycode, &keyTranslateState); + if (!twoKCHRChars) return nil; + // Unpack the fields + char firstChar = (char)((twoKCHRChars & 0x00FF0000) >> 16); + char secondChar = (char)(twoKCHRChars & 0x000000FF); + // May have one or two characters + if (firstChar && secondChar) { + NSString *str1 + = [[[NSString alloc] initWithBytes:&firstChar + length:1 + encoding:NSMacOSRomanStringEncoding] autorelease]; + NSString *str2 + = [[[NSString alloc] initWithBytes:&secondChar + length:1 + encoding:NSMacOSRomanStringEncoding] autorelease]; + keystrokeString = [NSString stringWithFormat:@"%@%@", + [str1 uppercaseString], + [str2 uppercaseString]]; + } else { + keystrokeString = [[[NSString alloc] initWithBytes:&secondChar + length:1 + encoding:NSMacOSRomanStringEncoding] autorelease]; + [keystrokeString uppercaseString]; + } + } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + + // Sanity we got a stroke + if (!keystrokeString || ![keystrokeString length]) return nil; + + // Sanity check the keystroke string for unprintable characters + NSMutableCharacterSet *validChars = + [[[NSMutableCharacterSet alloc] init] autorelease]; + + [validChars formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]]; + [validChars formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; + [validChars formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet]]; + for (unsigned int i = 0; i < [keystrokeString length]; i++) { + if (![validChars characterIsMember:[keystrokeString characterAtIndex:i]]) { + return nil; + } + } + + if (!useGlyph) { + // menus want glyphs in the original lowercase forms, so we only upper this + // if we aren't using it as a glyph. + keystrokeString = [keystrokeString uppercaseString]; + } + + return keystrokeString; + +} + +@end + +@implementation GTMHotKeyFieldEditor + +GTMOBJECT_SINGLETON_BOILERPLATE(GTMHotKeyFieldEditor, sharedHotKeyFieldEditor) + +- (id)init { + + self = [super init]; + if (!self) return nil; + [self setFieldEditor:YES]; // We are a field editor + + return self; + +} + +- (void)dealloc { + + [hotKeyDict_ release]; + [super dealloc]; + +} + +- (NSArray *)acceptableDragTypes { + + // Don't take drags + return [NSArray array]; + +} + +- (NSArray *)readablePasteboardTypes { + + // No pasting + return [NSArray array]; + +} + +- (NSArray *)writablePasteboardTypes { + + // No copying + return [NSArray array]; + +} + +- (BOOL)becomeFirstResponder { + + // We need to lose focus any time the window is not key + NSNotificationCenter *dc = [NSNotificationCenter defaultCenter]; + [dc addObserver:self + selector:@selector(windowResigned:) + name:NSWindowDidResignKeyNotification + object:[self window]]; + return [super becomeFirstResponder]; + +} + +- (BOOL)resignFirstResponder { + + // No longer interested in window resign + [[NSNotificationCenter defaultCenter] removeObserver:self]; + return [super resignFirstResponder]; + +} + +// Private method we use to get out of global hotkey capture when the window +// is no longer front +- (void)windowResigned:(NSNotification *)notification { + + // Lose our focus + [[self window] makeFirstResponder:[self window]]; + +} + +- (BOOL)shouldDrawInsertionPoint { + + // Show an insertion point, because we'll kill our own focus after + // each entry + return YES; + +} + +- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange + granularity:(NSSelectionGranularity)granularity { + + // Always select everything + return NSMakeRange(0, [[self textStorage] length]); + +} + +- (void)keyDown:(NSEvent *)theEvent { + + if ([self shouldBypassEvent:theEvent]) { + [super keyDown:theEvent]; + } else { + // Try to eat the event + [self processEventToHotKeyAndString:theEvent]; + } + +} + +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { + + if ([self shouldBypassEvent:theEvent]) { + return [super performKeyEquivalent:theEvent]; + } else { + // We always eat these key strokes while we have focus + [self processEventToHotKeyAndString:theEvent]; + return YES; + } + +} + +// Private do method that tell us to ignore certain events +- (BOOL)shouldBypassEvent:(NSEvent *)theEvent { + + UInt16 keyCode = [theEvent keyCode]; + NSUInteger modifierFlags + = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; + + // Ignore all events containing tabs. They have special meaning to fields + // and some (Cmd Tab variants) are always consumed by the Dock, so users + // just shouldn't be able to use them. + if (keyCode == 48) { // Tab + // Just to be extra clear if the user is trying to use Dock hotkeys beep + // at them + if ((modifierFlags == NSCommandKeyMask) || + (modifierFlags == (NSCommandKeyMask | NSShiftKeyMask))) { + NSBeep(); + } + return YES; + } + + // Don't eat Cmd-Q. Users could have it as a hotkey, but its more likely + // they're trying to quit + if ((keyCode == 12) && (modifierFlags == NSCommandKeyMask)) { + return YES; + } + // Same for Cmd-W, user is probably trying to close the window + if ((keyCode == 13) && (modifierFlags == NSCommandKeyMask)) { + return YES; + } + + return NO; + +} + +// Private method that turns events into strings and dictionaries for our +// hotkey plumbing. +- (void)processEventToHotKeyAndString:(NSEvent *)theEvent { + + // Construct a dictionary of the event as a hotkey pref + NSDictionary *newHotKey = [self hotKeyDictionaryForEvent:theEvent]; + if (!newHotKey) { + NSBeep(); + return; // No action, but don't give up focus + } + NSString *prettyString = [GTMHotKeyTextField displayStringForHotKey:newHotKey]; + if (!prettyString) { + NSBeep(); + return; + } + + // Replacement range + NSRange replaceRange = NSMakeRange(0, [[self textStorage] length]); + + // Ask for permission to replace + if (![self shouldChangeTextInRange:replaceRange + replacementString:prettyString]) { + // If replacement was disallowed, change nothing, including hotKeyDict_ + NSBeep(); + return; + } + + // Replacement was allowed, update + [hotKeyDict_ autorelease]; + hotKeyDict_ = [newHotKey retain]; + + // Set string on self, allowing super to handle attribute copying + [self setString:prettyString]; + + // Finish the change + [self didChangeText]; + + // Force editing to end. This sends focus off into space slightly, but + // its better than constantly capturing user events. This is exactly + // like the Apple editor in their Keyboard pref pane. + [[[self delegate] cell] endEditing:self]; + +} + +- (NSDictionary *)hotKeyDictionary { + + return hotKeyDict_; + +} + +- (void)setHotKeyDictionary:(NSDictionary *)hotKey { + + [hotKeyDict_ autorelease]; + hotKeyDict_ = [hotKey copy]; + // Update content + NSString *prettyString = nil; + if (hotKeyDict_) { + prettyString = [GTMHotKeyTextField displayStringForHotKey:hotKey]; + } + if (!prettyString) { + prettyString = @""; + } + [self setString:prettyString]; + +} + +- (NSDictionary *)hotKeyDictionaryForEvent:(NSEvent *)event{ + + if (!event) return nil; + + // Check event + NSUInteger flags = [event modifierFlags]; + UInt16 keycode = [event keyCode]; + // If the event has no modifiers do nothing + NSUInteger allModifiers = (NSCommandKeyMask | NSAlternateKeyMask | + NSControlKeyMask | NSShiftKeyMask); + if (!(flags & allModifiers)) return nil; + // If the event has high bits in keycode do nothing + if (keycode & 0xFF00) return nil; + + // Clean the flags to only contain things we care about + UInt32 cleanFlags = 0; + if (flags & NSCommandKeyMask) cleanFlags |= NSCommandKeyMask; + if (flags & NSAlternateKeyMask) cleanFlags |= NSAlternateKeyMask; + if (flags & NSControlKeyMask) cleanFlags |= NSControlKeyMask; + if (flags & NSShiftKeyMask) cleanFlags |= NSShiftKeyMask; + + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:keycode], + kGTMHotKeyKeyCodeKey, + [NSNumber numberWithUnsignedInt:cleanFlags], + kGTMHotKeyModifierFlagsKey, + nil]; + +} +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextFieldTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextFieldTest.m new file mode 100644 index 00000000..ee1bfc2b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMHotKeyTextFieldTest.m @@ -0,0 +1,204 @@ +// GTMHotKeyTextFieldTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMHotKeyTextField.h" + +#import "GTMSenTestCase.h" + +@interface GTMHotKeyTextField (PrivateMethods) +// Private methods which we want to access to test ++ (BOOL)isValidHotKey:(NSDictionary *)hotKey; ++ (NSString *)displayStringForHotKey:(NSDictionary *)hotKey; +@end + +@interface GTMHotKeyTextFieldTest : GTMTestCase +@end + +@implementation GTMHotKeyTextFieldTest + +- (void)testStringForModifierFlags { + + // Make sure only the flags we expect generate things in their strings + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSAlphaShiftKeyMask] length], + (NSUInteger)0, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSShiftKeyMask] length], + (NSUInteger)1, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSControlKeyMask] length], + (NSUInteger)1, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSAlternateKeyMask] length], + (NSUInteger)1, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSCommandKeyMask] length], + (NSUInteger)1, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSNumericPadKeyMask] length], + (NSUInteger)0, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSHelpKeyMask] length], + (NSUInteger)0, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:NSFunctionKeyMask] length], + (NSUInteger)0, nil); + + // And some quick checks combining flags to make sure the string gets longer + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:(NSShiftKeyMask | + NSAlternateKeyMask)] length], + (NSUInteger)2, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:(NSShiftKeyMask | + NSAlternateKeyMask | + NSCommandKeyMask)] length], + (NSUInteger)3, nil); + STAssertEquals([[GTMHotKeyTextField stringForModifierFlags:(NSShiftKeyMask | + NSAlternateKeyMask | + NSCommandKeyMask | + NSControlKeyMask)] length], + (NSUInteger)4, nil); + +} + +- (void)testStringForKeycode_useGlyph_resourceBundle { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + STAssertNotNil(bundle, @"failed to get our bundle?"); + NSString *str; + + // We need a better test, but for now, we'll just loop through things we know + // we handle. + + // TODO: we need to force the pre leopard code path during tests. + + UInt16 testData[] = { + 123, 124, 125, 126, 122, 120, 99, 118, 96, 97, 98, 100, 101, 109, 103, 111, + 105, 107, 113, 106, 117, 36, 76, 48, 49, 51, 71, 53, 115, 116, 119, 121, + 114, 65, 67, 69, 75, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, + }; + for (int useGlyph = 0 ; useGlyph < 2 ; ++useGlyph) { + for (size_t i = 0; i < (sizeof(testData) / sizeof(UInt16)); ++i) { + UInt16 keycode = testData[i]; + + str = [GTMHotKeyTextField stringForKeycode:keycode + useGlyph:useGlyph + resourceBundle:bundle]; + STAssertNotNil(str, + @"failed to get a string for keycode %u (useGlyph:%@)", + keycode, (useGlyph ? @"YES" : @"NO")); + STAssertGreaterThan([str length], (NSUInteger)0, + @"got an empty string for keycode %u (useGlyph:%@)", + keycode, (useGlyph ? @"YES" : @"NO")); + } + } +} + +- (void)testGTMHotKeyPrettyString { + NSDictionary *hkDict; + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertNotNil([GTMHotKeyTextField displayStringForHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertNotNil([GTMHotKeyTextField displayStringForHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertNotNil([GTMHotKeyTextField displayStringForHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertNil([GTMHotKeyTextField displayStringForHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionary]; + STAssertNotNil(hkDict, nil); + STAssertNil([GTMHotKeyTextField displayStringForHotKey:hkDict], nil); + + STAssertNil([GTMHotKeyTextField displayStringForHotKey:nil], nil); + +} + +- (void)testGTMHotKeyDictionaryAppearsValid { + NSDictionary *hkDict; + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertTrue([GTMHotKeyTextField isValidHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertFalse([GTMHotKeyTextField isValidHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:NSCommandKeyMask], + kGTMHotKeyModifierFlagsKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertFalse([GTMHotKeyTextField isValidHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kGTMHotKeyDoubledModifierKey, + [NSNumber numberWithUnsignedInt:114], + kGTMHotKeyKeyCodeKey, + nil]; + STAssertNotNil(hkDict, nil); + STAssertFalse([GTMHotKeyTextField isValidHotKey:hkDict], nil); + + hkDict = [NSDictionary dictionary]; + STAssertNotNil(hkDict, nil); + STAssertFalse([GTMHotKeyTextField isValidHotKey:hkDict], nil); + + STAssertFalse([GTMHotKeyTextField isValidHotKey:nil], nil); + + // Make sure it doesn't choke w/ an object of the wrong time (since the dicts + // have to be saved/reloaded. + hkDict = (id)[NSString string]; + STAssertNotNil(hkDict, nil); + STAssertFalse([GTMHotKeyTextField isValidHotKey:hkDict], nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.h new file mode 100644 index 00000000..0a7759f5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.h @@ -0,0 +1,60 @@ +// +// GTMLargeTypeWindow.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// GTMLargeTypeWindow displays a block of text in a large panel window much +// like Address Book displays phone numbers. It will also display an image +// so you can pop up "alerts" similar to the way BBEdit does when you attempt +// to do a find and find nothing. It will fade in and out appropriately when +// ordered forward or backward. +// A typical fire-and-forget type usage would be: +// GTMLargeTypeWindow *window +// = [[[GTMLargeTypeWindow alloc] initWithString:@"Foo"] autorelease]; +// [window makeKeyAndOrderFront:nil]; + +// NB This class appears to have a problem with GC on 10.5.6 and below. +// Radar 6137322 CIFilter crashing when run with GC enabled +// This appears to be an Apple bug with GC. +// We do a copy animation that causes things to crash, but only with GC +// on. Currently I have left this enabled in GTMLargeTypeWindow pending +// info from Apple on the bug. It's hard to reproduce, and only appears +// at this time on our test machines. +// Dual-Core Intel Xeon with ATI Radeon X1300 + +// Amount of time to fade the window in or out +const NSTimeInterval kGTMLargeTypeWindowFadeTime; + +@interface GTMLargeTypeWindow : NSPanel +// Creates a display window with |string| displayed. +// Formats |string| as best as possible to fill the screen. +- (id)initWithString:(NSString *)string; +// Creates a display window with |attrString| displayed. +// Expects you to format it as you want it to appear. +- (id)initWithAttributedString:(NSAttributedString *)attrString; +// Creates a display window with |image| displayed. +// Make sure you set the image size to what you want +- (id)initWithImage:(NSImage*)image; +// Creates a display window with |view| displayed. +- (id)initWithContentView:(NSView *)view; + +// Copy the text out of the window if appropriate. This is normally called +// as part of the responder chain so that the user can copy the displayed text +// using cmd-c. +- (void)copy:(id)sender; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.m new file mode 100644 index 00000000..97847aaa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindow.m @@ -0,0 +1,366 @@ +// +// GTMLargeTypeWindow.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import "GTMLargeTypeWindow.h" +#import "GTMGeometryUtils.h" +#import "GTMNSBezierPath+RoundRect.h" +#import "GTMMethodCheck.h" + +// Amount of time to fade the window in or out +const NSTimeInterval kGTMLargeTypeWindowFadeTime = 0.333; + +// How far to inset the text from the edge of the window +static const CGFloat kEdgeInset = 16.0; + +// Give us an alpha value for our backing window +static const CGFloat kTwoThirdsAlpha = 0.66; + +@interface GTMLargeTypeCopyAnimation : NSAnimation +@end + +@interface GTMLargeTypeBackgroundView : NSView { + CIFilter *transition_; + GTMLargeTypeCopyAnimation *animation_; +} +- (void)animateCopy; +@end + +@interface GTMLargeTypeWindow (GTMLargeTypeWindowPrivate) ++ (CGFloat)displayWidth; +- (void)animateWithEffect:(NSString*)effect; +@end + +@implementation GTMLargeTypeWindow + +- (id)initWithString:(NSString *)string { + if ([string length] == 0) { + _GTMDevLog(@"GTMLargeTypeWindow got an empty string"); + [self release]; + return nil; + } + CGFloat displayWidth = [[self class] displayWidth]; + NSMutableAttributedString *attrString + = [[[NSMutableAttributedString alloc] initWithString:string] autorelease]; + + NSRange fullRange = NSMakeRange(0, [string length]); + [attrString addAttribute:NSForegroundColorAttributeName + value:[NSColor whiteColor] + range:fullRange]; + + NSMutableParagraphStyle *style + = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; + [style setAlignment:NSCenterTextAlignment]; + [attrString addAttribute:NSParagraphStyleAttributeName + value:style + range:fullRange]; + + NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; + [textShadow setShadowOffset:NSMakeSize( 5, -5 )]; + [textShadow setShadowBlurRadius:10]; + [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0 + alpha:kTwoThirdsAlpha]]; + [attrString addAttribute:NSShadowAttributeName + value:textShadow + range:fullRange]; + + // Try and find a size that fits without iterating too many times. + // We start going 50 pixels at a time, then 10, then 1 + int size = -26; // start at 24 (-26 + 50) + int offsets[] = { 50, 10, 1 }; + NSSize bigSize = NSMakeSize(MAXFLOAT, MAXFLOAT); + NSStringDrawingOptions options = (NSStringDrawingUsesDeviceMetrics | + NSStringDrawingOneShot); + for (size_t i = 0; i < sizeof(offsets) / sizeof(int); ++i) { + for(size = size + offsets[i]; size >= 24 && size < 300; size += offsets[i]) { + NSFont *font = [NSFont boldSystemFontOfSize:size] ; + [attrString addAttribute:NSFontAttributeName + value:font + range:fullRange]; + NSRect textSize = [attrString boundingRectWithSize:bigSize + options:options]; + NSSize maxAdvanceSize = [font maximumAdvancement]; + if (textSize.size.width + maxAdvanceSize.width > displayWidth) { + size = size - offsets[i]; + break; + } + } + } + + // Bounds check our values + if (size > 300) { + size = 300; + } else if (size < 24) { + size = 24; + } + [attrString addAttribute:NSFontAttributeName + value:[NSFont boldSystemFontOfSize:size] + range:fullRange]; + return [self initWithAttributedString:attrString]; +} + +- (id)initWithAttributedString:(NSAttributedString *)attrString { + if ([attrString length] == 0) { + _GTMDevLog(@"GTMLargeTypeWindow got an empty string"); + [self release]; + return nil; + } + CGFloat displayWidth =[[self class] displayWidth]; + NSRect frame = NSMakeRect(0, 0, displayWidth, 0); + NSTextView *textView = [[[NSTextView alloc] initWithFrame:frame] autorelease]; + [textView setEditable:NO]; + [textView setSelectable:NO]; + [textView setDrawsBackground:NO]; + [[textView textStorage] setAttributedString:attrString]; + [textView sizeToFit]; + + return [self initWithContentView:textView]; +} + +- (id)initWithImage:(NSImage*)image { + if (!image) { + _GTMDevLog(@"GTMLargeTypeWindow got an empty image"); + [self release]; + return nil; + } + NSRect rect = GTMNSRectOfSize([image size]); + NSImageView *imageView + = [[[NSImageView alloc] initWithFrame:rect] autorelease]; + [imageView setImage:image]; + return [self initWithContentView:imageView]; +} + +- (id)initWithContentView:(NSView *)view { + NSRect bounds = NSZeroRect; + if (view) { + bounds = [view bounds]; + } + if (!view || bounds.size.height <= 0 || bounds.size.width <= 0) { + _GTMDevLog(@"GTMLargeTypeWindow got an empty view"); + [self release]; + return nil; + } + NSRect screenRect = [[NSScreen mainScreen] frame]; + NSRect windowRect = GTMNSAlignRectangles([view frame], + screenRect, + GTMRectAlignCenter); + windowRect = NSInsetRect(windowRect, -kEdgeInset, -kEdgeInset); + windowRect = NSIntegralRect(windowRect); + NSUInteger mask = NSBorderlessWindowMask | NSNonactivatingPanelMask; + self = [super initWithContentRect:windowRect + styleMask:mask + backing:NSBackingStoreBuffered + defer:NO]; + if (self) { + [self setFrame:GTMNSAlignRectangles(windowRect, + screenRect, + GTMRectAlignCenter) + display:YES]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setOpaque:NO]; + [self setLevel:NSFloatingWindowLevel]; + [self setHidesOnDeactivate:NO]; + + GTMLargeTypeBackgroundView *content + = [[[GTMLargeTypeBackgroundView alloc] initWithFrame:NSZeroRect] + autorelease]; + [self setHasShadow:YES]; + [self setContentView:content]; + [self setAlphaValue:0]; + [self setIgnoresMouseEvents:YES]; + [view setFrame:GTMNSAlignRectangles([view frame], + [content frame], + GTMRectAlignCenter)]; + [content addSubview:view]; + [self setInitialFirstResponder:view]; + } + return self; +} + +- (void)copy:(id)sender { + id firstResponder = [self initialFirstResponder]; + if ([firstResponder respondsToSelector:@selector(textStorage)]) { + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self]; + [pb setString:[[firstResponder textStorage] string] + forType:NSStringPboardType]; + } + + // Give the user some feedback that a copy has occurred + [(GTMLargeTypeBackgroundView*)[self contentView] animateCopy]; +} + +- (BOOL)canBecomeKeyWindow { + return YES; +} + +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { + NSString *chars = [theEvent charactersIgnoringModifiers]; + NSUInteger flags = ([theEvent modifierFlags] & + NSDeviceIndependentModifierFlagsMask); + BOOL isValid = (flags == NSCommandKeyMask) && [chars isEqualToString:@"c"]; + if (isValid) { + [self copy:self]; + } + return isValid; +} + +- (void)keyDown:(NSEvent *)theEvent { + [self close]; +} + +- (void)resignKeyWindow { + [super resignKeyWindow]; + if([self isVisible]) { + [self close]; + } +} + +- (void)makeKeyAndOrderFront:(id)sender { + [super makeKeyAndOrderFront:sender]; + [self animateWithEffect:NSViewAnimationFadeInEffect]; +} + +- (void)orderFront:(id)sender { + [super orderFront:sender]; + [self animateWithEffect:NSViewAnimationFadeInEffect]; +} + +- (void)orderOut:(id)sender { + [self animateWithEffect:NSViewAnimationFadeOutEffect]; + [super orderOut:sender]; +} + ++ (CGFloat)displayWidth { + NSRect screenRect = [[NSScreen mainScreen] frame]; + // This is just a rough calculation to make us fill a good proportion + // of the main screen. + return NSWidth( screenRect ) * 11.0 / 12.0 - 2.0 * kEdgeInset; +} + +- (void)animateWithEffect:(NSString*)effect { + NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys: + self, NSViewAnimationTargetKey, + effect, NSViewAnimationEffectKey, + nil]; + NSArray *animation = [NSArray arrayWithObject:fadeIn]; + NSViewAnimation *viewAnim + = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease]; + [viewAnim setDuration:kGTMLargeTypeWindowFadeTime]; + [viewAnim setAnimationBlockingMode:NSAnimationBlocking]; + [viewAnim startAnimation]; +} +@end + +@implementation GTMLargeTypeBackgroundView +GTM_METHOD_CHECK(NSBezierPath, gtm_appendBezierPathWithRoundRect:cornerRadius:); + +- (void)dealloc { + // If we get released while animating, we'd better clean up. + [animation_ stopAnimation]; + [animation_ release]; + [transition_ release]; + [super dealloc]; +} + +- (BOOL)isOpaque { + return NO; +} + +- (void)drawRect:(NSRect)rect { + rect = [self bounds]; + NSBezierPath *roundRect = [NSBezierPath bezierPath]; + CGFloat minRadius = MIN(NSWidth(rect), NSHeight(rect)) * 0.5f; + + [roundRect gtm_appendBezierPathWithRoundRect:rect + cornerRadius:MIN(minRadius, 32)]; + [roundRect addClip]; + if (transition_) { + NSNumber *val = [NSNumber numberWithFloat:[animation_ currentValue]]; + [transition_ setValue:val forKey:@"inputTime"]; + CIImage *outputCIImage = [transition_ valueForKey:@"outputImage"]; + [outputCIImage drawInRect:rect + fromRect:rect + operation:NSCompositeSourceOver + fraction:1.0]; + } else { + [[NSColor colorWithDeviceWhite:0 alpha:kTwoThirdsAlpha] set]; + + NSRectFill(rect); + } +} + +- (void)animateCopy { + // This does a photocopy swipe to show folks that their copy has succceeded + // Store off a copy of our background + NSRect bounds = [self bounds]; + NSBitmapImageRep *rep = [self bitmapImageRepForCachingDisplayInRect:bounds]; + NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:context]; + [self drawRect:bounds]; + [NSGraphicsContext restoreGraphicsState]; + CIVector *extent = [CIVector vectorWithX:bounds.origin.x + Y:bounds.origin.y + Z:bounds.size.width + W:bounds.size.height]; + CIFilter *transition = [CIFilter filterWithName:@"CICopyMachineTransition"]; + [transition setDefaults]; + [transition setValue:extent + forKey:@"inputExtent"]; + CIImage *image = [[CIImage alloc] initWithBitmapImageRep:rep]; + + [transition setValue:image forKey:@"inputImage"]; + [transition setValue:image forKey:@"inputTargetImage"]; + [transition setValue:[NSNumber numberWithInt:0] + forKey:@"inputTime"]; + [transition valueForKey:@"outputImage"]; + [image release]; + transition_ = [transition retain]; + animation_ = [[GTMLargeTypeCopyAnimation alloc] initWithDuration:0.5 + animationCurve:NSAnimationLinear]; + [animation_ setFrameRate:0.0f]; + [animation_ setDelegate:self]; + [animation_ setAnimationBlockingMode:NSAnimationBlocking]; + [animation_ startAnimation]; +} + +- (void)animationDidEnd:(NSAnimation*)animation { + [animation_ release]; + animation_ = nil; + [transition_ release]; + transition_ = nil; + [self display]; +} + +- (float)animation:(NSAnimation*)animation + valueForProgress:(NSAnimationProgress)progress { + // This gives us half the copy animation, so we don't swing back + // Don't want too much gratuitous effect + // 0.6 is required by experimentation. 0.5 doesn't do it + return progress * 0.6f; +} +@end + +@implementation GTMLargeTypeCopyAnimation +- (void)setCurrentProgress:(NSAnimationProgress)progress { + [super setCurrentProgress:progress]; + [[self delegate] display]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindowTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindowTest.m new file mode 100644 index 00000000..65ea1013 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLargeTypeWindowTest.m @@ -0,0 +1,198 @@ +// +// GTMLargeTypeWindowTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMLargeTypeWindow.h" +#import "GTMNSObject+UnitTesting.h" +#import "GTMUnitTestDevLog.h" +#import "GTMGarbageCollection.h" +#import "GTMSystemVersion.h" + +NSString *const kLongTextBlock = + @"`Twas brillig, and the slithy toves " + "Did gyre and gimble in the wabe: " + "all mimsy were the borogoves, " + "and the mome raths outgrabe. " + "Beware the Jabberwock, my son! " + "The jaws that bite, the claws that catch! " + "Beware the Jubjub bird, and shun " + "the frumious Bandersnatch! " + "He took his vorpal sword in hand: " + "long time the manxome foe he sought -- " + "so rested he by the Tumtum tree, " + "and stood awhile in thought. " + "And, as in uffish thought he stood, " + "the Jabberwock, with eyes of flame, " + "came whiffling through the tulgey wood, " + "and burbled as it came! " + "One, two! One, two! And through and through " + "the vorpal blade went snicker-snack! " + "He left it dead, and with its head " + "he went galumphing back. " + "And, has thou slain the Jabberwock? " + "Come to my arms, my beamish boy! " + "O frabjous day! Callooh! Callay! " + "He chortled in his joy."; + +NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see."; + +NSString *const kShortTextBlock = @"Short"; + +@interface GTMLargeTypeWindowTest : GTMTestCase +@end + +@implementation GTMLargeTypeWindowTest +- (BOOL)shouldDoAnimateCopy { + // NOTE: Animated copy tests are disabled when GC is on. + // See the comment/warning in the GTMLargeTypeWindow.h for more details, + // but we disable them to avoid the tests failing (crashing) when it's Apple's + // bug. Please bump the system check as appropriate when new systems are + // tested. Currently broken on 10.5.6 and below. + // Radar 6137322 CIFilter crashing when run with GC enabled + SInt32 major, minor, bugfix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix]; + if (!(GTMIsGarbageCollectionEnabled() + && major <= 10 && minor <= 5 && bugfix <= 6)) { + return YES; + } else { + NSLog(@"--- animated copy not run because of GC incompatibilites ---"); + return NO; + } +} + +- (void)testLargeTypeWindowIllegalInits { + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"]; + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:@""] autorelease]; + STAssertNil(window, nil); + + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"]; + window = [[[GTMLargeTypeWindow alloc] initWithString:nil] autorelease]; + STAssertNil(window, nil); + + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"]; + NSAttributedString *attrString = [[[NSAttributedString alloc] + initWithString:@""] autorelease]; + window = [[[GTMLargeTypeWindow alloc] + initWithAttributedString:attrString] autorelease]; + STAssertNil(window, nil); + + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"]; + window = [[[GTMLargeTypeWindow alloc] + initWithAttributedString:nil] autorelease]; + STAssertNil(window, nil); + + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty view"]; + window = [[[GTMLargeTypeWindow alloc] initWithContentView:nil] autorelease]; + STAssertNil(window, nil); + + [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty image"]; + window = [[[GTMLargeTypeWindow alloc] initWithImage:nil] autorelease]; + STAssertNil(window, nil); +} + +- (void)testLargeTypeWindowMediumText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kMediumTextBlock] autorelease]; + STAssertNotNil(window, nil); + STAssertTrue([window canBecomeKeyWindow], nil); + [window makeKeyAndOrderFront:nil]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + [[NSRunLoop currentRunLoop] runUntilDate:endDate]; + GTMAssertObjectStateEqualToStateNamed(window, + @"GTMLargeTypeWindowMediumTextTest", + nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kMediumTextBlock, nil); + } + [window keyDown:nil]; +} + +- (void)testLargeTypeWindowShortText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kShortTextBlock] autorelease]; + STAssertNotNil(window, nil); + STAssertTrue([window canBecomeKeyWindow], nil); + [window makeKeyAndOrderFront:nil]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + [[NSRunLoop currentRunLoop] runUntilDate:endDate]; + GTMAssertObjectStateEqualToStateNamed(window, + @"GTMLargeTypeWindowShortTextTest", + nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kShortTextBlock, nil); + } + [window resignKeyWindow]; +} + +- (void)testLargeTypeWindowLongText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kLongTextBlock] autorelease]; + STAssertNotNil(window, nil); + [window orderFront:nil]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + [[NSRunLoop currentRunLoop] runUntilDate:endDate]; + // Can't do state for long text as it will wrap differently on different + // sized screens. + GTMAssertObjectStateEqualToStateNamed(window, + @"GTMLargeTypeWindowLongTextTest", + nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kLongTextBlock, nil); + } + [window keyDown:nil]; +} + +- (void)testLargeTypeWindowImageText { + NSImage *image = [NSApp applicationIconImage]; + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithImage:image] autorelease]; + STAssertNotNil(window, nil); + [window makeKeyAndOrderFront:nil]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + [[NSRunLoop currentRunLoop] runUntilDate:endDate]; + GTMAssertObjectStateEqualToStateNamed(window, + @"GTMLargeTypeWindowImageTest", + nil); + NSString *testString = @"TestString"; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self]; + [pb setString:testString forType:NSStringPboardType]; + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + // Pasteboard should not change for an image + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, testString, nil); + } + [window resignKeyWindow]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.h new file mode 100644 index 00000000..d85a4eb9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.h @@ -0,0 +1,76 @@ +// +// GTMLinearRGBShading.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMShading.h" +#import "GTMCalculatedRange.h" + +/// A shading that does returns smooth linear values for RGB. +// +/// Thus if you create a shading from 0.0->red to 1.0->blue you will get +/// \verbatim +/// - 0.5->purple +/// - 0.75->eggplant +/// - 0.25->magenta +/// \endverbatim + +@interface GTMLinearRGBShading : GTMCalculatedRange { +@private + CGFunctionRef function_; // function used to calculated shading (STRONG) + CGColorSpaceRef colorSpace_; // colorspace used for shading (STRONG) + BOOL isCalibrated_; // are we using calibrated or device RGB. + CGFloat colorValue_[4]; // the RGBA color values +} + +/// Generate a shading with color |begin| at position 0.0 and color |end| at 1.0. +// +// Args: +// begin: color at beginning of range +// end: color at end of range +// colorSpaceName: name of colorspace to draw into must be either +// NSCalibratedRGBColorSpace or NSDeviceRGBColorSpace +// +// Returns: +// a GTMLinearRGBShading ++ (id)shadingFromColor:(NSColor *)begin toColor:(NSColor *)end + fromSpaceNamed:(NSString*)colorSpaceName; + +/// Generate a shading with a collection of colors at various positions. +// +// Args: +// colors: a C style array containg the colors we are adding +// colorSpaceName: name of colorspace to draw into must be either +// NSCalibratedRGBColorSpace or NSDeviceRGBColorSpace +// positions: a C style array containg the positions we want to +// add the colors at +// numberOfColors: how many colors/positions we are adding +// +// Returns: +// a GTMLinearRGBShading ++ (id)shadingWithColors:(NSColor **)colors + fromSpaceNamed:(NSString*)colorSpaceName + atPositions:(CGFloat *)positions + count:(NSUInteger)numberOfColors; + +/// Designated initializer +// Args: +// colorSpaceName - name of the colorspace to use must be either +// NSCalibratedRGBColorSpace or NSDeviceRGBColorSpace +- (id)initWithColorSpaceName:(NSString*)colorSpaceName; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.m new file mode 100644 index 00000000..9434186c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShading.m @@ -0,0 +1,204 @@ +// +// GTMLinearRGBShading.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLinearRGBShading.h" +#import "GTMDefines.h" + +// Carbon callback function required for CoreGraphics +static void cShadeFunction(void *info, const CGFloat *inPos, CGFloat *outVals); + +@implementation GTMLinearRGBShading ++ (id)shadingFromColor:(NSColor *)begin toColor:(NSColor *)end + fromSpaceNamed:(NSString*)colorSpaceName { + NSColor *theColors[] = { begin, end }; + CGFloat thePositions[] = { 0.0, 1.0 }; + return [[self class] shadingWithColors:theColors + fromSpaceNamed:colorSpaceName + atPositions:thePositions + count:(sizeof(thePositions)/sizeof(CGFloat))]; +} + ++ (id)shadingWithColors:(NSColor **)colors fromSpaceNamed:(NSString*)colorSpaceName + atPositions:(CGFloat *)positions count:(NSUInteger)count { + + GTMLinearRGBShading *theShading = [[[[self class] alloc] initWithColorSpaceName:colorSpaceName] autorelease]; + for (NSUInteger i = 0; i < count; ++i) { + [theShading insertStop:colors[i] atPosition:positions[i]]; + } + return theShading; +} + +- (id)initWithColorSpaceName:(NSString*)colorSpaceName { + if ((self = [super init])) { + if ([colorSpaceName isEqualToString:NSDeviceRGBColorSpace]) { + isCalibrated_ = NO; + } else if ([colorSpaceName isEqualToString:NSCalibratedRGBColorSpace]) { + isCalibrated_ = YES; + } + else { + [self release]; + self = nil; + } + } + return self; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + if (nil != function_) { + CGFunctionRelease(function_); + } + if (nil != colorSpace_) { + CGColorSpaceRelease(colorSpace_); + } + [super finalize]; +} +#endif + +- (void)dealloc { + if (nil != function_) { + CGFunctionRelease(function_); + } + if (nil != colorSpace_) { + CGColorSpaceRelease(colorSpace_); + } + [super dealloc]; +} + + +- (void)insertStop:(id)item atPosition:(CGFloat)position { + NSString *colorSpaceName = isCalibrated_ ? NSCalibratedRGBColorSpace : NSDeviceRGBColorSpace; + NSColor *tempColor = [item colorUsingColorSpaceName: colorSpaceName]; + if (nil != tempColor) { + [super insertStop:tempColor atPosition:position]; + } +} + +// Calculate a linear value based on our stops +- (id)valueAtPosition:(CGFloat)position { + NSUInteger positionIndex = 0; + NSUInteger colorCount = [self stopCount]; + CGFloat stop1Position = 0.0; + NSColor *stop1Color = [self stopAtIndex:positionIndex position:&stop1Position]; + positionIndex += 1; + CGFloat stop2Position = 0.0; + NSColor *stop2Color = nil; + if (colorCount > 1) { + stop2Color = [self stopAtIndex:positionIndex position:&stop2Position]; + positionIndex += 1; + } else { + // if we only have one value, that's what we return + stop2Position = stop1Position; + stop2Color = stop1Color; + } + + while (positionIndex < colorCount && stop2Position < position) { + stop1Color = stop2Color; + stop1Position = stop2Position; + stop2Color = [self stopAtIndex:positionIndex position:&stop2Position]; + positionIndex += 1; + } + + if (position <= stop1Position) { + // if we are less than our lowest position, return our first color + [stop1Color getRed:&colorValue_[0] green:&colorValue_[1] + blue:&colorValue_[2] alpha:&colorValue_[3]]; + } else if (position >= stop2Position) { + // likewise if we are greater than our highest position, return the last color + [stop2Color getRed:&colorValue_[0] green:&colorValue_[1] + blue:&colorValue_[2] alpha:&colorValue_[3]]; + } else { + // otherwise interpolate between the two + position = (position - stop1Position) / (stop2Position - stop1Position); + CGFloat red1, red2, green1, green2, blue1, blue2, alpha1, alpha2; + [stop1Color getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1]; + [stop2Color getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2]; + + colorValue_[0] = (red2 - red1) * position + red1; + colorValue_[1] = (green2 - green1) * position + green1; + colorValue_[2] = (blue2 - blue1) * position + blue1; + colorValue_[3] = (alpha2 - alpha1) * position + alpha1; + } + + // Yes, I am casting a CGFloat[] to an id to pass it by the compiler. This + // significantly improves performance though as I avoid creating an NSColor + // for every scanline which later has to be cleaned up in an autorelease pool + // somewhere. Causes guardmalloc to run significantly faster. + return (id)colorValue_; +} + +// +// switch from C to obj-C. The callback to a shader is a c function +// but we want to call our objective c object to do all the +// calculations for us. We have passed our function our +// GTMLinearRGBShading as an obj-c object in the |info| so +// we just turn around and ask it to calculate our value based +// on |inPos| and then stick the results back in |outVals| +// +// Args: +// info: is the GTMLinearRGBShading as an +// obj-C object. +// inPos: the position to calculate values for. This is a pointer to +// a single float value +// outVals: where we store our return values. Since we are calculating +// an RGBA color, this is a pointer to an array of four float values +// ranging from 0.0 to 1.0 +// +// +static void cShadeFunction(void *info, const CGFloat *inPos, CGFloat *outVals) { + id object = (id)info; + CGFloat *colorValue = (CGFloat*)[object valueAtPosition:*inPos]; + outVals[0] = colorValue[0]; + outVals[1] = colorValue[1]; + outVals[2] = colorValue[2]; + outVals[3] = colorValue[3]; +} + +- (CGFunctionRef) shadeFunction { + // lazily create the function as necessary + if (nil == function_) { + // We have to go to carbon here, and create the CGFunction. Note that this + // diposed if necessary in the dealloc call. + const CGFunctionCallbacks shadeFunctionCallbacks = { 0, &cShadeFunction, NULL }; + + // TODO: this code assumes that we have a range from 0.0 to 1.0 + // which may not be true according to the stops that the user has given us. + // In general you have stops at 0.0 and 1.0, so this will do for right now + // but may be an issue in the future. + const CGFloat inRange[2] = { 0.0, 1.0 }; + const CGFloat outRange[8] = { 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 }; + function_ = CGFunctionCreate(self, + sizeof(inRange) / (sizeof(CGFloat) * 2), inRange, + sizeof(outRange) / (sizeof(CGFloat) * 2), outRange, + &shadeFunctionCallbacks); + } + return function_; +} + +- (CGColorSpaceRef)colorSpace { + // lazily create the colorspace as necessary + if (nil == colorSpace_) { + if (isCalibrated_) { + colorSpace_ = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + } else { + colorSpace_ = CGColorSpaceCreateDeviceRGB(); + } + } + return colorSpace_; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShadingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShadingTest.m new file mode 100644 index 00000000..38802e60 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLinearRGBShadingTest.m @@ -0,0 +1,132 @@ +// +// GTMLinearRGBShadingTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMSenTestCase.h" +#import "GTMLinearRGBShading.h" + +@interface GTMLinearRGBShadingTest : GTMTestCase +@end + +@implementation GTMLinearRGBShadingTest +- (void)testShadingFrom { + // Create a shading from red to blue, and check if 50% is purple + NSColor *red = [NSColor redColor]; + NSColor *blue = [NSColor blueColor]; + NSColor *purple = [NSColor purpleColor]; + GTMLinearRGBShading *theShading = + [GTMLinearRGBShading shadingFromColor:red + toColor:blue + fromSpaceNamed:NSCalibratedRGBColorSpace]; + STAssertNotNil(theShading,nil); + STAssertEquals([theShading stopCount], (NSUInteger)2, nil); + CGFloat *theColor = (CGFloat*)[theShading valueAtPosition: 0.5]; + STAssertEqualsWithAccuracy(theColor[0], [purple redComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[1], [purple greenComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[2], [purple blueComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[3], [purple alphaComponent], 0.001, nil); +} + +- (void)testShadingWith { + // Create a shading with kColorCount colors and make sure all the values are there. + enum { kColorCount = 100 }; + NSColor *theColors[kColorCount]; + CGFloat thePositions[kColorCount]; + const CGFloat kColorIncrement = 1.0 / kColorCount; + for (NSUInteger i = 0; i < kColorCount; i++) { + CGFloat newValue = kColorIncrement * i; + thePositions[i] = newValue; + theColors[i] = [NSColor colorWithCalibratedRed:newValue + green:newValue + blue:newValue + alpha:newValue]; + } + GTMLinearRGBShading *theShading = + [GTMLinearRGBShading shadingWithColors:theColors + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:thePositions + count:kColorCount]; + for (NSUInteger i = 0; i < kColorCount; i++) { + CGFloat newValue = kColorIncrement * i; + CGFloat *theColor = (CGFloat*)[theShading valueAtPosition:newValue]; + STAssertEqualsWithAccuracy(theColor[0], newValue, 0.001, nil); + STAssertEqualsWithAccuracy(theColor[1], newValue, 0.001, nil); + STAssertEqualsWithAccuracy(theColor[2], newValue, 0.001, nil); + STAssertEqualsWithAccuracy(theColor[3], newValue, 0.001, nil); + } + // Create a shading with 1 color to test that special handling + NSColor *purple = [NSColor purpleColor]; + NSColor *singleColor[1] = { purple }; + CGFloat singlePosition[1] = { 0.5 }; + theShading = + [GTMLinearRGBShading shadingWithColors:singleColor + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:singlePosition + count:1]; + // test over a range to make sure we always get the same color + for (NSUInteger i = 0; i < kColorCount; i++) { + CGFloat newValue = kColorIncrement * i; + CGFloat *theColor = (CGFloat*)[theShading valueAtPosition:newValue]; + STAssertEqualsWithAccuracy(theColor[0], [purple redComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[1], [purple greenComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[2], [purple blueComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[3], [purple alphaComponent], 0.001, nil); + } +} + +- (void)testShadeFunction { + GTMLinearRGBShading *theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:nil + count:0]; + CGFunctionRef theFunction = [theShading shadeFunction]; + STAssertNotNULL(theFunction, nil); + STAssertEquals(CFGetTypeID(theFunction), CGFunctionGetTypeID(), nil); +} + +- (void)testColorSpace { + // Calibrated RGB + GTMLinearRGBShading *theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:nil + count:0]; + CGColorSpaceRef theColorSpace = [theShading colorSpace]; + STAssertNotNULL(theColorSpace, nil); + STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil); + + // Device RGB + theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSDeviceRGBColorSpace + atPositions:nil + count:0]; + theColorSpace = [theShading colorSpace]; + STAssertNotNULL(theColorSpace, nil); + STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil); + + // Device CMYK (not supported) + theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSDeviceCMYKColorSpace + atPositions:nil + count:0]; + STAssertNULL(theShading, nil); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.h new file mode 100644 index 00000000..b4375b4c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.h @@ -0,0 +1,88 @@ +// +// GTMLoginItems.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +/// Login items key constants, used as keys in |+loginItems| +// +// Item name +GTM_EXTERN NSString * const kGTMLoginItemsNameKey; +// Item path +GTM_EXTERN NSString * const kGTMLoginItemsPathKey; +// Hidden (NSNumber bool) +GTM_EXTERN NSString * const kGTMLoginItemsHiddenKey; + +/// GTMLoginItems +// +/// A helper class to manipulate the user's Login Items. +@interface GTMLoginItems : NSObject + +/// Obtain a complete list of all login items. +// +// Returns: +// Autoreleased array of dictionaries keyed with kGTMLoginItemsPathKey, etc. +// ++ (NSArray *)loginItems:(NSError **)errorInfo; + +/// Check if the given path is in the current user's Login Items +// +// Args: +// path: path to the application +// +// Returns: +// YES if the path is in the Login Items +// ++ (BOOL)pathInLoginItems:(NSString *)path; + +/// Check if the given name is in the current user's Login Items +// +// Args: +// name: name to the application +// +// Returns: +// YES if the name is in the Login Items +// ++ (BOOL)itemWithNameInLoginItems:(NSString *)name; + +/// Add the given path to the current user's Login Items. Does nothing if the +/// path is already there. +// +// Args: +// path: path to add +// hide: Set to YES to have the item launch hidden +// ++ (void)addPathToLoginItems:(NSString *)path hide:(BOOL)hide; + +/// Remove the given path from the current user's Login Items. Does nothing if +/// the path is not there. +// +// Args: +// path: the path to remove +// ++ (void)removePathFromLoginItems:(NSString *)path; + +/// Remove the given item name from the current user's Login Items. Does nothing +/// if no item with that name is present. +// +// Args: +// name: name of the item to remove +// ++ (void)removeItemWithNameFromLoginItems:(NSString *)name; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.m new file mode 100644 index 00000000..f124ef50 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.m @@ -0,0 +1,193 @@ +// +// GTMLoginItems.m +// Based on AELoginItems from DTS. +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLoginItems.h" +#import "GTMDefines.h" + +#include + +// Exposed constants +NSString * const kGTMLoginItemsNameKey = @"Name"; +NSString * const kGTMLoginItemsPathKey = @"Path"; +NSString * const kGTMLoginItemsHiddenKey = @"Hide"; + +@interface GTMLoginItems (PrivateMethods) ++ (NSInteger)indexOfLoginItemWithValue:(id)value + forKey:(NSString *)key + loginItems:(NSArray *)items; ++ (BOOL)compileAndRunScript:(NSString *)script + withError:(NSError **)errorInfo; +@end + +@implementation GTMLoginItems (PrivateMethods) + ++ (NSInteger)indexOfLoginItemWithValue:(id)value + forKey:(NSString *)key + loginItems:(NSArray *)items { + if (!value || !key || !items) return NSNotFound; + NSDictionary *item = nil; + NSInteger found = -1; + GTM_FOREACH_OBJECT(item, items) { + ++found; + id itemValue = [item objectForKey:key]; + if (itemValue && [itemValue isEqual:value]) { + return found; + } + } + return NSNotFound; +} + ++ (BOOL)compileAndRunScript:(NSString *)script + withError:(NSError **)errorInfo { + if ([script length] == 0) { + // COV_NF_START - no real way to test this + if (errorInfo) + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-90 userInfo:nil]; + return NO; + // COV_NF_END + } + NSAppleScript *query = [[[NSAppleScript alloc] initWithSource:script] autorelease]; + NSDictionary *errDict = nil; + if ( ![query compileAndReturnError:&errDict]) { + // COV_NF_START - no real way to test this + if (errorInfo) + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-91 userInfo:errDict]; + return NO; + // COV_NF_END + } + NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict]; + if (!scriptResult) { + // COV_NF_START - no real way to test this + if (errorInfo) + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-92 userInfo:errDict]; + return NO; + // COV_NF_END + } + // we don't process the result + return YES; +} + +@end + +@implementation GTMLoginItems + ++ (NSArray*)loginItems:(NSError **)errorInfo { + NSDictionary *errDict = nil; + // get the script compiled and saved off + static NSAppleScript *query = nil; + if (!query) { + NSString *querySource = @"tell application \"System Events\" to get properties of login items"; + query = [[NSAppleScript alloc] initWithSource:querySource]; + if ( ![query compileAndReturnError:&errDict]) { + // COV_NF_START - no real way to test this + if (errorInfo) + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-1 userInfo:errDict]; + [query release]; + query = nil; + return nil; + // COV_NF_END + } + } + // run the script + NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict]; + if (!scriptResult) { + // COV_NF_START - no real way to test this + if (errorInfo) + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-2 userInfo:errDict]; + return nil; + // COV_NF_END + } + // build our results + NSMutableArray *result = [NSMutableArray array]; + NSInteger count = [scriptResult numberOfItems]; + for (NSInteger i = 0; i < count; ++i) { + NSAppleEventDescriptor *aeItem = [scriptResult descriptorAtIndex:i+1]; + NSAppleEventDescriptor *hidn = [aeItem descriptorForKeyword:kAEHidden]; + NSAppleEventDescriptor *nam = [aeItem descriptorForKeyword:pName]; + NSAppleEventDescriptor *ppth = [aeItem descriptorForKeyword:'ppth']; + NSMutableDictionary *item = [NSMutableDictionary dictionary]; + if (hidn && [hidn booleanValue]) { + [item setObject:[NSNumber numberWithBool:YES] forKey:kGTMLoginItemsHiddenKey]; + } + if (nam) { + NSString *name = [nam stringValue]; + if (name) { + [item setObject:name forKey:kGTMLoginItemsNameKey]; + } + } + if (ppth) { + NSString *path = [ppth stringValue]; + if (path) { + [item setObject:path forKey:kGTMLoginItemsPathKey]; + } + } + [result addObject:item]; + } + + return result; +} + ++ (BOOL)pathInLoginItems:(NSString *)path { + NSArray *loginItems = [self loginItems:nil]; + NSInteger itemIndex = [self indexOfLoginItemWithValue:path + forKey:kGTMLoginItemsPathKey + loginItems:loginItems]; + return (itemIndex != NSNotFound) ? YES : NO; +} + ++ (BOOL)itemWithNameInLoginItems:(NSString *)name { + NSArray *loginItems = [self loginItems:nil]; + NSInteger itemIndex = [self indexOfLoginItemWithValue:name + forKey:kGTMLoginItemsNameKey + loginItems:loginItems]; + return (itemIndex != NSNotFound) ? YES : NO; +} + ++ (void)addPathToLoginItems:(NSString*)path hide:(BOOL)hide { + if (!path) return; + // make sure it isn't already there + if ([self pathInLoginItems:path]) return; + // now append it + NSString *scriptSource = + [NSString stringWithFormat: + @"tell application \"System Events\" to make new login item with properties { path:\"%s\", hidden:%s } at end", + [path UTF8String], + (hide ? "yes" : "no")]; + [self compileAndRunScript:scriptSource withError:nil]; +} + ++ (void)removePathFromLoginItems:(NSString*)path { + if ([path length] == 0) return; + NSString *scriptSource = + [NSString stringWithFormat: + @"tell application \"System Events\" to delete (login items whose path is \"%s\")", + [path UTF8String]]; + [self compileAndRunScript:scriptSource withError:nil]; +} + ++ (void)removeItemWithNameFromLoginItems:(NSString *)name { + if ([name length] == 0) return; + NSString *scriptSource = + [NSString stringWithFormat: + @"tell application \"System Events\" to delete (login items whose name is \"%s\")", + [name UTF8String]]; + [self compileAndRunScript:scriptSource withError:nil]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItemsTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItemsTest.m new file mode 100644 index 00000000..50b74820 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMLoginItemsTest.m @@ -0,0 +1,137 @@ +// +// GTMLoginItemsTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMSenTestCase.h" +#import "GTMLoginItems.h" + + // we don't really run this test because if someone had it in some automated + // tests, then if something did fail, it could leave things in the login items + // on the computer which could be a nasty surprise. +#define MODIFICATION_TESTS_ENABLED 0 + + +@interface GTMLoginItemsTest : GTMTestCase +@end + +static BOOL ItemsListHasPath(NSArray *items, NSString *path) { + NSDictionary *item = nil; + GTM_FOREACH_OBJECT(item, items) { + NSString *itemPath = [item objectForKey:kGTMLoginItemsPathKey]; + if (itemPath && [itemPath isEqual:path]) { + return YES; + } + } + return NO; +} + +@implementation GTMLoginItemsTest + +- (void)testNoModification { + + NSError *error = nil; + NSString *bogusAppPath = @"/Applications/AppThatDoesNotExist.app"; + NSString *bogusAppName = @"AppThatDoesNotExist"; + + // fetch the starting values + NSArray *initialItems = [GTMLoginItems loginItems:&error]; + STAssertNotNil(initialItems, @"shouldn't be nil (%@)", error); + STAssertFalse(ItemsListHasPath(initialItems, bogusAppPath), + @"bogusApp shouldn't be in list to start for test (%@)", initialItems); + + // check by path + STAssertFalse([GTMLoginItems pathInLoginItems:bogusAppPath], nil); + + // check by name + STAssertFalse([GTMLoginItems itemWithNameInLoginItems:bogusAppName], nil); + + // remove it by path + [GTMLoginItems removePathFromLoginItems:bogusAppPath]; + NSArray *curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + + // remove it by name + [GTMLoginItems removeItemWithNameFromLoginItems:bogusAppName]; + curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + +} + +- (void)testModification { + +#if MODIFICATION_TESTS_ENABLED + + NSError *error = nil; + NSString *textEditPath = @"/Applications/TextEdit.app"; + NSString *textEditName = @"TextEdit"; + + // fetch the starting values + NSArray *initialItems = [GTMLoginItems loginItems:&error]; + STAssertNotNil(initialItems, @"shouldn't be nil (%@)", error); + STAssertFalse(ItemsListHasPath(initialItems, textEditPath), + @"textedit shouldn't be in list to start for test (%@)", initialItems); + + // add textedit + [GTMLoginItems addPathToLoginItems:textEditPath hide:NO]; + NSArray *curItems = [GTMLoginItems loginItems:nil]; + STAssertNotEqualObjects(initialItems, curItems, nil); + + // check by path + STAssertTrue([GTMLoginItems pathInLoginItems:textEditPath], nil); + + // check by name + STAssertTrue([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); + + // remove it by path + [GTMLoginItems removePathFromLoginItems:textEditPath]; + curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + + // check by path + STAssertFalse([GTMLoginItems pathInLoginItems:textEditPath], nil); + + // check by name + STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); + + // add textedit + [GTMLoginItems addPathToLoginItems:textEditPath hide:NO]; + curItems = [GTMLoginItems loginItems:nil]; + STAssertNotEqualObjects(initialItems, curItems, nil); + + // check by path + STAssertTrue([GTMLoginItems pathInLoginItems:textEditPath], nil); + + // check by name + STAssertTrue([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); + + // remove it by name + [GTMLoginItems removeItemWithNameFromLoginItems:textEditName]; + curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + + // check by path + STAssertFalse([GTMLoginItems pathInLoginItems:textEditPath], nil); + + // check by name + STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); + +#endif // MODIFICATION_TESTS_ENABLED + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.h new file mode 100644 index 00000000..a1b022ed --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.h @@ -0,0 +1,33 @@ +// +// GTMNSBezierPath+CGPath.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Category for extracting a CGPathRef from a NSBezierPath +@interface NSBezierPath (GTMBezierPathCGPathAdditions) + +/// Extract a CGPathRef from a NSBezierPath. +// +// Args: +// +// Returns: +// Converted autoreleased CGPathRef. +// nil if failure. +- (CGPathRef)gtm_CGPath; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.m new file mode 100644 index 00000000..3624d9eb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPath.m @@ -0,0 +1,70 @@ +// +// GTMNSBezierPath+CGPath.m +// +// Category for extracting a CGPathRef from a NSBezierPath +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// +#import "GTMNSBezierPath+CGPath.h" +#import "GTMDefines.h" +#import "GTMGarbageCollection.h" + +@implementation NSBezierPath (GTMBezierPathCGPathAdditions) + +// Extract a CGPathRef from a NSBezierPath. +// +// Args: +// +// Returns: +// Converted CGPathRef. +// nil if failure. +- (CGPathRef)gtm_CGPath { + CGMutablePathRef thePath = CGPathCreateMutable(); + if (!thePath) return nil; + + NSInteger elementCount = [self elementCount]; + + // The maximum number of points is 3 for a NSCurveToBezierPathElement. + // (controlPoint1, controlPoint2, and endPoint) + NSPoint controlPoints[3]; + + for (NSInteger i = 0; i < elementCount; i++) { + switch ([self elementAtIndex:i associatedPoints:controlPoints]) { + case NSMoveToBezierPathElement: + CGPathMoveToPoint(thePath, &CGAffineTransformIdentity, + controlPoints[0].x, controlPoints[0].y); + break; + case NSLineToBezierPathElement: + CGPathAddLineToPoint(thePath, &CGAffineTransformIdentity, + controlPoints[0].x, controlPoints[0].y); + break; + case NSCurveToBezierPathElement: + CGPathAddCurveToPoint(thePath, &CGAffineTransformIdentity, + controlPoints[0].x, controlPoints[0].y, + controlPoints[1].x, controlPoints[1].y, + controlPoints[2].x, controlPoints[2].y); + break; + case NSClosePathBezierPathElement: + CGPathCloseSubpath(thePath); + break; + default: // COV_NF_START + _GTMDevLog(@"Unknown element at [NSBezierPath (GTMBezierPathCGPathAdditions) cgPath]"); + break; // COV_NF_END + }; + } + return (CGPathRef)GTMCFAutorelease(thePath); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPathTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPathTest.m new file mode 100644 index 00000000..3c99a19c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+CGPathTest.m @@ -0,0 +1,75 @@ +// +// GTMNSBezierPath+CGPathTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import +#import "GTMNSBezierPath+CGPath.h" +#import "GTMAppKit+UnitTesting.h" +#import "GTMSenTestCase.h" + +@interface GTMNSBezierPath_CGPathTest : GTMTestCase +@end + +@implementation GTMNSBezierPath_CGPathTest + +- (void)testCGPath { + GTMAssertDrawingEqualToImageNamed(self, + NSMakeSize(100, 100), + @"GTMNSBezierPath+CGPathTest", + nil, nil); +} + + +// Draws all of our tests so that we can compare this to our stored image file. +- (void)gtm_unitTestViewDrawRect:(NSRect)rect contextInfo:(void*)contextInfo{ + NSBezierPath *thePath = [NSBezierPath bezierPath]; + NSPoint theStart = NSMakePoint(20.0, 20.0); + + // Test moveto/lineto + [thePath moveToPoint: theStart]; + for (NSUInteger i = 0; i < 10; ++i) { + NSPoint theNewPoint = NSMakePoint(i * 5, i * 10); + [thePath lineToPoint: theNewPoint]; + theNewPoint = NSMakePoint(i * 2, i * 6); + [thePath moveToPoint: theNewPoint]; + } + + // Test moveto/curveto + for (NSUInteger i = 0; i < 10; ++i) { + NSPoint startPoint = NSMakePoint(5.0, 50.0); + NSPoint endPoint = NSMakePoint(55.0, 50.0); + NSPoint controlPoint1 = NSMakePoint(17.5, 50.0 + 5.0 * i); + NSPoint controlPoint2 = NSMakePoint(42.5, 50.0 - 5.0 * i); + [thePath moveToPoint:startPoint]; + [thePath curveToPoint:endPoint controlPoint1:controlPoint1 controlPoint2:controlPoint2]; + } + // test close + [thePath closePath]; + + CGPathRef cgPath = [thePath gtm_CGPath]; + STAssertNotNULL(cgPath, @"Nil CGPath"); + + CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; + STAssertNotNULL(cgContext, @"Nil cgContext"); + + CGContextAddPath(cgContext, cgPath); + CGContextStrokePath(cgContext); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.h new file mode 100644 index 00000000..b0b48de5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.h @@ -0,0 +1,48 @@ +// +// GTMNSBezierPath+RoundRect.h +// +// Category for adding utility functions for creating +// round rectangles. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +/// Category for adding utility functions for creating round rectangles. +@interface NSBezierPath (GMBezierPathRoundRectAdditions) + +/// Inscribe a round rectangle inside of rectangle |rect| with a corner radius of |radius| +// +// Args: +// rect: outer rectangle to inscribe into +// radius: radius of the corners. |radius| is clamped internally +// to be no larger than the smaller of half |rect|'s width or height +// +// Returns: +// Auto released NSBezierPath ++ (NSBezierPath *)gtm_bezierPathWithRoundRect:(NSRect)rect + cornerRadius:(CGFloat)radius; + +/// Adds a path which is a round rectangle inscribed inside of rectangle |rect| with a corner radius of |radius| +// +// Args: +// rect: outer rectangle to inscribe into +// radius: radius of the corners. |radius| is clamped internally +// to be no larger than the smaller of half |rect|'s width or height +- (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect + cornerRadius:(CGFloat)radius; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.m new file mode 100644 index 00000000..d4e5050d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRect.m @@ -0,0 +1,68 @@ +// +// GTMNSBezierPath+RoundRect.h +// +// Category for adding utility functions for creating +// round rectangles. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSBezierPath+RoundRect.h" + +@implementation NSBezierPath (GTMBezierPathRoundRectAdditions) + + ++ (NSBezierPath *)gtm_bezierPathWithRoundRect:(NSRect)rect + cornerRadius:(CGFloat)radius { + NSBezierPath *bezier = [NSBezierPath bezierPath]; + [bezier gtm_appendBezierPathWithRoundRect:rect cornerRadius:radius]; + return bezier; +} + + +- (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect + cornerRadius:(CGFloat)radius { + if (!NSIsEmptyRect(rect)) { + if (radius > 0.0) { + // Clamp radius to be no larger than half the rect's width or height. + radius = MIN(radius, 0.5 * MIN(rect.size.width, rect.size.height)); + + NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); + NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); + NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); + + [self moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))]; + [self appendBezierPathWithArcFromPoint:topLeft + toPoint:rect.origin + radius:radius]; + [self appendBezierPathWithArcFromPoint:rect.origin + toPoint:bottomRight + radius:radius]; + [self appendBezierPathWithArcFromPoint:bottomRight + toPoint:topRight + radius:radius]; + [self appendBezierPathWithArcFromPoint:topRight + toPoint:topLeft + radius:radius]; + [self closePath]; + } else { + // When radius <= 0.0, use plain rectangle. + [self appendBezierPathWithRect:rect]; + } + } +} + + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRectTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRectTest.m new file mode 100644 index 00000000..5bdf3a38 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+RoundRectTest.m @@ -0,0 +1,102 @@ +// +// GTMNSBezierPath+RoundRectTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import +#import "GTMNSBezierPath+RoundRect.h" +#import "GTMAppKit+UnitTesting.h" + +@interface GTMNSBezierPath_RoundRectTest : GTMTestCase +@end + +@implementation GTMNSBezierPath_RoundRectTest + +- (void)testRoundRects { + GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(490, 430), + @"GTMNSBezierPath+RoundRectTest", nil, nil); +} + +// Draws all of our tests so that we can compare this to our stored TIFF file. +- (void)gtm_unitTestViewDrawRect:(NSRect)rect contextInfo:(void*)contextInfo{ + NSRect theRects[] = { + NSMakeRect(0.0, 10.0, 0.0, 0.0), //Empty Rect test + NSMakeRect(50.0, 10.0, 30.0, 30.0), //Square Test + NSMakeRect(100.0, 10.0, 1.0, 2.0), //Small Test + NSMakeRect(120.0, 10.0, 15.0, 20.0), //Medium Test + NSMakeRect(140.0, 10.0, 150.0, 30.0), //Large Test + NSMakeRect(300.0, 10.0, 150.0, 30.0) //Large Test 2 (for different radius) + }; + const NSUInteger theRectCount = sizeof(theRects) / sizeof(NSRect); + + // Line Width Tests + CGFloat theLineWidths[] = { 0.5, 50.0, 2.0 }; + const NSUInteger theLineWidthCount = sizeof(theLineWidths) / sizeof(CGFloat); + NSUInteger i,j; + + for (i = 0; i < theLineWidthCount; ++i) { + for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 20.0 : 0.0 ); + NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] + cornerRadius:cornerRadius]; + [roundRect setLineWidth: theLineWidths[i]]; + [roundRect stroke]; + CGFloat newWidth = 35.0; + if (i < theLineWidthCount - 1) { + newWidth += theLineWidths[i + 1] + theLineWidths[i]; + } + theRects[j].origin.y += newWidth; + } + } + + // Fill test + NSColor *theColors[] = { + [NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:1.0], + [NSColor colorWithCalibratedRed:0.2 green:0.4 blue:0.6 alpha:0.4] + }; + const NSUInteger theColorCount = sizeof(theColors)/sizeof(NSColor); + + for (i = 0; i < theColorCount; ++i) { + for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 10.0 : 0.0 ); + NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] + cornerRadius:cornerRadius]; + [theColors[i] setFill]; + [roundRect fill]; + theRects[j].origin.y += 35.0; + } + } + + // Flatness test + CGFloat theFlatness[] = {0.0, 0.1, 1.0, 10.0}; + const NSUInteger theFlatnessCount = sizeof(theFlatness)/sizeof(CGFloat); + + for (i = 0; i < theFlatnessCount; i++) { + for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 6.0 : 0.0 ); + NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] + cornerRadius:cornerRadius]; + [roundRect setFlatness:theFlatness[i]]; + [roundRect stroke]; + theRects[j].origin.y += 35.0; + } + } +} + + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.h new file mode 100644 index 00000000..5d687282 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.h @@ -0,0 +1,121 @@ +// +// GTMNSBezierPath+Shading.h +// +// Category for radial and axial stroke and fill functions for NSBezierPaths +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +@protocol GTMShading; + +// +/// Category for radial and axial stroke and fill functions for NSBezierPaths +// +@interface NSBezierPath (GTMBezierPathShadingAdditions) + +/// Stroke the path axially with a color blend defined by |shading|. +// +/// The fill will extend from |fromPoint| to |toPoint| and will extend +/// indefinitely perpendicular to the axis of the line defined by the +/// two points. You can extend beyond the |fromPoint|/|toPoint by setting +/// |extendingStart|/|extendingEnd| respectively. +// +// Args: +// fromPoint: point to start the shading at +// toPoint: point to end the shading at +// extendingStart: should we extend the shading before |fromPoint| using +// the first color in our shading? +// extendingEnd: should we extend the shading after |toPoint| using the +// last color in our shading? +// shading: the shading to use to take our colors from. +// +- (void)gtm_strokeAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading; + +/// Stroke the path radially with a color blend defined by |shading|. +// +/// The fill will extend from the circle with center |fromPoint| +/// and radius |fromRadius| to the circle with center |toPoint| +/// with radius |toRadius|. +/// You can extend beyond the |fromPoint|/|toPoint| by setting +/// |extendingStart|/|extendingEnd| respectively. +// +// Args: +// fromPoint: center of the circle to start the shading at +// fromRadius: radius of the circle to start the shading at +// toPoint: center of the circle to to end the shading at +// toRadius: raidus of the circle to end the shading at +// extendingStart: should we extend the shading before |fromPoint| using +// the first color in our shading? +// extendingEnd: should we extend the shading after |toPoint| using the +// last color in our shading? +// shading: the shading to use to take our colors from. +// +- (void)gtm_strokeRadiallyFrom:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading; + +/// Fill the path radially with a color blend defined by |shading|. +// +/// The fill will extend from the circle with center |fromPoint| +/// and radius |fromRadius| to the circle with center |toPoint| +/// with radius |toRadius|. +/// You can extend beyond the |fromPoint|/|toPoint by setting +/// |extendingStart|/|extendingEnd| respectively. +// +// Args: +// fromPoint: center of the circle to start the shading at +// fromRadius: radius of the circle to start the shading at +// toPoint: center of the circle to to end the shading at +// toRadius: radius of the circle to end the shading at +// extendingStart: should we extend the shading before |fromPoint| using +// the first color in our shading? +// extendingEnd: should we extend the shading after |toPoint| using the +// last color in our shading? +// shading: the shading to use to take our colors from. +// +- (void)gtm_fillAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading; + +/// Fill the path radially with a color blend defined by |shading|. +// +/// The fill will extend from the circle with center |fromPoint| +/// and radius |fromRadius| to the circle with center |toPoint| +/// with radius |toRadius|. +/// You can extend beyond the |fromPoint|/|toPoint by setting +/// |extendingStart|/|extendingEnd| respectively. +// +// Args: +// fromPoint: center of the circle to start the shading at +// fromRadius: radius of the circle to start the shading at +// toPoint: center of the circle to to end the shading at +// toRadius: radius of the circle to end the shading at +// extendingStart: should we extend the shading before |fromPoint| using +// the first color in our shading? +// extendingEnd: should we extend the shading after |toPoint| using the +// last color in our shading? +// shading: the shading to use to take our colors from. +// +- (void)gtm_fillRadiallyFrom:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.m new file mode 100644 index 00000000..d4c1ddd3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+Shading.m @@ -0,0 +1,216 @@ +// +// GTMNSBezierPath+Shading.m +// +// Category for radial and axial stroke and fill functions for NSBezierPaths +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSBezierPath+Shading.h" +#import "GTMNSBezierPath+CGPath.h" +#import "GTMShading.h" +#import "GTMGeometryUtils.h" +#import "GTMMethodCheck.h" + +@interface NSBezierPath (GTMBezierPathShadingAdditionsPrivate) +// Fills a CGPathRef either axially or radially with the given shading. +// +// Args: +// path: path to fill +// axially: if YES fill axially, otherwise fill radially +// asStroke: if YES, clip to the stroke of the path, otherwise +// clip to the fill +// from: where to shade from +// fromRadius: in a radial fill, the radius of the from circle +// to: where to shade to +// toRadius: in a radial fill, the radius of the to circle +// extendingStart: if true, extend the fill with the first color of the shade +// beyond |from| away from |to| +// extendingEnd: if true, extend the fill with the last color of the shade +// beyond |to| away from |from| +// shading: the shading to use for the fill +// +- (void)gtm_fillCGPath:(CGPathRef)path + axially:(BOOL)axially + asStroke:(BOOL)asStroke + from:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading; + +// Returns the point which is the projection of a line from point |pointA| +// to |pointB| by length +// +// Args: +// pointA: first point +// pointB: second point +// length: distance to project beyond |pointB| which is in line with +// |pointA| and |pointB| +// +// Returns: +// the projected point +- (NSPoint)gtm_projectLineFrom:(NSPoint)pointA + to:(NSPoint)pointB + by:(CGFloat)length; +@end + + +@implementation NSBezierPath (GTMBezierPathAdditionsPrivate) + +- (void)gtm_fillCGPath:(CGPathRef)path + axially:(BOOL)axially asStroke:(BOOL)asStroke + from:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading { + CGFunctionRef shadingFunction = [shading shadeFunction]; + if (nil != shadingFunction) { + CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + if (nil != currentContext) { + CGContextSaveGState(currentContext); + CGFloat lineWidth = [self lineWidth]; + CGContextSetLineWidth(currentContext, lineWidth); + if (asStroke) { + // if we are using the stroke, we offset the from and to points + // by half the stroke width away from the center of the stroke. + // Otherwise we tend to end up with fills that only cover half of the + // because users set the start and end points based on the center + // of the stroke. + CGFloat halfWidth = lineWidth * 0.5; + fromPoint = [self gtm_projectLineFrom:toPoint to:fromPoint by:halfWidth]; + toPoint = [self gtm_projectLineFrom:fromPoint to:toPoint by:-halfWidth]; + } + CGColorSpaceRef colorspace = [shading colorSpace]; + if (nil != colorspace) { + CGPoint toCGPoint = GTMNSPointToCGPoint(toPoint); + CGPoint fromCGPoint = GTMNSPointToCGPoint(fromPoint); + CGShadingRef myCGShading; + if(axially) { + myCGShading = CGShadingCreateAxial(colorspace, fromCGPoint, + toCGPoint, shadingFunction, + extendingStart == YES, + extendingEnd == YES); + } + else { + myCGShading = CGShadingCreateRadial(colorspace, fromCGPoint, fromRadius, + toCGPoint, toRadius, shadingFunction, + extendingStart == YES, + extendingEnd == YES); + } + + if (nil != myCGShading) { + CGContextAddPath(currentContext,path); + if(asStroke) { + CGContextReplacePathWithStrokedPath(currentContext); + } + CGContextClip(currentContext); + CGContextDrawShading(currentContext, myCGShading); + CGShadingRelease(myCGShading); + } + } + CGContextRestoreGState(currentContext); + } + } +} + + +- (NSPoint)gtm_projectLineFrom:(NSPoint)pointA + to:(NSPoint)pointB + by:(CGFloat)length { + NSPoint newPoint = pointB; + CGFloat x = (pointB.x - pointA.x); + CGFloat y = (pointB.y - pointA.y); + if (fpclassify(x) == FP_ZERO) { + newPoint.y += length; + } else if (fpclassify(y) == FP_ZERO) { + newPoint.x += length; + } else { +#if CGFLOAT_IS_DOUBLE + CGFloat angle = atan(y / x); + newPoint.x += sin(angle) * length; + newPoint.y += cos(angle) * length; +#else + CGFloat angle = atanf(y / x); + newPoint.x += sinf(angle) * length; + newPoint.y += cosf(angle) * length; +#endif + } + return newPoint; +} + +@end + + +@implementation NSBezierPath (GTMBezierPathShadingAdditions) +GTM_METHOD_CHECK(NSBezierPath, gtm_CGPath); + +- (void)gtm_strokeAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading { + CGPathRef thePath = [self gtm_CGPath]; + if (nil != thePath) { + [self gtm_fillCGPath:thePath axially:YES asStroke:YES + from:fromPoint fromRadius:(CGFloat)0.0 + to:toPoint toRadius:(CGFloat)0.0 + extendingStart:extendingStart extendingEnd:extendingEnd + shading:shading]; + } +} + + +- (void)gtm_strokeRadiallyFrom:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading { + CGPathRef thePath = [self gtm_CGPath]; + if (nil != thePath) { + [self gtm_fillCGPath:thePath axially:NO asStroke:YES + from:fromPoint fromRadius:fromRadius + to:toPoint toRadius:toRadius + extendingStart:extendingStart extendingEnd:extendingEnd + shading:shading]; + } +} + + +- (void)gtm_fillAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading { + CGPathRef thePath = [self gtm_CGPath]; + if (nil != thePath) { + [self gtm_fillCGPath:thePath axially:YES asStroke:NO + from:fromPoint fromRadius:(CGFloat)0.0 + to:toPoint toRadius:(CGFloat)0.0 + extendingStart:extendingStart extendingEnd:extendingEnd + shading:shading]; + } +} + + +- (void)gtm_fillRadiallyFrom:(NSPoint)fromPoint fromRadius:(CGFloat)fromRadius + to:(NSPoint)toPoint toRadius:(CGFloat)toRadius + extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd + shading:(id)shading { + CGPathRef thePath = [self gtm_CGPath]; + if (nil != thePath) { + [self gtm_fillCGPath:thePath axially:NO asStroke:NO + from:fromPoint fromRadius:fromRadius + to:toPoint toRadius:toRadius + extendingStart:extendingStart extendingEnd:extendingEnd + shading:shading]; + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+ShadingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+ShadingTest.m new file mode 100644 index 00000000..a9dfbefa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSBezierPath+ShadingTest.m @@ -0,0 +1,177 @@ +// +// GTMNSBezierPath+ShadingTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import + +#import "GTMLinearRGBShading.h" +#import "GTMAppKit+UnitTesting.h" +#import "GTMNSBezierPath+Shading.h" + +@interface GTMNSBezierPath_ShadingTest : GTMTestCase +@end + +@implementation GTMNSBezierPath_ShadingTest + +- (void)testShadings { + GTMAssertDrawingEqualToImageNamed(self, + NSMakeSize(310, 410), + @"GTMNSBezierPath+ShadingTest", nil, nil); +} + +- (void)gtm_unitTestViewDrawRect:(NSRect)rect contextInfo:(void*)contextInfo { + + NSColor *theColorArray[] = { [NSColor blueColor], + [NSColor redColor], [NSColor yellowColor], + [NSColor blueColor], [NSColor greenColor], + [NSColor redColor] }; + CGFloat theFloatArray[] = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }; + + GTMLinearRGBShading *shading = + [GTMLinearRGBShading shadingWithColors:theColorArray + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:theFloatArray + count:sizeof(theFloatArray)/sizeof(CGFloat)]; + NSBezierPath *shadedPath; + + // axial stroke rect - diagonal fill + NSRect axialStrokeRect = NSMakeRect(10.0f, 10.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; + [shadedPath setLineWidth: 10.0f]; + NSPoint startPoint = NSMakePoint(axialStrokeRect.origin.x + 20.0f, + axialStrokeRect.origin.y + 20.0f); + NSPoint endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial stroke rect - v line fill + axialStrokeRect = NSMakeRect(110.0f, 10.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; + [shadedPath setLineWidth: 10.0f]; + startPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f, + axialStrokeRect.origin.y + 20.0f); + endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial stroke rect - h line fill + axialStrokeRect = NSMakeRect(210.0f, 10.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; + [shadedPath setLineWidth: 10.0f]; + startPoint = NSMakePoint(axialStrokeRect.origin.x + 20.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f); + endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f); + [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial fill rect - diagonal fill + NSRect axialFillRect = NSMakeRect(10.0f, 110.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; + startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f, + axialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width - 20.0f, + axialFillRect.origin.y + axialFillRect.size.height - 20.0f); + [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial fill rect - v line fill + axialFillRect = NSMakeRect(110.0f, 110.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; + startPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f, + axialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f, + axialFillRect.origin.y + axialFillRect.size.height - 20.0f); + [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial fill rect - h line fill + axialFillRect = NSMakeRect(210.0f, 110.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; + startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f, + axialFillRect.origin.y + axialFillRect.size.height / 2.0f); + endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width - 20.0f, + axialFillRect.origin.y + axialFillRect.size.height / 2.0f); + [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // radial stroke rect - diagonal fill + NSRect radialStrokeRect = NSMakeRect(10.0f, 210.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; + startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f, + radialStrokeRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width - 20.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial stroke rect - v line fill + radialStrokeRect = NSMakeRect(110.0f, 210.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; + startPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f, + radialStrokeRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial stroke rect - h line fill + radialStrokeRect = NSMakeRect(210.0f, 210.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; + startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f); + endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width - 20.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f); + [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - diagonal fill + NSRect radialFillRect = NSMakeRect(10.0f, 310.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; + startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f, + radialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width - 20.0f, + radialFillRect.origin.y + radialFillRect.size.height - 20.0f); + [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - v line fill + radialFillRect = NSMakeRect(110.0f, 310.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; + startPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f, + radialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f, + radialFillRect.origin.y + radialFillRect.size.height - 20.0f); + [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - h line fill + radialFillRect = NSMakeRect(210.0f, 310.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; + startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f, + radialFillRect.origin.y + radialFillRect.size.height / 2.0f); + endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width - 20.0f, + radialFillRect.origin.y + radialFillRect.size.height / 2.0f); + [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.h new file mode 100644 index 00000000..c1501cdc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.h @@ -0,0 +1,65 @@ +// +// GTMNSColor+Luminance.h +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +enum { + GTMColorationBaseHighlight, + GTMColorationBaseMidtone, + GTMColorationBaseShadow, + GTMColorationBasePenumbra, + GTMColorationLightHighlight, + GTMColorationLightMidtone, + GTMColorationLightShadow, + GTMColorationLightPenumbra, + GTMColorationDarkHighlight, + GTMColorationDarkMidtone, + GTMColorationDarkShadow, + GTMColorationDarkPenumbra +}; +typedef NSUInteger GTMColorationUse; + +@interface NSColorSpace (GTMNSColorSpaceLuminanceHelpers) ++ (NSColorSpace *)gtm_labColorSpace; +@end + +@interface NSColor (GTMLuminanceAdditions) +- (CGFloat)gtm_luminance; + +// Create a color modified by lightening or darkening it (-1.0 to 1.0) +- (NSColor *)gtm_colorByAdjustingLuminance:(CGFloat)luminance; + +// Create a color modified by lightening or darkening it (-1.0 to 1.0) +- (NSColor *)gtm_colorByAdjustingLuminance:(CGFloat)luminance + saturation:(CGFloat)saturation; + +// Returns a color adjusted for a specific usage +- (NSColor *)gtm_colorAdjustedFor:(GTMColorationUse)use; +- (NSColor *)gtm_colorAdjustedFor:(GTMColorationUse)use faded:(BOOL)fade; + +// Returns whether the color is in the dark half of the spectrum +- (BOOL)gtm_isDarkColor; + +// Returns a color that is legible on this color. (Nothing to do with textColor) +- (NSColor *)gtm_legibleTextColor; +@end + +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.m new file mode 100644 index 00000000..5b10dbe6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+Luminance.m @@ -0,0 +1,153 @@ +// +// GTMNSColor+Luminance.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +#import "GTMNSColor+Luminance.h" + +static const CGFloat kGTMLuminanceDarkCutoff = 0.6; + +@implementation NSColorSpace (GTMNSColorSpaceLuminanceHelpers) + +// TODO(alcor): we may want to keep one of these around for performance reasons ++ (NSColorSpace *)gtm_labColorSpace { + // Observer= 2°, Illuminant= D65 + // TODO(alcor): these should come from ColorSync + CGFloat whitePoint[3] = {0.95047, 1.0, 1.08883}; + CGFloat blackPoint[3] = {0, 0, 0}; + CGFloat range[4] = {-127, 127, -127, 127}; + CGColorSpaceRef cs = CGColorSpaceCreateLab(whitePoint, blackPoint, range); + NSColorSpace *space = nil; + if (cs) { + space = [[[NSColorSpace alloc] initWithCGColorSpace:cs] autorelease]; + CGColorSpaceRelease(cs); + } + return space; +} +@end + +@implementation NSColor (GTMLuminance) + +- (NSColor *)labColor { + return [self colorUsingColorSpace:[NSColorSpace gtm_labColorSpace]]; +} + +- (CGFloat)gtm_luminance { + CGFloat lab[4]; + lab[0] = 0.0; + [[self labColor] getComponents:lab]; + return lab[0] / 100.0; +} + +- (NSColor *)gtm_colorByAdjustingLuminance:(CGFloat)luminance + saturation:(CGFloat)saturation { + CGFloat lab[4]; + [[self labColor] getComponents:lab]; + lab[0] *= 1.0 + luminance; + // If luminance is greater than 100, we desaturate it so that we don't get + // wild colors coming out of the forumula + if (lab[0] > 100) { + CGFloat clipping = lab[0] - 100; + CGFloat desaturation = (50.0 - clipping) / 50.0; + saturation = MIN(saturation, desaturation); + } + lab[1] *= saturation; + lab[2] *= saturation; + return [NSColor colorWithColorSpace:[NSColorSpace gtm_labColorSpace] + components:lab + count:sizeof(lab) / sizeof(lab[0])]; +} + +- (NSColor *)gtm_colorByAdjustingLuminance:(CGFloat)luminance { + return [self gtm_colorByAdjustingLuminance:luminance saturation:1.0]; +} + +// TODO(alcor): these constants are largely made up, come up with a consistent +// set of values or at least guidelines +- (NSColor *)gtm_colorAdjustedFor:(GTMColorationUse)use { + NSColor *color = nil; + switch (use) { + case GTMColorationBaseHighlight: + color = [self gtm_colorByAdjustingLuminance:0.15]; + break; + case GTMColorationBaseMidtone: + color = self; + break; + case GTMColorationBaseShadow: + color = [self gtm_colorByAdjustingLuminance:-0.15]; + break; + case GTMColorationBasePenumbra: + color = [self gtm_colorByAdjustingLuminance:-0.10]; + break; + case GTMColorationLightHighlight: + color = [self gtm_colorByAdjustingLuminance:0.25]; + color = [color blendedColorWithFraction:0.9 ofColor:[NSColor whiteColor]]; + break; + case GTMColorationLightMidtone: + color = [self blendedColorWithFraction:0.8 ofColor:[NSColor whiteColor]]; + break; + case GTMColorationLightShadow: + color = [self blendedColorWithFraction:0.7 ofColor:[NSColor whiteColor]]; + color = [color gtm_colorByAdjustingLuminance:-0.02]; + break; + case GTMColorationLightPenumbra: + color = [self blendedColorWithFraction:0.8 ofColor:[NSColor whiteColor]]; + color = [color gtm_colorByAdjustingLuminance:-0.01]; + break; + case GTMColorationDarkHighlight: + color = [self gtm_colorByAdjustingLuminance:-0.20]; + break; + case GTMColorationDarkMidtone: + color = [self gtm_colorByAdjustingLuminance:-0.25]; + break; + case GTMColorationDarkShadow: + color = [self gtm_colorByAdjustingLuminance:-0.30 saturation:1.4]; + break; + case GTMColorationDarkPenumbra: + color = [self gtm_colorByAdjustingLuminance:-0.25]; + break; + default: + _GTMDevLog(@"Invalid Coloration Use %d", use); + color = self; + break; + } + return color; +} +const CGFloat kDefaultFade = 0.3; + +- (NSColor *)gtm_colorAdjustedFor:(GTMColorationUse)use faded:(BOOL)fade { + NSColor *color = [self gtm_colorAdjustedFor:use]; + if (fade) { + CGFloat luminance = [color gtm_luminance]; + color = [color gtm_colorByAdjustingLuminance: + kDefaultFade * (1.0 - luminance) + saturation:kDefaultFade]; + } + return color; +} + +- (BOOL)gtm_isDarkColor { + return [self gtm_luminance] < kGTMLuminanceDarkCutoff; +} + +- (NSColor *)gtm_legibleTextColor { + return [self gtm_isDarkColor] ? [NSColor whiteColor] : [NSColor blackColor]; +} + +@end +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+LuminanceTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+LuminanceTest.m new file mode 100644 index 00000000..82eb0145 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSColor+LuminanceTest.m @@ -0,0 +1,72 @@ +// +// GTMNSColor+LuminanceTest.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +#import "GTMSenTestCase.h" +#import "GTMNSColor+Luminance.h" + +@interface GTMNSColor_LuminanceTest : GTMTestCase +@end + +@implementation GTMNSColor_LuminanceTest + +- (void)testLuminance { + NSColor *midtone = [NSColor blueColor]; + NSColor *darker = [midtone gtm_colorAdjustedFor:GTMColorationBaseShadow]; + NSColor *lighter = [midtone gtm_colorAdjustedFor:GTMColorationBaseHighlight]; + NSColor *lightest = [midtone gtm_colorAdjustedFor:GTMColorationLightHighlight]; + NSColor *darkest = [midtone gtm_colorAdjustedFor:GTMColorationDarkShadow]; + + // The relationships of the other values are not set, so we don't test them yet + STAssertGreaterThanOrEqual([lightest gtm_luminance], + [lighter gtm_luminance], nil); + STAssertGreaterThanOrEqual([lighter gtm_luminance], + [midtone gtm_luminance], nil); + STAssertGreaterThanOrEqual([midtone gtm_luminance], + [darker gtm_luminance], nil); + STAssertGreaterThanOrEqual([darker gtm_luminance], + [darkest gtm_luminance], nil); + STAssertGreaterThanOrEqual([[NSColor whiteColor] gtm_luminance], + (CGFloat)0.95, nil); + STAssertGreaterThanOrEqual([[NSColor yellowColor] gtm_luminance], + (CGFloat)0.90, nil); + STAssertEqualsWithAccuracy([[NSColor blueColor] gtm_luminance], + (CGFloat)0.35, 0.10, nil); + STAssertEqualsWithAccuracy([[NSColor redColor] gtm_luminance], + (CGFloat)0.50, 0.10, nil); + STAssertLessThanOrEqual([[NSColor blackColor] gtm_luminance], + (CGFloat)0.30, nil); + STAssertTrue([[NSColor blackColor] gtm_isDarkColor], nil); + STAssertTrue([[NSColor blueColor] gtm_isDarkColor], nil); + STAssertTrue([[NSColor redColor] gtm_isDarkColor], nil); + STAssertTrue(![[NSColor whiteColor] gtm_isDarkColor], nil); + STAssertTrue(![[NSColor yellowColor] gtm_isDarkColor], nil); + STAssertGreaterThanOrEqual([[[NSColor blackColor] gtm_legibleTextColor] + gtm_luminance], + [[NSColor grayColor] gtm_luminance], nil); + STAssertLessThanOrEqual([[[NSColor whiteColor] gtm_legibleTextColor] + gtm_luminance], + [[NSColor grayColor] gtm_luminance], nil); +} + +@end + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.h new file mode 100644 index 00000000..7d485771 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.h @@ -0,0 +1,51 @@ +// +// GTMNSImage+Scaling.h +// +// Scales NSImages to a variety of sizes for drawing +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#import +#import "GTMDefines.h" + +@interface NSImage (GTMNSImageScaling) + +// Return an existing representation of a size +- (NSImageRep *)gtm_representationOfSize:(NSSize)size; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +// Return the exact or next largest representation for a size +// If you are on SnowLeopard use +// -[NSImage bestRepresentationForRect:context:hints:] +- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size; +#endif + +// Create a new represetation for a given size +- (BOOL)gtm_createRepresentationOfSize:(NSSize)size; + +// Create 32 and 16px reps +- (BOOL)gtm_createIconRepresentations; + +// Remove reps larger than a given size and create a new rep if needed +- (void)gtm_shrinkToSize:(NSSize)size; + +// Remove reps larger than a given size +- (void)gtm_removeRepresentationsLargerThanSize:(NSSize)size; + +// Return a dup shrunk to a given size +- (NSImage *)gtm_duplicateOfSize:(NSSize)size; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.m new file mode 100644 index 00000000..8283b298 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+Scaling.m @@ -0,0 +1,183 @@ +// +// GTMNSImage+Scaling.m +// +// Scales NSImages to a variety of sizes for drawing +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSImage+Scaling.h" +#import "GTMGeometryUtils.h" + +@implementation NSImage (GTMNSImageScaling) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +// If you are on SnowLeopard use +// -[NSImage bestRepresentationForRect:context:hints:] +- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size { + NSImageRep *bestRep = [self gtm_representationOfSize:size]; + if (bestRep) { + return bestRep; + } + NSArray *reps = [self representations]; + + CGFloat repDistance = CGFLOAT_MAX; + + NSImageRep *thisRep; + GTM_FOREACH_OBJECT(thisRep, reps) { + CGFloat thisDistance; + thisDistance = MIN(size.width - [thisRep size].width, + size.height - [thisRep size].height); + + if (repDistance < 0 && thisDistance > 0) continue; + if (ABS(thisDistance) < ABS(repDistance) + || (thisDistance < 0 && repDistance > 0)) { + repDistance = thisDistance; + bestRep = thisRep; + } + } + + if (!bestRep) { + bestRep = [self bestRepresentationForDevice:nil]; + } + + return bestRep; +} +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + +- (NSImageRep *)gtm_representationOfSize:(NSSize)size { + NSArray *reps = [self representations]; + + NSImageRep *thisRep; + GTM_FOREACH_OBJECT(thisRep, reps) { + if (NSEqualSizes([thisRep size], size)) { + return thisRep; + } + } + return nil; +} + +- (BOOL)gtm_createIconRepresentations { + [self setFlipped:NO]; + [self gtm_createRepresentationOfSize:NSMakeSize(16, 16)]; + [self gtm_createRepresentationOfSize:NSMakeSize(32, 32)]; + [self setScalesWhenResized:NO]; + return YES; +} + +- (BOOL)gtm_createRepresentationOfSize:(NSSize)size { + if ([self gtm_representationOfSize:size]) { + return NO; + } + + NSBitmapImageRep *bestRep; +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + bestRep = (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size]; +#else + bestRep + = (NSBitmapImageRep *)[self bestRepresentationForRect:GTMNSRectOfSize(size) + context:nil + hints:nil]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + + NSRect drawRect = GTMNSScaleRectToRect(GTMNSRectOfSize([bestRep size]), + GTMNSRectOfSize(size), + GTMScaleProportionally, + GTMRectAlignCenter); + + if ([bestRep respondsToSelector:@selector(CGImage)]) { + CGImageRef imageRef = (CGImageRef)[bestRep performSelector:@selector(CGImage)]; + + CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); + if (!cspace) return NO; + + CGContextRef smallContext = + CGBitmapContextCreate(NULL, + size.width, + size.height, + 8, // bits per component + size.width * 4, // bytes per pixel + cspace, + kCGBitmapByteOrder32Host + | kCGImageAlphaPremultipliedLast); + CFRelease(cspace); + + if (!smallContext) return NO; + + + CGContextDrawImage(smallContext, GTMNSRectToCGRect(drawRect), imageRef); + + CGImageRef smallImage = CGBitmapContextCreateImage(smallContext); + + if (smallImage) { + NSBitmapImageRep *cgRep = + [[[NSBitmapImageRep alloc] initWithCGImage:smallImage] autorelease]; + [self addRepresentation:cgRep]; + CGImageRelease(smallImage); + } else { + CGContextRelease(smallContext); + return NO; + } + CGContextRelease(smallContext); + return YES; + } else { + // This functionality is here to allow it to work under Tiger + // It can probably only be called safely from the main thread + NSImage* scaledImage = [[NSImage alloc] initWithSize:size]; + [scaledImage lockFocus]; + NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext]; + [graphicsContext setImageInterpolation:NSImageInterpolationHigh]; + [graphicsContext setShouldAntialias:YES]; + [bestRep drawInRect:drawRect]; + NSBitmapImageRep* iconRep = + [[[NSBitmapImageRep alloc] initWithFocusedViewRect: + NSMakeRect(0, 0, size.width, size.height)] autorelease]; + [scaledImage unlockFocus]; + [scaledImage release]; + [self addRepresentation:iconRep]; + return YES; + } + return NO; +} + +- (void)gtm_removeRepresentationsLargerThanSize:(NSSize)size { + NSMutableArray *repsToRemove = [NSMutableArray array]; + NSImageRep *thisRep; + // Remove them in a second loop so we don't change things will doing the + // initial loop. + GTM_FOREACH_OBJECT(thisRep, [self representations]) { + if ([thisRep size].width > size.width + && [thisRep size].height > size.height) { + [repsToRemove addObject:thisRep]; + } + } + GTM_FOREACH_OBJECT(thisRep, repsToRemove) { + [self removeRepresentation:thisRep]; + } +} + +- (NSImage *)gtm_duplicateOfSize:(NSSize)size { + NSImage *duplicate = [[self copy] autorelease]; + [duplicate gtm_shrinkToSize:size]; + [duplicate setFlipped:NO]; + return duplicate; +} + +- (void)gtm_shrinkToSize:(NSSize)size { + [self gtm_createRepresentationOfSize:size]; + [self setSize:size]; + [self gtm_removeRepresentationsLargerThanSize:size]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+ScalingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+ScalingTest.m new file mode 100644 index 00000000..5679b7c2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSImage+ScalingTest.m @@ -0,0 +1,64 @@ +// +// GTMNSImage+ScalingTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import "GTMSenTestCase.h" + +#import "GTMNSImage+Scaling.h" +#import "GTMGeometryUtils.h" + +@interface GTMNSImage_ScalingTest : GTMTestCase +@end + +@implementation GTMNSImage_ScalingTest + +- (void)testScaling { + NSImage *testImage = [NSImage imageNamed:@"NSApplicationIcon"]; + + NSImageRep *rep = nil; + NSRect bestRepRect = NSMakeRect(0, 0, 99, 99); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 + rep = [testImage bestRepresentationForRect:bestRepRect + context:nil + hints:nil]; +#else + rep = [testImage gtm_bestRepresentationForSize:bestRepRect.size]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 + + STAssertTrue(NSEqualSizes([rep size], NSMakeSize(128, 128)), nil); + + [testImage gtm_createIconRepresentations]; + STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(16, 16)], nil); + STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(32, 32)], nil); + + NSImage *duplicate = [testImage gtm_duplicateOfSize: NSMakeSize(48, 48)]; + bestRepRect = NSMakeRect(0, 0, 50, 50); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 + rep = [duplicate bestRepresentationForRect:bestRepRect + context:nil + hints:nil]; +#else + rep = [duplicate gtm_bestRepresentationForSize:bestRepRect.size]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 + STAssertTrue(NSEqualSizes([rep size], NSMakeSize(48, 48)), nil); + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.h new file mode 100644 index 00000000..483833fa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.h @@ -0,0 +1,92 @@ +// +// GTMNSWorkspace+Running.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// Process Dictionary keys +// +// NOTE: According to ProcessInformationCopyDictionary, the following may not be +// in the dictionary depending on the type of process: +// kGTMWorkspaceRunningParentPSN, kGTMWorkspaceRunningFileType, +// kGTMWorkspaceRunningFileCreator, kGTMWorkspaceRunningPID, +// kGTMWorkspaceRunningBundlePath, kGTMWorkspaceRunningBundleIdentifier, +// kGTMWorkspaceRunningBundleName, kGTMWorkspaceRunningBundleExecutable, +// And experience says the follow might also not be there: +// kGTMWorkspaceRunningIsHidden + +// Make sure to use numberToProcessSerialNumber: on the return values +// of these keys to get valid PSNs on both Leopard and Tiger. +// Numeric types come back as a NSNumber. +GTM_EXTERN NSString *const kGTMWorkspaceRunningPSN; // long long +GTM_EXTERN NSString *const kGTMWorkspaceRunningParentPSN; // long long + +GTM_EXTERN NSString *const kGTMWorkspaceRunningFlavor; // SInt32 +GTM_EXTERN NSString *const kGTMWorkspaceRunningAttributes; // SInt32 +GTM_EXTERN NSString *const kGTMWorkspaceRunningFileType; // NSString +GTM_EXTERN NSString *const kGTMWorkspaceRunningFileCreator; // NSString +GTM_EXTERN NSString *const kGTMWorkspaceRunningPID; // long +GTM_EXTERN NSString *const kGTMWorkspaceRunningLSBackgroundOnly; // bool +GTM_EXTERN NSString *const kGTMWorkspaceRunningLSUIElement; // bool +GTM_EXTERN NSString *const kGTMWorkspaceRunningIsHidden; // bool +GTM_EXTERN NSString *const kGTMWorkspaceRunningCheckedIn; // bool +GTM_EXTERN NSString *const kGTMWorkspaceRunningLSUIPresentationMode; // Short +GTM_EXTERN NSString *const kGTMWorkspaceRunningBundlePath; // NSString +GTM_EXTERN NSString *const kGTMWorkspaceRunningBundleVersion; // NSString +// The docs for ProcessInformationCopyDictionary say we should use the constants +// instead of the raw string values, so map our values to those keys. +#define kGTMWorkspaceRunningBundleIdentifier (NSString*)kCFBundleIdentifierKey // NSString +#define kGTMWorkspaceRunningBundleName (NSString*)kCFBundleNameKey // NSString +#define kGTMWorkspaceRunningBundleExecutable (NSString*)kCFBundleExecutableKey // NSString + +// A category for getting information about other running processes +@interface NSWorkspace (GTMWorkspaceRunningAdditions) + +// Returns a YES/NO if a process w/ the given identifier is running +- (BOOL)gtm_isAppWithIdentifierRunning:(NSString *)identifier; + +// Returns a dictionary with info for our process. +//See Process Dictionary Keys above for values +- (NSDictionary *)gtm_processInfoDictionary; + +// Returns a dictionary with info for the active process. +// See Process Dictionary Keys above for values +- (NSDictionary *)gtm_processInfoDictionaryForActiveApp; + +// Returns a dictionary with info for the process. +//See Process Dictionary Keys above for values +- (NSDictionary *)gtm_processInfoDictionaryForPID:(pid_t)pid; + +// Returns a dictionary with info for the process. +// See Process Dictionary Keys above for values +- (NSDictionary *)gtm_processInfoDictionaryForPSN:(const ProcessSerialNumberPtr)psn; + +// Returns true if we were launched as a login item. +- (BOOL)gtm_wasLaunchedAsLoginItem; + +// Returns true if we were launched by a given bundleid +- (BOOL)gtm_wasLaunchedByProcess:(NSString*)bundleid; + +// Returns true if the PSN was found for the running app with bundleID +- (BOOL)gtm_processSerialNumber:(ProcessSerialNumber*)outPSN + withBundleID:(NSString*)bundleID; + +// Converts PSNs stored in NSNumbers to real PSNs +- (ProcessSerialNumber)gtm_numberToProcessSerialNumber:(NSNumber*)number; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.m new file mode 100644 index 00000000..973ad22b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+Running.m @@ -0,0 +1,173 @@ +// +// GTMNSWorkspace+Running.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSWorkspace+Running.h" +#import +#import +#import "GTMGarbageCollection.h" +#import "GTMSystemVersion.h" + +NSString *const kGTMWorkspaceRunningPSN = @"PSN"; +NSString *const kGTMWorkspaceRunningFlavor = @"Flavor"; +NSString *const kGTMWorkspaceRunningAttributes = @"Attributes"; +NSString *const kGTMWorkspaceRunningParentPSN = @"ParentPSN"; +NSString *const kGTMWorkspaceRunningFileType = @"FileType"; +NSString *const kGTMWorkspaceRunningFileCreator = @"FileCreator"; +NSString *const kGTMWorkspaceRunningPID = @"pid"; +NSString *const kGTMWorkspaceRunningLSBackgroundOnly = @"LSBackgroundOnly"; +NSString *const kGTMWorkspaceRunningLSUIElement = @"LSUIElement"; +NSString *const kGTMWorkspaceRunningIsHidden = @"IsHiddenAttr"; +NSString *const kGTMWorkspaceRunningCheckedIn = @"IsCheckedInAttr"; +NSString *const kGTMWorkspaceRunningLSUIPresentationMode + = @"LSUIPresentationMode"; +NSString *const kGTMWorkspaceRunningBundlePath = @"BundlePath"; +NSString *const kGTMWorkspaceRunningBundleVersion = @"CFBundleVersion"; + +@implementation NSWorkspace (GTMWorkspaceRunningAdditions) + +/// Returns a YES/NO if a process w/ the given identifier is running +- (BOOL)gtm_isAppWithIdentifierRunning:(NSString *)identifier { + if ([identifier length] == 0) return NO; + NSArray *launchedApps = [self launchedApplications]; + NSArray *buildIDs + = [launchedApps valueForKey:@"NSApplicationBundleIdentifier"]; + return [buildIDs containsObject:identifier]; +} + +- (NSDictionary *)gtm_processInfoDictionaryForPID:(pid_t)pid { + NSDictionary *dict = nil; + ProcessSerialNumber psn; + if (GetProcessForPID(pid, &psn) == noErr) { + dict = [self gtm_processInfoDictionaryForPSN:&psn]; + } + return dict; +} + +- (NSDictionary *)gtm_processInfoDictionaryForPSN:(ProcessSerialNumberPtr)psn { + NSDictionary *dict = nil; + if (psn) { + CFDictionaryRef cfDict + = ProcessInformationCopyDictionary(psn, + kProcessDictionaryIncludeAllInformationMask); + dict = GTMCFAutorelease(cfDict); + } + return dict; +} + +- (NSDictionary *)gtm_processInfoDictionary { + NSDictionary *dict = nil; + ProcessSerialNumber selfNumber; + if (MacGetCurrentProcess(&selfNumber) == noErr) { + dict = [self gtm_processInfoDictionaryForPSN:&selfNumber]; + } + return dict; +} + +- (NSDictionary *)gtm_processInfoDictionaryForActiveApp { + NSDictionary *processDict = nil; + ProcessSerialNumber psn; + OSStatus status = GetFrontProcess(&psn); + if (status == noErr) { + processDict = [self gtm_processInfoDictionaryForPSN:&psn]; + } + return processDict; +} + +- (BOOL)gtm_wasLaunchedAsLoginItem { + // If the launching process was 'loginwindow', we were launched as a login + // item + return [self gtm_wasLaunchedByProcess:@"com.apple.loginwindow"]; +} + +- (BOOL)gtm_wasLaunchedByProcess:(NSString*)bundleid { + BOOL wasLaunchedByProcess = NO; + NSDictionary *processInfo = [self gtm_processInfoDictionary]; + if (processInfo) { + NSNumber *processNumber + = [processInfo objectForKey:kGTMWorkspaceRunningParentPSN]; + ProcessSerialNumber parentPSN + = [self gtm_numberToProcessSerialNumber:processNumber]; + NSDictionary *parentProcessInfo + = [self gtm_processInfoDictionaryForPSN:&parentPSN]; + NSString *parentBundle + = [parentProcessInfo objectForKey:kGTMWorkspaceRunningBundleIdentifier]; + wasLaunchedByProcess + = [parentBundle isEqualToString:bundleid]; + } + return wasLaunchedByProcess; +} + +- (BOOL)gtm_processSerialNumber:(ProcessSerialNumber*)outPSN + withBundleID:(NSString*)bundleID { + if (!outPSN || [bundleID length] == 0) { + return NO; + } + + NSArray *apps = [self launchedApplications]; + + NSEnumerator *enumerator = [apps objectEnumerator]; + NSDictionary *dict; + + while ((dict = [enumerator nextObject])) { + NSString *nextID = [dict objectForKey:@"NSApplicationBundleIdentifier"]; + + if ([nextID isEqualToString:bundleID]) { + NSNumber *psn + = [dict objectForKey:@"NSApplicationProcessSerialNumberLow"]; + outPSN->lowLongOfPSN = [psn unsignedIntValue]; + + psn = [dict objectForKey:@"NSApplicationProcessSerialNumberHigh"]; + outPSN->highLongOfPSN = [psn unsignedIntValue]; + + return YES; + } + } + + return NO; +} + +- (ProcessSerialNumber)gtm_numberToProcessSerialNumber:(NSNumber*)number { + // There is a bug in Tiger where they were packing ProcessSerialNumbers + // incorrectly into the longlong that they stored in the dictionary. + // This fixes it. + ProcessSerialNumber outPSN = { kNoProcess, kNoProcess}; + if (number) { + long long temp = [number longLongValue]; + UInt32 hi = (UInt32)((temp >> 32) & 0x00000000FFFFFFFFLL); + UInt32 lo = (UInt32)((temp >> 0) & 0x00000000FFFFFFFFLL); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + outPSN.highLongOfPSN = hi; + outPSN.lowLongOfPSN = lo; +#else // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + if ([GTMSystemVersion isLeopardOrGreater]) { + outPSN.highLongOfPSN = hi; + outPSN.lowLongOfPSN = lo; + } else { +#if TARGET_RT_BIG_ENDIAN + outPSN.highLongOfPSN = hi; + outPSN.lowLongOfPSN = lo; +#else + outPSN.highLongOfPSN = lo; + outPSN.lowLongOfPSN = hi; +#endif // TARGET_RT_BIG_ENDIAN + } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + } + return outPSN; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+RunningTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+RunningTest.m new file mode 100644 index 00000000..4c9af6c5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMNSWorkspace+RunningTest.m @@ -0,0 +1,78 @@ +// +// GTMNSWorkspace+RunningTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSWorkspace+Running.h" +#import + +@interface GTMNSWorkspace_RunningTest : GTMTestCase +@end + +@implementation GTMNSWorkspace_RunningTest + +- (void)testBasics { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + STAssertTrue([ws gtm_isAppWithIdentifierRunning:@"com.apple.finder"], nil); + STAssertFalse([ws gtm_isAppWithIdentifierRunning:@"com.google.nothing"], nil); + + NSDictionary *processInfo = [ws gtm_processInfoDictionary]; + STAssertNotNil(processInfo, nil); + + BOOL wasLaunchedAsLoginItem = [ws gtm_wasLaunchedAsLoginItem]; + STAssertFalse(wasLaunchedAsLoginItem, nil); + + pid_t pid = getpid(); + NSDictionary *processInfo2 = [ws gtm_processInfoDictionaryForPID:pid]; + STAssertNotNil(processInfo2, nil); + STAssertEqualObjects(processInfo, processInfo2, nil); + + ProcessSerialNumber num = { 0, 0 }; + BOOL gotPSN = [ws gtm_processSerialNumber:&num + withBundleID:@"com.apple.finder"]; + STAssertTrue(gotPSN, nil); + STAssertGreaterThan(num.highLongOfPSN + num.lowLongOfPSN, (UInt32)0, nil); + gotPSN = [ws gtm_processSerialNumber:&num + withBundleID:@"bad.bundle.id"]; + STAssertFalse(gotPSN, nil); + + gotPSN = [ws gtm_processSerialNumber:NULL + withBundleID:nil]; + STAssertFalse(gotPSN, nil); + + processInfo = [ws gtm_processInfoDictionaryForActiveApp]; + STAssertNotNil(processInfo, nil); + + // Only check the keys that have to be there + NSString *const keys[] = { + kGTMWorkspaceRunningPSN, + kGTMWorkspaceRunningFlavor, kGTMWorkspaceRunningAttributes, + kGTMWorkspaceRunningLSBackgroundOnly, + kGTMWorkspaceRunningLSUIElement, + kGTMWorkspaceRunningCheckedIn, + kGTMWorkspaceRunningBundleVersion, + kGTMWorkspaceRunningLSUIPresentationMode, + + }; + for (size_t i = 0; i < sizeof(keys) / sizeof(NSString *); ++i) { + NSString *const key = keys[i]; + STAssertNotNil([processInfo objectForKey:key], + @"Couldn't get %@ from %@", key, processInfo); + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMShading.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMShading.h new file mode 100644 index 00000000..27e163ea --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMShading.h @@ -0,0 +1,41 @@ +// +// GTMShading.h +// +// A protocol for an object that can be used as a shader. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +/// \cond Protocols + +@protocol GTMShading +// Returns the shadefunction for using in a shader. +// This shadefunction shoud never be released. It is owned by the implementor +// of the GTMShading protocol. +// +// Returns: +// a shading function. +- (CGFunctionRef)shadeFunction; + +// Returns the colorSpace for using in a shader. +// This colorSpace shoud never be released. It is owned by the implementor +// of the GTMShading protocol. +// +// Returns: +// a color space. +- (CGColorSpaceRef)colorSpace; +@end + +/// \endcond diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.h new file mode 100644 index 00000000..5f4700e3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.h @@ -0,0 +1,78 @@ +// +// GTMTheme.h +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +// Sent whenever the theme changes. Object => GTMTheme that changed +GTM_EXTERN NSString *kGTMThemeDidChangeNotification; + +enum { + GTMThemeStyleTabBarSelected, + GTMThemeStyleTabBarDeselected, + GTMThemeStyleWindow, + GTMThemeStyleToolBar, + GTMThemeStyleToolBarButton, + GTMThemeStyleToolBarButtonPressed, + GTMThemeStyleBookmarksBar, +}; +typedef NSUInteger GTMThemeStyle; + +// GTMTheme provides a range of values for procedural drawing of UI elements +// based on interpolation of a single background color + +@interface GTMTheme : NSObject { + @private + NSColor *backgroundColor_; // bound to user defaults + NSImage *backgroundImage_; // bound to user defaults + NSMutableDictionary *values_; // cached values +} + +// Access the global theme. By default this is bound to user defaults ++ (GTMTheme *)defaultTheme; ++ (void)setDefaultTheme:(GTMTheme *)theme; + +// returns base theme color +- (NSColor *)backgroundColor; + +// base background color +- (NSImage *)backgroundImage; + +// NSColor (or pattern color) for the background of the window +- (NSColor *)windowBackgroundColor:(BOOL)active; + +// NSGradient for specific usage, active indicates whether the window is key +- (NSGradient *)gradientForStyle:(GTMThemeStyle)style active:(BOOL)active; + +// Outline color for stroke, active indicates whether the window is key +- (NSColor *)strokeColorForStyle:(GTMThemeStyle)style active:(BOOL)active; + +// Indicates whether luminance is dark or light +- (BOOL)styleIsDark:(GTMThemeStyle)style active:(BOOL)active; + +// Background style for this style and state +- (NSBackgroundStyle)interiorBackgroundStyleForStyle:(GTMThemeStyle)style + active:(BOOL)active; + +// NSColor version of the gradient (for window backgrounds, etc) +- (NSColor *)patternColorForStyle:(GTMThemeStyle)style active:(BOOL)active; +@end + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.m new file mode 100644 index 00000000..aa7c9be0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMTheme.m @@ -0,0 +1,390 @@ +// +// GTMTheme.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +#import "GTMTheme.h" +#import "GTMNSColor+Luminance.h" + +static GTMTheme *gGTMDefaultTheme = nil; +NSString *kGTMThemeDidChangeNotification = @"kGTMThemeDidChangeNotification"; + +@interface GTMTheme () +- (void)bindToUserDefaults; +- (void)sendChangeNotification; +@end + +@implementation GTMTheme + ++ (void)setDefaultTheme:(GTMTheme *)theme { + if (gGTMDefaultTheme != theme) { + [gGTMDefaultTheme release]; + gGTMDefaultTheme = [theme retain]; + [gGTMDefaultTheme sendChangeNotification]; + } +} + ++ (GTMTheme *)defaultTheme { + @synchronized (self) { + if (!gGTMDefaultTheme) { + gGTMDefaultTheme = [[self alloc] init]; + [gGTMDefaultTheme bindToUserDefaults]; + } + } + return gGTMDefaultTheme; +} + +- (void)bindToUserDefaults { + NSUserDefaultsController * controller + = [NSUserDefaultsController sharedUserDefaultsController]; + [self bind:@"backgroundColor" + toObject:controller + withKeyPath:@"values.GTMThemeBackgroundColor" + options:[NSDictionary dictionaryWithObjectsAndKeys: + NSUnarchiveFromDataTransformerName, + NSValueTransformerNameBindingOption, + nil]]; + + [self bind:@"backgroundImage" + toObject:controller + withKeyPath:@"values.GTMThemeBackgroundImageData" + options:[NSDictionary dictionaryWithObjectsAndKeys: + NSUnarchiveFromDataTransformerName, + NSValueTransformerNameBindingOption, + nil]]; +} + +- (id)init { + self = [super init]; + if (self != nil) { + values_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)finalize { + [self unbind:@"backgroundColor"]; + [self unbind:@"backgroundImage"]; + [super finalize]; +} + +- (void)dealloc { + [self unbind:@"backgroundColor"]; + [self unbind:@"backgroundImage"]; + [values_ release]; + [super dealloc]; +} + +- (void)sendChangeNotification { + [[NSNotificationCenter defaultCenter] + postNotificationName:kGTMThemeDidChangeNotification + object:self]; +} + +- (id)keyForSelector:(SEL)selector + style:(GTMThemeStyle)style + active:(BOOL)active { + return [NSString stringWithFormat:@"%p.%d.%d", selector, style, active]; +} + +- (id)valueForSelector:(SEL)selector + style:(GTMThemeStyle)style + active:(BOOL)active { + id value = [values_ objectForKey: + [self keyForSelector:selector style:style active:active]]; + return value; +} + +- (void)cacheValue:(id)value + forSelector:(SEL)selector + style:(GTMThemeStyle)style + active:(BOOL)active { + id key = [self keyForSelector:selector style:style active:active]; + if (key && value) [values_ setObject:value forKey:key]; +} + +- (void)setBackgroundColor:(NSColor *)value { + if (backgroundColor_ != value) { + [backgroundColor_ release]; + backgroundColor_ = [value retain]; + [values_ removeAllObjects]; + [self sendChangeNotification]; + } +} +- (NSColor *)backgroundColor { + // For nil, we return a color that works with a normal textured window + if (!backgroundColor_) + return [NSColor colorWithCalibratedWhite:0.75 alpha:1.0]; + return backgroundColor_; +} + +- (void)setBackgroundImage:(NSImage *)value { + if (backgroundImage_ != value) { + [backgroundImage_ release]; + backgroundImage_ = [value retain]; + [self sendChangeNotification]; + } +} + +- (NSColor *)windowBackgroundColor:(BOOL)active { + NSColor *color = nil; + if (backgroundImage_) { + // TODO(alcor): dim images when disabled + color = [NSColor colorWithPatternImage:backgroundImage_]; + } else if (backgroundColor_) { + color = [self patternColorForStyle:GTMThemeStyleWindow active:active]; + } + return color; +} + +- (NSImage *)backgroundImage { + return backgroundImage_; +} + +- (NSBackgroundStyle)interiorBackgroundStyleForStyle:(GTMThemeStyle)style + active:(BOOL)active { + id value = [self valueForSelector:_cmd style:style active:active]; + if (value) return [value intValue]; + + NSGradient *gradient = [self gradientForStyle:style active:active]; + NSColor *color = [gradient interpolatedColorAtLocation:0.5]; + BOOL dark = [color gtm_isDarkColor]; + value = [NSNumber numberWithInt: dark ? NSBackgroundStyleLowered + : NSBackgroundStyleRaised]; + [self cacheValue:value forSelector:_cmd style:style active:active]; + return [value intValue]; +} + +- (BOOL)styleIsDark:(GTMThemeStyle)style active:(BOOL)active { + id value = [self valueForSelector:_cmd style:style active:active]; + if (value) return [value boolValue]; + + if (style == GTMThemeStyleToolBarButtonPressed) { + value = [NSNumber numberWithBool:YES]; + } else { + value = [NSNumber numberWithBool:[[self backgroundColor] gtm_isDarkColor]]; + } + [self cacheValue:value forSelector:_cmd style:style active:active]; + return [value boolValue]; +} + +- (NSColor *)patternColorForStyle:(GTMThemeStyle)style active:(BOOL)active { + NSColor *color = [self valueForSelector:_cmd style:style active:active]; + if (color) return color; + + NSGradient *gradient = [self gradientForStyle:style active:active]; + if (gradient) { + // create a gradient image for the background + CGRect r = CGRectZero; + // TODO(alcor): figure out a better way to get an image that is the right + // size + r.size = CGSizeMake(4, 36); + size_t bytesPerRow = 4 * r.size.width; + + CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + CGContextRef context = CGBitmapContextCreate(NULL, + r.size.width, + r.size.height, + 8, + bytesPerRow, + space, + kCGImageAlphaPremultipliedFirst); + CGColorSpaceRelease(space); + NSGraphicsContext *nsContext + = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:nsContext]; + [gradient drawInRect:NSMakeRect(0, 0, r.size.width, r.size.height) + angle:270]; + [NSGraphicsContext restoreGraphicsState]; + + CGImageRef cgImage = CGBitmapContextCreateImage(context); + CGContextRelease(context); + NSBitmapImageRep *rep = nil; + if (cgImage) { + rep = [[[NSBitmapImageRep alloc] initWithCGImage:cgImage] + autorelease]; + CGImageRelease(cgImage); + } + + NSImage *image = [[[NSImage alloc] initWithSize:NSSizeFromCGSize(r.size)] + autorelease]; + [image addRepresentation:rep]; + + color = [NSColor colorWithPatternImage:image]; + } + [self cacheValue:color forSelector:_cmd style:style active:active]; + return color; +} + +- (NSGradient *)gradientForStyle:(GTMThemeStyle)style active:(BOOL)active { + NSGradient *gradient = [self valueForSelector:_cmd style:style active:active]; + if (gradient) return gradient; + + BOOL useDarkColors = backgroundImage_ != nil || style == GTMThemeStyleWindow; + + NSUInteger uses[4]; + if (useDarkColors) { + uses[0] = GTMColorationBaseHighlight; + uses[1] = GTMColorationBaseMidtone; + uses[2] = GTMColorationBaseShadow; + uses[3] = GTMColorationBasePenumbra; + } else { + uses[0] = GTMColorationLightHighlight; + uses[1] = GTMColorationLightMidtone; + uses[2] = GTMColorationLightShadow; + uses[3] = GTMColorationLightPenumbra; + } + NSColor *backgroundColor = [self backgroundColor]; + switch (style) { + case GTMThemeStyleTabBarDeselected: { + NSColor *startColor = [[backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active] + colorWithAlphaComponent:0.667]; + NSColor *endColor = [[backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active] + colorWithAlphaComponent:0.667]; + + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + break; + } + case GTMThemeStyleTabBarSelected: { + NSColor *startColor = [backgroundColor gtm_colorAdjustedFor:uses[0] + faded:!active]; + NSColor *endColor = [backgroundColor gtm_colorAdjustedFor:uses[1] + faded:!active]; + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + break; + } + case GTMThemeStyleWindow: { + CGFloat luminance = [backgroundColor gtm_luminance]; + + // Adjust luminance so it never hits black + if (luminance < 0.5) { + CGFloat adjustment = (0.5 - luminance) / 1.5; + backgroundColor + = [backgroundColor gtm_colorByAdjustingLuminance:adjustment]; + } + NSColor *startColor = [backgroundColor gtm_colorAdjustedFor:uses[1] + faded:!active]; + NSColor *endColor = [backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active]; + + + if (!active) { + startColor = [startColor gtm_colorByAdjustingLuminance:0.1 + saturation:0.5]; + endColor = [endColor gtm_colorByAdjustingLuminance:0.1 + saturation:0.5]; + + } + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + break; + } + case GTMThemeStyleToolBar: { + NSColor *startColor = [backgroundColor gtm_colorAdjustedFor:uses[1] + faded:!active]; + NSColor *endColor = [backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active]; + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + break; + } + case GTMThemeStyleToolBarButton: { + NSColor *startColor = [backgroundColor gtm_colorAdjustedFor:uses[0] + faded:!active]; + NSColor *midColor = [backgroundColor gtm_colorAdjustedFor:uses[1] + faded:!active]; + NSColor *endColor = [backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active]; + NSColor *glowColor = [backgroundColor gtm_colorAdjustedFor:uses[3] + faded:!active]; + + gradient = [[[NSGradient alloc] initWithColorsAndLocations: + startColor, 0.0, + midColor, 0.5, + endColor, 0.9, + glowColor, 1.0, + nil] autorelease]; + break; + } + case GTMThemeStyleToolBarButtonPressed: { + NSColor *startColor = [backgroundColor + gtm_colorAdjustedFor:GTMColorationBaseShadow + faded:!active]; + NSColor *endColor = [backgroundColor + gtm_colorAdjustedFor:GTMColorationBaseMidtone + faded:!active]; + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + break; + } + case GTMThemeStyleBookmarksBar: { + NSColor *startColor = [backgroundColor gtm_colorAdjustedFor:uses[2] + faded:!active]; + NSColor *endColor = [backgroundColor gtm_colorAdjustedFor:uses[3] + faded:!active]; + + gradient = [[[NSGradient alloc] initWithStartingColor:startColor + endingColor:endColor] + autorelease]; + + break; + } + default: + _GTMDevLog(@"Unexpected style: %d", style); + break; + } + + [self cacheValue:gradient forSelector:_cmd style:style active:active]; + return gradient; +} + +- (NSColor *)strokeColorForStyle:(GTMThemeStyle)style active:(BOOL)active { + NSColor *color = [self valueForSelector:_cmd style:style active:active]; + if (color) return color; + NSColor *backgroundColor = [self backgroundColor]; + switch (style) { + case GTMThemeStyleToolBarButton: + color = [[backgroundColor gtm_colorAdjustedFor:GTMColorationDarkShadow + faded:!active] + colorWithAlphaComponent:0.3]; + break; + case GTMThemeStyleToolBar: + case GTMThemeStyleBookmarksBar: + default: + color = [[self backgroundColor] gtm_colorAdjustedFor:GTMColorationBaseShadow + faded:!active]; + break; + } + + [self cacheValue:color forSelector:_cmd style:style active:active]; + return color; +} + +@end + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMThemeTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMThemeTest.m new file mode 100644 index 00000000..3e37c1fe --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/AppKit/GTMThemeTest.m @@ -0,0 +1,67 @@ +// +// GTMThemeTest.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +#import "GTMSenTestCase.h" +#import "GTMTheme.h" + +@interface GTMThemeTest : GTMTestCase +@end + +@implementation GTMThemeTest + +- (void)testTheming { + GTMTheme *theme = [GTMTheme defaultTheme]; + + // When there are no values, use window default colors + STAssertEqualObjects([theme backgroundColor], + [NSColor colorWithCalibratedWhite:0.75 alpha:1.0], nil); + STAssertNil([theme windowBackgroundColor:YES], nil); + STAssertNil([theme backgroundImage], nil); + + NSColor *color = [NSColor redColor]; + NSData *colorData = [NSArchiver archivedDataWithRootObject:color]; + [[NSUserDefaults standardUserDefaults] setObject:colorData + forKey:@"GTMThemeBackgroundColor"]; + + STAssertNotNil([theme windowBackgroundColor:YES], nil); + STAssertNotNil([theme patternColorForStyle:GTMThemeStyleToolBar + active:YES], nil); + STAssertNotNil([theme strokeColorForStyle:GTMThemeStyleToolBar + active:YES], nil); + STAssertNotNil([theme gradientForStyle:GTMThemeStyleToolBar + active:YES], nil); + + STAssertEqualObjects([theme backgroundColor], + color, nil); + + // TODO(alcor): add more of these cases once the constants are more concrete + STAssertEquals([theme interiorBackgroundStyleForStyle:GTMThemeStyleToolBar + active:YES], + (NSBackgroundStyle)NSBackgroundStyleRaised, nil); + + [[NSUserDefaults standardUserDefaults] removeObjectForKey: + @"GTMThemeBackgroundColor"]; +} + +@end + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildScripts/BuildAllSDKs.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildScripts/BuildAllSDKs.sh new file mode 100644 index 00000000..32a867d4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildScripts/BuildAllSDKs.sh @@ -0,0 +1,116 @@ +#!/bin/sh +# BuildAllSDKs.sh +# +# This script builds the Tiger, Leopard, SnowLeopard and iPhone versions of the +# requested target in the current basic config (debug, release, debug-gcov). +# +# Copyright 2006-2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +GTM_PROJECT_TARGET="$1" +GTMIPHONE_PROJECT_TARGET="$2" +STARTING_TARGET="${TARGET_NAME}" +SCRIPT_APP="${TMPDIR}DoBuild.app" + +REQUESTED_BUILD_STYLE=$(echo "${BUILD_STYLE}" | sed -E "s/(.*OrLater-)?(.*)/\2/") +# See if we were told to clean instead of build. +PROJECT_ACTION="build" +if [ "${ACTION}" == "clean" ]; then + PROJECT_ACTION="clean" +fi + +# get available SDKs and PLATFORMS +AVAILABLE_MACOS_SDKS=`eval ls ${DEVELOPER_SDK_DIR}` +AVAILABLE_PLATFORMS=`eval ls ${DEVELOPER_DIR}/Platforms` + +# build up our GTMiPhone parts +GTMIPHONE_OPEN_EXTRAS="" +GTMIPHONE_BUILD_EXTRAS="" +if [ "${GTMIPHONE_PROJECT_TARGET}" != "" ]; then + GTMIPHONE_OPEN_EXTRAS=" + if \"${AVAILABLE_PLATFORMS}\" contains \"iPhoneSimulator.platform\" then + -- make sure both project files are open + open posix file \"${SRCROOT}/GTM.xcodeproj\" + open posix file \"${SRCROOT}/GTMiPhone.xcodeproj\" + end if" + GTMIPHONE_BUILD_EXTRAS=" + if \"${AVAILABLE_PLATFORMS}\" contains \"iPhoneSimulator.platform\" then + with timeout of 9999 seconds + tell project \"GTMiPhone\" + -- do the GTMiPhone build + ${PROJECT_ACTION} using build configuration \"${REQUESTED_BUILD_STYLE}\" + set active target to target \"${STARTING_TARGET}\" + end tell + end timeout + end if" +fi + +# build up our GTM AppleScript +OUR_BUILD_SCRIPT="on run + tell application \"Xcode\" + activate + ${GTMIPHONE_OPEN_EXTRAS} + if \"${AVAILABLE_PLATFORMS}\" contains \"MacOSX.platform\" then + tell project \"GTM\" + -- wait for build to finish + set x to 0 + repeat while currently building + delay 0.5 + set x to x + 1 + if x > 6 then + display alert \"GTM is still building, can't start.\" + return + end if + end repeat + -- do the GTM builds + with timeout of 9999 seconds + if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.4u.sdk\" then + set active target to target \"${GTM_PROJECT_TARGET}\" + set buildResult to ${PROJECT_ACTION} using build configuration \"TigerOrLater-${REQUESTED_BUILD_STYLE}\" + set active target to target \"${STARTING_TARGET}\" + if buildResult is not equal to \"Build succeeded\" then + return + end if + end if + if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.5.sdk\" then + set active target to target \"${GTM_PROJECT_TARGET}\" + set buildResult to ${PROJECT_ACTION} using build configuration \"LeopardOrLater-${REQUESTED_BUILD_STYLE}\" + set active target to target \"${STARTING_TARGET}\" + if buildResult is not equal to \"Build succeeded\" then + return + end if + end if + if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.6.sdk\" then + set active target to target \"${GTM_PROJECT_TARGET}\" + set buildResult to ${PROJECT_ACTION} using build configuration \"SnowLeopardOrLater-${REQUESTED_BUILD_STYLE}\" + set active target to target \"${STARTING_TARGET}\" + if buildResult is not equal to \"Build succeeded\" then + return + end if + end if + end timeout + end tell + end if + ${GTMIPHONE_BUILD_EXTRAS} + end tell +end run" + +# Xcode won't actually let us spawn this and run it w/ osascript because it +# watches and waits for everything we have spawned to exit before the build is +# considered done, so instead we compile this to a script app, and then use +# open to invoke it, there by escaping our little sandbox. +# xcode defeats this: ( echo "${OUR_BUILD_SCRIPT}" | osascript - & ) +rm -rf "${SCRIPT_APP}" +echo "${OUR_BUILD_SCRIPT}" | osacompile -o "${SCRIPT_APP}" -x +open "${SCRIPT_APP}" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildingAndUsing.txt b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildingAndUsing.txt new file mode 100644 index 00000000..67bbd797 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/BuildingAndUsing.txt @@ -0,0 +1,18 @@ +The GTM project provides a Framework target and Unit Testing targets. + +Unit Testing Targets - + +These targets are there to make sure all of GTM is working, and reflect the +hierarchy of the source tree. + +Building the "All UnitTests" target will build all of the unittests for the +current configuration included in the GTM package. We require that "All +UnitTests" builds cleanly before we will accept any code submissions. + +Framework Target - + +These targets are there to make it easy for anyone to quickly add GTM sources +to their own project to start using it or playing around with it. However, +the intent is for a developer to manually add the sources to their project in +the end to reduce the total size of their product (since they only have to +include the parts of GTM they need). diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/COPYING b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/COPYING new file mode 100644 index 00000000..a95e82aa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2007 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugSelectorValidation.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugSelectorValidation.h new file mode 100644 index 00000000..19d8b8eb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugSelectorValidation.h @@ -0,0 +1,100 @@ +// +// GTMDebugSelectorValidation.h +// +// This file should only be included within an implimation file. In any +// function that takes an object and selector to invoke, you should call: +// +// GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, @encode(arg1type), ..., NULL) +// or +// GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(obj, sel, @encode(returnType), @encode(arg1type), ..., NULL) +// +// This will then validate that the selector is defined and using the right +// type(s), this can help catch errors much earlier then waiting for the +// selector to actually fire (and in the case of error selectors, might never +// really be tested until in the field). +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#if DEBUG + +#import +#import "GTMDefines.h" + +static void GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(id obj, SEL sel, const char *retType, ...) { + + // verify that the object's selector is implemented with the proper + // number and type of arguments + va_list argList; + va_start(argList, retType); + + if (obj && sel) { + // check that the selector is implemented + _GTMDevAssert([obj respondsToSelector:sel], + @"\"%@\" selector \"%@\" is unimplemented or misnamed", + NSStringFromClass([obj class]), + NSStringFromSelector(sel)); + + const char *expectedArgType; + NSUInteger argCount = 2; // skip self and _cmd + NSMethodSignature *sig = [obj methodSignatureForSelector:sel]; + + // check that each expected argument is present and of the correct type + while ((expectedArgType = va_arg(argList, const char*)) != 0) { + + if ([sig numberOfArguments] > argCount) { + const char *foundArgType = [sig getArgumentTypeAtIndex:argCount]; + + _GTMDevAssert(0 == strncmp(foundArgType, expectedArgType, strlen(expectedArgType)), + @"\"%@\" selector \"%@\" argument %d should be type %s", + NSStringFromClass([obj class]), + NSStringFromSelector(sel), + (argCount - 2), + expectedArgType); + } + argCount++; + } + + // check that the proper number of arguments are present in the selector + _GTMDevAssert(argCount == [sig numberOfArguments], + @"\"%@\" selector \"%@\" should have %d arguments", + NSStringFromClass([obj class]), + NSStringFromSelector(sel), + (argCount - 2)); + + // if asked, validate the return type + if (retType && (strcmp("gtm_skip_return_test", retType) != 0)) { + const char *foundRetType = [sig methodReturnType]; + _GTMDevAssert(0 == strncmp(foundRetType, retType, strlen(retType)), + @"\"%@\" selector \"%@\" return type should be type %s", + NSStringFromClass([obj class]), + NSStringFromSelector(sel), + retType); + } + } + + va_end(argList); +} + +#define GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, ...) \ + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments((obj), (sel), "gtm_skip_return_test", __VA_ARGS__) + +#else // DEBUG + +// make it go away if not debug +#define GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(obj, sel, retType, ...) do { } while (0) +#define GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, ...) do { } while (0) + +#endif // DEBUG diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.h new file mode 100644 index 00000000..0636159c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.h @@ -0,0 +1,55 @@ +// +// GTMDebugThreadValidation.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#if DEBUG +#import "GTMDefines.h" +#import + +// GTMAssertRunningOnMainThread will allow you to verify that you are +// currently running on the main thread. This can be useful for checking +// under DEBUG to make sure that code that requires being run on the main thread +// is doing so. Use the GTMAssertRunningOnMainThread macro, don't use +// the _GTMAssertRunningOnMainThread or _GTMIsRunningOnMainThread +// helper functions. + +// On Leopard and above we can just use NSThread functionality. +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +BOOL _GTMIsRunningOnMainThread(void); +#else // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +#import +GTM_INLINE BOOL _GTMIsRunningOnMainThread(void) { + return [NSThread isMainThread]; +} +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +GTM_INLINE void _GTMAssertRunningOnMainThread(const char *func, + const char *file, + int lineNum) { + _GTMDevAssert(_GTMIsRunningOnMainThread(), + @"%s not being run on main thread (%s - %d)", + func, file, lineNum); +} + +#define GTMAssertRunningOnMainThread() \ + (_GTMAssertRunningOnMainThread(__func__, __FILE__, __LINE__)) + +#else // DEBUG + +#define GTMAssertRunningOnMainThread() do { } while (0) + +#endif // DEBUG diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.m new file mode 100644 index 00000000..5889cd88 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidation.m @@ -0,0 +1,38 @@ +// +// GTMDebugThreadValidation.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#if DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +#import "GTMDebugThreadValidation.h" + +static NSThread *gGTMMainThread = nil; + +static __attribute__((constructor)) void _GTMInitThread(void) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + gGTMMainThread = [NSThread currentThread]; + [gGTMMainThread retain]; + [pool release]; +} + + +BOOL _GTMIsRunningOnMainThread(void) { + return [[NSThread currentThread] isEqual:gGTMMainThread]; +} + +#endif // DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidationTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidationTest.m new file mode 100644 index 00000000..66bd51b7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMDebugThreadValidationTest.m @@ -0,0 +1,110 @@ +// +// GTMDebugThreadValidationTest.m +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMDebugThreadValidation.h" + +// GTMDebugThreadValidation only happens on debug builds +#if DEBUG + +@interface GTMDebugThreadValidationTest : GTMTestCase +@end + +// A cheap flag for knowing when our thread has run + +static volatile BOOL gGTMDebugThreadValidationTestDone = NO; + +// This is an assertion handler that just records that an assertion has fired. +@interface GTMDebugThreadValidationCheckAssertionHandler : NSAssertionHandler { + @private + BOOL handledAssertion_; +} +- (void)handleFailureInMethod:(SEL)selector + object:(id)object + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format,...; + +- (void)handleFailureInFunction:(NSString *)functionName + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format,...; +- (BOOL)didHandleAssertion; +@end + +@implementation GTMDebugThreadValidationTest +- (void)testOnMainThread { + STAssertNoThrow(GTMAssertRunningOnMainThread(), nil); +} + +- (void)threadFunc:(NSMutableString *)result { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + // We'll insert our own assertion handler that will get called on the assert + // so that we don't have to worry about the log, and exception being thrown. + GTMDebugThreadValidationCheckAssertionHandler *handler = + [[[GTMDebugThreadValidationCheckAssertionHandler alloc] init] autorelease]; + NSMutableDictionary *threadDictionary + = [[NSThread currentThread] threadDictionary]; + [threadDictionary setObject:handler forKey:@"NSAssertionHandler"]; + GTMAssertRunningOnMainThread(); + if ([handler didHandleAssertion]) { + [result setString:@"ASSERTED"]; + } + [threadDictionary removeObjectForKey:@"NSAssertionHandler"]; + gGTMDebugThreadValidationTestDone = YES; + [pool release]; +} + +- (void)testOnOtherThread { + NSMutableString *result = [NSMutableString string]; + gGTMDebugThreadValidationTestDone = NO; + [NSThread detachNewThreadSelector:@selector(threadFunc:) + toTarget:self + withObject:result]; + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + + while (!gGTMDebugThreadValidationTestDone) { + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.01]; + [loop runUntilDate:date]; + } + STAssertEqualStrings(result, @"ASSERTED", @"GTMAssertRunningOnMainThread did " + @"not assert while running on another thread"); +} +@end + +@implementation GTMDebugThreadValidationCheckAssertionHandler + +- (void)handleFailureInMethod:(SEL)selector + object:(id)object + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format,... { + handledAssertion_ = YES; +} + +- (void)handleFailureInFunction:(NSString *)functionName + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format,... { + handledAssertion_ = YES; +} + +- (BOOL)didHandleAssertion { + return handledAssertion_; +} +@end +#endif // DEBUG diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.h new file mode 100644 index 00000000..7b0919b0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.h @@ -0,0 +1,88 @@ +// +// GTMMethodCheck.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import +#import + +/// A macro for enforcing debug time checks to make sure all required methods are linked in +// +// When using categories, it can be very easy to forget to include the +// implementation of a category. +// Let's say you had a class foo that depended on method bar of class baz, and +// method bar was implemented as a member of a category. +// You could add the following code: +// @implementation foo +// GTM_METHOD_CHECK(baz, bar) +// @end +// and the code would check to make sure baz was implemented just before main +// was called. This works for both dynamic libraries, and executables. +// +// Classes (or one of their superclasses) being checked must conform to the +// NSObject protocol. We will check this, and spit out a warning if a class does +// not conform to NSObject. +// +// This is not compiled into release builds. + +#ifdef DEBUG + +#ifdef __cplusplus +extern "C" { +#endif + +// If you get an error for GTMMethodCheckMethodChecker not being defined, +// you need to link in GTMMethodCheck.m. We keep it hidden so that we can have +// it living in several separate images without conflict. +// Functions with the ((constructor)) attribute are called after all +loads +// have been called. See "Initializing Objective-C Classes" in +// http://developer.apple.com/documentation/DeveloperTools/Conceptual/DynamicLibraries/Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-DontLinkElementID_20 + +__attribute__ ((constructor, visibility("hidden"))) void GTMMethodCheckMethodChecker(void); + +#ifdef __cplusplus +}; +#endif + +// This is the "magic". +// A) we need a multi layer define here so that the stupid preprocessor +// expands __LINE__ out the way we want it. We need LINE so that each of +// out GTM_METHOD_CHECKs generates a unique class method for the class. +#define GTM_METHOD_CHECK(class, method) GTM_METHOD_CHECK_INNER(class, method, __LINE__) +#define GTM_METHOD_CHECK_INNER(class, method, line) GTM_METHOD_CHECK_INNER_INNER(class, method, line) + +// B) Create up a class method called xxGMethodCheckMethod+class+line that the +// GTMMethodCheckMethodChecker function can look for and call. We +// look for GTMMethodCheckMethodChecker to enforce linkage of +// GTMMethodCheck.m. +#define GTM_METHOD_CHECK_INNER_INNER(class, method, line) \ ++ (void)xxGTMMethodCheckMethod ## class ## line { \ + void (*addr)() = GTMMethodCheckMethodChecker; \ + if (addr && ![class instancesRespondToSelector:@selector(method)] \ + && ![class respondsToSelector:@selector(method)]) { \ + fprintf(stderr, "%s:%d: error: We need method '%s' to be linked in for class '%s'\n", \ + __FILE__, line, #method, #class); \ + exit(EX_SOFTWARE); \ + } \ +} + +#else // !DEBUG + +// Do nothing in release. +#define GTM_METHOD_CHECK(class, method) + +#endif // DEBUG diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.m new file mode 100644 index 00000000..2f88dc36 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheck.m @@ -0,0 +1,163 @@ +// +// GTMMethodCheck.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Don't want any of this in release builds +#ifdef DEBUG +#import "GTMDefines.h" +#import "GTMMethodCheck.h" +#import "GTMObjC2Runtime.h" +#import + +// Checks to see if the cls passed in (or one of it's superclasses) conforms +// to NSObject protocol. Inheriting from NSObject is the easiest way to do this +// but not all classes (i.e. NSProxy) inherit from NSObject. Also, some classes +// inherit from Object instead of NSObject which is fine, and we'll count as +// conforming to NSObject for our needs. +static BOOL ConformsToNSObjectProtocol(Class cls) { + // If we get nil, obviously doesn't conform. + if (!cls) return NO; + const char *className = class_getName(cls); + if (!className) return NO; + + // We're going to assume that all Apple classes will work + // (and aren't being checked) + // Note to apple: why doesn't obj-c have real namespaces instead of two + // letter hacks? If you name your own classes starting with NS this won't + // work for you. + // Some classes (like _NSZombie) start with _NS. + // On Leopard we have to look for CFObject as well. + // On iPhone we check Object as well + if ((strncmp(className, "NS", 2) == 0) + || (strncmp(className, "_NS", 3) == 0) + || (strcmp(className, "CFObject") == 0) +#if GTM_IPHONE_SDK + || (strcmp(className, "Object") == 0) +#endif + ) { + return YES; + } + +// iPhone SDK does not define the |Object| class, so we instead test for the +// |NSObject| class. +#if GTM_IPHONE_SDK + // Iterate through all the protocols |cls| supports looking for NSObject. + if (cls == [NSObject class] + || class_conformsToProtocol(cls, @protocol(NSObject))) { + return YES; + } +#else + // Iterate through all the protocols |cls| supports looking for NSObject. + if (cls == [Object class] + || class_conformsToProtocol(cls, @protocol(NSObject))) { + return YES; + } +#endif + + // Recursively check the superclasses. + return ConformsToNSObjectProtocol(class_getSuperclass(cls)); +} + +void GTMMethodCheckMethodChecker(void) { + // Run through all the classes looking for class methods that are + // prefixed with xxGMMethodCheckMethod. If it finds one, it calls it. + // See GTMMethodCheck.h to see what it does. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int numClasses = 0; + int newNumClasses = objc_getClassList(NULL, 0); + int i; + Class *classes = NULL; + while (numClasses < newNumClasses) { + numClasses = newNumClasses; + classes = realloc(classes, sizeof(Class) * numClasses); + _GTMDevAssert(classes, @"Unable to allocate memory for classes"); + newNumClasses = objc_getClassList(classes, numClasses); + } + for (i = 0; i < numClasses && classes; ++i) { + Class cls = classes[i]; + + // Since we are directly calling objc_msgSend, we need to conform to + // @protocol(NSObject), or else we will tumble into a _objc_msgForward + // recursive loop when we try and call a function by name. + if (!ConformsToNSObjectProtocol(cls)) { + // COV_NF_START + _GTMDevLog(@"GTMMethodCheckMethodChecker: Class %s does not conform to " + "@protocol(NSObject), so won't be checked", + class_getName(cls)); + continue; + // COV_NF_END + } + // Since we are looking for a class method (+xxGMMethodCheckMethod...) + // we need to query the isa pointer to see what methods it support, but + // send the method (if it's supported) to the class itself. + unsigned int count; + Class metaClass = objc_getMetaClass(class_getName(cls)); + Method *methods = class_copyMethodList(metaClass, &count); + unsigned int j; + for (j = 0; j < count; ++j) { + SEL selector = method_getName(methods[j]); + const char *name = sel_getName(selector); + if (strstr(name, "xxGTMMethodCheckMethod") == name) { + // Check to make sure that the method we are checking comes + // from the same image that we are in. Since GTMMethodCheckMethodChecker + // is not exported, we should always find the copy in our local + // image. We compare the address of it's image with the address of + // the image which implements the method we want to check. If + // they match we continue. This does two things: + // a) minimizes the amount of calls we make to the xxxGTMMethodCheck + // methods. They should only be called once. + // b) prevents initializers for various classes being called too early + Dl_info methodCheckerInfo; + if (!dladdr(GTMMethodCheckMethodChecker, + &methodCheckerInfo)) { + // COV_NF_START + // Don't know how to force this case in a unittest. + // Certainly hope we never see it. + _GTMDevLog(@"GTMMethodCheckMethodChecker: Unable to get dladdr info " + "for GTMMethodCheckMethodChecker while introspecting +[%@ %@]]", + class_getName(cls), name); + continue; + // COV_NF_END + } + Dl_info methodInfo; + if (!dladdr(method_getImplementation(methods[j]), + &methodInfo)) { + // COV_NF_START + // Don't know how to force this case in a unittest + // Certainly hope we never see it. + _GTMDevLog(@"GTMMethodCheckMethodChecker: Unable to get dladdr info " + "for %@ while introspecting +[%@ %@]]", name, + class_getName(cls), name); + continue; + // COV_NF_END + } + if (methodCheckerInfo.dli_fbase == methodInfo.dli_fbase) { + objc_msgSend(cls, selector); + } + } + } + if (methods) { + free(methods); + } + } + if (classes) { + free(classes); + } + [pool release]; +} + +#endif // DEBUG diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheckTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheckTest.m new file mode 100644 index 00000000..974dfafd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/DebugUtils/GTMMethodCheckTest.m @@ -0,0 +1,53 @@ +// +// GTMMethodCheckTest.m +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMMethodCheck.h" + +static BOOL gTestCheckVar = NO; + +@interface GTMMethodCheckTest : GTMTestCase ++ (void)GTMMethodCheckTestClassMethod; +@end + +@implementation GTMMethodCheckTest +GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestMethod); +GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestClassMethod); + +- (void)GTMMethodCheckTestMethod { +} + ++ (void)GTMMethodCheckTestClassMethod { +} + ++ (void)xxGTMMethodCheckMethodTestCheck { + // This gets called because of its special name by GMMethodCheck + // Look at the Macros in GMMethodCheck.h for details. + gTestCheckVar = YES; +} + +- (void)testGTMMethodCheck { +#ifdef DEBUG + // GTMMethodCheck only runs in debug + STAssertTrue(gTestCheckVar, @"Should be true"); +#endif + + // Next two calls just verify our code coverage + [self GTMMethodCheckTestMethod]; + [[self class] GTMMethodCheckTestClassMethod]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.h new file mode 100644 index 00000000..e8657279 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.h @@ -0,0 +1,222 @@ +// +// GTMAbstractDOListener.h +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +@class GTMReceivePortDelegate; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +// Abstract base class for DO "listeners". +// A class that needs to vend itself over DO should subclass this abstract +// class. This class takes care of certain things like creating a new thread +// to handle requests, setting request/reply timeouts, and ensuring the vended +// object only gets requests that comply with the specified protocol. +// +// Subclassers will want to use the +// GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL macro for easier debugging +// of stack traces. Please read it's description below. +// +@interface GTMAbstractDOListener : NSObject { + @protected + NSString *registeredName_; + __weak Protocol *protocol_; + NSConnection *connection_; + BOOL isRunningInNewThread_; + BOOL shouldShutdown_; + NSTimeInterval requestTimeout_; + NSTimeInterval replyTimeout_; + NSPort *port_; + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + GTMReceivePortDelegate *receivePortDelegate_; // Strong (only used on Tiger) +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +} + +// Returns a set of all live instances of GTMAbstractDOListener subclasses. +// If no listeners have been created, this will return an empty array--not nil. +// +// TODO: Remove this method +// ++ (NSArray *)allListeners; + +// Initializer. This actually calls +// initWithRegisteredName:protocol:port with [NSMachPort port] as the port. +// +// Args: +// name - the name that the object will register under +// proto - the protocol that this object (self) should conform to +// +- (id)initWithRegisteredName:(NSString *)name protocol:(Protocol *)proto; + +// The designated initializer. +// +// Args: +// name - the name used to register the port. While not necessarily required +// for an NSSocketPort this class still requires it. +// proto - the protocol that this object (self) should conform to +// port - the port to be used when creating the NSConnection. If a NSMachPort +// is being used then initWithRegisteredName:protocol is recommended. +// Otherwise the port must be allocted by the caller. +// +- (id)initWithRegisteredName:(NSString *)name + protocol:(Protocol *)proto + port:(NSPort *)port; + +// Returns the name that this server will register with the +// mach port name sever. This is the name of the port that this class +// will "listen" on when -runInNewThread is called. +// +// Returns: +// The registered name as a string +// +- (NSString *)registeredName; + +// Sets the registered name to use when listening over DO. This only makes +// sense to be called before -runInNewThread has been called, because +// -runInNewThread will listen on this "registered name", so setting it +// afterwards would do nothing. +// +// Args: +// name - the name to register under. May not be nil. +// +- (void)setRegisteredName:(NSString *)name; + +// Get/set the request timeout interval. If set to a value less than 0, +// the default DO connection timeout will be used (maximum possible value). +// +- (NSTimeInterval)requestTimeout; +- (void)setRequestTimeout:(NSTimeInterval)timeout; + +// Get/set the reply timeout interval. If set to a value less than 0, +// the default DO connection timeout will be used (maximum possible value). +// +- (NSTimeInterval)replyTimeout; +- (void)setReplyTimeout:(NSTimeInterval)timeout; + +// Returns the listeners associated NSConnection. May be nil if no connection +// has been setup yet. +// +- (NSConnection *)connection; + +// Starts the DO system listening using the current thread and current runloop. +// It only makes sense to call this method -OR- -runInNewThread, but not both. +// Returns YES if it was able to startup the DO listener, NO otherwise. +// +- (BOOL)runInCurrentThread; + +// Starts the DO system listening, and creates a new thread to handle the DO +// connections. It only makes sense to call this method -OR- +// -runInCurrentThread, but not both. +// if |errObject| is non nil, it will be used along with |selector| and +// |argument| to signal that the startup of the listener in the new thread +// failed. The actual selector will be invoked back on the main thread so +// it does not have to be thread safe. +// The most basic way to call this method is as follows: +// [listener runInNewThreadWithErrorTarget:nil +// selector:NULL +// withObjectArgument:nil]; +// +// Note: Using the example above you will not know if the listener failed to +// startup due to some error. +// +- (void)runInNewThreadWithErrorTarget:(id)errObject + selector:(SEL)selector + withObjectArgument:(id)argument; + +// Shuts down the connection. If it was running in a new thread, that thread +// should exit (within about 10 seconds). This call does not block. +// +// NOTE: This method is called in -dealloc, so if -runInNewThread had previously +// been called, -dealloc will return *before* the thread actually exits. This +// can be a problem as "self" may be gone before the thread exits. This is a +// bug and needs to be fixed. Currently, to be safe, only call -shutdown if +// -runInCurrentThread had previously been called. +// +- (void)shutdown; + +@end + + +// Methods that subclasses may implement to vary the behavior of this abstract +// class. +// +@interface GTMAbstractDOListener (GTMAbstractDOListenerSubclassMethods) + +// Called by the -runIn* methods. In the case where a new thread is being used, +// this method is called on the new thread. The default implementation of this +// method just returns YES, but subclasses can override it to do subclass +// specific initialization. If this method returns NO, the -runIn* method that +// called it will fail with an error. +// +// Returns: +// YES if the -runIn* method should continue successfully, NO if the it should +// fail. +// +- (BOOL)doRunInitialization; + +// Called as the "main" for the thread spun off by GTMAbstractDOListener. +// Not really for use by subclassers, except to use the +// GTMABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL macro defined below. +// +// This method runs forever in a new thread. This method actually starts the +// DO connection listening. +// +- (void)threadMain:(NSInvocation *)failureCallback; + +@end + +// GTMAbstractDOListeners used to be hard to debug because crashes in their +// stacks looked like this: +// +// #0 0x90009cd7 in mach_msg_trap () +// #1 0x90009c38 in mach_msg () +// #2 0x9082d2b3 in CFRunLoopRunSpecific () +// #3 0x9082cace in CFRunLoopRunInMode () +// #4 0x9282ad3a in -[NSRunLoop runMode:beforeDate:] () +// #5 0x928788e4 in -[NSRunLoop runUntilDate:] () +// #6 0x00052696 in -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] ... +// #7 0x927f52e0 in forkThreadForFunction () +// #8 0x90024227 in _pthread_body () +// +// and there was no good way to figure out what thread had the problem because +// they all originated from +// -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] +// +// If you add GTMABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL to the impl of your +// subclass you will get a stack that looks like this: +// #0 0x90009cd7 in mach_msg_trap () +// #1 0x90009c38 in mach_msg () +// #2 0x9082d2b3 in CFRunLoopRunSpecific () +// #3 0x9082cace in CFRunLoopRunInMode () +// #4 0x9282ad3a in -[NSRunLoop runMode:beforeDate:] () +// #5 0x928788e4 in -[NSRunLoop runUntilDate:] () +// #6 0x00052696 in -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] ... +// #7 0x0004b35c in -[GDStatsListener threadMain:] +// #8 0x927f52e0 in forkThreadForFunction () #9 0x90024227 in _pthread_body () +// +// so we can see that this was the GDStatsListener thread that failed. +// It will look something like this +// @implemetation MySubclassOfGTMAbstractDOListenerSubclassMethods +// GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL +// .... +// @end + +#define GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL \ + - (void)threadMain:(NSInvocation *)failureCallback { \ + [super threadMain:failureCallback]; \ + } diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.m new file mode 100644 index 00000000..772960bb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.m @@ -0,0 +1,438 @@ +// +// GTMAbstractDOListener.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMAbstractDOListener.h" +#import "GTMSystemVersion.h" +#import + +// Hack workaround suggested by DTS for the DO deadlock bug. Basically, this +// class intercepts the delegate role for DO's receive port (which is an +// NSMachPort). When -handlePortMessage: is called, it verifies that the send +// and receive ports are not nil, then forwards the message on to the original +// delegate. If the ports are nil, then the resulting NSConnection would +// eventually cause us to deadlock. In this case, it simply ignores the +// message. This is only need on Tiger. +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +@interface GTMReceivePortDelegate : NSObject { + __weak id delegate_; +} +- (id)initWithDelegate:(id)delegate; +- (void)handlePortMessage:(NSPortMessage *)message; +@end +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +@interface GTMAbstractDOListener (PrivateMethods) +- (BOOL)startListening; +- (void)stopListening; + +// Returns a description of the port based on the type of port. +- (NSString *)portDescription; + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +// Uses the GTMReceivePortDelegate hack (see comments above) if we're on Tiger. +- (void)hackaroundTigerDOWedgeBug:(NSConnection *)conn; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +@end + +// Static global set that holds a pointer to all instances of +// GTMAbstractDOListener subclasses. +// +static NSMutableSet *gAllListeners = nil; + +@implementation GTMAbstractDOListener + ++ (void)initialize { + if (self == [GTMAbstractDOListener class]) { + // We create the set using CFSetCreateMutable because we don't + // want to retain things in this set. If we retained things in the + // set we would never be able to dealloc ourselves because we + // add "self" to this set in it's init routine would cause an + // extra retain to be added to it. + gAllListeners = (NSMutableSet*)CFSetCreateMutable(NULL, 0, NULL); + } +} + ++ (NSArray *)allListeners { + // We return an NSArray instead of an NSSet here because NSArrays look nicer + // when displayed as %@ + NSArray *allListeners = nil; + + @synchronized (gAllListeners) { + allListeners = [gAllListeners allObjects]; + } + return allListeners; +} + +- (id)init { + return [self initWithRegisteredName:nil protocol:NULL]; +} + +- (id)initWithRegisteredName:(NSString *)name protocol:(Protocol *)proto { + return [self initWithRegisteredName:name + protocol:proto + port:[NSMachPort port]]; +} + +- (id)initWithRegisteredName:(NSString *)name + protocol:(Protocol *)proto + port:(NSPort *)port { + self = [super init]; + if (!self) { + return nil; + } + + if ((!proto) || (!port) || (!name)) { + if (!proto) { + _GTMDevLog(@"Failed to create a listener, a protocol must be specified"); + } + + if (!port) { + _GTMDevLog(@"Failed to create a listener, a port must be specified"); + } + + if (!name) { + _GTMDevLog(@"Failed to create a listener, a name must be specified"); + } + + [self release]; + return nil; + } + + registeredName_ = [name copy]; + protocol_ = proto; // Can't retain protocols + port_ = [port retain]; + + requestTimeout_ = -1; + replyTimeout_ = -1; + + _GTMDevAssert(gAllListeners, @"gAllListeners is not nil"); + @synchronized (gAllListeners) { + [gAllListeners addObject:self]; + } + + return self; +} + +- (void)dealloc { + _GTMDevAssert(gAllListeners, @"gAllListeners is not nil"); + @synchronized (gAllListeners) { + [gAllListeners removeObject:self]; + } + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + [receivePortDelegate_ release]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + + [self shutdown]; + [port_ release]; + [registeredName_ release]; + [super dealloc]; +} + + +#pragma mark Getters and Setters + +- (NSString *)registeredName { + return registeredName_; +} + +- (void)setRegisteredName:(NSString *)name { + if (!name) { + return; + } + [registeredName_ autorelease]; + registeredName_ = [name copy]; +} + +- (NSTimeInterval)requestTimeout { + return requestTimeout_; +} + +- (void)setRequestTimeout:(NSTimeInterval)timeout { + requestTimeout_ = timeout; +} + +- (NSTimeInterval)replyTimeout { + return replyTimeout_; +} + +- (void)setReplyTimeout:(NSTimeInterval)timeout { + replyTimeout_ = timeout; +} + +- (NSConnection *)connection { + return connection_; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@<%p> { name=\"%@\", %@ }", + [self class], self, registeredName_, [self portDescription]]; +} + +#pragma mark "Run" methods + +- (BOOL)runInCurrentThread { + return [self startListening]; +} + +- (void)runInNewThreadWithErrorTarget:(id)errObject + selector:(SEL)selector + withObjectArgument:(id)argument { + NSInvocation *invocation = nil; + + _GTMDevAssert(((errObject != nil && selector != NULL) || + (!errObject && !selector)), @"errObject and selector must " + @"both be nil or not nil"); + + // create an invocation we can use if things fail + if (errObject) { + NSMethodSignature *signature = + [errObject methodSignatureForSelector:selector]; + invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:selector]; + [invocation setTarget:errObject]; + + // If the selector they passed in takes an arg (i.e., it has at least one + // colon in the selector name), then set the first user-specified arg to be + // the |argument| they specified. The first two args are self and _cmd. + if ([signature numberOfArguments] > 2) { + [invocation setArgument:&argument atIndex:2]; + } + + [invocation retainArguments]; + } + + shouldShutdown_ = NO; + [NSThread detachNewThreadSelector:@selector(threadMain:) + toTarget:self + withObject:invocation]; +} + +- (void)shutdown { + // If we're not running in a new thread (then we're running in the "current" + // thread), tear down the NSConnection here. If we are running in a new + // thread we just set the shouldShutdown_ flag, and the thread will teardown + // the NSConnection itself. + if (!isRunningInNewThread_) { + [self stopListening]; + } else { + shouldShutdown_ = YES; + } +} + +@end + +@implementation GTMAbstractDOListener (PrivateMethods) + +- (BOOL)startListening { + BOOL result = NO; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + connection_ = [[NSConnection alloc] initWithReceivePort:port_ sendPort:nil]; + + NSProtocolChecker *checker = + [NSProtocolChecker protocolCheckerWithTarget:self + protocol:protocol_]; + + if (requestTimeout_ >= 0) { + [connection_ setRequestTimeout:requestTimeout_]; + } + + if (replyTimeout_ >= 0) { + [connection_ setReplyTimeout:replyTimeout_]; + } + + // Set the connection's root object to be the protocol checker so that only + // methods listed in the protocol_ are available via DO. + [connection_ setRootObject:checker]; + + // Allow subclasses to be the connection delegate + [connection_ setDelegate:self]; + + // Because of radar 5493309 we need to do this. [NSConnection registeredName:] + // returns NO when the connection is created using an NSSocketPort under + // Leopard. + // + // The recommendation from Apple was to use the command: + // [NSConnection registerName:withNameServer:]. + NSPortNameServer *server; + if ([port_ isKindOfClass:[NSSocketPort class]]) { + server = [NSSocketPortNameServer sharedInstance]; + } else { + server = [NSPortNameServer systemDefaultPortNameServer]; + } + + BOOL registered = [connection_ registerName:registeredName_ + withNameServer:server]; + + if (registeredName_ && registered) { +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + [self hackaroundTigerDOWedgeBug:connection_]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + + result = YES; + + _GTMDevLog(@"listening on %@ with name '%@'", [self portDescription], + registeredName_); + } else { + _GTMDevLog(@"failed to register %@ with %@", connection_, registeredName_); + } + + // we're good, so call the overrideable initializer + if (result) { + // Call the virtual "runIn*" initializer + result = [self doRunInitialization]; + } + + [pool drain]; + + return result; +} + +- (void)stopListening { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [connection_ invalidate]; + [connection_ release]; + connection_ = nil; + [pool drain]; +} + +- (NSString *)portDescription { + NSString *portDescription; + if ([port_ isKindOfClass:[NSMachPort class]]) { + portDescription = [NSString stringWithFormat:@"mach_port=%#x", + [(NSMachPort *)port_ machPort]]; + } else { + portDescription = [NSString stringWithFormat:@"port=%@", + [port_ description]]; + } + return portDescription; +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +- (void)hackaroundTigerDOWedgeBug:(NSConnection *)conn { + if ([GTMSystemVersion isTiger]) { + NSPort *receivePort = [conn receivePort]; + if ([receivePort isKindOfClass:[NSMachPort class]]) { + id portDelegate = [receivePort delegate]; + receivePortDelegate_ = + [[GTMReceivePortDelegate alloc] initWithDelegate:portDelegate]; + [receivePort setDelegate:receivePortDelegate_]; + } + } +} +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +@end + +@implementation GTMAbstractDOListener (GTMAbstractDOListenerSubclassMethods) + +- (BOOL)doRunInitialization { + return YES; +} + +// +// -threadMain: +// + +// +- (void)threadMain:(NSInvocation *)failureCallback { + isRunningInNewThread_ = YES; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // register + if ([self startListening]) { + // spin + for (;;) { // Run forever + + // check if we were asked to shutdown + if (shouldShutdown_) { + break; + } + + NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; + // Wrap our runloop in case we get an exception from DO + @try { + NSDate *waitDate = [NSDate dateWithTimeIntervalSinceNow:10]; + [[NSRunLoop currentRunLoop] runUntilDate:waitDate]; + } @catch (id e) { + _GTMDevLog(@"Listener '%@' caught exception: %@", registeredName_, e); + } + [localPool drain]; + } + } else { + // failed, if we had something to invoke, call it on the main thread + if (failureCallback) { + [failureCallback performSelectorOnMainThread:@selector(invoke) + withObject:nil + waitUntilDone:NO]; + } + } + + [self stopListening]; + [pool drain]; + + isRunningInNewThread_ = NO; +} + +@end + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +@implementation GTMReceivePortDelegate + +- (id)initWithDelegate:(id)delegate { + if ((self = [super init])) { + delegate_ = delegate; // delegates aren't retained + } + return self; +} + +- (void)handlePortMessage:(NSPortMessage *)message { + NSPort *receivePort = [message receivePort]; + NSPort *sendPort = [message sendPort]; + + // If we don't have a sensible send or receive port, just act like + // the message never arrived. Otherwise, hand it off to the original + // delegate (which is the NSMachPort itself). + if (receivePort == nil || sendPort == nil || [receivePort isEqual:sendPort]) { + _GTMDevLog(@"Dropping port message destined for itself to avoid DO wedge."); + } else { + // Uncomment for super-duper verbose DO message forward logging + // _GTMDevLog(@"--> Forwarding message %@ to delegate %@", + // message, delegate_); + [delegate_ handlePortMessage:message]; + } + + // If processing the message caused us to drop no longer being the delegate, + // set us back. Due to interactions between NSConnection and NSMachPort, + // it's possible for the NSMachPort's delegate to get set back to its + // original value. If that happens, we set it back to the value we want. + if ([delegate_ delegate] != self) { + if ([delegate_ delegate] == delegate_) { + _GTMDevLog(@"Restoring DO delegate to %@", self); + [delegate_ setDelegate:self]; + } else { + _GTMDevLog(@"GMReceivePortDelegate replaced with %@", + [delegate_ delegate]); + } + } +} +@end +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListenerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListenerTest.m new file mode 100644 index 00000000..6076724a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListenerTest.m @@ -0,0 +1,61 @@ +// +// GTMAbstractDOListenerTest.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMAbstractDOListener.h" + +// Needed for GTMIsGarbageCollectionEnabled +#import "GTMGarbageCollection.h" + +@interface GTMAbstractDOListenerTest : GTMTestCase +@end + +// TODO: we need to add more tests for this class. Examples: send messages and +// send messages that are in the protocol. + +@implementation GTMAbstractDOListenerTest + +- (void)testAbstractDOListenerRelease { + NSUInteger listenerCount = [[GTMAbstractDOListener allListeners] count]; + GTMAbstractDOListener *listener = + [[GTMAbstractDOListener alloc] initWithRegisteredName:@"FOO" + protocol:@protocol(NSObject) + port:[NSPort port]]; + STAssertNotNil(listener, nil); + + // We throw an autorelease pool here because allStores does a couple of + // autoreleased retains on us which would screws up our retain count + // numbers. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + STAssertEquals([[GTMAbstractDOListener allListeners] count], + listenerCount + 1, nil); + [pool drain]; + + if (!GTMIsGarbageCollectionEnabled()) { + // Not much point with GC on. + STAssertEquals([listener retainCount], (NSUInteger)1, nil); + } + + [listener release]; + if (!GTMIsGarbageCollectionEnabled()) { + STAssertEquals([[GTMAbstractDOListener allListeners] count], listenerCount, + nil); + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.h new file mode 100644 index 00000000..169b1c3c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.h @@ -0,0 +1,183 @@ +// +// GTMBase64.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// GTMBase64 +// +/// Helper for handling Base64 and WebSafeBase64 encodings +// +/// The webSafe methods use different character set and also the results aren't +/// always padded to a multiple of 4 characters. This is done so the resulting +/// data can be used in urls and url query arguments without needing any +/// encoding. You must use the webSafe* methods together, the data does not +/// interop with the RFC methods. +// +@interface GTMBase64 : NSObject + +// +// Standard Base64 (RFC) handling +// + +// encodeData: +// +/// Base64 encodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)encodeData:(NSData *)data; + +// decodeData: +// +/// Base64 decodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)decodeData:(NSData *)data; + +// encodeBytes:length: +// +/// Base64 encodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length; + +// decodeBytes:length: +// +/// Base64 decodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length; + +// stringByEncodingData: +// +/// Base64 encodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByEncodingData:(NSData *)data; + +// stringByEncodingBytes:length: +// +/// Base64 encodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length; + +// decodeString: +// +/// Base64 decodes contents of the NSString. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)decodeString:(NSString *)string; + +// +// Modified Base64 encoding so the results can go onto urls. +// +// The changes are in the characters generated and also allows the result to +// not be padded to a multiple of 4. +// Must use the matching call to encode/decode, won't interop with the +// RFC versions. +// + +// webSafeEncodeData:padded: +// +/// WebSafe Base64 encodes contents of the NSData object. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeEncodeData:(NSData *)data + padded:(BOOL)padded; + +// webSafeDecodeData: +// +/// WebSafe Base64 decodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)webSafeDecodeData:(NSData *)data; + +// webSafeEncodeBytes:length:padded: +// +/// WebSafe Base64 encodes the data pointed at by |bytes|. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeEncodeBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded; + +// webSafeDecodeBytes:length: +// +/// WebSafe Base64 decodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length; + +// stringByWebSafeEncodingData:padded: +// +/// WebSafe Base64 encodes contents of the NSData object. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByWebSafeEncodingData:(NSData *)data + padded:(BOOL)padded; + +// stringByWebSafeEncodingBytes:length:padded: +// +/// WebSafe Base64 encodes the data pointed at by |bytes|. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded; + +// webSafeDecodeString: +// +/// WebSafe Base64 decodes contents of the NSString. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)webSafeDecodeString:(NSString *)string; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.m new file mode 100644 index 00000000..9f9ffbfc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64.m @@ -0,0 +1,694 @@ +// +// GTMBase64.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMBase64.h" +#import "GTMDefines.h" + +static const char *kBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char *kWebSafeBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +static const char kBase64PaddingChar = '='; +static const char kBase64InvalidChar = 99; + +static const char kBase64DecodeChars[] = { + // This array was generated by the following code: + // #include + // #include + // #include + // main() + // { + // static const char Base64[] = + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + // char *pos; + // int idx, i, j; + // printf(" "); + // for (i = 0; i < 255; i += 8) { + // for (j = i; j < i + 8; j++) { + // pos = strchr(Base64, j); + // if ((pos == NULL) || (j == 0)) + // idx = 99; + // else + // idx = pos - Base64; + // if (idx == 99) + // printf(" %2d, ", idx); + // else + // printf(" %2d/*%c*/,", idx, j); + // } + // printf("\n "); + // } + // } + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 62/*+*/, 99, 99, 99, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, 99, 99, 99, 99, 99, 99, + 99, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, 99, 99, 99, 99, 99, + 99, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +static const char kWebSafeBase64DecodeChars[] = { + // This array was generated by the following code: + // #include + // #include + // #include + // main() + // { + // static const char Base64[] = + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + // char *pos; + // int idx, i, j; + // printf(" "); + // for (i = 0; i < 255; i += 8) { + // for (j = i; j < i + 8; j++) { + // pos = strchr(Base64, j); + // if ((pos == NULL) || (j == 0)) + // idx = 99; + // else + // idx = pos - Base64; + // if (idx == 99) + // printf(" %2d, ", idx); + // else + // printf(" %2d/*%c*/,", idx, j); + // } + // printf("\n "); + // } + // } + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 62/*-*/, 99, 99, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, 99, 99, 99, 99, 99, 99, + 99, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, 99, 99, 99, 99, 63/*_*/, + 99, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +// Tests a character to see if it's a whitespace character. +// +// Returns: +// YES if the character is a whitespace character. +// NO if the character is not a whitespace character. +// +GTM_INLINE BOOL IsSpace(unsigned char c) { + // we use our own mapping here because we don't want anything w/ locale + // support. + static BOOL kSpaces[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 0-9 + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 10-19 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20-29 + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 30-39 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-49 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50-59 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60-69 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 70-79 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-89 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90-99 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 100-109 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 110-119 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120-129 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 130-139 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140-149 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150-159 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-169 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170-179 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180-189 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190-199 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200-209 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210-219 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220-229 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230-239 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-249 + 0, 0, 0, 0, 0, 1, // 250-255 + }; + return kSpaces[c]; +} + +// Calculate how long the data will be once it's base64 encoded. +// +// Returns: +// The guessed encoded length for a source length +// +GTM_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen, BOOL padded) { + NSUInteger intermediate_result = 8 * srcLen + 5; + NSUInteger len = intermediate_result / 6; + if (padded) { + len = ((len + 3) / 4) * 4; + } + return len; +} + +// Tries to calculate how long the data will be once it's base64 decoded. +// Unlike the above, this is always an upperbound, since the source data +// could have spaces and might end with the padding characters on them. +// +// Returns: +// The guessed decoded length for a source length +// +GTM_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) { + return (srcLen + 3) / 4 * 3; +} + + +@interface GTMBase64 (PrivateMethods) + ++(NSData *)baseEncode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + padded:(BOOL)padded; + ++(NSData *)baseDecode:(const void *)bytes + length:(NSUInteger)length + charset:(const char*)charset + requirePadding:(BOOL)requirePadding; + ++(NSUInteger)baseEncode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + padded:(BOOL)padded; + ++(NSUInteger)baseDecode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + requirePadding:(BOOL)requirePadding; + +@end + + +@implementation GTMBase64 + +// +// Standard Base64 (RFC) handling +// + ++(NSData *)encodeData:(NSData *)data { + return [self baseEncode:[data bytes] + length:[data length] + charset:kBase64EncodeChars + padded:YES]; +} + ++(NSData *)decodeData:(NSData *)data { + return [self baseDecode:[data bytes] + length:[data length] + charset:kBase64DecodeChars + requirePadding:YES]; +} + ++(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseEncode:bytes + length:length + charset:kBase64EncodeChars + padded:YES]; +} + ++(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseDecode:bytes + length:length + charset:kBase64DecodeChars + requirePadding:YES]; +} + ++(NSString *)stringByEncodingData:(NSData *)data { + NSString *result = nil; + NSData *converted = [self baseEncode:[data bytes] + length:[data length] + charset:kBase64EncodeChars + padded:YES]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length { + NSString *result = nil; + NSData *converted = [self baseEncode:bytes + length:length + charset:kBase64EncodeChars + padded:YES]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSData *)decodeString:(NSString *)string { + NSData *result = nil; + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (data) { + result = [self baseDecode:[data bytes] + length:[data length] + charset:kBase64DecodeChars + requirePadding:YES]; + } + return result; +} + +// +// Modified Base64 encoding so the results can go onto urls. +// +// The changes are in the characters generated and also the result isn't +// padded to a multiple of 4. +// Must use the matching call to encode/decode, won't interop with the +// RFC versions. +// + ++(NSData *)webSafeEncodeData:(NSData *)data + padded:(BOOL)padded { + return [self baseEncode:[data bytes] + length:[data length] + charset:kWebSafeBase64EncodeChars + padded:padded]; +} + ++(NSData *)webSafeDecodeData:(NSData *)data { + return [self baseDecode:[data bytes] + length:[data length] + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; +} + ++(NSData *)webSafeEncodeBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded { + return [self baseEncode:bytes + length:length + charset:kWebSafeBase64EncodeChars + padded:padded]; +} + ++(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseDecode:bytes + length:length + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; +} + ++(NSString *)stringByWebSafeEncodingData:(NSData *)data + padded:(BOOL)padded { + NSString *result = nil; + NSData *converted = [self baseEncode:[data bytes] + length:[data length] + charset:kWebSafeBase64EncodeChars + padded:padded]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded { + NSString *result = nil; + NSData *converted = [self baseEncode:bytes + length:length + charset:kWebSafeBase64EncodeChars + padded:padded]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSData *)webSafeDecodeString:(NSString *)string { + NSData *result = nil; + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (data) { + result = [self baseDecode:[data bytes] + length:[data length] + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; + } + return result; +} + +@end + +@implementation GTMBase64 (PrivateMethods) + +// +// baseEncode:length:charset:padded: +// +// Does the common lifting of creating the dest NSData. it creates & sizes the +// data for the results. |charset| is the characters to use for the encoding +// of the data. |padding| controls if the encoded data should be padded to a +// multiple of 4. +// +// Returns: +// an autorelease NSData with the encoded data, nil if any error. +// ++(NSData *)baseEncode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + padded:(BOOL)padded { + // how big could it be? + NSUInteger maxLength = CalcEncodedLength(length, padded); + // make space + NSMutableData *result = [NSMutableData data]; + [result setLength:maxLength]; + // do it + NSUInteger finalLength = [self baseEncode:bytes + srcLen:length + destBytes:[result mutableBytes] + destLen:[result length] + charset:charset + padded:padded]; + if (finalLength) { + _GTMDevAssert(finalLength == maxLength, @"how did we calc the length wrong?"); + } else { + // shouldn't happen, this means we ran out of space + result = nil; + } + return result; +} + +// +// baseDecode:length:charset:requirePadding: +// +// Does the common lifting of creating the dest NSData. it creates & sizes the +// data for the results. |charset| is the characters to use for the decoding +// of the data. +// +// Returns: +// an autorelease NSData with the decoded data, nil if any error. +// +// ++(NSData *)baseDecode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + requirePadding:(BOOL)requirePadding { + // could try to calculate what it will end up as + NSUInteger maxLength = GuessDecodedLength(length); + // make space + NSMutableData *result = [NSMutableData data]; + [result setLength:maxLength]; + // do it + NSUInteger finalLength = [self baseDecode:bytes + srcLen:length + destBytes:[result mutableBytes] + destLen:[result length] + charset:charset + requirePadding:requirePadding]; + if (finalLength) { + if (finalLength != maxLength) { + // resize down to how big it was + [result setLength:finalLength]; + } + } else { + // either an error in the args, or we ran out of space + result = nil; + } + return result; +} + +// +// baseEncode:srcLen:destBytes:destLen:charset:padded: +// +// Encodes the buffer into the larger. returns the length of the encoded +// data, or zero for an error. +// |charset| is the characters to use for the encoding +// |padded| tells if the result should be padded to a multiple of 4. +// +// Returns: +// the length of the encoded data. zero if any error. +// ++(NSUInteger)baseEncode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + padded:(BOOL)padded { + if (!srcLen || !destLen || !srcBytes || !destBytes) { + return 0; + } + + char *curDest = destBytes; + const unsigned char *curSrc = (const unsigned char *)(srcBytes); + + // Three bytes of data encodes to four characters of cyphertext. + // So we can pump through three-byte chunks atomically. + while (srcLen > 2) { + // space? + _GTMDevAssert(destLen >= 4, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)]; + curDest[2] = charset[((curSrc[1] & 0x0f) << 2) + (curSrc[2] >> 6)]; + curDest[3] = charset[curSrc[2] & 0x3f]; + + curDest += 4; + curSrc += 3; + srcLen -= 3; + destLen -= 4; + } + + // now deal with the tail (<=2 bytes) + switch (srcLen) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cypherblock. + _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[(curSrc[0] & 0x03) << 4]; + curDest += 2; + destLen -= 2; + if (padded) { + _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong"); + curDest[0] = kBase64PaddingChar; + curDest[1] = kBase64PaddingChar; + curDest += 2; + } + break; + case 2: + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cypherblock. + _GTMDevAssert(destLen >= 3, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)]; + curDest[2] = charset[(curSrc[1] & 0x0f) << 2]; + curDest += 3; + destLen -= 3; + if (padded) { + _GTMDevAssert(destLen >= 1, @"our calc for encoded length was wrong"); + curDest[0] = kBase64PaddingChar; + curDest += 1; + } + break; + } + // return the length + return (curDest - destBytes); +} + +// +// baseDecode:srcLen:destBytes:destLen:charset:requirePadding: +// +// Decodes the buffer into the larger. returns the length of the decoded +// data, or zero for an error. +// |charset| is the character decoding buffer to use +// +// Returns: +// the length of the encoded data. zero if any error. +// ++(NSUInteger)baseDecode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + requirePadding:(BOOL)requirePadding { + if (!srcLen || !destLen || !srcBytes || !destBytes) { + return 0; + } + + int decode; + NSUInteger destIndex = 0; + int state = 0; + char ch = 0; + while (srcLen-- && (ch = *srcBytes++) != 0) { + if (IsSpace(ch)) // Skip whitespace + continue; + + if (ch == kBase64PaddingChar) + break; + + decode = charset[(unsigned int)ch]; + if (decode == kBase64InvalidChar) + return 0; + + // Four cyphertext characters decode to three bytes. + // Therefore we can be in one of four states. + switch (state) { + case 0: + // We're at the beginning of a four-character cyphertext block. + // This sets the high six bits of the first byte of the + // plaintext block. + _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] = decode << 2; + state = 1; + break; + case 1: + // We're one character into a four-character cyphertext block. + // This sets the low two bits of the first plaintext byte, + // and the high four bits of the second plaintext byte. + _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode >> 4; + destBytes[destIndex+1] = (decode & 0x0f) << 4; + destIndex++; + state = 2; + break; + case 2: + // We're two characters into a four-character cyphertext block. + // This sets the low four bits of the second plaintext + // byte, and the high two bits of the third plaintext byte. + // However, if this is the end of data, and those two + // bits are zero, it could be that those two bits are + // leftovers from the encoding of data that had a length + // of two mod three. + _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode >> 2; + destBytes[destIndex+1] = (decode & 0x03) << 6; + destIndex++; + state = 3; + break; + case 3: + // We're at the last character of a four-character cyphertext block. + // This sets the low six bits of the third plaintext byte. + _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode; + destIndex++; + state = 0; + break; + } + } + + // We are done decoding Base-64 chars. Let's see if we ended + // on a byte boundary, and/or with erroneous trailing characters. + if (ch == kBase64PaddingChar) { // We got a pad char + if ((state == 0) || (state == 1)) { + return 0; // Invalid '=' in first or second position + } + if (srcLen == 0) { + if (state == 2) { // We run out of input but we still need another '=' + return 0; + } + // Otherwise, we are in state 3 and only need this '=' + } else { + if (state == 2) { // need another '=' + while ((ch = *srcBytes++) && (srcLen-- > 0)) { + if (!IsSpace(ch)) + break; + } + if (ch != kBase64PaddingChar) { + return 0; + } + } + // state = 1 or 2, check if all remain padding is space + while ((ch = *srcBytes++) && (srcLen-- > 0)) { + if (!IsSpace(ch)) { + return 0; + } + } + } + } else { + // We ended by seeing the end of the string. + + if (requirePadding) { + // If we require padding, then anything but state 0 is an error. + if (state != 0) { + return 0; + } + } else { + // Make sure we have no partial bytes lying around. Note that we do not + // require trailing '=', so states 2 and 3 are okay too. + if (state == 1) { + return 0; + } + } + } + + // If then next piece of output was valid and got written to it means we got a + // very carefully crafted input that appeared valid but contains some trailing + // bits past the real length, so just toss the thing. + if ((destIndex < destLen) && + (destBytes[destIndex] != 0)) { + return 0; + } + + return destIndex; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64Test.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64Test.m new file mode 100644 index 00000000..084ea1e0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMBase64Test.m @@ -0,0 +1,437 @@ +// +// GTMBase64Test.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMBase64.h" +#include // for randiom/srandomdev + +static void FillWithRandom(char *data, NSUInteger len) { + char *max = data + len; + for ( ; data < max ; ++data) { + *data = random() & 0xFF; + } +} + +static BOOL NoEqualChar(NSData *data) { + const char *scan = [data bytes]; + const char *max = scan + [data length]; + for ( ; scan < max ; ++scan) { + if (*scan == '=') { + return NO; + } + } + return YES; +} + +@interface GTMBase64Test : GTMTestCase +@end + +@implementation GTMBase64Test + +- (void)setUp { + // seed random from /dev/random + srandomdev(); +} + +- (void)testBase64 { + // generate a range of sizes w/ random content + for (int x = 1 ; x < 1024 ; ++x) { + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:x]; + FillWithRandom([data mutableBytes], [data length]); + + // w/ *Bytes apis + NSData *encoded = [GTMBase64 encodeBytes:[data bytes] length:[data length]]; + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + NSData *dataPrime = [GTMBase64 decodeBytes:[encoded bytes] + length:[encoded length]]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Bytes apis"); + + // w/ *Data apis + encoded = [GTMBase64 encodeData:data]; + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + dataPrime = [GTMBase64 decodeData:encoded]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Data apis"); + + // Bytes to String and back + NSString *encodedString = [GTMBase64 stringByEncodingBytes:[data bytes] + length:[data length]]; + STAssertEquals(([encodedString length] % 4), (NSUInteger)0, + @"encoded size for Bytes to Strings should be a multiple of 4"); + dataPrime = [GTMBase64 decodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Bytes to Strings"); + + // Data to String and back + encodedString = [GTMBase64 stringByEncodingData:data]; + STAssertEquals(([encodedString length] % 4), (NSUInteger)0, + @"encoded size for Data to Strings should be a multiple of 4"); + dataPrime = [GTMBase64 decodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Bytes to Strings"); + } + + { + // now test all byte values + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:256]; + unsigned char *scan = (unsigned char*)[data mutableBytes]; + for (int x = 0 ; x <= 255 ; ++x) { + *scan++ = x; + } + + // w/ *Bytes apis + NSData *encoded = [GTMBase64 encodeBytes:[data bytes] length:[data length]]; + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + NSData *dataPrime = [GTMBase64 decodeBytes:[encoded bytes] + length:[encoded length]]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Bytes apis"); + + // w/ *Data apis + encoded = [GTMBase64 encodeData:data]; + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + dataPrime = [GTMBase64 decodeData:encoded]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Data apis"); + + // Bytes to String and back + NSString *encodedString = [GTMBase64 stringByEncodingBytes:[data bytes] + length:[data length]]; + STAssertEquals(([encodedString length] % 4), (NSUInteger)0, + @"encoded size for Bytes to Strings should be a multiple of 4"); + dataPrime = [GTMBase64 decodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Bytes to Strings"); + + // Data to String and back + encodedString = [GTMBase64 stringByEncodingData:data]; + STAssertEquals(([encodedString length] % 4), (NSUInteger)0, + @"encoded size for Data to Strings should be a multiple of 4"); + dataPrime = [GTMBase64 decodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Data to Strings"); + } + + { + // test w/ a mix of spacing characters + + // generate some data, encode it, and add spaces + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:253]; // should get some padding chars on the end + FillWithRandom([data mutableBytes], [data length]); + + NSString *encodedString = [GTMBase64 stringByEncodingData:data]; + NSMutableString *encodedAndSpaced = + [[encodedString mutableCopy] autorelease]; + + NSString *spaces[] = { @"\t", @"\n", @"\r", @" " }; + const NSUInteger numSpaces = sizeof(spaces) / sizeof(NSString*); + for (int x = 0 ; x < 512 ; ++x) { + NSUInteger offset = random() % ([encodedAndSpaced length] + 1); + [encodedAndSpaced insertString:spaces[random() % numSpaces] + atIndex:offset]; + } + + // we'll need it as data for apis + NSData *encodedAsData = + [encodedAndSpaced dataUsingEncoding:NSASCIIStringEncoding]; + STAssertNotNil(encodedAsData, @"failed to extract from string"); + STAssertEquals([encodedAsData length], [encodedAndSpaced length], + @"lengths for encoded string and data didn't match?"); + + // all the decode modes + NSData *dataPrime = [GTMBase64 decodeData:encodedAsData]; + STAssertEqualObjects(data, dataPrime, + @"failed Data decode w/ spaces"); + dataPrime = [GTMBase64 decodeBytes:[encodedAsData bytes] + length:[encodedAsData length]]; + STAssertEqualObjects(data, dataPrime, + @"failed Bytes decode w/ spaces"); + dataPrime = [GTMBase64 decodeString:encodedAndSpaced]; + STAssertEqualObjects(data, dataPrime, + @"failed String decode w/ spaces"); + } +} + +- (void)testWebSafeBase64 { + // loop to test w/ and w/o padding + for (int paddedLoop = 0; paddedLoop < 2 ; ++paddedLoop) { + BOOL padded = (paddedLoop == 1); + + // generate a range of sizes w/ random content + for (int x = 1 ; x < 1024 ; ++x) { + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:x]; + FillWithRandom([data mutableBytes], [data length]); + + // w/ *Bytes apis + NSData *encoded = [GTMBase64 webSafeEncodeBytes:[data bytes] + length:[data length] + padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via *Bytes apis had a base64 padding char"); + } + NSData *dataPrime = [GTMBase64 webSafeDecodeBytes:[encoded bytes] + length:[encoded length]]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Bytes apis"); + + // w/ *Data apis + encoded = [GTMBase64 webSafeEncodeData:data padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via *Data apis had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeData:encoded]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Data apis"); + + // Bytes to String and back + NSString *encodedString = + [GTMBase64 stringByWebSafeEncodingBytes:[data bytes] + length:[data length] + padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via Bytes to Strings had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Bytes to Strings"); + + // Data to String and back + encodedString = + [GTMBase64 stringByWebSafeEncodingData:data padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via Data to Strings had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Data to Strings"); + } + + { + // now test all byte values + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:256]; + unsigned char *scan = (unsigned char*)[data mutableBytes]; + for (int x = 0 ; x <= 255 ; ++x) { + *scan++ = x; + } + + // w/ *Bytes apis + NSData *encoded = + [GTMBase64 webSafeEncodeBytes:[data bytes] + length:[data length] + padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via *Bytes apis had a base64 padding char"); + } + NSData *dataPrime = [GTMBase64 webSafeDecodeBytes:[encoded bytes] + length:[encoded length]]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Bytes apis"); + + // w/ *Data apis + encoded = [GTMBase64 webSafeEncodeData:data padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via *Data apis had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeData:encoded]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Data apis"); + + // Bytes to String and back + NSString *encodedString = + [GTMBase64 stringByWebSafeEncodingBytes:[data bytes] + length:[data length] + padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Bytes apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via Bytes to Strings had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Bytes to Strings"); + + // Data to String and back + encodedString = + [GTMBase64 stringByWebSafeEncodingData:data padded:padded]; + if (padded) { + STAssertEquals(([encoded length] % 4), (NSUInteger)0, + @"encoded size via *Data apis should be a multiple of 4"); + } else { + STAssertTrue(NoEqualChar(encoded), + @"encoded via Data to Strings had a base64 padding char"); + } + dataPrime = [GTMBase64 webSafeDecodeString:encodedString]; + STAssertEqualObjects(data, dataPrime, + @"failed to round trip for Data to Strings"); + } + + { + // test w/ a mix of spacing characters + + // generate some data, encode it, and add spaces + NSMutableData *data = [NSMutableData data]; + STAssertNotNil(data, @"failed to alloc data block"); + + [data setLength:253]; // should get some padding chars on the end + FillWithRandom([data mutableBytes], [data length]); + + NSString *encodedString = [GTMBase64 stringByWebSafeEncodingData:data + padded:padded]; + NSMutableString *encodedAndSpaced = + [[encodedString mutableCopy] autorelease]; + + NSString *spaces[] = { @"\t", @"\n", @"\r", @" " }; + const NSUInteger numSpaces = sizeof(spaces) / sizeof(NSString*); + for (int x = 0 ; x < 512 ; ++x) { + NSUInteger offset = random() % ([encodedAndSpaced length] + 1); + [encodedAndSpaced insertString:spaces[random() % numSpaces] + atIndex:offset]; + } + + // we'll need it as data for apis + NSData *encodedAsData = + [encodedAndSpaced dataUsingEncoding:NSASCIIStringEncoding]; + STAssertNotNil(encodedAsData, @"failed to extract from string"); + STAssertEquals([encodedAsData length], [encodedAndSpaced length], + @"lengths for encoded string and data didn't match?"); + + // all the decode modes + NSData *dataPrime = [GTMBase64 webSafeDecodeData:encodedAsData]; + STAssertEqualObjects(data, dataPrime, + @"failed Data decode w/ spaces"); + dataPrime = [GTMBase64 webSafeDecodeBytes:[encodedAsData bytes] + length:[encodedAsData length]]; + STAssertEqualObjects(data, dataPrime, + @"failed Bytes decode w/ spaces"); + dataPrime = [GTMBase64 webSafeDecodeString:encodedAndSpaced]; + STAssertEqualObjects(data, dataPrime, + @"failed String decode w/ spaces"); + } + } // paddedLoop +} + +- (void)testErrors { + const int something = 0; + NSString *nonAscString = [NSString stringWithUTF8String:"This test ©™®๒०᠐٧"]; + + STAssertNil([GTMBase64 encodeData:nil], @"it worked?"); + STAssertNil([GTMBase64 decodeData:nil], @"it worked?"); + STAssertNil([GTMBase64 encodeBytes:NULL length:10], @"it worked?"); + STAssertNil([GTMBase64 encodeBytes:&something length:0], @"it worked?"); + STAssertNil([GTMBase64 decodeBytes:NULL length:10], @"it worked?"); + STAssertNil([GTMBase64 decodeBytes:&something length:0], @"it worked?"); + STAssertNil([GTMBase64 stringByEncodingData:nil], @"it worked?"); + STAssertNil([GTMBase64 stringByEncodingBytes:NULL length:10], @"it worked?"); + STAssertNil([GTMBase64 stringByEncodingBytes:&something length:0], @"it worked?"); + STAssertNil([GTMBase64 decodeString:nil], @"it worked?"); + // test some pads at the end that aren't right + STAssertNil([GTMBase64 decodeString:@"=="], @"it worked?"); // just pads + STAssertNil([GTMBase64 decodeString:@"vw="], @"it worked?"); // missing pad (in state 2) + STAssertNil([GTMBase64 decodeString:@"vw"], @"it worked?"); // missing pad (in state 2) + STAssertNil([GTMBase64 decodeString:@"NNw"], @"it worked?"); // missing pad (in state 3) + STAssertNil([GTMBase64 decodeString:@"vw=v"], @"it worked?"); // missing pad, has something else + STAssertNil([GTMBase64 decodeString:@"v="], @"it worked?"); // missing a needed char, has pad instead + STAssertNil([GTMBase64 decodeString:@"v"], @"it worked?"); // missing a needed char + STAssertNil([GTMBase64 decodeString:@"vw== vw"], @"it worked?"); + STAssertNil([GTMBase64 decodeString:nonAscString], @"it worked?"); + STAssertNil([GTMBase64 decodeString:@"@@@not valid###"], @"it worked?"); + // carefully crafted bad input to make sure we don't overwalk + STAssertNil([GTMBase64 decodeString:@"WD=="], @"it worked?"); + + STAssertNil([GTMBase64 webSafeEncodeData:nil padded:YES], @"it worked?"); + STAssertNil([GTMBase64 webSafeDecodeData:nil], @"it worked?"); + STAssertNil([GTMBase64 webSafeEncodeBytes:NULL length:10 padded:YES], + @"it worked?"); + STAssertNil([GTMBase64 webSafeEncodeBytes:&something length:0 padded:YES], + @"it worked?"); + STAssertNil([GTMBase64 webSafeDecodeBytes:NULL length:10], @"it worked?"); + STAssertNil([GTMBase64 webSafeDecodeBytes:&something length:0], @"it worked?"); + STAssertNil([GTMBase64 stringByWebSafeEncodingData:nil padded:YES], + @"it worked?"); + STAssertNil([GTMBase64 stringByWebSafeEncodingBytes:NULL + length:10 + padded:YES], + @"it worked?"); + STAssertNil([GTMBase64 stringByWebSafeEncodingBytes:&something + length:0 + padded:YES], + @"it worked?"); + STAssertNil([GTMBase64 webSafeDecodeString:nil], @"it worked?"); + // test some pads at the end that aren't right + STAssertNil([GTMBase64 webSafeDecodeString:@"=="], @"it worked?"); // just pad chars + STAssertNil([GTMBase64 webSafeDecodeString:@"aw="], @"it worked?"); // missing pad + STAssertNil([GTMBase64 webSafeDecodeString:@"aw=a"], @"it worked?"); // missing pad, has something else + STAssertNil([GTMBase64 webSafeDecodeString:@"a"], @"it worked?"); // missing a needed char + STAssertNil([GTMBase64 webSafeDecodeString:@"a="], @"it worked?"); // missing a needed char, has pad instead + STAssertNil([GTMBase64 webSafeDecodeString:@"aw== a"], @"it worked?"); // missing pad + STAssertNil([GTMBase64 webSafeDecodeString:nonAscString], @"it worked?"); + STAssertNil([GTMBase64 webSafeDecodeString:@"@@@not valid###"], @"it worked?"); + // carefully crafted bad input to make sure we don't overwalk + STAssertNil([GTMBase64 webSafeDecodeString:@"WD=="], @"it worked?"); + + // make sure our local helper is working right + STAssertFalse(NoEqualChar([NSData dataWithBytes:"aa=zz" length:5]), @""); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.h new file mode 100644 index 00000000..5710da61 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.h @@ -0,0 +1,102 @@ +// +// GTMCalculatedRange.h +// +// This is a collection that allows you to calculate a value based on +// defined stops in a range. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +/// Allows you to calculate a value based on defined stops in a range. +// +/// For example if you have a range from 0.0 to 1.0 where the stop +/// located at 0.0 is red and the stop located at 1.0 is blue, +/// the value based on the position 0.5 would come out as purple assuming +/// that the valueAtPosition function calculates a purely linear mapping between +/// the stops at 0.0 and 1.0. Stops have indices and are sorted from lowest to +/// highest. The example above would have 2 stops. Stop 0 would be red and stop +/// 1 would be blue. +/// +/// Subclasses of GTMCalculatedRange are expected to override the valueAtPosition: +/// method to return a value based on the position passed in, and the stops +/// that are currently set in the range. Stops do not necessarily have to +/// be the same type as the values that are calculated, but normally they are. +@interface GTMCalculatedRange : NSObject { + NSMutableArray *storage_; +} + +// Adds a stop to the range at |position|. If there is already a stop +// at position |position| it is replaced. +// +// Args: +// item: the object to place at |position|. +// position: the position in the range to put |item|. +// +- (void)insertStop:(id)item atPosition:(CGFloat)position; + +// Removes a stop from the range at |position|. +// +// Args: +// position: the position in the range to remove |item|. +// +// Returns: +// YES if there is a stop at |position| that has been removed +// NO if there is not a stop at the |position| +- (BOOL)removeStopAtPosition:(CGFloat)position; + +// Removes stop |index| from the range. Stops are ordered +// based on position where index of x < index of y if position +// of x < position of y. +// +// Args: +// item: the object to place at |position|. +// position: the position in the range to put |item|. +// +- (void)removeStopAtIndex:(NSUInteger)index; + +// Returns the number of stops in the range. +// +// Returns: +// number of stops +- (NSUInteger)stopCount; + +// Returns the value at position |position|. +// This function should be overridden by subclasses to calculate a +// value for any given range. +// The default implementation returns a value if there happens to be +// a stop for the given position. Otherwise it returns nil. +// +// Args: +// position: the position to calculate a value for. +// +// Returns: +// value for position +- (id)valueAtPosition:(CGFloat)position; + +// Returns the |index|'th stop and position in the set. +// Throws an exception if out of range. +// +// Args: +// index: the index of the stop +// outPosition: a pointer to a value to be filled in with a position. +// this can be NULL, in which case no position is returned. +// +// Returns: +// the stop at the index. +- (id)stopAtIndex:(NSUInteger)index position:(CGFloat*)outPosition; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.m new file mode 100644 index 00000000..5ab491d8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRange.m @@ -0,0 +1,148 @@ +// +// GTMCalculatedRange.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMCalculatedRange.h" + +// Our internal storage type. It keeps track of an item and it's +// position. +@interface GTMCalculatedRangeStopPrivate : NSObject { + id item_; // the item (STRONG) + CGFloat position_; // +} ++ (id)stopWithObject:(id)item position:(CGFloat)inPosition; +- (id)initWithObject:(id)item position:(CGFloat)inPosition; +- (id)item; +- (CGFloat)position; +@end + +GTM_INLINE BOOL FPEqual(CGFloat a, CGFloat b) { + return (fpclassify(a - b) == FP_ZERO); +} + +@implementation GTMCalculatedRangeStopPrivate ++ (id)stopWithObject:(id)item position:(CGFloat)inPosition { + return [[[[self class] alloc] initWithObject:item position:inPosition] autorelease]; +} + +- (id)initWithObject:(id)item position:(CGFloat)inPosition { + self = [super init]; + if (self != nil) { + item_ = [item retain]; + position_ = inPosition; + } + return self; +} + +- (void)dealloc { + [item_ release]; + [super dealloc]; +} + +- (id)item { + return item_; +} + +- (CGFloat)position { + return position_; +} + +- (NSString *)description { + return [NSString stringWithFormat: @"%f %@", position_, item_]; +} +@end + +@implementation GTMCalculatedRange +- (id)init { + self = [super init]; + if (self != nil) { + storage_ = [[NSMutableArray arrayWithCapacity:0] retain]; + } + return self; +} +- (void)dealloc { + [storage_ release]; + [super dealloc]; +} + +- (void)insertStop:(id)item atPosition:(CGFloat)position { + NSUInteger positionIndex = 0; + GTMCalculatedRangeStopPrivate *theStop; + GTM_FOREACH_OBJECT(theStop, storage_) { + if ([theStop position] < position) { + positionIndex += 1; + } + else if (FPEqual([theStop position], position)) { + // remove and stop the enum since we just modified the object + [storage_ removeObjectAtIndex:positionIndex]; + break; + } + } + [storage_ insertObject:[GTMCalculatedRangeStopPrivate stopWithObject:item position:position] + atIndex:positionIndex]; +} + +- (BOOL)removeStopAtPosition:(CGFloat)position { + NSUInteger positionIndex = 0; + BOOL foundStop = NO; + GTMCalculatedRangeStopPrivate *theStop; + GTM_FOREACH_OBJECT(theStop, storage_) { + if (FPEqual([theStop position], position)) { + break; + } else { + positionIndex += 1; + } + } + if (nil != theStop) { + [self removeStopAtIndex:positionIndex]; + foundStop = YES; + } + return foundStop; +} + +- (void)removeStopAtIndex:(NSUInteger)positionIndex { + [storage_ removeObjectAtIndex:positionIndex]; +} + +- (NSUInteger)stopCount { + return [storage_ count]; +} + +- (id)stopAtIndex:(NSUInteger)positionIndex position:(CGFloat*)outPosition { + GTMCalculatedRangeStopPrivate *theStop = [storage_ objectAtIndex:positionIndex]; + if (nil != outPosition) { + *outPosition = [theStop position]; + } + return [theStop item]; +} + +- (id)valueAtPosition:(CGFloat)position { + id theValue = nil; + GTMCalculatedRangeStopPrivate *theStop; + GTM_FOREACH_OBJECT(theStop, storage_) { + if (FPEqual([theStop position], position)) { + theValue = [theStop item]; + break; + } + } + return theValue; +} + +- (NSString *)description { + return [storage_ description]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRangeTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRangeTest.m new file mode 100644 index 00000000..1790072a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMCalculatedRangeTest.m @@ -0,0 +1,101 @@ +// +// GTMCalculatedRangeTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMCalculatedRange.h" +#import "GTMSenTestCase.h" + +@interface GTMCalculatedRangeTest : GTMTestCase { + GTMCalculatedRange *range_; +} +@end + +@implementation GTMCalculatedRangeTest +NSString *kStrings[] = { @"Fee", @"Fi", @"Fo", @"Fum" }; +const NSUInteger kStringCount = sizeof(kStrings) / sizeof(NSString*); +const CGFloat kOddPosition = 0.14159265f; +const CGFloat kExistingPosition = 0.5f; +const NSUInteger kExisitingIndex = 2; + +- (void)setUp { + range_ = [[GTMCalculatedRange alloc] init]; + for(NSUInteger i = kStringCount; i > 0; --i) { + [range_ insertStop:kStrings[kStringCount - i] atPosition: 1.0f / i]; + } +} + +- (void)tearDown { + [range_ release]; +} + +- (void)testInsertStop { + // new position + NSString *theString = @"I smell the blood of an Englishman!"; + [range_ insertStop:theString atPosition:kOddPosition]; + STAssertEquals([range_ stopCount], kStringCount + 1, @"Stop count was bad"); + NSString *getString = [range_ valueAtPosition:kOddPosition]; + STAssertNotNil(getString, @"String was bad"); + STAssertEquals(theString, getString, @"Stops weren't equal"); + // existing position + NSString *theStringTake2 = @"I smell the blood of an Englishman! Take 2"; + [range_ insertStop:theStringTake2 atPosition:kOddPosition]; + STAssertEquals([range_ stopCount], kStringCount + 1, @"Stop count was bad"); + getString = [range_ valueAtPosition:kOddPosition]; + STAssertNotNil(getString, @"String was bad"); + STAssertEquals(theStringTake2, getString, @"Stops weren't equal"); + STAssertNotEquals(theString, getString, @"Should be the new value"); + STAssertNotEqualObjects(theString, getString, @"Should be the new value"); +} + +- (void)testRemoveStopAtPosition { + STAssertFalse([range_ removeStopAtPosition: kOddPosition], @"Was able to remove non-existant stop"); + STAssertTrue([range_ removeStopAtPosition: kExistingPosition], @"Was unable to remove good stop"); + STAssertEquals([range_ stopCount], kStringCount - 1, @"Removing stop should adjust stop count"); +} + +- (void)testRemoveStopAtIndex { + STAssertThrows([range_ removeStopAtIndex: kStringCount], @"Was able to remove non-existant stop"); + STAssertNoThrow([range_ removeStopAtIndex: kStringCount - 1], @"Was unable to remove good stop"); + STAssertEquals([range_ stopCount], kStringCount - 1, @"Removing stop should adjust stop count"); +} + +- (void)testStopCount { + STAssertEquals([range_ stopCount], kStringCount, @"Bad stop count"); +} + +- (void)testValueAtPosition { + STAssertEqualObjects([range_ valueAtPosition: kExistingPosition], kStrings[kExisitingIndex], nil); + STAssertNotEqualObjects([range_ valueAtPosition: kExistingPosition], kStrings[kStringCount - 1], nil); + STAssertNil([range_ valueAtPosition: kOddPosition], nil); +} + +- (void)testStopAtIndex { + CGFloat thePosition; + + STAssertEqualObjects([range_ stopAtIndex:kStringCount - 1 position:nil], kStrings[kStringCount - 1], nil); + STAssertEqualObjects([range_ stopAtIndex:kExisitingIndex position:&thePosition], kStrings[kExisitingIndex], nil); + STAssertEquals(thePosition, kExistingPosition, nil); + STAssertNotEqualObjects([range_ stopAtIndex:kStringCount - 1 position:nil], kStrings[2], nil); + STAssertThrows([range_ stopAtIndex:kStringCount position:nil], nil); +} + +- (void)testDescription { + // we expect a description of atleast a few chars + STAssertGreaterThan([[range_ description] length], (NSUInteger)10, nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.h new file mode 100644 index 00000000..ce30db99 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.h @@ -0,0 +1,53 @@ +// +// GTMExceptionalInlines.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// This file exists because when you have full warnings on you can run into +// troubles with functions that Apple has inlined that have structures or +// local variables defined in them. +// You only see this warning if you have -Wuninitialized turned on, +// and you will only see them in release mode. -Wno-unitialized turns them +// off, but you also lose all the good warnings that come with -Wuninitialized. +// If you have the inline versions of any of the functions below in a +// @syncronized, or @try block, you will get +// warning: variable 'r' might be clobbered by 'longjmp' or 'vfork' +// By moving this local vars "out of line" you fix the problem. +// These functions do nothing more than act as "out of line" calls to the +// functions they are masking to avoid the warning. +// If you run into others, feel free to add them. + +// Please only use these to avoid the warning above. Use the Apple defined +// functions where possible. + +FOUNDATION_EXPORT NSRange GTMNSMakeRange(NSUInteger loc, NSUInteger len); +FOUNDATION_EXPORT CFRange GTMCFRangeMake(NSUInteger loc, NSUInteger len); + +FOUNDATION_EXPORT CGPoint GTMCGPointMake(CGFloat x, CGFloat y); +FOUNDATION_EXPORT CGSize GTMCGSizeMake(CGFloat width, CGFloat height); +FOUNDATION_EXPORT CGRect GTMCGRectMake(CGFloat x, CGFloat y, + CGFloat width, CGFloat height); + +#if !GTM_IPHONE_SDK +// iPhone does not have NSTypes defined, only CGTypes. So no NSRect, NSPoint etc. +FOUNDATION_EXPORT NSPoint GTMNSMakePoint(CGFloat x, CGFloat y); +FOUNDATION_EXPORT NSSize GTMNSMakeSize(CGFloat w, CGFloat h); +FOUNDATION_EXPORT NSRect GTMNSMakeRect(CGFloat x, CGFloat y, + CGFloat w, CGFloat h); +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.m new file mode 100644 index 00000000..d803ea9d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlines.m @@ -0,0 +1,56 @@ +// +// GTMExceptionalInlines.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMExceptionalInlines.h" + +NSRange GTMNSMakeRange(NSUInteger loc, NSUInteger len) { + return NSMakeRange(loc, len); +} + +CFRange GTMCFRangeMake(NSUInteger loc, NSUInteger len) { + return CFRangeMake(loc, len); +} + +CGPoint GTMCGPointMake(CGFloat x, CGFloat y) { + return CGPointMake(x, y); +} + +CGSize GTMCGSizeMake(CGFloat width, CGFloat height) { + return CGSizeMake(width, height); +} + +CGRect GTMCGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { + return CGRectMake(x, y, width, height); +} + +#if !GTM_IPHONE_SDK +// iPhone does not have NSTypes defined, only CGTypes. So no NSRect, NSPoint etc. + +NSPoint GTMNSMakePoint(CGFloat x, CGFloat y) { + return NSMakePoint(x, y); +} + +NSSize GTMNSMakeSize(CGFloat w, CGFloat h) { + return NSMakeSize(w, h); +} + +NSRect GTMNSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h) { + return NSMakeRect(x, y, w, h); +} + +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlinesTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlinesTest.m new file mode 100644 index 00000000..61422362 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMExceptionalInlinesTest.m @@ -0,0 +1,71 @@ +// +// GTMExceptionalInlinesTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMExceptionalInlines.h" + +@interface GTMExceptionalInlinesTest : GTMTestCase +@end + +@implementation GTMExceptionalInlinesTest +- (void)testExceptionalInlines { + // Numbers chosen basically at random. + NSUInteger loc = 5; + NSUInteger len = 10; + CGFloat x = 22.5; + CGFloat y = 40.2; + CGFloat h = 21.6; + CGFloat w = 54.2; + + NSRange range1 = GTMNSMakeRange(loc, len); + NSRange range2 = NSMakeRange(loc, len); + STAssertTrue(NSEqualRanges(range1, range2), nil); + + CFRange cfrange1 = GTMCFRangeMake(loc, len); + CFRange cfrange2 = CFRangeMake(loc, len); + STAssertEquals(cfrange1.length, cfrange2.length, nil); + STAssertEquals(cfrange1.location, cfrange2.location, nil); + + + CGPoint cgpoint1 = GTMCGPointMake(x, y); + CGPoint cgpoint2 = CGPointMake(x, y); + STAssertTrue(CGPointEqualToPoint(cgpoint1, cgpoint2), nil); + + CGSize cgsize1 = GTMCGSizeMake(x, y); + CGSize cgsize2 = CGSizeMake(x, y); + STAssertTrue(CGSizeEqualToSize(cgsize1, cgsize2), nil); + + CGRect cgrect1 = GTMCGRectMake(x, y, w, h); + CGRect cgrect2 = CGRectMake(x, y, w, h); + STAssertTrue(CGRectEqualToRect(cgrect1, cgrect2), nil); + +#if !GTM_IPHONE_SDK + NSPoint point1 = GTMNSMakePoint(x, y); + NSPoint point2 = NSMakePoint(x, y); + STAssertTrue(NSEqualPoints(point1, point2), nil); + + NSSize size1 = GTMNSMakeSize(w, h); + NSSize size2 = NSMakeSize(w, h); + STAssertTrue(NSEqualSizes(size1, size2), nil); + + NSRect rect1 = GTMNSMakeRect(x, y, w, h); + NSRect rect2 = NSMakeRect(x, y, w, h); + STAssertTrue(NSEqualRects(rect1, rect2), nil); +#endif +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.h new file mode 100644 index 00000000..a81d433e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.h @@ -0,0 +1,78 @@ +// +// GTMFileSystemKQueue.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import // for kqueue() and kevent and the NOTE_* constants + +// Event constants +enum { + kGTMFileSystemKQueueDeleteEvent = NOTE_DELETE, + kGTMFileSystemKQueueWriteEvent = NOTE_WRITE, + kGTMFileSystemKQueueExtendEvent = NOTE_EXTEND, + kGTMFileSystemKQueueAttributeChangeEvent = NOTE_ATTRIB, + kGTMFileSystemKQueueLinkChangeEvent = NOTE_LINK, + kGTMFileSystemKQueueRenameEvent = NOTE_RENAME, + kGTMFileSystemKQueueRevokeEvent = NOTE_REVOKE, + kGTMFileSystemKQueueAllEvents = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | + NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | + NOTE_REVOKE, +}; +typedef unsigned int GTMFileSystemKQueueEvents; + +// GTMFileSystemKQueue. +// +// This is a very simple, easy-to-use class for registering handlers that get +// called when a events happen to a given file system path. +// +// The default runloop for the first path kqueued is used for notification +// delivery, so keep that in mind when you're using this class. This class +// explicitly does not handle arbitrary runloops and threading. +// +@interface GTMFileSystemKQueue : NSObject { + @private + NSString *path_; + int fd_; + GTMFileSystemKQueueEvents events_; + BOOL acrossReplace_; + __weak id target_; + SEL action_; +} + +// |path| is the full path to monitor. |events| is a combination of events +// listed above that you want notification of. |acrossReplace| will cause this +// object to reattach when a the file is deleted & recreated or moved out of the +// way and a new one put in place. |selector| should be of the signature: +// - (void)fileSystemKQueue:(GTMFileSystemKQueue *)fskq +// events:(GTMFileSystemKQueueEvents)events; +// where the events can be one or more of the events listed above ORed together. +// +// NOTE: |acrossReplace| is not fool proof. If the file is renamed/deleted, +// then the object will make one attempt at the time it gets the rename/delete +// to reopen the file. If the new file has not been created, no more action is +// taken. To handle the file coming into existance later, you need to monitor +// the directory in some other way. +- (id)initWithPath:(NSString *)path + forEvents:(GTMFileSystemKQueueEvents)events + acrossReplace:(BOOL)acrossReplace + target:(id)target + action:(SEL)action; + +- (NSString *)path; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.m new file mode 100644 index 00000000..ad516f70 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueue.m @@ -0,0 +1,259 @@ +// +// GTMFileSystemKQueue.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMFileSystemKQueue.h" +#import +#import "GTMDefines.h" +#import "GTMDebugSelectorValidation.h" + + +// File descriptor for the kqueue that will hold all of our file system events. +static int gFileSystemKQueueFileDescriptor = 0; + +// A wrapper around the kqueue file descriptor so we can put it into a +// runloop. +static CFSocketRef gRunLoopSocket = NULL; + + +@interface GTMFileSystemKQueue (PrivateMethods) +- (void)notify:(GTMFileSystemKQueueEvents)eventFFlags; +- (void)addFileDescriptorMonitor:(int)fd; +- (int)registerWithKQueue; +- (void)unregisterWithKQueue; +@end + + +@implementation GTMFileSystemKQueue + +-(id)init { + // Folks shouldn't call init directly, so they get what they deserve. + _GTMDevLog(@"Don't call init, use " + @"initWithPath:forEvents:acrossReplace:target:action:"); + return [self initWithPath:nil forEvents:0 acrossReplace:NO + target:nil action:nil]; +} + + +- (id)initWithPath:(NSString *)path + forEvents:(GTMFileSystemKQueueEvents)events + acrossReplace:(BOOL)acrossReplace + target:(id)target + action:(SEL)action { + + if ((self = [super init])) { + + fd_ = -1; + path_ = [path copy]; + events_ = events; + acrossReplace_ = acrossReplace; + + target_ = target; // Don't retain since target will most likely retain us. + action_ = action; + if ([path_ length] == 0 || !events_ || !target_ || !action_) { + [self release]; + return nil; + } + + // Make sure it imples what we expect + GTMAssertSelectorNilOrImplementedWithArguments(target_, + action_, + @encode(GTMFileSystemKQueue*), + @encode(GTMFileSystemKQueueEvents), + NULL); + + fd_ = [self registerWithKQueue]; + if (fd_ < 0) { + [self release]; + return nil; + } + } + return self; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + [self unregisterWithKQueue]; + + [super finalize]; +} +#endif + +- (void)dealloc { + [self unregisterWithKQueue]; + [path_ release]; + + [super dealloc]; +} + +- (NSString *)path { + return path_; +} + +// Cribbed from Advanced Mac OS X Programming. +static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type, + CFDataRef address, const void *data, void *info) { + // We're using CFRunLoop calls here. Even when used on the main thread, they + // don't trigger the draining of the main application's autorelease pool that + // NSRunLoop provides. If we're used in a UI-less app, this means that + // autoreleased objects would never go away, so we provide our own pool here. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + struct kevent event; + + if (kevent(gFileSystemKQueueFileDescriptor, NULL, 0, &event, 1, NULL) == -1) { + _GTMDevLog(@"could not pick up kqueue event. Errno %d", errno); // COV_NF_LINE + } else { + GTMFileSystemKQueue *fskq = (GTMFileSystemKQueue *)event.udata; + [fskq notify:event.fflags]; + } + + [pool drain]; +} + +// Cribbed from Advanced Mac OS X Programming +- (void)addFileDescriptorMonitor:(int)fd { + _GTMDevAssert(gRunLoopSocket == NULL, @"socket should be NULL at this point"); + + CFSocketContext context = { 0, NULL, NULL, NULL, NULL }; + gRunLoopSocket = CFSocketCreateWithNative(kCFAllocatorDefault, + fd, + kCFSocketReadCallBack, + SocketCallBack, + &context); + if (gRunLoopSocket == NULL) { + _GTMDevLog(@"could not CFSocketCreateWithNative"); // COV_NF_LINE + goto bailout; // COV_NF_LINE + } + + CFRunLoopSourceRef rls; + rls = CFSocketCreateRunLoopSource(NULL, gRunLoopSocket, 0); + if (rls == NULL) { + _GTMDevLog(@"could not create a run loop source"); // COV_NF_LINE + goto bailout; // COV_NF_LINE + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, + kCFRunLoopDefaultMode); + CFRelease(rls); + + bailout: + return; + +} + +// Returns the FD we got in registering +- (int)registerWithKQueue { + + // Make sure we have our kqueue. + if (gFileSystemKQueueFileDescriptor == 0) { + gFileSystemKQueueFileDescriptor = kqueue(); + + if (gFileSystemKQueueFileDescriptor == -1) { + // COV_NF_START + _GTMDevLog(@"could not make filesystem kqueue. Errno %d", errno); + return -1; + // COV_NF_END + } + + // Add the kqueue file descriptor to the runloop. + [self addFileDescriptorMonitor:gFileSystemKQueueFileDescriptor]; + } + + int newFD = open([path_ fileSystemRepresentation], O_EVTONLY, 0); + if (newFD >= 0) { + + // Add a new event for the file. + struct kevent filter; + EV_SET(&filter, newFD, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + events_, 0, self); + + const struct timespec noWait = { 0, 0 }; + if (kevent(gFileSystemKQueueFileDescriptor, &filter, 1, NULL, 0, &noWait) == -1) { + // COV_NF_START + _GTMDevLog(@"could not add event for path %@. Errno %d", path_, errno); + close(newFD); + newFD = -1; + // COV_NF_END + } + } + + return newFD; +} + +- (void)unregisterWithKQueue { + // Short-circuit cases where we didn't actually register a kqueue event. + if (fd_ < 0) return; + + struct kevent filter; + EV_SET(&filter, fd_, EVFILT_VNODE, EV_DELETE, 0, 0, self); + + const struct timespec noWait = { 0, 0 }; + if (kevent(gFileSystemKQueueFileDescriptor, &filter, 1, NULL, 0, &noWait) != 0) { + _GTMDevLog(@"could not remove event for path %@. Errno %d", path_, errno); // COV_NF_LINE + } + + // Now close the file down + close(fd_); + fd_ = -1; +} + + +- (void)notify:(GTMFileSystemKQueueEvents)eventFFlags { + + // Some notifications get a little bit of overhead first + + if (eventFFlags & NOTE_REVOKE) { + // COV_NF_START - no good way to do this in a unittest + // Assume revoke means unmount and give up + [self unregisterWithKQueue]; + // COV_NF_END + } + + if (eventFFlags & NOTE_DELETE) { + [self unregisterWithKQueue]; + if (acrossReplace_) { + fd_ = [self registerWithKQueue]; + } + } + + if (eventFFlags & NOTE_RENAME) { + // If we're doing it across replace, we move to the new fd for the new file + // that might have come onto the path. if we aren't doing accross replace, + // nothing to do, just stay on the file. + if (acrossReplace_) { + int newFD = [self registerWithKQueue]; + if (newFD >= 0) { + [self unregisterWithKQueue]; + fd_ = newFD; + } + } + } + + // Now, fire the selector + NSMethodSignature *methodSig = [target_ methodSignatureForSelector:action_]; + _GTMDevAssert(methodSig != nil, @"failed to get the signature?"); + NSInvocation *invocation + = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setTarget:target_]; + [invocation setSelector:action_]; + [invocation setArgument:self atIndex:2]; + [invocation setArgument:&eventFFlags atIndex:3]; + [invocation invoke]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueueTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueueTest.m new file mode 100644 index 00000000..c2ded100 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFileSystemKQueueTest.m @@ -0,0 +1,394 @@ +// +// GTMFileSystemKQueueTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMFileSystemKQueue.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMFileSystemKQueueTest : GTMTestCase { + @private + NSString *testPath_; + NSString *testPath2_; +} +@end + + +// Helper class to serve as callback target of the kqueue test +@interface GTMFSKQTestHelper : NSObject { + @private + int writes_, renames_, deletes_; +} +@end + +@implementation GTMFSKQTestHelper + +- (void)callbackForQueue:(GTMFileSystemKQueue *)queue + events:(GTMFileSystemKQueueEvents)event { + if (event & kGTMFileSystemKQueueWriteEvent) { + ++writes_; + } + if (event & kGTMFileSystemKQueueDeleteEvent) { + ++deletes_; + } + if (event & kGTMFileSystemKQueueRenameEvent) { + ++renames_; + } +} +- (int)totals { + return writes_ + renames_ + deletes_; +} +- (int)writes { + return writes_; +} +- (int)renames { + return renames_; +} +- (int)deletes { + return deletes_; +} +@end + + +@implementation GTMFileSystemKQueueTest + +- (void)setUp { + NSString *temp = NSTemporaryDirectory(); + testPath_ + = [[temp stringByAppendingPathComponent: + @"GTMFileSystemKQueueTest.testfile"] retain]; + testPath2_ = [[testPath_ stringByAppendingPathExtension:@"2"] retain]; + + // make sure the files aren't in the way of the test + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeFileAtPath:testPath_ handler:nil]; + [fm removeFileAtPath:testPath2_ handler:nil]; +} + +- (void)tearDown { + // make sure we clean up the files from a failed test + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeFileAtPath:testPath_ handler:nil]; + [fm removeFileAtPath:testPath2_ handler:nil]; + + [testPath_ release]; + testPath_ = nil; + [testPath2_ release]; + testPath2_ = nil; +} + +- (void)testInit { + GTMFileSystemKQueue *testKQ; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + // init should fail + [GTMUnitTestDevLog expectString:@"Don't call init, use " + @"initWithPath:forEvents:acrossReplace:target:action:"]; + testKQ = [[[GTMFileSystemKQueue alloc] init] autorelease]; + STAssertNil(testKQ, nil); + + // no path + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:nil + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // not events + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:0 + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // no target + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:nil + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // no handler + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:0 + acrossReplace:YES + target:helper + action:nil] autorelease]; + STAssertNil(testKQ, nil); + + + // path that doesn't exist + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/path/that/does/not/exist" + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); +} + +- (void)spinForEvents:(GTMFSKQTestHelper *)helper { + // Spin the runloop for a second so that the helper callbacks fire + unsigned int attempts = 0; + int initialTotals = [helper totals]; + while (([helper totals] == initialTotals) && (attempts < 10)) { // Try for up to 2s + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + attempts++; + } +} + +- (void)testWriteAndDelete { + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + + STAssertEquals([helper writes], 1, nil); + STAssertEquals([helper deletes], 1, nil); + STAssertEquals([helper renames], 0, nil); +} + +- (void)testWriteAndDeleteAndWrite { + + // One will pass YES to |acrossReplace|, the other will pass NO. + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + GTMFSKQTestHelper *helper2 = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + // Create a temp file path + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + GTMFileSystemKQueue *testKQ2 + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:NO + target:helper2 + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ2, nil); + STAssertEqualObjects([testKQ2 path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + STAssertEquals([helper2 totals], 1, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Recreate + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + [testFH writeData:[@"ha!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to it again + [testFH writeData:[@"continued..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 4, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + [testKQ2 release]; + testKQ2 = nil; + + STAssertEquals([helper writes], 2, nil); + STAssertEquals([helper deletes], 2, nil); + STAssertEquals([helper renames], 0, nil); + STAssertEquals([helper2 writes], 1, nil); + STAssertEquals([helper2 deletes], 1, nil); + STAssertEquals([helper2 renames], 0, nil); +} + +- (void)testWriteAndRenameAndWrite { + + // One will pass YES to |acrossReplace|, the other will pass NO. + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + GTMFSKQTestHelper *helper2 = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper2, nil); + + // Create a temp file path + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + GTMFileSystemKQueue *testKQ2 + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:NO + target:helper2 + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ2, nil); + STAssertEqualObjects([testKQ2 path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + STAssertEquals([helper2 totals], 1, nil); + + // Move it and create the file again + STAssertTrue([fm movePath:testPath_ toPath:testPath2_ handler:nil], nil); + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFHPrime + = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFHPrime, nil); + [testFHPrime writeData:[@"eh?" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to the new file + [testFHPrime writeData:[@"continue..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to the old file + [testFH writeData:[@"continue old..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 3, nil); + + // and now close old + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath2_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 4, nil); + + // and now close new + [testFHPrime closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 4, nil); + STAssertEquals([helper2 totals], 4, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + [testKQ2 release]; + testKQ2 = nil; + + STAssertEquals([helper writes], 2, nil); + STAssertEquals([helper deletes], 1, nil); + STAssertEquals([helper renames], 1, nil); + STAssertEquals([helper2 writes], 2, nil); + STAssertEquals([helper2 deletes], 1, nil); + STAssertEquals([helper2 renames], 1, nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.h new file mode 100644 index 00000000..90853b54 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.h @@ -0,0 +1,51 @@ +// +// GTMFourCharCode +// Wrapper for FourCharCodes +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// FourCharCodes are OSTypes, ResTypes etc. This class wraps them if +// you need to store them in dictionaries etc. +@interface GTMFourCharCode : NSObject { + FourCharCode code_; +} + +// returns a string for a FourCharCode ++ (id)stringWithFourCharCode:(FourCharCode)code; + +// String must be 4 chars or less, or you will get nil back. ++ (id)fourCharCodeWithString:(NSString*)string; ++ (id)fourCharCodeWithFourCharCode:(FourCharCode)code; + +// String must be 4 chars or less, or you will get nil back. +- (id)initWithString:(NSString*)string; + +// Designated Initializer +- (id)initWithFourCharCode:(FourCharCode)code; + +// Returns 'APPL' for "APPL" +- (FourCharCode)fourCharCode; + +// For FourCharCode of 'APPL' returns "APPL". For 1 returns "\0\0\0\1" +- (NSString*)stringValue; + +// For FourCharCode of "APPL" returns an NSNumber with 1095782476 (0x4150504C). +// For 1 returns 1. +- (NSNumber*)numberValue; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.m new file mode 100644 index 00000000..f5a08bff --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCode.m @@ -0,0 +1,98 @@ +// +// GTMFourCharCode.m +// Wrapper for FourCharCodes +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import "GTMFourCharCode.h" +#import "GTMGarbageCollection.h" +#import + +@implementation GTMFourCharCode + ++ (id)stringWithFourCharCode:(FourCharCode)code { + return GTMCFAutorelease(UTCreateStringForOSType(code)); +} + ++ (id)fourCharCodeWithString:(NSString*)string { + return [[[self alloc] initWithString:string] autorelease]; +} + ++ (id)fourCharCodeWithFourCharCode:(FourCharCode)code { + return [[[self alloc] initWithFourCharCode:code] autorelease]; +} + +- (id)initWithString:(NSString*)string { + NSUInteger length = [string length]; + if (length == 0 || length > 4) { + [self release]; + return nil; + } else { + return [self initWithFourCharCode:UTGetOSTypeFromString((CFStringRef)string)]; + } +} + +- (id)initWithFourCharCode:(FourCharCode)code { + if ((self = [super init])) { + code_ = code; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + if ((self = [super init])) { + code_ = [aDecoder decodeInt32ForKey:@"FourCharCode"]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt32:code_ forKey:@"FourCharCode"]; +} + +- (id)copyWithZone:(NSZone *)zone { + return [[[self class] alloc] initWithFourCharCode:code_]; +} + +- (BOOL)isEqual:(id)object { + return [object isKindOfClass:[self class]] && [object fourCharCode] == code_; +} + +- (NSUInteger)hash { + return (NSUInteger)code_; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ - %@ (0x%X)", + [self class], + [self stringValue], + code_]; +} + +- (FourCharCode)fourCharCode { + return code_; +} + +- (NSString*)stringValue { + return GTMCFAutorelease(UTCreateStringForOSType(code_)); +} + +- (NSNumber*)numberValue { + return [NSNumber numberWithUnsignedInt:code_]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCodeTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCodeTest.m new file mode 100644 index 00000000..f91b8f2b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMFourCharCodeTest.m @@ -0,0 +1,82 @@ +// +// GTMFourCharCodeTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMFourCharCode.h" + +@interface GTMFourCharCodeTest : GTMTestCase +@end + +@implementation GTMFourCharCodeTest + +const FourCharCode kGTMHighMacOSRomanCode = 0xA5A8A9AA; // '•®©™' + +- (void)testFourCharCode { + GTMFourCharCode *fcc = [GTMFourCharCode fourCharCodeWithString:@"APPL"]; + STAssertNotNil(fcc, nil); + STAssertEqualObjects([fcc stringValue], @"APPL", nil); + STAssertEqualObjects([fcc numberValue], [NSNumber numberWithUnsignedInt:'APPL'], nil); + STAssertEquals([fcc fourCharCode], (FourCharCode)'APPL', nil); + + STAssertEqualObjects([fcc description], @"GTMFourCharCode - APPL (0x4150504C)", nil); + STAssertEquals([fcc hash], (NSUInteger)'APPL', nil); + + GTMFourCharCode *fcc2 = [GTMFourCharCode fourCharCodeWithFourCharCode:kGTMHighMacOSRomanCode]; + STAssertNotNil(fcc2, nil); + STAssertEqualObjects([fcc2 stringValue], @"•®©™", nil); + STAssertEqualObjects([fcc2 numberValue], [NSNumber numberWithUnsignedInt:kGTMHighMacOSRomanCode], nil); + STAssertEquals([fcc2 fourCharCode], (FourCharCode)kGTMHighMacOSRomanCode, nil); + + STAssertNotEqualObjects(fcc, fcc2, nil); + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:fcc]; + STAssertNotNil(data, nil); + fcc2 = (GTMFourCharCode*)[NSKeyedUnarchiver unarchiveObjectWithData:data]; + STAssertNotNil(fcc2, nil); + STAssertEqualObjects(fcc, fcc2, nil); + + fcc = [[[GTMFourCharCode alloc] initWithFourCharCode:'\?\?\?\?'] autorelease]; + STAssertNotNil(fcc, nil); + STAssertEqualObjects([fcc stringValue], @"????", nil); + STAssertEqualObjects([fcc numberValue], [NSNumber numberWithUnsignedInt:'\?\?\?\?'], nil); + STAssertEquals([fcc fourCharCode], (FourCharCode)'\?\?\?\?', nil); + + fcc = [[[GTMFourCharCode alloc] initWithString:@"????"] autorelease]; + STAssertNotNil(fcc, nil); + STAssertEqualObjects([fcc stringValue], @"????", nil); + STAssertEqualObjects([fcc numberValue], [NSNumber numberWithUnsignedInt:'\?\?\?\?'], nil); + STAssertEquals([fcc fourCharCode], (FourCharCode)'\?\?\?\?', nil); + + fcc = [GTMFourCharCode fourCharCodeWithFourCharCode:1]; + STAssertNotNil(fcc, nil); + STAssertEqualObjects([fcc stringValue], @"\0\0\0\1", nil); + STAssertEqualObjects([fcc numberValue], [NSNumber numberWithUnsignedInt:1], nil); + STAssertEquals([fcc fourCharCode], (FourCharCode)1, nil); + + + fcc = [GTMFourCharCode fourCharCodeWithString:@"BADDSTRING"]; + STAssertNil(fcc, nil); +} + +- (void)testStringWithCode { + STAssertEqualObjects([GTMFourCharCode stringWithFourCharCode:'APPL'], @"APPL", nil); + STAssertEqualObjects([GTMFourCharCode stringWithFourCharCode:1], @"\0\0\0\1", nil); + STAssertEqualObjects([GTMFourCharCode stringWithFourCharCode:kGTMHighMacOSRomanCode], @"•®©™", nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGarbageCollection.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGarbageCollection.h new file mode 100644 index 00000000..93d4efab --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGarbageCollection.h @@ -0,0 +1,72 @@ +// +// GTMGarbageCollection.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +#import "GTMDefines.h" + +// This allows us to easily move our code from GC to non GC. +// They are no-ops unless we are require Leopard or above. +// See +// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/index.html +// and +// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1 +// for details. + +#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) && !GTM_IPHONE_SDK +// General use would be to call this through GTMCFAutorelease +// but there may be a reason the you want to make something collectable +// but not autoreleased, especially in pure GC code where you don't +// want to bother with the nop autorelease. Done as a define instead of an +// inline so that tools like Clang's scan-build don't report code as leaking. +#define GTMNSMakeCollectable(cf) ((id)NSMakeCollectable(cf)) + +// GTMNSMakeUncollectable is for global maps, etc. that we don't +// want released ever. You should still retain these in non-gc code. +GTM_INLINE void GTMNSMakeUncollectable(id object) { + [[NSGarbageCollector defaultCollector] disableCollectorForPointer:object]; +} + +// Hopefully no code really needs this, but GTMIsGarbageCollectionEnabled is +// a common way to check at runtime if GC is on. +// There are some places where GC doesn't work w/ things w/in Apple's +// frameworks, so this is here so GTM unittests and detect it, and not run +// individual tests to work around bugs in Apple's frameworks. +GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { + return ([NSGarbageCollector defaultCollector] != nil); +} + +#else + +#define GTMNSMakeCollectable(cf) ((id)(cf)) + +GTM_INLINE void GTMNSMakeUncollectable(id object) { +} + +GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { + return NO; +} + +#endif + +// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it +// to the autorelease pool in non-GC mode. Either way it is taken care +// of. Done as a define instead of an inline so that tools like Clang's +// scan-build don't report code as leaking. +#define GTMCFAutorelease(cf) ([GTMNSMakeCollectable(cf) autorelease]) + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.h new file mode 100644 index 00000000..c3d6b1af --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.h @@ -0,0 +1,452 @@ +// +// GTMGeometryUtils.h +// +// Utilities for geometrical utilities such as conversions +// between different types. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +enum { + GTMScaleProportionally = 0, // Fit proportionally + GTMScaleToFit, // Forced fit (distort if necessary) + GTMScaleNone, // Don't scale (clip) + GTMScaleToFillProportionally = 101 // Scale proportionally to fill area +}; +typedef NSUInteger GTMScaling; + +enum { + GTMRectAlignCenter = 0, + GTMRectAlignTop, + GTMRectAlignTopLeft, + GTMRectAlignTopRight, + GTMRectAlignLeft, + GTMRectAlignBottom, + GTMRectAlignBottomLeft, + GTMRectAlignBottomRight, + GTMRectAlignRight +}; +typedef NSUInteger GTMRectAlignment; + +#pragma mark - +#pragma mark CG - Point On Rect +/// Return middle of min X side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of min X side of rect +GTM_INLINE CGPoint GTMCGMidMinX(CGRect rect) { + return CGPointMake(CGRectGetMinX(rect), CGRectGetMidY(rect)); +} + +/// Return middle of max X side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of max X side of rect +GTM_INLINE CGPoint GTMCGMidMaxX(CGRect rect) { + return CGPointMake(CGRectGetMaxX(rect), CGRectGetMidY(rect)); +} + +/// Return middle of max Y side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of max Y side of rect +GTM_INLINE CGPoint GTMCGMidMaxY(CGRect rect) { + return CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)); +} + +/// Return middle of min Y side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of min Y side of rect +GTM_INLINE CGPoint GTMCGMidMinY(CGRect rect) { + return CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); +} + +/// Return center of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the center of rect +GTM_INLINE CGPoint GTMCGCenter(CGRect rect) { + return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); +} + +#pragma mark - +#pragma mark CG - Rect-Size Conversion + +/// Return size of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// size of rectangle +GTM_INLINE CGSize GTMCGRectSize(CGRect rect) { + return CGSizeMake(CGRectGetWidth(rect), CGRectGetHeight(rect)); +} + +/// Return rectangle of size +// +// Args: +// size - size +// +// Returns: +// rectangle of size (origin 0,0) +GTM_INLINE CGRect GTMCGRectOfSize(CGSize size) { + return CGRectMake(0.0f, 0.0f, size.width, size.height); +} + +#pragma mark - +#pragma mark CG - Rect Scaling and Alignment + +/// Scales an CGRect +// +// Args: +// inRect: Rect to scale +// xScale: fraction to scale (1.0 is 100%) +// yScale: fraction to scale (1.0 is 100%) +// +// Returns: +// Converted Rect +GTM_INLINE CGRect GTMCGRectScale(CGRect inRect, CGFloat xScale, CGFloat yScale) { + return CGRectMake(inRect.origin.x, inRect.origin.y, + inRect.size.width * xScale, inRect.size.height * yScale); +} + + +/// Align rectangles +// +// Args: +// alignee - rect to be aligned +// aligner - rect to be aligned from +// alignment - way to align the rectangles +CGRect GTMCGAlignRectangles(CGRect alignee, CGRect aligner, + GTMRectAlignment alignment); +/// Scale rectangle +// +// Args: +// scalee - rect to be scaled +// size - size to scale to +// scaling - way to scale the rectangle +CGRect GTMCGScaleRectangleToSize(CGRect scalee, CGSize size, + GTMScaling scaling); + +#pragma mark - +#pragma mark CG - Miscellaneous + +/// Calculate the distance between two points. +// +// Args: +// pt1 first point +// pt2 second point +// +// Returns: +// Distance +GTM_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) { + CGFloat dX = pt1.x - pt2.x; + CGFloat dY = pt1.y - pt2.y; +#if CGFLOAT_IS_DOUBLE + return sqrt(dX * dX + dY * dY); +#else + return sqrtf(dX * dX + dY * dY); +#endif +} + +#if !GTM_IPHONE_SDK +// iPhone does not have NSTypes defined, only CGTypes. So no NSRect, NSPoint etc. + +#pragma mark - +// All of the conversion routines below are basically copied from the +// NSGeometry header in the 10.5 sdk. + +#pragma mark NS <-> CG Point Conversion + +/// Quickly convert from a CGPoint to a NSPoint. +// +/// CGPoints are relative to 0,0 in lower left; +/// NSPoints are relative to 0,0 in lower left +// +// Args: +// inPoint: CGPoint to convert +// +// Returns: +// Converted NSPoint +GTM_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) { + _GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size); + union convertUnion {NSPoint ns; CGPoint cg;}; + return ((union convertUnion *)&inPoint)->ns; +} + +/// Quickly convert from a NSPoint to a CGPoint. +// +/// CGPoints are relative to 0,0 in lower left; +/// NSPoints are relative to 0,0 in lower left +// +// Args: +// inPoint: NSPoint to convert +// +// Returns: +// Converted CGPoint +GTM_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) { + _GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size); + union convertUnion {NSPoint ns; CGPoint cg;}; + return ((union convertUnion *)&inPoint)->cg; +} + +#pragma mark - +#pragma mark NS <-> CG Rect Conversion + +/// Convert from a CGRect to a NSRect. +// +/// NSRect are relative to 0,0 in lower left; +/// CGRect are relative to 0,0 in lower left +// +// Args: +// inRect: CGRect to convert +// +// Returns: +// Converted NSRect +GTM_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) { + _GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size); + union convertUnion {NSRect ns; CGRect cg;}; + return ((union convertUnion *)&inRect)->ns; +} + +/// Convert from a NSRect to a CGRect. +// +/// NSRect are relative to 0,0 in lower left; +/// CGRect are relative to 0,0 in lower left +// +// Args: +// inRect: NSRect to convert +// +// Returns: +// Converted CGRect +GTM_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) { + _GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size); + union convertUnion {NSRect ns; CGRect cg;}; + return ((union convertUnion *)&inRect)->cg; +} + + +#pragma mark - +#pragma mark NS <-> CG Size Conversion + +/// Convert from a CGSize to an NSSize. +// +// Args: +// inSize: CGSize to convert +// +// Returns: +// Converted NSSize +GTM_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) { + _GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size); + union convertUnion {NSSize ns; CGSize cg;}; + return ((union convertUnion *)&inSize)->ns; +} + +/// Convert from a NSSize to a CGSize. +// +// Args: +// inSize: NSSize to convert +// +// Returns: +// Converted CGSize +GTM_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) { + _GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size); + union convertUnion {NSSize ns; CGSize cg;}; + return ((union convertUnion *)&inSize)->cg; +} + +#pragma mark - +#pragma mark NS - Point On Rect + +/// Return middle of min X side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of min X side of rect +GTM_INLINE NSPoint GTMNSMidMinX(NSRect rect) { + return NSMakePoint(NSMinX(rect), NSMidY(rect)); +} + +/// Return middle of max X side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of max X side of rect +GTM_INLINE NSPoint GTMNSMidMaxX(NSRect rect) { + return NSMakePoint(NSMaxX(rect), NSMidY(rect)); +} + +/// Return middle of max Y side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of max Y side of rect +GTM_INLINE NSPoint GTMNSMidMaxY(NSRect rect) { + return NSMakePoint(NSMidX(rect), NSMaxY(rect)); +} + +/// Return middle of min Y side of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the middle of min Y side of rect +GTM_INLINE NSPoint GTMNSMidMinY(NSRect rect) { + return NSMakePoint(NSMidX(rect), NSMinY(rect)); +} + +/// Return center of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// point located in the center of rect +GTM_INLINE NSPoint GTMNSCenter(NSRect rect) { + return NSMakePoint(NSMidX(rect), NSMidY(rect)); +} + +#pragma mark - +#pragma mark NS - Rect-Size Conversion + +/// Return size of rectangle +// +// Args: +// rect - rectangle +// +// Returns: +// size of rectangle +GTM_INLINE NSSize GTMNSRectSize(NSRect rect) { + return NSMakeSize(NSWidth(rect), NSHeight(rect)); +} + +/// Return rectangle of size +// +// Args: +// size - size +// +// Returns: +// rectangle of size (origin 0,0) +GTM_INLINE NSRect GTMNSRectOfSize(NSSize size) { + return NSMakeRect(0.0f, 0.0f, size.width, size.height); +} + +#pragma mark - +#pragma mark NS - Rect Scaling and Alignment + +/// Scales an NSRect +// +// Args: +// inRect: Rect to scale +// xScale: fraction to scale (1.0 is 100%) +// yScale: fraction to scale (1.0 is 100%) +// +// Returns: +// Converted Rect +GTM_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) { + return NSMakeRect(inRect.origin.x, inRect.origin.y, + inRect.size.width * xScale, inRect.size.height * yScale); +} + +/// Align rectangles +// +// Args: +// alignee - rect to be aligned +// aligner - rect to be aligned from +GTM_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner, + GTMRectAlignment alignment) { + return GTMCGRectToNSRect(GTMCGAlignRectangles(GTMNSRectToCGRect(alignee), + GTMNSRectToCGRect(aligner), + alignment)); +} + +/// Align a rectangle to another +// +// Args: +// scalee - rect to be scaled +// scaler - rect to scale to +// scaling - way to scale the rectangle +// alignment - way to align the scaled rectangle +GTM_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee, + NSRect scaler, + GTMScaling scaling, + GTMRectAlignment alignment) { + + return GTMCGRectToNSRect( + GTMCGAlignRectangles( + GTMCGScaleRectangleToSize(GTMNSRectToCGRect(scalee), + GTMNSSizeToCGSize(scaler.size), + scaling), + GTMNSRectToCGRect(scaler), + alignment)); +} + +/// Scale rectangle +// +// Args: +// scalee - rect to be scaled +// size - size to scale to +// scaling - way to scale the rectangle +GTM_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size, + GTMScaling scaling) { + return GTMCGRectToNSRect(GTMCGScaleRectangleToSize(GTMNSRectToCGRect(scalee), + GTMNSSizeToCGSize(size), + scaling)); +} + +#pragma mark - +#pragma mark NS - Miscellaneous + +/// Calculate the distance between two points. +// +// Args: +// pt1 first point +// pt2 second point +// +// Returns: +// Distance +GTM_INLINE CGFloat GTMNSDistanceBetweenPoints(NSPoint pt1, NSPoint pt2) { + return GTMCGDistanceBetweenPoints(GTMNSPointToCGPoint(pt1), + GTMNSPointToCGPoint(pt2)); +} + +#endif // !GTM_IPHONE_SDK diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.m new file mode 100644 index 00000000..07de80c3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtils.m @@ -0,0 +1,108 @@ +// +// GTMGeometryUtils.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMGeometryUtils.h" + +/// Align rectangles +// +// Args: +// alignee - rect to be aligned +// aligner - rect to be aligned to +// alignment - alignment to be applied to alignee based on aligner + +CGRect GTMCGAlignRectangles(CGRect alignee, CGRect aligner, GTMRectAlignment alignment) { + switch (alignment) { + case GTMRectAlignTop: + alignee.origin.x = aligner.origin.x + (CGRectGetWidth(aligner) * .5f - CGRectGetWidth(alignee) * .5f); + alignee.origin.y = aligner.origin.y + CGRectGetHeight(aligner) - CGRectGetHeight(alignee); + break; + + case GTMRectAlignTopLeft: + alignee.origin.x = aligner.origin.x; + alignee.origin.y = aligner.origin.y + CGRectGetHeight(aligner) - CGRectGetHeight(alignee); + break; + + case GTMRectAlignTopRight: + alignee.origin.x = aligner.origin.x + CGRectGetWidth(aligner) - CGRectGetWidth(alignee); + alignee.origin.y = aligner.origin.y + CGRectGetHeight(aligner) - CGRectGetHeight(alignee); + break; + + case GTMRectAlignLeft: + alignee.origin.x = aligner.origin.x; + alignee.origin.y = aligner.origin.y + (CGRectGetHeight(aligner) * .5f - CGRectGetHeight(alignee) * .5f); + break; + + case GTMRectAlignBottomLeft: + alignee.origin.x = aligner.origin.x; + alignee.origin.y = aligner.origin.y; + break; + + case GTMRectAlignBottom: + alignee.origin.x = aligner.origin.x + (CGRectGetWidth(aligner) * .5f - CGRectGetWidth(alignee) * .5f); + alignee.origin.y = aligner.origin.y; + break; + + case GTMRectAlignBottomRight: + alignee.origin.x = aligner.origin.x + CGRectGetWidth(aligner) - CGRectGetWidth(alignee); + alignee.origin.y = aligner.origin.y; + break; + + case GTMRectAlignRight: + alignee.origin.x = aligner.origin.x + CGRectGetWidth(aligner) - CGRectGetWidth(alignee); + alignee.origin.y = aligner.origin.y + (CGRectGetHeight(aligner) * .5f - CGRectGetHeight(alignee) * .5f); + break; + + default: + case GTMRectAlignCenter: + alignee.origin.x = aligner.origin.x + (CGRectGetWidth(aligner) * .5f - CGRectGetWidth(alignee) * .5f); + alignee.origin.y = aligner.origin.y + (CGRectGetHeight(aligner) * .5f - CGRectGetHeight(alignee) * .5f); + break; + } + return alignee; +} + +CGRect GTMCGScaleRectangleToSize(CGRect scalee, CGSize size, GTMScaling scaling) { + switch (scaling) { + + case GTMScaleToFillProportionally: + case GTMScaleProportionally: { + CGFloat height = CGRectGetHeight(scalee); + CGFloat width = CGRectGetWidth(scalee); + if (isnormal(height) && isnormal(width) && + (height > size.height || width > size.width)) { + CGFloat horiz = size.width / width; + CGFloat vert = size.height / height; + BOOL expand = (scaling == GTMScaleToFillProportionally); + // We use the smaller scale unless expand is true. In that case, larger. + CGFloat newScale = ((horiz < vert) ^ expand) ? horiz : vert; + scalee = GTMCGRectScale(scalee, newScale, newScale); + } + break; + } + + case GTMScaleToFit: + scalee.size = size; + break; + + case GTMScaleNone: + default: + // Do nothing + break; + } + return scalee; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtilsTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtilsTest.m new file mode 100644 index 00000000..38b86fbd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMGeometryUtilsTest.m @@ -0,0 +1,331 @@ +// +// GTMGeometryUtilsTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMGeometryUtils.h" + +@interface GTMGeometryUtilsTest : GTMTestCase +@end + +@implementation GTMGeometryUtilsTest + +#if !GTM_IPHONE_SDK +- (void)testGTMCGPointToNSPoint { + CGPoint cgPoint = CGPointMake(15.1,6.2); + NSPoint nsPoint = GTMCGPointToNSPoint(cgPoint); + STAssertTrue(CGPointEqualToPoint(*(CGPoint*)&nsPoint, cgPoint), nil); +} + +- (void)testGTMNSPointToCGPoint { + NSPoint nsPoint = NSMakePoint(10.2,1.5); + CGPoint cgPoint = GTMNSPointToCGPoint(nsPoint); + STAssertTrue(CGPointEqualToPoint(cgPoint, *(CGPoint*)&nsPoint), nil); +} + +- (void)testGTMCGRectToNSRect { + CGRect cgRect = CGRectMake(1.5,2.4,10.6,11.7); + NSRect nsRect = GTMCGRectToNSRect(cgRect); + STAssertTrue(CGRectEqualToRect(cgRect, *(CGRect*)&nsRect), nil); +} + +- (void)testGTMNSRectToCGRect { + NSRect nsRect = NSMakeRect(4.6,3.2,22.1,45.0); + CGRect cgRect = GTMNSRectToCGRect(nsRect); + STAssertTrue(CGRectEqualToRect(cgRect, *(CGRect*)&nsRect), nil); +} + +- (void)testGTMCGSizeToNSSize { + CGSize cgSize = {5,6}; + NSSize nsSize = GTMCGSizeToNSSize(cgSize); + STAssertTrue(CGSizeEqualToSize(cgSize, *(CGSize*)&nsSize), nil); +} + +- (void)testGTMNSSizeToCGSize { + NSSize nsSize = {22,15}; + CGSize cgSize = GTMNSSizeToCGSize(nsSize); + STAssertTrue(CGSizeEqualToSize(cgSize, *(CGSize*)&nsSize), nil); +} + +- (void)testGTMNSPointsOnRect { + NSRect rect = NSMakeRect(0, 0, 2, 2); + + NSPoint point = GTMNSMidMinX(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)0.0, (CGFloat)0.01, nil); + + point = GTMNSMidMaxX(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)2.0, (CGFloat)0.01, nil); + + point = GTMNSMidMaxY(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)2.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); + + point = GTMNSMidMinY(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)0.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); + + point = GTMNSCenter(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); +} + +- (void)testGTMNSRectSize { + NSSize nsSize = GTMNSRectSize(NSMakeRect(1, 1, 10, 5)); + STAssertEqualsWithAccuracy(nsSize.width, (CGFloat)10.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(nsSize.height, (CGFloat)5.0, (CGFloat)0.01, nil); +} + +- (void)testGTMNSRectOfSize { + NSRect outRect = GTMNSRectOfSize(NSMakeSize(10, 5)); + NSRect expectedRect = NSMakeRect(0, 0, 10, 5); + STAssertEquals(outRect, expectedRect, nil); +} + +- (void)testGTMNSAlignRectangles { + typedef struct { + NSPoint expectedOrigin; + GTMRectAlignment alignment; + } TestData; + + TestData data[] = { + { {1,2}, GTMRectAlignTop }, + { {0,2}, GTMRectAlignTopLeft }, + { {2,2}, GTMRectAlignTopRight }, + { {0,1}, GTMRectAlignLeft }, + { {1,0}, GTMRectAlignBottom }, + { {0,0}, GTMRectAlignBottomLeft }, + { {2,0}, GTMRectAlignBottomRight }, + { {2,1}, GTMRectAlignRight }, + { {1,1}, GTMRectAlignCenter }, + }; + + NSRect rect1 = NSMakeRect(0, 0, 4, 4); + NSRect rect2 = NSMakeRect(0, 0, 2, 2); + + NSRect expectedRect; + expectedRect.size = NSMakeSize(2, 2); + + for (size_t i = 0; i < sizeof(data) / sizeof(TestData); i++) { + expectedRect.origin = data[i].expectedOrigin; + NSRect outRect = GTMNSAlignRectangles(rect2, rect1, data[i].alignment); + STAssertEquals(outRect, expectedRect, nil); + } +} + +- (void)testGTMNSScaleRectangleToSize { + NSRect rect = NSMakeRect(0.0f, 0.0f, 10.0f, 10.0f); + typedef struct { + NSSize size_; + NSSize newSize_; + } Test; + Test tests[] = { + { { 5.0, 10.0 }, { 5.0, 5.0 } }, + { { 10.0, 5.0 }, { 5.0, 5.0 } }, + { { 10.0, 10.0 }, { 10.0, 10.0 } }, + { { 11.0, 11.0, }, { 10.0, 10.0 } }, + { { 5.0, 2.0 }, { 2.0, 2.0 } }, + { { 2.0, 5.0 }, { 2.0, 2.0 } }, + { { 2.0, 2.0 }, { 2.0, 2.0 } }, + { { 0.0, 10.0 }, { 0.0, 0.0 } } + }; + + for (size_t i = 0; i < sizeof(tests) / sizeof(Test); ++i) { + NSRect result = GTMNSScaleRectangleToSize(rect, tests[i].size_, + GTMScaleProportionally); + STAssertEquals(result, GTMNSRectOfSize(tests[i].newSize_), @"failed on test %zd", i); + } + + NSRect result = GTMNSScaleRectangleToSize(NSZeroRect, tests[0].size_, + GTMScaleProportionally); + STAssertEquals(result, NSZeroRect, nil); + + result = GTMNSScaleRectangleToSize(rect, tests[0].size_, + GTMScaleToFit); + STAssertEquals(result, GTMNSRectOfSize(tests[0].size_), nil); + + result = GTMNSScaleRectangleToSize(rect, tests[0].size_, + GTMScaleNone); + STAssertEquals(result, rect, nil); +} + + +- (void)testGTMNSScaleRectToRect { + typedef struct { + NSRect expectedRect; + GTMScaling scaling; + GTMRectAlignment alignment; + } TestData; + + NSRect rect1 = NSMakeRect(0, 0, 4, 4); + NSRect rect2 = NSMakeRect(0, 0, 2, 1); + + TestData data[] = { + { NSMakeRect(2, 3, 2, 1), GTMScaleToFillProportionally, GTMRectAlignTopRight }, + { NSMakeRect(0, 0, 4, 4), GTMScaleToFit, GTMRectAlignCenter }, + { NSMakeRect(1, 1.5, 2, 1), GTMScaleNone, GTMRectAlignCenter }, + { NSMakeRect(1, 0, 2, 1), GTMScaleProportionally, GTMRectAlignBottom }, + }; + + for (size_t i = 0; i < sizeof(data) / sizeof(TestData); i++) { + NSRect outRect = GTMNSScaleRectToRect(rect2, rect1, data[i].scaling, data[i].alignment); + STAssertEquals(outRect, data[i].expectedRect, nil); + } +} + + +- (void)testGTMNSDistanceBetweenPoints { + NSPoint pt1 = NSMakePoint(0, 0); + NSPoint pt2 = NSMakePoint(3, 4); + STAssertEquals(GTMNSDistanceBetweenPoints(pt1, pt2), (CGFloat)5.0, nil); + STAssertEquals(GTMNSDistanceBetweenPoints(pt2, pt1), (CGFloat)5.0, nil); + pt1 = NSMakePoint(1, 1); + pt2 = NSMakePoint(1, 1); + STAssertEquals(GTMNSDistanceBetweenPoints(pt1, pt2), (CGFloat)0.0, nil); +} + +- (void)testGTMNSRectScaling { + NSRect rect = NSMakeRect(1.0f, 2.0f, 5.0f, 10.0f); + NSRect rect2 = NSMakeRect((CGFloat)1.0, (CGFloat)2.0, (CGFloat)1.0, (CGFloat)12.0); + STAssertEquals(GTMNSRectScale(rect, (CGFloat)0.2, (CGFloat)1.2), + rect2, nil); +} + +#endif // !GTM_IPHONE_SDK + +- (void)testGTMCGDistanceBetweenPoints { + CGPoint pt1 = CGPointMake(0, 0); + CGPoint pt2 = CGPointMake(3, 4); + STAssertEquals(GTMCGDistanceBetweenPoints(pt1, pt2), (CGFloat)5.0, nil); + STAssertEquals(GTMCGDistanceBetweenPoints(pt2, pt1), (CGFloat)5.0, nil); + pt1 = CGPointMake(1, 1); + pt2 = CGPointMake(1, 1); + STAssertEquals(GTMCGDistanceBetweenPoints(pt1, pt2), (CGFloat)0.0, nil); +} + +- (void)testGTMCGAlignRectangles { + typedef struct { + CGPoint expectedOrigin; + GTMRectAlignment alignment; + } TestData; + + TestData data[] = { + { {1,2}, GTMRectAlignTop }, + { {0,2}, GTMRectAlignTopLeft }, + { {2,2}, GTMRectAlignTopRight }, + { {0,1}, GTMRectAlignLeft }, + { {1,0}, GTMRectAlignBottom }, + { {0,0}, GTMRectAlignBottomLeft }, + { {2,0}, GTMRectAlignBottomRight }, + { {2,1}, GTMRectAlignRight }, + { {1,1}, GTMRectAlignCenter }, + }; + + CGRect rect1 = CGRectMake(0, 0, 4, 4); + CGRect rect2 = CGRectMake(0, 0, 2, 2); + + CGRect expectedRect; + expectedRect.size = CGSizeMake(2, 2); + + for (size_t i = 0; i < sizeof(data) / sizeof(TestData); i++) { + expectedRect.origin = data[i].expectedOrigin; + CGRect outRect = GTMCGAlignRectangles(rect2, rect1, data[i].alignment); + STAssertEquals(outRect, expectedRect, nil); + } +} + +- (void)testGTMCGPointsOnRect { + CGRect rect = CGRectMake(0, 0, 2, 2); + + CGPoint point = GTMCGMidMinX(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)0.0, (CGFloat)0.01, nil); + + point = GTMCGMidMaxX(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)2.0, (CGFloat)0.01, nil); + + point = GTMCGMidMaxY(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)2.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); + + point = GTMCGMidMinY(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)0.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); + + point = GTMCGCenter(rect); + STAssertEqualsWithAccuracy(point.y, (CGFloat)1.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(point.x, (CGFloat)1.0, (CGFloat)0.01, nil); +} + +- (void)testGTMCGRectSize { + CGSize cgSize = GTMCGRectSize(CGRectMake(1, 1, 10, 5)); + STAssertEqualsWithAccuracy(cgSize.width, (CGFloat)10.0, (CGFloat)0.01, nil); + STAssertEqualsWithAccuracy(cgSize.height, (CGFloat)5.0, (CGFloat)0.01, nil); +} + +- (void)testGTMCGRectOfSize { + CGRect outRect = GTMCGRectOfSize(CGSizeMake(10, 5)); + CGRect expectedRect = CGRectMake(0, 0, 10, 5); + STAssertEquals(outRect, expectedRect, nil); +} + +- (void)testGTMCGRectScaling { + CGRect rect = CGRectMake(1.0f, 2.0f, 5.0f, 10.0f); + CGRect rect2 = CGRectMake((CGFloat)1.0, (CGFloat)2.0, (CGFloat)1.0, (CGFloat)12.0); + STAssertEquals(GTMCGRectScale(rect, (CGFloat)0.2, (CGFloat)1.2), + rect2, nil); +} + +- (void)testGTMCGScaleRectangleToSize { + CGRect rect = CGRectMake(0.0f, 0.0f, 10.0f, 10.0f); + typedef struct { + CGSize size_; + CGSize newSize_; + } Test; + Test tests[] = { + { { 5.0, 10.0 }, { 5.0, 5.0 } }, + { { 10.0, 5.0 }, { 5.0, 5.0 } }, + { { 10.0, 10.0 }, { 10.0, 10.0 } }, + { { 11.0, 11.0, }, { 10.0, 10.0 } }, + { { 5.0, 2.0 }, { 2.0, 2.0 } }, + { { 2.0, 5.0 }, { 2.0, 2.0 } }, + { { 2.0, 2.0 }, { 2.0, 2.0 } }, + { { 0.0, 10.0 }, { 0.0, 0.0 } } + }; + + for (size_t i = 0; i < sizeof(tests) / sizeof(Test); ++i) { + CGRect result = GTMCGScaleRectangleToSize(rect, tests[i].size_, + GTMScaleProportionally); + STAssertEquals(result, GTMCGRectOfSize(tests[i].newSize_), @"failed on test %zd", i); + } + + CGRect result = GTMCGScaleRectangleToSize(CGRectZero, tests[0].size_, + GTMScaleProportionally); + STAssertEquals(result, CGRectZero, nil); + + result = GTMCGScaleRectangleToSize(rect, tests[0].size_, + GTMScaleToFit); + STAssertEquals(result, GTMCGRectOfSize(tests[0].size_), nil); + + result = GTMCGScaleRectangleToSize(rect, tests[0].size_, + GTMScaleNone); + STAssertEquals(result, rect, nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPFetcher.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPFetcher.h new file mode 100644 index 00000000..7377d1c3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPFetcher.h @@ -0,0 +1,22 @@ +// +// GTMHTTPFetcher.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This class is no more. If you want something like it's functionality, look +// at using the version in the Objective-C GData Client +// (http://code.google.com/p/gdata-objectivec-client/). It provides the same +// functionality and will continue to be maintained. diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.h new file mode 100644 index 00000000..0caa1492 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.h @@ -0,0 +1,137 @@ +// +// GTMHTTPServer.h +// +// This is a *very* *simple* webserver that can be built into something, it is +// not meant to stand up a site, it sends all requests to its delegate for +// processing on the main thread. It does not support pipelining, etc. It's +// great for places where you need a simple webserver to unittest some code +// that hits a server. +// +// NOTE: there are several TODOs left in here as markers for things that could +// be done if one wanted to add more to this class. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// +// Based a little on HTTPServer, part of the CocoaHTTPServer sample code +// http://developer.apple.com/samplecode/CocoaHTTPServer/index.html +// + +#import +#import "GTMDefines.h" + +#if GTM_IPHONE_SDK +#import +#endif // GTM_IPHONE_SDK + +// Global contants needed for errors from start + +#undef _EXTERN +#undef _INITIALIZE_AS +#ifdef GTMHTTPSERVER_DEFINE_GLOBALS +#define _EXTERN +#define _INITIALIZE_AS(x) =x +#else +#define _EXTERN GTM_EXTERN +#define _INITIALIZE_AS(x) +#endif + +_EXTERN NSString* kGTMHTTPServerErrorDomain _INITIALIZE_AS(@"com.google.mactoolbox.HTTPServerDomain"); +enum { + kGTMHTTPServerSocketCreateFailedError = -100, + kGTMHTTPServerBindFailedError = -101, + kGTMHTTPServerListenFailedError = -102, + kGTMHTTPServerHandleCreateFailedError = -103, +}; + +@class GTMHTTPRequestMessage, GTMHTTPResponseMessage; + +// ---------------------------------------------------------------------------- + +// See comment at top of file for the intened use of this class. +@interface GTMHTTPServer : NSObject { + @private + __weak id delegate_; + uint16_t port_; + BOOL localhostOnly_; + NSFileHandle *listenHandle_; + NSMutableArray *connections_; +} + +// The delegate must support the httpServer:handleRequest: method in +// NSObject(GTMHTTPServerDeletateMethods) below. +- (id)initWithDelegate:(id)delegate; + +- (id)delegate; + +// Passing port zero will let one get assigned. +- (uint16_t)port; +- (void)setPort:(uint16_t)port; + +// Receive connections on the localHost loopback address only or on all +// interfaces for this machine. The default is to only listen on localhost. +- (BOOL)localhostOnly; +- (void)setLocalhostOnly:(BOOL)yesno; + +// Start/Stop the web server. If there is an error starting up the server, |NO| +// is returned, and the specific startup failure can be returned in |error| (see +// above for the error domain and error codes). If the server is started, |YES| +// is returned and the server's delegate is called for any requests that come +// in. +- (BOOL)start:(NSError **)error; +- (void)stop; + +// returns the number of requests currently active in the server (i.e.-being +// read in, sent replies). +- (NSUInteger)activeRequestCount; + +@end + +@interface NSObject (GTMHTTPServerDeletateMethods) +- (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server + handleRequest:(GTMHTTPRequestMessage *)request; +@end + +// ---------------------------------------------------------------------------- + +// Encapsulates an http request, one of these is sent to the server's delegate +// for each request. +@interface GTMHTTPRequestMessage : NSObject { + @private + CFHTTPMessageRef message_; +} +- (NSString *)version; +- (NSURL *)URL; +- (NSString *)method; +- (NSData *)body; +- (NSDictionary *)allHeaderFieldValues; +@end + +// ---------------------------------------------------------------------------- + +// Encapsulates an http response, the server's delegate should return one for +// each request received. +@interface GTMHTTPResponseMessage : NSObject { + @private + CFHTTPMessageRef message_; +} ++ (id)responseWithHTMLString:(NSString *)htmlString; ++ (id)responseWithBody:(NSData *)body + contentType:(NSString *)contentType + statusCode:(int)statusCode; ++ (id)emptyResponseWithCode:(int)statusCode; +// TODO: class method for redirections? +// TODO: add helper for expire/no-cache +- (void)setValue:(NSString*)value forHeaderField:(NSString*)headerField; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.m new file mode 100644 index 00000000..4a7a859c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServer.m @@ -0,0 +1,595 @@ +// +// GTMHTTPServer.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// +// Based a little on HTTPServer, part of the CocoaHTTPServer sample code +// http://developer.apple.com/samplecode/CocoaHTTPServer/index.html +// + +#import +#import +#import + +#define GTMHTTPSERVER_DEFINE_GLOBALS +#import "GTMHTTPServer.h" +#import "GTMDebugSelectorValidation.h" +#import "GTMGarbageCollection.h" +#import "GTMDefines.h" + +@interface GTMHTTPServer (PrivateMethods) +- (void)acceptedConnectionNotification:(NSNotification *)notification; +- (NSMutableDictionary *)connectionWithFileHandle:(NSFileHandle *)fileHandle; +- (void)dataAvailableNotification:(NSNotification *)notification; +- (NSMutableDictionary *)lookupConnection:(NSFileHandle *)fileHandle; +- (void)closeConnection:(NSMutableDictionary *)connDict; +- (void)sendResponseOnNewThread:(NSMutableDictionary *)connDict; +- (void)sentResponse:(NSMutableDictionary *)connDict; +@end + +// keys for our connection dictionaries +static NSString *kFileHandle = @"FileHandle"; +static NSString *kRequest = @"Request"; +static NSString *kResponse = @"Response"; + +@interface GTMHTTPRequestMessage (PrivateHelpers) +- (BOOL)isHeaderComplete; +- (BOOL)appendData:(NSData *)data; +- (NSString *)headerFieldValueForKey:(NSString *)key; +- (UInt32)contentLength; +- (void)setBody:(NSData *)body; +@end + +@interface GTMHTTPResponseMessage (PrivateMethods) +- (id)initWithBody:(NSData *)body + contentType:(NSString *)contentType + statusCode:(int)statusCode; +- (NSData*)serializedData; +@end + +@implementation GTMHTTPServer + +- (id)init { + return [self initWithDelegate:nil]; +} + +- (id)initWithDelegate:(id)delegate { + self = [super init]; + if (self) { + if (!delegate) { + _GTMDevLog(@"missing delegate"); + [self release]; + return nil; + } + delegate_ = delegate; + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(delegate_, + @selector(httpServer:handleRequest:), + // return type + @encode(GTMHTTPResponseMessage *), + // args + @encode(GTMHTTPServer *), + @encode(GTMHTTPRequestMessage *), + NULL); + localhostOnly_ = YES; + connections_ = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)dealloc { + [self stop]; + [connections_ release]; + [super dealloc]; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + [self stop]; + [super finalize]; +} +#endif + +- (id)delegate { + return delegate_; +} + +- (uint16_t)port { + return port_; +} + +- (void)setPort:(uint16_t)port { + port_ = port; +} + +- (BOOL)localhostOnly { + return localhostOnly_; +} + +- (void)setLocalhostOnly:(BOOL)yesno { + localhostOnly_ = yesno; +} + +- (BOOL)start:(NSError **)error { + _GTMDevAssert(listenHandle_ == nil, + @"start called when we already have a listenHandle_"); + + if (error) *error = NULL; + + NSInteger startFailureCode = 0; + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd <= 0) { + // COV_NF_START - we'd need to use up *all* sockets to test this? + startFailureCode = kGTMHTTPServerSocketCreateFailedError; + goto startFailed; + // COV_NF_END + } + + // enable address reuse quicker after we are done w/ our socket + int yes = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (void *)&yes, (socklen_t)sizeof(yes)) != 0) { + _GTMDevLog(@"failed to mark the socket as reusable"); // COV_NF_LINE + } + + // bind + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); + addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_port = htons(port_); + if (localhostOnly_) { + addr.sin_addr.s_addr = htonl(0x7F000001); + } else { + // COV_NF_START - testing this could cause a leopard firewall prompt during tests. + addr.sin_addr.s_addr = htonl(INADDR_ANY); + // COV_NF_END + } + if (bind(fd, (struct sockaddr*)(&addr), (socklen_t)sizeof(addr)) != 0) { + startFailureCode = kGTMHTTPServerBindFailedError; + goto startFailed; + } + + // collect the port back out + if (port_ == 0) { + socklen_t len = (socklen_t)sizeof(addr); + if (getsockname(fd, (struct sockaddr*)(&addr), &len) == 0) { + port_ = ntohs(addr.sin_port); + } + } + + // tell it to listen for connections + if (listen(fd, 5) != 0) { + // COV_NF_START + startFailureCode = kGTMHTTPServerListenFailedError; + goto startFailed; + // COV_NF_END + } + + // now use a filehandle to accept connections + listenHandle_ = + [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES]; + if (listenHandle_ == nil) { + // COV_NF_START - we'd need to run out of memory to test this? + startFailureCode = kGTMHTTPServerHandleCreateFailedError; + goto startFailed; + // COV_NF_END + } + + // setup notifications for connects + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(acceptedConnectionNotification:) + name:NSFileHandleConnectionAcceptedNotification + object:listenHandle_]; + [listenHandle_ acceptConnectionInBackgroundAndNotify]; + + // TODO: maybe hit the delegate incase it wants to register w/ NSNetService, + // or just know we're up and running? + + return YES; + +startFailed: + if (error) { + *error = [[[NSError alloc] initWithDomain:kGTMHTTPServerErrorDomain + code:startFailureCode + userInfo:nil] autorelease]; + } + if (fd > 0) { + close(fd); + } + return NO; +} + +- (void)stop { + if (listenHandle_) { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self + name:NSFileHandleConnectionAcceptedNotification + object:listenHandle_]; + [listenHandle_ release]; + listenHandle_ = nil; + // TODO: maybe hit the delegate in case it wants to unregister w/ + // NSNetService, or just know we've stopped running? + } + [connections_ removeAllObjects]; +} + +- (NSUInteger)activeRequestCount { + return [connections_ count]; +} + +- (NSString *)description { + NSString *result = + [NSString stringWithFormat:@"%@<%p>{ port=%d localHostOnly=%@ status=%@ }", + [self class], self, port_, (localhostOnly_ ? @"YES" : @"NO"), + (listenHandle_ != nil ? @"Started" : @"Stopped") ]; + return result; +} + + +@end + +@implementation GTMHTTPServer (PrivateMethods) + +- (void)acceptedConnectionNotification:(NSNotification *)notification { + NSDictionary *userInfo = [notification userInfo]; + NSFileHandle *newConnection = + [userInfo objectForKey:NSFileHandleNotificationFileHandleItem]; + _GTMDevAssert(newConnection != nil, + @"failed to get the connection in the notification: %@", + notification); + + // make sure we accept more... + [listenHandle_ acceptConnectionInBackgroundAndNotify]; + + // TODO: could let the delegate look at the address, before we start working + // on it. + + NSMutableDictionary *connDict = + [self connectionWithFileHandle:newConnection]; + [connections_ addObject:connDict]; +} + +- (NSMutableDictionary *)connectionWithFileHandle:(NSFileHandle *)fileHandle { + NSMutableDictionary *result = [NSMutableDictionary dictionary]; + + [result setObject:fileHandle forKey:kFileHandle]; + + GTMHTTPRequestMessage *request = + [[[GTMHTTPRequestMessage alloc] init] autorelease]; + [result setObject:request forKey:kRequest]; + + // setup for data notifications + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(dataAvailableNotification:) + name:NSFileHandleReadCompletionNotification + object:fileHandle]; + [fileHandle readInBackgroundAndNotify]; + + return result; +} + +- (void)dataAvailableNotification:(NSNotification *)notification { + NSFileHandle *connectionHandle = [notification object]; + NSMutableDictionary *connDict = [self lookupConnection:connectionHandle]; + if (connDict == nil) return; // we are no longer tracking this one + + NSDictionary *userInfo = [notification userInfo]; + NSData *readData = [userInfo objectForKey:NSFileHandleNotificationDataItem]; + if ([readData length] == 0) { + // remote side closed + [self closeConnection:connDict]; + return; + } + + // Like Apple's sample, we just keep adding data until we get a full header + // and any referenced body. + + GTMHTTPRequestMessage *request = [connDict objectForKey:kRequest]; + [request appendData:readData]; + + // Is the header complete yet? + if (![request isHeaderComplete]) { + // more data... + [connectionHandle readInBackgroundAndNotify]; + return; + } + + // Do we have all the body? + UInt32 contentLength = [request contentLength]; + NSData *body = [request body]; + NSUInteger bodyLength = [body length]; + if (contentLength > bodyLength) { + // need more data... + [connectionHandle readInBackgroundAndNotify]; + return; + } + + if (contentLength < bodyLength) { + // We got extra (probably someone trying to pipeline on us), trim + // and let the extra data go... + NSData *newBody = [NSData dataWithBytes:[body bytes] + length:contentLength]; + [request setBody:newBody]; + _GTMDevLog(@"Got %lu extra bytes on http request, ignoring them", + (unsigned long)(bodyLength - contentLength)); + } + + GTMHTTPResponseMessage *response = nil; + @try { + // Off to the delegate + response = [delegate_ httpServer:self handleRequest:request]; + } @catch (NSException *e) { + _GTMDevLog(@"Exception trying to handle http request: %@", e); + } // COV_NF_LINE - radar 5851992 only reachable w/ an uncaught exception which isn't testable + + if (!response) { + [self closeConnection:connDict]; + return; + } + + // We don't support connection reuse, so we add (force) the header to close + // every connection. + [response setValue:@"close" forHeaderField:@"Connection"]; + + // spawn thread to send reply (since we do a blocking send) + [connDict setObject:response forKey:kResponse]; + [NSThread detachNewThreadSelector:@selector(sendResponseOnNewThread:) + toTarget:self + withObject:connDict]; +} + +- (NSMutableDictionary *)lookupConnection:(NSFileHandle *)fileHandle { + NSMutableDictionary *result = nil; + NSUInteger max = [connections_ count]; + for (NSUInteger x = 0; x < max; ++x) { + NSMutableDictionary *connDict = [connections_ objectAtIndex:x]; + if (fileHandle == [connDict objectForKey:kFileHandle]) { + result = connDict; + break; + } + } + return result; +} + +- (void)closeConnection:(NSMutableDictionary *)connDict { + // remove the notification + NSFileHandle *connectionHandle = [connDict objectForKey:kFileHandle]; + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self + name:NSFileHandleReadCompletionNotification + object:connectionHandle]; + // in a non GC world, we're fine just letting the connect get closed when + // the object is release when it comes out of connections_, but in a GC world + // it won't get cleaned up + [connectionHandle closeFile]; + + // remove it from the list + [connections_ removeObject:connDict]; +} + +- (void)sendResponseOnNewThread:(NSMutableDictionary *)connDict { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + @try { + GTMHTTPResponseMessage *response = [connDict objectForKey:kResponse]; + NSFileHandle *connectionHandle = [connDict objectForKey:kFileHandle]; + NSData *serialized = [response serializedData]; + [connectionHandle writeData:serialized]; + } @catch (NSException *e) { // COV_NF_START - causing an exception here is to hard in a test + // TODO: let the delegate know about the exception (but do it on the main + // thread) + _GTMDevLog(@"exception while sending reply: %@", e); + } // COV_NF_END + + // back to the main thread to close things down + [self performSelectorOnMainThread:@selector(sentResponse:) + withObject:connDict + waitUntilDone:NO]; + + [pool release]; +} + +- (void)sentResponse:(NSMutableDictionary *)connDict { + // make sure we're still tracking this connection (in case server was stopped) + NSFileHandle *connection = [connDict objectForKey:kFileHandle]; + NSMutableDictionary *connDict2 = [self lookupConnection:connection]; + if (connDict != connDict2) return; + + // TODO: message the delegate that it was sent + + // close it down + [self closeConnection:connDict]; +} + +@end + +#pragma mark - + +@implementation GTMHTTPRequestMessage + +- (id)init { + self = [super init]; + if (self) { + message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, YES); + } + return self; +} + +- (void)dealloc { + if (message_) { + CFRelease(message_); + } + [super dealloc]; +} + +- (NSString *)version { + return GTMCFAutorelease(CFHTTPMessageCopyVersion(message_)); +} + +- (NSURL *)URL { + return GTMCFAutorelease(CFHTTPMessageCopyRequestURL(message_)); +} + +- (NSString *)method { + return GTMCFAutorelease(CFHTTPMessageCopyRequestMethod(message_)); +} + +- (NSData *)body { + return GTMCFAutorelease(CFHTTPMessageCopyBody(message_)); +} + +- (NSDictionary *)allHeaderFieldValues { + return GTMCFAutorelease(CFHTTPMessageCopyAllHeaderFields(message_)); +} + +- (NSString *)description { + CFStringRef desc = CFCopyDescription(message_); + NSString *result = + [NSString stringWithFormat:@"%@<%p>{ message=%@ }", [self class], self, desc]; + CFRelease(desc); + return result; +} + +@end + +@implementation GTMHTTPRequestMessage (PrivateHelpers) + +- (BOOL)isHeaderComplete { + return CFHTTPMessageIsHeaderComplete(message_) ? YES : NO; +} + +- (BOOL)appendData:(NSData *)data { + return CFHTTPMessageAppendBytes(message_, + [data bytes], [data length]) ? YES : NO; +} + +- (NSString *)headerFieldValueForKey:(NSString *)key { + CFStringRef value = NULL; + if (key) { + value = CFHTTPMessageCopyHeaderFieldValue(message_, (CFStringRef)key); + } + return GTMCFAutorelease(value); +} + +- (UInt32)contentLength { + return [[self headerFieldValueForKey:@"Content-Length"] intValue]; +} + +- (void)setBody:(NSData *)body { + if (!body) { + body = [NSData data]; // COV_NF_LINE - can only happen in we fail to make the new data object + } + CFHTTPMessageSetBody(message_, (CFDataRef)body); +} + +@end + +#pragma mark - + +@implementation GTMHTTPResponseMessage + +- (id)init { + return [self initWithBody:nil contentType:nil statusCode:0]; +} + +- (void)dealloc { + if (message_) { + CFRelease(message_); + } + [super dealloc]; +} + ++ (id)responseWithHTMLString:(NSString *)htmlString { + return [self responseWithBody:[htmlString dataUsingEncoding:NSUTF8StringEncoding] + contentType:@"text/html; charset=UTF-8" + statusCode:200]; +} + ++ (id)responseWithBody:(NSData *)body + contentType:(NSString *)contentType + statusCode:(int)statusCode { + return [[[[self class] alloc] initWithBody:body + contentType:contentType + statusCode:statusCode] autorelease]; +} + ++ (id)emptyResponseWithCode:(int)statusCode { + return [[[[self class] alloc] initWithBody:nil + contentType:nil + statusCode:statusCode] autorelease]; +} + +- (void)setValue:(NSString*)value forHeaderField:(NSString*)headerField { + if ([headerField length] == 0) return; + if (value == nil) { + value = @""; + } + CFHTTPMessageSetHeaderFieldValue(message_, + (CFStringRef)headerField, (CFStringRef)value); +} + +- (NSString *)description { + CFStringRef desc = CFCopyDescription(message_); + NSString *result = + [NSString stringWithFormat:@"%@<%p>{ message=%@ }", [self class], self, desc]; + CFRelease(desc); + return result; +} + +@end + +@implementation GTMHTTPResponseMessage (PrivateMethods) + +- (id)initWithBody:(NSData *)body + contentType:(NSString *)contentType + statusCode:(int)statusCode { + self = [super init]; + if (self) { + if ((statusCode < 100) || (statusCode > 599)) { + [self release]; + return nil; + } + message_ = CFHTTPMessageCreateResponse(kCFAllocatorDefault, + statusCode, NULL, + kCFHTTPVersion1_0); + if (!message_) { + // COV_NF_START + [self release]; + return nil; + // COV_NF_END + } + NSUInteger bodyLength = 0; + if (body) { + bodyLength = [body length]; + CFHTTPMessageSetBody(message_, (CFDataRef)body); + } + if ([contentType length] == 0) { + contentType = @"text/html"; + } + NSString *bodyLenStr = + [NSString stringWithFormat:@"%lu", (unsigned long)bodyLength]; + [self setValue:bodyLenStr forHeaderField:@"Content-Length"]; + [self setValue:contentType forHeaderField:@"Content-Type"]; + } + return self; +} + +- (NSData *)serializedData { + return GTMCFAutorelease(CFHTTPMessageCopySerializedMessage(message_)); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServerTest.m new file mode 100644 index 00000000..fd962afc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMHTTPServerTest.m @@ -0,0 +1,574 @@ +// +// GTMHTTPServerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import +#import +#import "GTMSenTestCase.h" +#import "GTMUnitTestDevLog.h" +#import "GTMHTTPServer.h" +#import "GTMRegex.h" + +@interface GTMHTTPServerTest : GTMTestCase { + NSData *fetchedData_; +} +@end + +@interface GTMHTTPServerTest (PrivateMethods) +- (NSData *)fetchFromPort:(unsigned short)port + payload:(NSString *)payload + chunkSize:(NSUInteger)chunkSize; +- (NSFileHandle *)fileHandleSendingToPort:(unsigned short)port + payload:(NSString *)payload + chunkSize:(NSUInteger)chunkSize; +- (void)readFinished:(NSNotification *)notification; +@end + +// helper class +@interface TestServerDelegate : NSObject { + NSMutableArray *requests_; + NSMutableArray *responses_; +} ++ (id)testServerDelegate; +- (NSUInteger)requestCount; +- (GTMHTTPRequestMessage *)popRequest; +- (void)pushResponse:(GTMHTTPResponseMessage *)message; +@end + +// helper that throws while handling its request +@interface TestThrowingServerDelegate : TestServerDelegate +- (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server + handleRequest:(GTMHTTPRequestMessage *)request; +@end + +// The timings used for waiting for replies +const NSTimeInterval kGiveUpInterval = 5.0; +const NSTimeInterval kRunLoopInterval = 0.01; + +// the size we break writes up into to test the reading code and how long to +// wait between writes. +const NSUInteger kSendChunkSize = 12; +const NSTimeInterval kSendChunkInterval = 0.05; + +// ---------------------------------------------------------------------------- + +@implementation GTMHTTPServerTest + +- (void)testInit { + // bad delegates + [GTMUnitTestDevLog expectString:@"missing delegate"]; + STAssertNil([[GTMHTTPServer alloc] init], nil); + [GTMUnitTestDevLog expectString:@"missing delegate"]; + STAssertNil([[GTMHTTPServer alloc] initWithDelegate:nil], nil); + + TestServerDelegate *delegate = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate, nil); + GTMHTTPServer *server = + [[[GTMHTTPServer alloc] initWithDelegate:delegate] autorelease]; + STAssertNotNil(server, nil); + + // some attributes + + STAssertTrue([server delegate] == delegate, nil); + + [server setLocalhostOnly:NO]; + STAssertFalse([server localhostOnly], nil); + [server setLocalhostOnly:YES]; + STAssertTrue([server localhostOnly], nil); + + STAssertEquals([server port], (uint16_t)0, nil); + [server setPort:8080]; + STAssertEquals([server port], (uint16_t)8080, nil); + [server setPort:80]; + STAssertEquals([server port], (uint16_t)80, nil); + + // description (atleast 10 chars) + STAssertGreaterThan([[server description] length], (NSUInteger)10, nil); +} + +- (void)testStartStop { + TestServerDelegate *delegate1 = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate1, nil); + GTMHTTPServer *server1 = + [[[GTMHTTPServer alloc] initWithDelegate:delegate1] autorelease]; + STAssertNotNil(server1, nil); + NSError *error = nil; + STAssertTrue([server1 start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + STAssertGreaterThanOrEqual([server1 port], (uint16_t)1024, + @"how'd we get a reserved port?"); + + TestServerDelegate *delegate2 = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate2, nil); + GTMHTTPServer *server2 = + [[[GTMHTTPServer alloc] initWithDelegate:delegate2] autorelease]; + STAssertNotNil(server2, nil); + + // try the reserved port + [server2 setPort:666]; + error = nil; + STAssertFalse([server2 start:&error], nil); + STAssertNotNil(error, nil); + STAssertEqualObjects([error domain], kGTMHTTPServerErrorDomain, nil); + STAssertEquals([error code], (NSInteger)kGTMHTTPServerBindFailedError, + @"port should have been reserved"); + + // try the same port + [server2 setPort:[server1 port]]; + error = nil; + STAssertFalse([server2 start:&error], nil); + STAssertNotNil(error, nil); + STAssertEqualObjects([error domain], kGTMHTTPServerErrorDomain, nil); + STAssertEquals([error code], (NSInteger)kGTMHTTPServerBindFailedError, + @"port should have been in use"); + + // try a random port again so we really start (prove two can run at once) + [server2 setPort:0]; + error = nil; + STAssertTrue([server2 start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + + // shut them down + [server1 stop]; + [server2 stop]; +} + +- (void)testRequests { + TestServerDelegate *delegate = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate, nil); + GTMHTTPServer *server = + [[[GTMHTTPServer alloc] initWithDelegate:delegate] autorelease]; + STAssertNotNil(server, nil); + NSError *error = nil; + STAssertTrue([server start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + + // a request to test all the fields of a request object + + NSString *payload = + @"PUT /some/server/path HTTP/1.0\r\n" + @"Content-Length: 16\r\n" + @"Custom-Header: Custom_Value\r\n" + @"\r\n" + @"this is the body"; + NSData *reply = + [self fetchFromPort:[server port] payload:payload chunkSize:kSendChunkSize]; + STAssertNotNil(reply, nil); + + GTMHTTPRequestMessage *request = [delegate popRequest]; + STAssertEqualObjects([request version], @"HTTP/1.0", nil); + STAssertEqualObjects([[request URL] absoluteString], @"/some/server/path", nil); + STAssertEqualObjects([request method], @"PUT", nil); + STAssertEqualObjects([request body], + [@"this is the body" dataUsingEncoding:NSUTF8StringEncoding], + nil); + NSDictionary *allHeaders = [request allHeaderFieldValues]; + STAssertNotNil(allHeaders, nil); + STAssertEquals([allHeaders count], (NSUInteger)2, nil); + STAssertEqualObjects([allHeaders objectForKey:@"Content-Length"], + @"16", nil); + STAssertEqualObjects([allHeaders objectForKey:@"Custom-Header"], + @"Custom_Value", nil); + STAssertGreaterThan([[request description] length], (NSUInteger)10, nil); + + // test different request types (in simple form) + + typedef struct { + NSString *method; + NSString *url; + } TestData; + + TestData data[] = { + { @"GET", @"/foo/bar" }, + { @"HEAD", @"/foo/baz" }, + { @"POST", @"/foo" }, + { @"PUT", @"/foo/spam" }, + { @"DELETE", @"/fooby/doo" }, + { @"TRACE", @"/something.html" }, + { @"CONNECT", @"/spam" }, + { @"OPTIONS", @"/wee/doggies" }, + }; + + for (size_t i = 0; i < sizeof(data) / sizeof(TestData); i++) { + payload = [NSString stringWithFormat:@"%@ %@ HTTP/1.0\r\n\r\n", + data[i].method, data[i].url]; + STAssertNotNil(payload, nil); + reply = [self fetchFromPort:[server port] + payload:payload + chunkSize:kSendChunkSize]; + STAssertNotNil(reply, // just want a reply in this test + @"failed of method %@", data[i].method); + request = [delegate popRequest]; + STAssertEqualObjects([[request URL] absoluteString], data[i].url, + @"urls didn't match for index %d", i); + STAssertEqualObjects([request method], data[i].method, + @"methods didn't match for index %d", i); + } + + [server stop]; +} + +- (void)testResponses { + + // some quick init tests for invalid things + STAssertNil([[GTMHTTPResponseMessage alloc] init], nil); + STAssertNil([GTMHTTPResponseMessage responseWithBody:nil + contentType:nil + statusCode:99], + nil); + STAssertNil([GTMHTTPResponseMessage responseWithBody:nil + contentType:nil + statusCode:602], + nil); + + TestServerDelegate *delegate = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate, nil); + GTMHTTPServer *server = + [[[GTMHTTPServer alloc] initWithDelegate:delegate] autorelease]; + STAssertNotNil(server, nil); + NSError *error = nil; + STAssertTrue([server start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + + // test the html helper + + GTMHTTPResponseMessage *expectedResponse = + [GTMHTTPResponseMessage responseWithHTMLString:@"Success!"]; + STAssertNotNil(expectedResponse, nil); + STAssertGreaterThan([[expectedResponse description] length], + (NSUInteger)0, nil); + [delegate pushResponse:expectedResponse]; + NSData *responseData = [self fetchFromPort:[server port] + payload:@"GET /foo HTTP/1.0\r\n\r\n" + chunkSize:kSendChunkSize]; + STAssertNotNil(responseData, nil); + NSString *responseString = + [[[NSString alloc] initWithData:responseData + encoding:NSUTF8StringEncoding] autorelease]; + STAssertNotNil(responseString, nil); + STAssertTrue([responseString hasPrefix:@"HTTP/1.0 200 OK"], nil); + STAssertTrue([responseString hasSuffix:@"Success!"], @"should end w/ our data"); + STAssertNotEquals([responseString rangeOfString:@"Content-Length: 8"].location, + (NSUInteger)NSNotFound, nil); + STAssertNotEquals([responseString rangeOfString:@"Content-Type: text/html; charset=UTF-8"].location, + (NSUInteger)NSNotFound, nil); + + // test the plain code response + + expectedResponse = [GTMHTTPResponseMessage emptyResponseWithCode:299]; + STAssertNotNil(expectedResponse, nil); + STAssertGreaterThan([[expectedResponse description] length], + (NSUInteger)0, nil); + [delegate pushResponse:expectedResponse]; + responseData = [self fetchFromPort:[server port] + payload:@"GET /foo HTTP/1.0\r\n\r\n" + chunkSize:kSendChunkSize]; + STAssertNotNil(responseData, nil); + responseString = + [[[NSString alloc] initWithData:responseData + encoding:NSUTF8StringEncoding] autorelease]; + STAssertNotNil(responseString, nil); + STAssertTrue([responseString hasPrefix:@"HTTP/1.0 299 "], nil); + STAssertNotEquals([responseString rangeOfString:@"Content-Length: 0"].location, + (NSUInteger)NSNotFound, nil); + STAssertNotEquals([responseString rangeOfString:@"Content-Type: text/html"].location, + (NSUInteger)NSNotFound, nil); + + // test the general api w/ extra header add + + expectedResponse = + [GTMHTTPResponseMessage responseWithBody:[@"FOO" dataUsingEncoding:NSUTF8StringEncoding] + contentType:@"some/type" + statusCode:298]; + STAssertNotNil(expectedResponse, nil); + STAssertGreaterThan([[expectedResponse description] length], + (NSUInteger)0, nil); + [expectedResponse setValue:@"Custom_Value" + forHeaderField:@"Custom-Header"]; + [expectedResponse setValue:nil + forHeaderField:@"Custom-Header2"]; + [delegate pushResponse:expectedResponse]; + responseData = [self fetchFromPort:[server port] + payload:@"GET /foo HTTP/1.0\r\n\r\n" + chunkSize:kSendChunkSize]; + STAssertNotNil(responseData, nil); + responseString = + [[[NSString alloc] initWithData:responseData + encoding:NSUTF8StringEncoding] autorelease]; + STAssertNotNil(responseString, nil); + STAssertTrue([responseString hasPrefix:@"HTTP/1.0 298"], nil); + STAssertTrue([responseString hasSuffix:@"FOO"], @"should end w/ our data"); + STAssertNotEquals([responseString rangeOfString:@"Content-Length: 3"].location, + (NSUInteger)NSNotFound, nil); + STAssertNotEquals([responseString rangeOfString:@"Content-Type: some/type"].location, + (NSUInteger)NSNotFound, nil); + STAssertNotEquals([responseString rangeOfString:@"Custom-Header: Custom_Value"].location, + (NSUInteger)NSNotFound, nil); + STAssertNotEquals([responseString rangeOfString:@"Custom-Header2: "].location, + (NSUInteger)NSNotFound, nil); + + [server stop]; +} + +- (void)testRequstEdgeCases { + // test all the odd things about requests + + TestServerDelegate *delegate = [TestServerDelegate testServerDelegate]; + STAssertNotNil(delegate, nil); + GTMHTTPServer *server = + [[[GTMHTTPServer alloc] initWithDelegate:delegate] autorelease]; + STAssertNotNil(server, nil); + NSError *error = nil; + STAssertTrue([server start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + + // extra data (ie-pipelining) + + NSString *payload = + @"GET /some/server/path HTTP/1.0\r\n" + @"\r\n" + @"GET /some/server/path/too HTTP/1.0\r\n" + @"\r\n"; + // don't chunk this, we want to make sure both requests get to our server + [GTMUnitTestDevLog expectString:@"Got 38 extra bytes on http request, " + "ignoring them"]; + NSData *reply = + [self fetchFromPort:[server port] payload:payload chunkSize:0]; + STAssertNotNil(reply, nil); + STAssertEquals([delegate requestCount], (NSUInteger)1, nil); + + // close w/o full request + { + // local pool so we can force our handle to close + NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; + NSFileHandle *handle = + [self fileHandleSendingToPort:[server port] + payload:@"GET /some/server/path HTTP/" + chunkSize:kSendChunkSize]; + STAssertNotNil(handle, nil); + // spin the run loop so reads the start of the request + NSDate* loopIntervalDate = + [NSDate dateWithTimeIntervalSinceNow:kRunLoopInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:loopIntervalDate]; + // make sure we see the request at this point + STAssertEquals([server activeRequestCount], (NSUInteger)1, + @"should have started the request by now"); + // force the connection closed and drop the pool to get all the cleanup to + // happen. + [handle closeFile]; + [localPool drain]; + // spin the run loop so it should see the close + loopIntervalDate = [NSDate dateWithTimeIntervalSinceNow:kRunLoopInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:loopIntervalDate]; + // make sure we didn't get a request (1 is from test before) and make sure + // we don't have some in flight. + STAssertEquals([delegate requestCount], (NSUInteger)1, + @"shouldn't have gotten another request"); + STAssertEquals([server activeRequestCount], (NSUInteger)0, + @"should have cleaned up the pending connection"); + } + +} + +- (void)testExceptionDuringRequest { + + TestServerDelegate *delegate = [TestThrowingServerDelegate testServerDelegate]; + STAssertNotNil(delegate, nil); + GTMHTTPServer *server = + [[[GTMHTTPServer alloc] initWithDelegate:delegate] autorelease]; + STAssertNotNil(server, nil); + NSError *error = nil; + STAssertTrue([server start:&error], @"failed to start (error=%@)", error); + STAssertNil(error, @"error: %@", error); + [GTMUnitTestDevLog expectString:@"Exception trying to handle http request: " + "To test our handling"]; + NSData *responseData = [self fetchFromPort:[server port] + payload:@"GET /foo HTTP/1.0\r\n\r\n" + chunkSize:kSendChunkSize]; + STAssertNotNil(responseData, nil); + STAssertEquals([responseData length], (NSUInteger)0, nil); + STAssertEquals([delegate requestCount], (NSUInteger)1, nil); + STAssertEquals([server activeRequestCount], (NSUInteger)0, nil); +} + +@end + +// ---------------------------------------------------------------------------- + +@implementation GTMHTTPServerTest (PrivateMethods) + +- (NSData *)fetchFromPort:(unsigned short)port + payload:(NSString *)payload + chunkSize:(NSUInteger)chunkSize { + fetchedData_ = nil; + + NSFileHandle *handle = [self fileHandleSendingToPort:port + payload:payload + chunkSize:chunkSize]; + + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(readFinished:) + name:NSFileHandleReadToEndOfFileCompletionNotification + object:handle]; + [handle readToEndOfFileInBackgroundAndNotify]; + + // wait for our reply + NSDate* giveUpDate = [NSDate dateWithTimeIntervalSinceNow:kGiveUpInterval]; + while (!fetchedData_ && [giveUpDate timeIntervalSinceNow] > 0) { + NSDate* loopIntervalDate = + [NSDate dateWithTimeIntervalSinceNow:kRunLoopInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:loopIntervalDate]; + } + + [center removeObserver:self + name:NSFileHandleReadToEndOfFileCompletionNotification + object:handle]; + + NSData *result = [fetchedData_ autorelease]; + fetchedData_ = nil; + return result; +} + +- (NSFileHandle *)fileHandleSendingToPort:(unsigned short)port + payload:(NSString *)payload + chunkSize:(NSUInteger)chunkSize { + int fd = socket(AF_INET, SOCK_STREAM, 0); + STAssertGreaterThan(fd, 0, @"failed to create socket"); + + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); + addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(0x7F000001); + int connectResult = + connect(fd, (struct sockaddr*)(&addr), (socklen_t)sizeof(addr)); + STAssertEquals(connectResult, 0, nil); + + NSFileHandle *handle = + [[[NSFileHandle alloc] initWithFileDescriptor:fd + closeOnDealloc:YES] autorelease]; + STAssertNotNil(handle, nil); + + NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding]; + + // we can send in one block or in chunked mode + if (chunkSize > 0) { + // we don't write the data in one large block, instead of write it out + // in bits to help test the data collection code. + NSUInteger length = [payloadData length]; + for (NSUInteger x = 0 ; x < length ; x += chunkSize) { + NSUInteger dataChunkSize = length - x; + if (dataChunkSize > chunkSize) { + dataChunkSize = chunkSize; + } + NSData *dataChunk + = [payloadData subdataWithRange:NSMakeRange(x, dataChunkSize)]; + [handle writeData:dataChunk]; + // delay after all but the last chunk to give it time to be read. + if ((x + chunkSize) < length) { + NSDate* loopIntervalDate = + [NSDate dateWithTimeIntervalSinceNow:kSendChunkInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:loopIntervalDate]; + } + } + } else { + [handle writeData:payloadData]; + } + + return handle; +} + +- (void)readFinished:(NSNotification *)notification { + NSDictionary *userInfo = [notification userInfo]; + fetchedData_ = + [[userInfo objectForKey:NSFileHandleNotificationDataItem] retain]; +} + +@end + +// ---------------------------------------------------------------------------- + +@implementation TestServerDelegate + +- (id)init { + self = [super init]; + if (self) { + requests_ = [[NSMutableArray alloc] init]; + responses_ = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)dealloc { + [requests_ release]; + [responses_ release]; + [super dealloc]; +} + ++ (id)testServerDelegate { + return [[[[self class] alloc] init] autorelease]; +} + +- (NSUInteger)requestCount { + return [requests_ count]; +} + +- (GTMHTTPRequestMessage *)popRequest { + GTMHTTPRequestMessage *result = [[[requests_ lastObject] retain] autorelease]; + [requests_ removeLastObject]; + return result; +} + +- (void)pushResponse:(GTMHTTPResponseMessage *)message { + [responses_ addObject:message]; +} + +- (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server + handleRequest:(GTMHTTPRequestMessage *)request { + [requests_ addObject:request]; + + GTMHTTPResponseMessage *result = nil; + if ([responses_ count] > 0) { + result = [[[responses_ lastObject] retain] autorelease]; + [responses_ removeLastObject]; + } else { + result = [GTMHTTPResponseMessage responseWithHTMLString:@"success"]; + } + return result; +} + +@end + +// ---------------------------------------------------------------------------- + +@implementation TestThrowingServerDelegate + +- (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server + handleRequest:(GTMHTTPRequestMessage *)request { + // let the base do its normal work for counts, etc. + [super httpServer:server handleRequest:request]; + NSException *exception = + [NSException exceptionWithName:@"InternalTestingException" + reason:@"To test our handling" + userInfo:nil]; + @throw exception; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.h new file mode 100644 index 00000000..2e2a7487 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.h @@ -0,0 +1,46 @@ +// +// GTMLightweightProxy.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// +// GTMLightweightProxy +// +// An object which does nothing but stand in for another object and forward +// messages (other than basic NSObject messages) to it, suitable for breaking +// retain cycles. It does *not* retain the represented object, so the +// represented object must be set to nil when that object is deallocated. +// +// Messages sent to a GTMLightweightProxy with no represented object set will +// be silently discarded. +// +@interface GTMLightweightProxy : NSProxy { + @private + __weak id representedObject_; +} + +// Initializes the object to represent |object|. +- (id)initWithRepresentedObject:(id)object; + +// Gets the object that the proxy represents. +- (id)representedObject; + +// Changes the proxy to represent |object| +- (void)setRepresentedObject:(id)object; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.m new file mode 100644 index 00000000..c00e44bd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.m @@ -0,0 +1,114 @@ +// +// GTMLightweightProxy.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLightweightProxy.h" +#import "GTMDefines.h" + +@implementation GTMLightweightProxy + +- (id)initWithRepresentedObject:(id)object { + // it's weak, we don't retain + representedObject_ = object; + return self; +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +#if GTM_SUPPORT_GC +// -[NSProxy finalize] is only in 10.5 or later +- (void)finalize { + representedObject_ = nil; + [super finalize]; +} +#endif +#endif + +- (void)dealloc { + // it's weak, we don't release + representedObject_ = nil; + [super dealloc]; +} + +- (id)representedObject { + // Use a local variable to avoid a bogus compiler warning. + id repObject = nil; + @synchronized(self) { + // Even though we don't retain this object, we hang it on the lifetime + // of the calling threads pool so it's lifetime is safe for at least that + // long. + repObject = [representedObject_ retain]; + } + return [repObject autorelease]; +} + +- (void)setRepresentedObject:(id)object { + @synchronized(self) { + representedObject_ = object; + } +} + +// Passes any unhandled method to the represented object if it responds to that +// method. +- (void)forwardInvocation:(NSInvocation*)invocation { + id target = [self representedObject]; + // Silently discard all messages when there's no represented object + if (!target) + return; + + SEL aSelector = [invocation selector]; + if ([target respondsToSelector:aSelector]) + [invocation invokeWithTarget:target]; +} + +// Gets the represented object's method signature for |selector|; necessary for +// forwardInvocation. +- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { + id target = [self representedObject]; + if (target) { + return [target methodSignatureForSelector:selector]; + } else { + // Apple's underlying forwarding code crashes if we return nil here. + // Since we are not going to use the invocation being constructed + // if there's no representedObject, a random valid NSMethodSignature is fine. + return [NSObject methodSignatureForSelector:@selector(alloc)]; + } +} + +// Prevents exceptions from unknown selectors if there is no represented +// object, and makes the exception come from the right place if there is one. +- (void)doesNotRecognizeSelector:(SEL)selector { + id target = [self representedObject]; + if (target) + [target doesNotRecognizeSelector:selector]; +} + +// Checks the represented object's selectors to allow clients of the proxy to +// do respondsToSelector: tests. +- (BOOL)respondsToSelector:(SEL)selector { + if ([super respondsToSelector:selector] || + selector == @selector(initWithRepresentedObject:) || + selector == @selector(representedObject) || + selector == @selector(setRepresentedObject:)) + { + return YES; + } + + id target = [self representedObject]; + return target && [target respondsToSelector:selector]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxyTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxyTest.m new file mode 100644 index 00000000..e50a9dc2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxyTest.m @@ -0,0 +1,85 @@ +// +// GTMLightweightProxyTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMLightweightProxy.h" + +@interface GTMLightweightProxyTest : GTMTestCase +- (BOOL)returnYes; +@end + +// Declare a non-existent method that we can call without compiler warnings. +@interface GTMLightweightProxyTest (GTMLightweightProxyTestMadeUpMethodDeclaration) +- (void)someMadeUpMethod; +@end + +@implementation GTMLightweightProxyTest + +- (void)testProxy { + id proxy + = [[[GTMLightweightProxy alloc] initWithRepresentedObject:self] autorelease]; + STAssertEqualObjects(self, [proxy representedObject], + @"Represented object setup failed"); + + // Check that it identifies itself as a proxy. + STAssertTrue([proxy isProxy], @"Should identify as a proxy"); + // Check that it passes class requests on + STAssertTrue([proxy isMemberOfClass:[self class]], + @"Should pass class requests through"); + + // Check that it claims to respond to its selectors. + STAssertTrue([proxy respondsToSelector:@selector(initWithRepresentedObject:)], + @"Claims not to respond to initWithRepresentedObject:"); + STAssertTrue([proxy respondsToSelector:@selector(representedObject)], + @"Claims not to respond to representedObject:"); + STAssertTrue([proxy respondsToSelector:@selector(setRepresentedObject:)], + @"Claims not to respond to setRepresentedObject:"); + // Check that it responds to its represented object's selectors + STAssertTrue([proxy respondsToSelector:@selector(returnYes)], + @"Claims not to respond to returnYes"); + // ... but not to made up selectors. + STAssertThrows([proxy someMadeUpMethod], + @"Calling a bogus method should throw"); + + // Check that callthrough works. + STAssertTrue([proxy returnYes], + @"Calling through to the represented object failed"); + + // Check that nilling out the represented object works. + [proxy setRepresentedObject:nil]; + STAssertTrue([proxy respondsToSelector:@selector(setRepresentedObject:)], + @"Claims not to respond to setRepresentedObject: after nilling" + @" out represented object"); + STAssertFalse([proxy respondsToSelector:@selector(returnYes)], + @"Claims to respond to returnYes after nilling out represented" + @" object"); + // Calling through once the represented object is nil should fail silently + STAssertNoThrow([proxy returnYes], + @"Calling through without a represented object should fail" + @" silently"); + // ... even when they are made up. + STAssertNoThrow([proxy someMadeUpMethod], + @"Calling a bogus method on a nilled proxy should not throw"); +} + +// Simple method to test calling through the proxy. +- (BOOL)returnYes { + return YES; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.h new file mode 100644 index 00000000..689a0d95 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.h @@ -0,0 +1,87 @@ +// +// GTMLogger+ASL.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import +#import "GTMLogger.h" + + +// GTMLogger (GTMLoggerASLAdditions) +// +// Adds a convenience creation method that allows you to get a standard +// GTMLogger object that is configured to write to ASL (Apple System Log) using +// the GTMLogASLWriter (declared below). +// +@interface GTMLogger (GTMLoggerASLAdditions) + +// Returns a new autoreleased GTMLogger instance that will log to ASL, using +// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter. ++ (id)standardLoggerWithASL; + +@end + + +@class GTMLoggerASLClient; + +// GTMLogASLWriter +// +// A GTMLogWriter implementation that will send log messages to ASL (Apple +// System Log facility). To use with GTMLogger simply set the "writer" for a +// GTMLogger to be an instance of this class. The following example sets the +// shared system logger to lot to ASL. +// +// [[GTMLogger sharedLogger] setWriter:[GTMLogASLWriter aslWriter]]; +// GTMLoggerInfo(@"Hi"); // This is sent to ASL +// +// See GTMLogger.h for more details and a higher-level view. +// +@interface GTMLogASLWriter : NSObject { + @private + __weak Class aslClientClass_; +} + +// Returns an autoreleased GTMLogASLWriter instance that uses an instance of +// GTMLoggerASLClient. ++ (id)aslWriter; + +// Designated initializer. Uses instances of the specified |clientClass| to talk +// to the ASL system. This method is typically only useful for testing. Users +// should generally NOT use this method to get an instance. Instead, simply use +// the +aslWriter method to obtain an instance. +- (id)initWithClientClass:(Class)clientClass; + +@end // GTMLogASLWriter + + +// Helper class used by GTMLogASLWriter to create an ASL client and write to the +// ASL log. This class is need to make management/cleanup of the aslclient work +// in a multithreaded environment. You'll need one of these GTMLoggerASLClient +// per thread (this is automatically handled by GTMLogASLWriter). +// +// This class should rarely (if EVER) be used directly. It's designed to be used +// internally by GTMLogASLWriter, and by some unit tests. It should not be +// used externally. +@interface GTMLoggerASLClient : NSObject { + @private + aslclient client_; +} + +// Sends the given string to ASL at the specified ASL log |level|. +- (void)log:(NSString *)msg level:(int)level; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.m new file mode 100644 index 00000000..90ea7e57 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASL.m @@ -0,0 +1,126 @@ +// +// GTMLogger+ASL.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLogger+ASL.h" +#import "GTMDefines.h" + + +@implementation GTMLogger (GTMLoggerASLAdditions) + ++ (id)standardLoggerWithASL { + id me = [self standardLogger]; + [me setWriter:[[[GTMLogASLWriter alloc] init] autorelease]]; + [me setFormatter:[[[GTMLogBasicFormatter alloc] init] autorelease]]; + return me; +} + +@end + + +@implementation GTMLogASLWriter + ++ (id)aslWriter { + return [[[self alloc] init] autorelease]; +} + +- (id)init { + return [self initWithClientClass:nil]; +} + +- (id)initWithClientClass:(Class)clientClass { + if ((self = [super init])) { + aslClientClass_ = clientClass; + if (aslClientClass_ == nil) { + aslClientClass_ = [GTMLoggerASLClient class]; + } + } + return self; +} + +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + static NSString *const kASLClientKey = @"GTMLoggerASLClientKey"; + + // Lookup the ASL client in the thread-local storage dictionary + NSMutableDictionary *tls = [[NSThread currentThread] threadDictionary]; + GTMLoggerASLClient *client = [tls objectForKey:kASLClientKey]; + + // If the ASL client wasn't found (e.g., the first call from this thread), + // then create it and store it in the thread-local storage dictionary + if (client == nil) { + client = [[[aslClientClass_ alloc] init] autorelease]; + [tls setObject:client forKey:kASLClientKey]; + } + + // Map the GTMLoggerLevel level to an ASL level. + int aslLevel = ASL_LEVEL_INFO; + switch (level) { + case kGTMLoggerLevelUnknown: + case kGTMLoggerLevelDebug: + case kGTMLoggerLevelInfo: + aslLevel = ASL_LEVEL_NOTICE; + break; + case kGTMLoggerLevelError: + aslLevel = ASL_LEVEL_ERR; + break; + case kGTMLoggerLevelAssert: + aslLevel = ASL_LEVEL_ALERT; + break; + } + + [client log:msg level:aslLevel]; +} + +@end // GTMLogASLWriter + + +@implementation GTMLoggerASLClient + +- (id)init { + if ((self = [super init])) { + client_ = asl_open(NULL, NULL, 0); + if (client_ == nil) { + // COV_NF_START - no real way to test this + [self release]; + return nil; + // COV_NF_END + } + } + return self; +} + +- (void)dealloc { + if (client_) asl_close(client_); + [super dealloc]; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + if (client_) asl_close(client_); + [super finalize]; +} +#endif + +// We don't test this one line because we don't want to pollute actual system +// logs with test messages. +// COV_NF_START +- (void)log:(NSString *)msg level:(int)level { + asl_log(client_, NULL, level, "%s", [msg UTF8String]); +} +// COV_NF_END + +@end // GTMLoggerASLClient diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASLTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASLTest.m new file mode 100644 index 00000000..cd324843 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger+ASLTest.m @@ -0,0 +1,90 @@ +// +// GTMLogger+ASLTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLogger+ASL.h" +#import "GTMSenTestCase.h" + +@interface DummyASLClient : GTMLoggerASLClient +@end + +static NSMutableArray *gDummyLog; // weak + +@implementation DummyASLClient + +- (void)log:(NSString *)msg level:(int)level { + NSString *line = [msg stringByAppendingFormat:@"@%d", level]; + [gDummyLog addObject:line]; +} + +@end + + +@interface GTMLogger_ASLTest : GTMTestCase +@end + +@implementation GTMLogger_ASLTest + +- (void)testCreation { + GTMLogger *aslLogger = [GTMLogger standardLoggerWithASL]; + STAssertNotNil(aslLogger, nil); + + GTMLogASLWriter *writer = [GTMLogASLWriter aslWriter]; + STAssertNotNil(writer, nil); +} + +- (void)testLogWriter { + gDummyLog = [[[NSMutableArray alloc] init] autorelease]; + GTMLogASLWriter *writer = [[[GTMLogASLWriter alloc] + initWithClientClass:[DummyASLClient class]] + autorelease]; + + + STAssertNotNil(writer, nil); + STAssertTrue([gDummyLog count] == 0, nil); + + // Log some messages + [writer logMessage:@"unknown" level:kGTMLoggerLevelUnknown]; + [writer logMessage:@"debug" level:kGTMLoggerLevelDebug]; + [writer logMessage:@"info" level:kGTMLoggerLevelInfo]; + [writer logMessage:@"error" level:kGTMLoggerLevelError]; + [writer logMessage:@"assert" level:kGTMLoggerLevelAssert]; + + // Inspect the logged message to make sure they were logged correctly. The + // dummy writer will save the messages w/ @level concatenated. The "level" + // will be the ASL level, not the GTMLogger level. GTMLogASLWriter will log + // all + NSArray *expected = [NSArray arrayWithObjects: + @"unknown@5", + @"debug@5", + @"info@5", + @"error@3", + @"assert@1", + nil]; + + STAssertEqualObjects(gDummyLog, expected, nil); + + gDummyLog = nil; +} + +- (void)testASLClient { + GTMLoggerASLClient *client = [[GTMLoggerASLClient alloc] init]; + STAssertNotNil(client, nil); + [client release]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.h new file mode 100644 index 00000000..1626b1b6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.h @@ -0,0 +1,458 @@ +// +// GTMLogger.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Key Abstractions +// ---------------- +// +// This file declares multiple classes and protocols that are used by the +// GTMLogger logging system. The 4 main abstractions used in this file are the +// following: +// +// * logger (GTMLogger) - The main logging class that users interact with. It +// has methods for logging at different levels and uses a log writer, a log +// formatter, and a log filter to get the job done. +// +// * log writer (GTMLogWriter) - Writes a given string to some log file, where +// a "log file" can be a physical file on disk, a POST over HTTP to some URL, +// or even some in-memory structure (e.g., a ring buffer). +// +// * log formatter (GTMLogFormatter) - Given a format string and arguments as +// a va_list, returns a single formatted NSString. A "formatted string" could +// be a string with the date prepended, a string with values in a CSV format, +// or even a string of XML. +// +// * log filter (GTMLogFilter) - Given a formatted log message as an NSString +// and the level at which the message is to be logged, this class will decide +// whether the given message should be logged or not. This is a flexible way +// to filter out messages logged at a certain level, messages that contain +// certain text, or filter nothing out at all. This gives the caller the +// flexibility to dynamically enable debug logging in Release builds. +// +// This file also declares some classes to handle the common log writer, log +// formatter, and log filter cases. Callers can also create their own writers, +// formatters, and filters and they can even build them on top of the ones +// declared here. Keep in mind that your custom writer/formatter/filter may be +// called from multiple threads, so it must be thread-safe. + +#import + +// Predeclaration of used protocols that are declared later in this file. +@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +#define CHECK_FORMAT_NSSTRING(a, b) __attribute__((format(__NSString__, a, b))) +#else +#define CHECK_FORMAT_NSSTRING(a, b) +#endif + +// GTMLogger +// +// GTMLogger is the primary user-facing class for an object-oriented logging +// system. It is built on the concept of log formatters (GTMLogFormatter), log +// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is +// sent to a GTMLogger to log a message, the message is formatted using the log +// formatter, then the log filter is consulted to see if the message should be +// logged, and if so, the message is sent to the log writer to be written out. +// +// GTMLogger is intended to be a flexible and thread-safe logging solution. Its +// flexibility comes from the fact that GTMLogger instances can be customized +// with user defined formatters, filters, and writers. And these writers, +// filters, and formatters can be combined, stacked, and customized in arbitrary +// ways to suit the needs at hand. For example, multiple writers can be used at +// the same time, and a GTMLogger instance can even be used as another +// GTMLogger's writer. This allows for arbitrarily deep logging trees. +// +// A standard GTMLogger uses a writer that sends messages to standard out, a +// formatter that smacks a timestamp and a few other bits of interesting +// information on the message, and a filter that filters out debug messages from +// release builds. Using the standard log settings, a log message will look like +// the following: +// +// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo= +// +// The output contains the date and time of the log message, the name of the +// process followed by its process ID/thread ID, the log level at which the +// message was logged (in the previous example the level was 1: +// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in +// this case, the log message was @"foo=%@", foo). +// +// Multiple instances of GTMLogger can be created, each configured their own +// way. Though GTMLogger is not a singleton (in the GoF sense), it does provide +// access to a shared (i.e., globally accessible) GTMLogger instance. This makes +// it convenient for all code in a process to use the same GTMLogger instance. +// The shared GTMLogger instance can also be configured in an arbitrary, and +// these configuration changes will affect all code that logs through the shared +// instance. + +// +// Log Levels +// ---------- +// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger +// doesn't take any special action based on the log level; it simply forwards +// this information on to formatters, filters, and writers, each of which may +// optionally take action based on the level. Since log level filtering is +// performed at runtime, log messages are typically not filtered out at compile +// time. The exception to this rule is that calls to the GTMLoggerDebug() macro +// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible +// with behavior that many developers are currently used to. Note that this +// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but +// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out. +// +// Standard loggers are created with the GTMLogLevelFilter log filter, which +// filters out certain log messages based on log level, and some other settings. +// +// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on +// GTMLogger itself, there are also C macros that make usage of the shared +// GTMLogger instance very convenient. These macros are: +// +// GTMLoggerDebug(...) +// GTMLoggerInfo(...) +// GTMLoggerError(...) +// +// Again, a notable feature of these macros is that GTMLogDebug() calls *will be +// compiled out of non-DEBUG builds*. +// +// Standard Loggers +// ---------------- +// GTMLogger has the concept of "standard loggers". A standard logger is simply +// a logger that is pre-configured with some standard/common writer, formatter, +// and filter combination. Standard loggers are created using the creation +// methods beginning with "standard". The alternative to a standard logger is a +// regular logger, which will send messages to stdout, with no special +// formatting, and no filtering. +// +// How do I use GTMLogger? +// ---------------------- +// The typical way you will want to use GTMLogger is to simply use the +// GTMLogger*() macros for logging from code. That way we can easily make +// changes to the GTMLogger class and simply update the macros accordingly. Only +// your application startup code (perhaps, somewhere in main()) should use the +// GTMLogger class directly in order to configure the shared logger, which all +// of the code using the macros will be using. Again, this is just the typical +// situation. +// +// To be complete, there are cases where you may want to use GTMLogger directly, +// or even create separate GTMLogger instances for some reason. That's fine, +// too. +// +// Examples +// -------- +// The following show some common GTMLogger use cases. +// +// 1. You want to log something as simply as possible. Also, this call will only +// appear in debug builds. In non-DEBUG builds it will be completely removed. +// +// GTMLoggerDebug(@"foo = %@", foo); +// +// 2. The previous example is similar to the following. The major difference is +// that the previous call (example 1) will be compiled out of Release builds +// but this statement will not be compiled out. +// +// [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo]; +// +// 3. Send all logging output from the shared logger to a file. We do this by +// creating an NSFileHandle for writing associated with a file, and setting +// that file handle as the logger's writer. +// +// NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" +// create:YES]; +// [[GTMLogger sharedLogger] setWriter:f]; +// GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log +// +// 4. Create a new GTMLogger that will log to a file. This example differs from +// the previous one because here we create a new GTMLogger that is different +// from the shared logger. +// +// GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"]; +// [logger logInfo:@"hi temp log file"]; +// +// 5. Create a logger that writes to stdout and does NOT do any formatting to +// the log message. This might be useful, for example, when writing a help +// screen for a command-line tool to standard output. +// +// GTMLogger *logger = [GTMLogger logger]; +// [logger logInfo:@"%@ version 0.1 usage", progName]; +// +// 6. Send log output to stdout AND to a log file. The trick here is that +// NSArrays function as composite log writers, which means when an array is +// set as the log writer, it forwards all logging messages to all of its +// contained GTMLogWriters. +// +// // Create array of GTMLogWriters +// NSArray *writers = [NSArray arrayWithObjects: +// [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES], +// [NSFileHandle fileHandleWithStandardOutput], nil]; +// +// GTMLogger *logger = [GTMLogger standardLogger]; +// [logger setWriter:writers]; +// [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log +// +// For futher details on log writers, formatters, and filters, see the +// documentation below. +// +// NOTE: GTMLogger is application level logging. By default it does nothing +// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose +// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro +// definitions in its prefix header (see GTMDefines.h for how one would do +// that). +// +@interface GTMLogger : NSObject { + @private + id writer_; + id formatter_; + id filter_; +} + +// +// Accessors for the shared logger instance +// + +// Returns a shared/global standard GTMLogger instance. Callers should typically +// use this method to get a GTMLogger instance, unless they explicitly want +// their own instance to configure for their own needs. This is the only method +// that returns a shared instance; all the rest return new GTMLogger instances. ++ (id)sharedLogger; + +// Sets the shared logger instance to |logger|. Future calls to +sharedLogger +// will return |logger| instead. ++ (void)setSharedLogger:(GTMLogger *)logger; + +// +// Creation methods +// + +// Returns a new autoreleased GTMLogger instance that will log to stdout, using +// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter. ++ (id)standardLogger; + +// Same as +standardLogger, but logs to stderr. ++ (id)standardLoggerWithStderr; + +// Returns a new standard GTMLogger instance with a log writer that will +// write to the file at |path|, and will use the GTMLogStandardFormatter and +// GTMLogLevelFilter classes. If |path| does not exist, it will be created. ++ (id)standardLoggerWithPath:(NSString *)path; + +// Returns an autoreleased GTMLogger instance that will use the specified +// |writer|, |formatter|, and |filter|. ++ (id)loggerWithWriter:(id)writer + formatter:(id)formatter + filter:(id)filter; + +// Returns an autoreleased GTMLogger instance that logs to stdout, with the +// basic formatter, and no filter. The returned logger differs from the logger +// returned by +standardLogger because this one does not do any filtering and +// does not do any special log formatting; this is the difference between a +// "regular" logger and a "standard" logger. ++ (id)logger; + +// Designated initializer. This method returns a GTMLogger initialized with the +// specified |writer|, |formatter|, and |filter|. See the setter methods below +// for what values will be used if nil is passed for a parameter. +- (id)initWithWriter:(id)writer + formatter:(id)formatter + filter:(id)filter; + +// +// Logging methods +// + +// Logs a message at the debug level (kGTMLoggerLevelDebug). +- (void)logDebug:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +// Logs a message at the info level (kGTMLoggerLevelInfo). +- (void)logInfo:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +// Logs a message at the error level (kGTMLoggerLevelError). +- (void)logError:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +// Logs a message at the assert level (kGTMLoggerLevelAssert). +- (void)logAssert:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); + + +// +// Accessors +// + +// Accessor methods for the log writer. If the log writer is set to nil, +// [NSFileHandle fileHandleWithStandardOutput] is used. +- (id)writer; +- (void)setWriter:(id)writer; + +// Accessor methods for the log formatter. If the log formatter is set to nil, +// GTMLogBasicFormatter is used. This formatter will format log messages in a +// plain printf style. +- (id)formatter; +- (void)setFormatter:(id)formatter; + +// Accessor methods for the log filter. If the log filter is set to nil, +// GTMLogNoFilter is used, which allows all log messages through. +- (id)filter; +- (void)setFilter:(id)filter; + +@end // GTMLogger + + +// Helper functions that are used by the convenience GTMLogger*() macros that +// enable the logging of function names. +@interface GTMLogger (GTMLoggerMacroHelpers) +- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... + CHECK_FORMAT_NSSTRING(2, 3); +- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... + CHECK_FORMAT_NSSTRING(2, 3); +- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... + CHECK_FORMAT_NSSTRING(2, 3); +- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... + CHECK_FORMAT_NSSTRING(2, 3); +@end // GTMLoggerMacroHelpers + + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug() +// calls will be compiled out of non-Debug builds. +#define GTMLoggerDebug(...) \ + [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__] +#define GTMLoggerInfo(...) \ + [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__] +#define GTMLoggerError(...) \ + [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__] +#define GTMLoggerAssert(...) \ + [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__] + +// If we're not in a debug build, remove the GTMLoggerDebug statements. This +// makes calls to GTMLoggerDebug "compile out" of Release builds +#ifndef DEBUG +#undef GTMLoggerDebug +#define GTMLoggerDebug(...) do {} while(0) +#endif + +// Log levels. +typedef enum { + kGTMLoggerLevelUnknown, + kGTMLoggerLevelDebug, + kGTMLoggerLevelInfo, + kGTMLoggerLevelError, + kGTMLoggerLevelAssert, +} GTMLoggerLevel; + + +// +// Log Writers +// + +// Protocol to be implemented by a GTMLogWriter instance. +@protocol GTMLogWriter +// Writes the given log message to where the log writer is configured to write. +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level; +@end // GTMLogWriter + + +// Simple category on NSFileHandle that makes NSFileHandles valid log writers. +// This is convenient because something like, say, +fileHandleWithStandardError +// now becomes a valid log writer. Log messages are written to the file handle +// with a newline appended. +@interface NSFileHandle (GTMFileHandleLogWriter) +// Opens the file at |path| in append mode, and creates the file with |mode| +// if it didn't previously exist. ++ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode; +@end // NSFileHandle + + +// This category makes NSArray a GTMLogWriter that can be composed of other +// GTMLogWriters. This is the classic Composite GoF design pattern. When the +// GTMLogWriter -logMessage:level: message is sent to the array, the array +// forwards the message to all of its elements that implement the GTMLogWriter +// protocol. +// +// This is useful in situations where you would like to send log output to +// multiple log writers at the same time. Simply create an NSArray of the log +// writers you wish to use, then set the array as the "writer" for your +// GTMLogger instance. +@interface NSArray (GTMArrayCompositeLogWriter) +@end // GTMArrayCompositeLogWriter + + +// This category adapts the GTMLogger interface so that it can be used as a log +// writer; it's an "adapter" in the GoF Adapter pattern sense. +// +// This is useful when you want to configure a logger to log to a specific +// writer with a specific formatter and/or filter. But you want to also compose +// that with a different log writer that may have its own formatter and/or +// filter. +@interface GTMLogger (GTMLoggerLogWriter) +@end // GTMLoggerLogWriter + + +// +// Log Formatters +// + +// Protocol to be implemented by a GTMLogFormatter instance. +@protocol GTMLogFormatter +// Returns a formatted string using the format specified in |fmt| and the va +// args specified in |args|. +- (NSString *)stringForFunc:(NSString *)func + withFormat:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level; +@end // GTMLogFormatter + + +// A basic log formatter that formats a string the same way that NSLog (or +// printf) would. It does not do anything fancy, nor does it add any data of its +// own. +@interface GTMLogBasicFormatter : NSObject +@end // GTMLogBasicFormatter + + +// A log formatter that formats the log string like the basic formatter, but +// also prepends a timestamp and some basic process info to the message, as +// shown in the following sample output. +// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here +@interface GTMLogStandardFormatter : GTMLogBasicFormatter { + @private + NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS + NSString *pname_; + pid_t pid_; +} +@end // GTMLogStandardFormatter + + +// +// Log Filters +// + +// Protocol to be imlemented by a GTMLogFilter instance. +@protocol GTMLogFilter +// Returns YES if |msg| at |level| should be filtered out; NO otherwise. +- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level; +@end // GTMLogFilter + + +// A log filter that filters messages at the kGTMLoggerLevelDebug level out of +// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered +// out of non-debug builds unless GTMVerboseLogging is set in the environment or +// the processes's defaults. Messages at the kGTMLoggerLevelError level are +// never filtered. +@interface GTMLogLevelFilter : NSObject +@end // GTMLogLevelFilter + + +// A simple log filter that does NOT filter anything out; +// -filterAllowsMessage:level will always return YES. This can be a convenient +// way to enable debug-level logging in release builds (if you so desire). +@interface GTMLogNoFilter : NSObject +@end // GTMLogNoFilter + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.m new file mode 100644 index 00000000..de941d2e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLogger.m @@ -0,0 +1,445 @@ +// +// GTMLogger.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLogger.h" +#import "GTMGarbageCollection.h" +#import +#import +#import +#import + + +// Define a trivial assertion macro to avoid dependencies +#ifdef DEBUG + #define GTMLOGGER_ASSERT(expr) assert(expr) +#else + #define GTMLOGGER_ASSERT(expr) +#endif + + +@interface GTMLogger (PrivateMethods) + +- (void)logInternalFunc:(const char *)func + format:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level; + +@end + + +// Reference to the shared GTMLogger instance. This is not a singleton, it's +// just an easy reference to one shared instance. +static GTMLogger *gSharedLogger = nil; + + +@implementation GTMLogger + +// Returns a pointer to the shared logger instance. If none exists, a standard +// logger is created and returned. ++ (id)sharedLogger { + @synchronized(self) { + if (gSharedLogger == nil) { + gSharedLogger = [[self standardLogger] retain]; + } + GTMLOGGER_ASSERT(gSharedLogger != nil); + } + return [[gSharedLogger retain] autorelease]; +} + ++ (void)setSharedLogger:(GTMLogger *)logger { + @synchronized(self) { + [gSharedLogger autorelease]; + gSharedLogger = [logger retain]; + } +} + ++ (id)standardLogger { + id writer = [NSFileHandle fileHandleWithStandardOutput]; + id fr = [[[GTMLogStandardFormatter alloc] init] autorelease]; + id filter = [[[GTMLogLevelFilter alloc] init] autorelease]; + return [self loggerWithWriter:writer formatter:fr filter:filter]; +} + ++ (id)standardLoggerWithStderr { + id me = [self standardLogger]; + [me setWriter:[NSFileHandle fileHandleWithStandardError]]; + return me; +} + ++ (id)standardLoggerWithPath:(NSString *)path { + NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644]; + if (fh == nil) return nil; + id me = [self standardLogger]; + [me setWriter:fh]; + return me; +} + ++ (id)loggerWithWriter:(id)writer + formatter:(id)formatter + filter:(id)filter { + return [[[self alloc] initWithWriter:writer + formatter:formatter + filter:filter] autorelease]; +} + ++ (id)logger { + return [[[self alloc] init] autorelease]; +} + +- (id)init { + return [self initWithWriter:nil formatter:nil filter:nil]; +} + +- (id)initWithWriter:(id)writer + formatter:(id)formatter + filter:(id)filter { + if ((self = [super init])) { + [self setWriter:writer]; + [self setFormatter:formatter]; + [self setFilter:filter]; + GTMLOGGER_ASSERT(formatter_ != nil); + GTMLOGGER_ASSERT(filter_ != nil); + GTMLOGGER_ASSERT(writer_ != nil); + } + return self; +} + +- (void)dealloc { + GTMLOGGER_ASSERT(writer_ != nil); + GTMLOGGER_ASSERT(formatter_ != nil); + GTMLOGGER_ASSERT(filter_ != nil); + [writer_ release]; + [formatter_ release]; + [filter_ release]; + [super dealloc]; +} + +- (id)writer { + GTMLOGGER_ASSERT(writer_ != nil); + return [[writer_ retain] autorelease]; +} + +- (void)setWriter:(id)writer { + @synchronized(self) { + [writer_ autorelease]; + if (writer == nil) + writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain]; + else + writer_ = [writer retain]; + } + GTMLOGGER_ASSERT(writer_ != nil); +} + +- (id)formatter { + GTMLOGGER_ASSERT(formatter_ != nil); + return [[formatter_ retain] autorelease]; +} + +- (void)setFormatter:(id)formatter { + @synchronized(self) { + [formatter_ autorelease]; + if (formatter == nil) + formatter_ = [[GTMLogBasicFormatter alloc] init]; + else + formatter_ = [formatter retain]; + } + GTMLOGGER_ASSERT(formatter_ != nil); +} + +- (id)filter { + GTMLOGGER_ASSERT(filter_ != nil); + return [[filter_ retain] autorelease]; +} + +- (void)setFilter:(id)filter { + @synchronized(self) { + [filter_ autorelease]; + if (filter == nil) + filter_ = [[GTMLogNoFilter alloc] init]; + else + filter_ = [filter retain]; + } + GTMLOGGER_ASSERT(filter_ != nil); +} + +- (void)logDebug:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug]; + va_end(args); +} + +- (void)logInfo:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo]; + va_end(args); +} + +- (void)logError:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError]; + va_end(args); +} + +- (void)logAssert:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert]; + va_end(args); +} + +@end // GTMLogger + + +@implementation GTMLogger (GTMLoggerMacroHelpers) + +- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug]; + va_end(args); +} + +- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo]; + va_end(args); +} + +- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError]; + va_end(args); +} + +- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert]; + va_end(args); +} + +@end // GTMLoggerMacroHelpers + + +@implementation GTMLogger (PrivateMethods) + +- (void)logInternalFunc:(const char *)func + format:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level { + GTMLOGGER_ASSERT(formatter_ != nil); + GTMLOGGER_ASSERT(filter_ != nil); + GTMLOGGER_ASSERT(writer_ != nil); + + NSString *fname = func ? [NSString stringWithUTF8String:func] : nil; + NSString *msg = [formatter_ stringForFunc:fname + withFormat:fmt + valist:args + level:level]; + if (msg && [filter_ filterAllowsMessage:msg level:level]) + [writer_ logMessage:msg level:level]; +} + +@end // PrivateMethods + + +@implementation NSFileHandle (GTMFileHandleLogWriter) + ++ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode { + int fd = -1; + if (path) { + int flags = O_WRONLY | O_APPEND | O_CREAT; + fd = open([path fileSystemRepresentation], flags, mode); + } + if (fd == -1) return nil; + return [[[self alloc] initWithFileDescriptor:fd + closeOnDealloc:YES] autorelease]; +} + +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + @synchronized(self) { + NSString *line = [NSString stringWithFormat:@"%@\n", msg]; + [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]]; + } +} + +@end // GTMFileHandleLogWriter + + +@implementation NSArray (GTMArrayCompositeLogWriter) + +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + @synchronized(self) { + id child = nil; + GTM_FOREACH_OBJECT(child, self) { + if ([child conformsToProtocol:@protocol(GTMLogWriter)]) + [child logMessage:msg level:level]; + } + } +} + +@end // GTMArrayCompositeLogWriter + + +@implementation GTMLogger (GTMLoggerLogWriter) + +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + switch (level) { + case kGTMLoggerLevelDebug: + [self logDebug:@"%@", msg]; + break; + case kGTMLoggerLevelInfo: + [self logInfo:@"%@", msg]; + break; + case kGTMLoggerLevelError: + [self logError:@"%@", msg]; + break; + case kGTMLoggerLevelAssert: + [self logAssert:@"%@", msg]; + break; + default: + // Ignore the message. + break; + } +} + +@end // GTMLoggerLogWriter + + +@implementation GTMLogBasicFormatter + +- (NSString *)stringForFunc:(NSString *)func + withFormat:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level { + // Performance note: since we always have to create a new NSString from the + // returned CFStringRef, we may want to do a quick check here to see if |fmt| + // contains a '%', and if not, simply return 'fmt'. + CFStringRef cfmsg = NULL; + cfmsg = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, + NULL, // format options + (CFStringRef)fmt, + args); + return GTMCFAutorelease(cfmsg); +} + +@end // GTMLogBasicFormatter + + +@implementation GTMLogStandardFormatter + +- (id)init { + if ((self = [super init])) { + dateFormatter_ = [[NSDateFormatter alloc] init]; + [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4]; + [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; + pname_ = [[[NSProcessInfo processInfo] processName] copy]; + pid_ = [[NSProcessInfo processInfo] processIdentifier]; + } + return self; +} + +- (void)dealloc { + [dateFormatter_ release]; + [pname_ release]; + [super dealloc]; +} + +- (NSString *)stringForFunc:(NSString *)func + withFormat:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level { + GTMLOGGER_ASSERT(dateFormatter_ != nil); + NSString *tstamp = nil; + @synchronized (dateFormatter_) { + tstamp = [dateFormatter_ stringFromDate:[NSDate date]]; + } + return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@", + tstamp, pname_, pid_, pthread_self(), + level, (func ? func : @"(no func)"), + [super stringForFunc:func withFormat:fmt valist:args level:level]]; +} + +@end // GTMLogStandardFormatter + + +@implementation GTMLogLevelFilter + +// Check the environment and the user preferences for the GTMVerboseLogging key +// to see if verbose logging has been enabled. The environment variable will +// override the defaults setting, so check the environment first. +// COV_NF_START +static BOOL IsVerboseLoggingEnabled(void) { + static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging"; + static char *env = NULL; + if (env == NULL) + env = getenv([kVerboseLoggingKey UTF8String]); + + if (env && env[0]) { + return (strtol(env, NULL, 10) != 0); + } + + return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey]; +} +// COV_NF_END + +// In DEBUG builds, log everything. If we're not in a debug build we'll assume +// that we're in a Release build. +- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { +#if DEBUG + return YES; +#endif + + BOOL allow = YES; + + switch (level) { + case kGTMLoggerLevelDebug: + allow = NO; + break; + case kGTMLoggerLevelInfo: + allow = (IsVerboseLoggingEnabled() == YES); + break; + case kGTMLoggerLevelError: + allow = YES; + break; + case kGTMLoggerLevelAssert: + allow = YES; + break; + default: + allow = YES; + break; + } + + return allow; +} + +@end // GTMLogLevelFilter + + +@implementation GTMLogNoFilter + +- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { + return YES; // Allow everything through +} + +@end // GTMLogNoFilter diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.h new file mode 100644 index 00000000..30e58ffa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.h @@ -0,0 +1,97 @@ +// +// GTMLoggerRingBufferWriter.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLogger.h" +#import "GTMDefines.h" + +typedef struct GTMRingBufferPair GTMRingBufferPair; + +// GTMLoggerRingBufferWriter is a GTMLogWriter that accumulates logged Info +// and Debug messages (when they're not compiled out in a release build) +// into a ring buffer. If an Error or Assert message is +// logged, all of the previously logged messages (up to the size of the +// buffer) are then logged. At that point the buffer resets itself. +// +// How to use: +// +// * Create a logger writer that you want to use to do the ultimate writing, +// such as to stdErr, or a log file, or an NSArray that aggregates other +// writers. +// id someWriter = ... +// +// * Make a new ring buffer with this writer, along with the buffer's +// capacity (which must be >= 1): +// rbw = +// [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:32 +// writer:someWriter]; +// +// * Set your logger's writer to be the ring buffer writer: +// [[GTMLogger sharedLogger] setWriter:rbw]; +// +// Note that this writer is at the end of the GTMLogger food chain, where the +// default filter removes Info messages in Release mode (Debug messages are +// compiled out). You can pass nil to GTMLogger's -setFilter to have it pass +// along all the messages. +// +@interface GTMLoggerRingBufferWriter : NSObject { + @private + id writer_; + GTMRingBufferPair *buffer_; + NSUInteger capacity_; + NSUInteger nextIndex_; // Index of the next element of |buffer_| to fill. + NSUInteger totalLogged_; // This > 0 and |nextIndex_| == 0 means we've wrapped. +} + +// Returns an autoreleased ring buffer writer. If |writer| is nil, +// then nil is returned. ++ (id)ringBufferWriterWithCapacity:(NSUInteger)capacity + writer:(id)loggerWriter; + +// Designated initializer. If |writer| is nil, then nil is returned. +// If you just use -init, nil will be returned. +- (id)initWithCapacity:(NSUInteger)capacity + writer:(id)loggerWriter; + +// How many messages will be logged before older messages get dropped +// on the floor. +- (NSUInteger)capacity; + +// The log writer that will get the buffered log messages if/when they +// need to be displayed. +- (id)writer; + +// How many log messages are currently in the buffer. +- (NSUInteger)count; + +// How many have been dropped on the floor since creation, or the last +// reset. +- (NSUInteger)droppedLogCount; + +// The total number of messages processed since creation, or the last +// reset. +- (NSUInteger)totalLogged; + +// Purge the contents and reset the counters. +- (void)reset; + +// Print out the contents without resetting anything. +// Contents are automatically printed and reset when an error-level +// message comes through. +- (void)dumpContents; + +@end // GTMLoggerRingBufferWriter diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.m new file mode 100644 index 00000000..4a8c7c6e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriter.m @@ -0,0 +1,248 @@ +// +// GTMLoggerRingBufferWriter.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLoggerRingBufferWriter.h" + +// Holds a message and a level. +struct GTMRingBufferPair { + // Explicitly using CFStringRef instead of NSString because in a GC world, the + // NSString will be collected because there is no way for the GC to know that + // there is a strong reference to the NSString in this data structure. By + // using a CFStringRef we can CFRetain it, and avoid the problem. + CFStringRef logMessage_; + GTMLoggerLevel level_; +}; + + +// There are two operations that involve iterating over the buffer +// contents and doing Something to them. This is a callback function +// that is called for every pair living in the buffer. +typedef void (GTMRingBufferPairCallback)(GTMLoggerRingBufferWriter *rbw, + GTMRingBufferPair *pair); + + +@interface GTMLoggerRingBufferWriter (PrivateMethods) + +// Add the message and level to the ring buffer. +- (void)addMessage:(NSString *)message level:(GTMLoggerLevel)level; + +// Walk the buffer invoking the callback. +- (void)iterateBufferWithCallback:(GTMRingBufferPairCallback)callback; + +@end // PrivateMethods + + +@implementation GTMLoggerRingBufferWriter + ++ (id)ringBufferWriterWithCapacity:(NSUInteger)capacity + writer:(id)writer { + GTMLoggerRingBufferWriter *rbw = + [[[self alloc] initWithCapacity:capacity + writer:writer] autorelease]; + return rbw; + +} // ringBufferWriterWithCapacity + + +- (id)initWithCapacity:(NSUInteger)capacity + writer:(id)writer { + if ((self = [super init])) { + writer_ = [writer retain]; + capacity_ = capacity; + + buffer_ = (GTMRingBufferPair *)calloc(capacity_, sizeof(GTMRingBufferPair)); + + nextIndex_ = 0; + + if (capacity_ == 0 || !buffer_ || !writer_) { + [self release]; + self = nil; + } + } + return self; + +} // initWithCapacity + + +- (id)init { + return [self initWithCapacity:0 writer:nil]; +} // init + + +- (void)dealloc { + [self reset]; + + [writer_ release]; + if (buffer_) { + free(buffer_); + } + + [super dealloc]; + +} // dealloc + + +- (NSUInteger)capacity { + return capacity_; +} // capacity + + +- (id)writer { + return writer_; +} // writer + + +- (NSUInteger)count { + NSUInteger count = 0; + @synchronized(self) { + if ((nextIndex_ == 0 && totalLogged_ > 0) + || totalLogged_ >= capacity_) { + // We've wrapped around + count = capacity_; + } else { + count = nextIndex_; + } + } + + return count; + +} // count + + +- (NSUInteger)droppedLogCount { + NSUInteger droppedCount = 0; + + @synchronized(self) { + if (capacity_ > totalLogged_) { + droppedCount = 0; + } else { + droppedCount = totalLogged_ - capacity_; + } + } + + return droppedCount; + +} // droppedLogCount + + +- (NSUInteger)totalLogged { + return totalLogged_; +} // totalLogged + + +// Assumes caller will do any necessary synchronization. +// This walks over the buffer, taking into account any wrap-around, +// and calls the callback on each pair. +- (void)iterateBufferWithCallback:(GTMRingBufferPairCallback)callback { + GTMRingBufferPair *scan, *stop; + + // If we've wrapped around, print out the ring buffer from |nextIndex_| + // to the end. + if (totalLogged_ >= capacity_) { + scan = buffer_ + nextIndex_; + stop = buffer_ + capacity_; + while (scan < stop) { + callback(self, scan); + ++scan; + } + } + + // And then print from the beginning to right before |nextIndex_| + scan = buffer_; + stop = buffer_ + nextIndex_; + while (scan < stop) { + callback(self, scan); + ++scan; + } + +} // iterateBufferWithCallback + + +// Used when resetting the buffer. This frees the string and zeros out +// the structure. +static void ResetCallback(GTMLoggerRingBufferWriter *rbw, + GTMRingBufferPair *pair) { + if (pair->logMessage_) { + CFRelease(pair->logMessage_); + } + pair->logMessage_ = nil; + pair->level_ = kGTMLoggerLevelUnknown; +} // ResetCallback + + +// Reset the contents. +- (void)reset { + @synchronized(self) { + [self iterateBufferWithCallback:ResetCallback]; + nextIndex_ = 0; + totalLogged_ = 0; + } + +} // reset + + +// Go ahead and log the stored backlog, writing it through the +// ring buffer's |writer_|. +static void PrintContentsCallback(GTMLoggerRingBufferWriter *rbw, + GTMRingBufferPair *pair) { + [[rbw writer] logMessage:(NSString*)pair->logMessage_ level:pair->level_]; +} // PrintContentsCallback + + +- (void)dumpContents { + @synchronized(self) { + [self iterateBufferWithCallback:PrintContentsCallback]; + } +} // printContents + + +// Assumes caller will do any necessary synchronization. +- (void)addMessage:(NSString *)message level:(GTMLoggerLevel)level { + NSUInteger newIndex = nextIndex_; + nextIndex_ = (nextIndex_ + 1) % capacity_; + + ++totalLogged_; + + // Now store the goodies. + GTMRingBufferPair *pair = buffer_ + newIndex; + if (pair->logMessage_) { + CFRelease(pair->logMessage_); + pair->logMessage_ = nil; + } + if (message) { + pair->logMessage_ = CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef)message); + } + pair->level_ = level; + +} // addMessage + + +// From the GTMLogWriter protocol. +- (void)logMessage:(NSString *)message level:(GTMLoggerLevel)level { + @synchronized(self) { + [self addMessage:(NSString*)message level:level]; + + if (level >= kGTMLoggerLevelError) { + [self dumpContents]; + [self reset]; + } + } + +} // logMessage + +@end // GTMLoggerRingBufferWriter diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriterTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriterTest.m new file mode 100644 index 00000000..1c5d72b1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerRingBufferWriterTest.m @@ -0,0 +1,363 @@ +// +// GTMLoggerRingBufferWriterTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMLoggerRingBufferWriter.h" +#import "GTMLogger.h" +#import "GTMUnitTestDevLog.h" + +// -------------------------------------------------- +// CountingWriter keeps a count of the number of times it has been +// told to write something, and also keeps track of what it was +// asked to log. + +@interface CountingWriter : NSObject { + @private + NSMutableArray *loggedContents_; +} + +- (NSUInteger)count; +- (NSArray *)loggedContents; +- (void)reset; + +@end // CountingWriter + +@implementation CountingWriter +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + if (!loggedContents_) { + loggedContents_ = [[NSMutableArray alloc] init]; + } + [loggedContents_ addObject:msg]; +} // logMessage + +- (void)dealloc { + [loggedContents_ release]; + [super dealloc]; +} // dealloc + +- (void)reset { + [loggedContents_ release]; + loggedContents_ = nil; +} // reset + +- (NSUInteger)count { + return [loggedContents_ count]; +} // count + +- (NSArray *)loggedContents { + return loggedContents_; +} // loggedContents + +@end // CountingWriter + + +@interface GTMLoggerRingBufferWriterTest : GTMTestCase { + @private + GTMLogger *logger_; + CountingWriter *countingWriter_; +} +@end // GTMLoggerRingBufferWriterTest + + +// -------------------------------------------------- + +@implementation GTMLoggerRingBufferWriterTest + +// Utilty to compare the set of messages captured by a CountingWriter +// with an array of expected messages. The messages are expected to +// be in the same order in both places. + +- (void)compareWriter:(CountingWriter *)writer + withExpectedLogging:(NSArray *)expected + line:(int)line { + NSArray *loggedContents = [writer loggedContents]; + + STAssertEquals([expected count], [loggedContents count], + @"count mismatch from line %d", line); + + for (unsigned int i = 0; i < [expected count]; i++) { + STAssertEqualObjects([expected objectAtIndex:i], + [loggedContents objectAtIndex:i], + @"logging mistmatch at index %d from line %d", + i, line); + } + +} // compareWithExpectedLogging + + +- (void)setUp { + countingWriter_ = [[CountingWriter alloc] init]; + logger_ = [[GTMLogger alloc] init]; +} // setUp + + +- (void)tearDown { + [countingWriter_ release]; + [logger_ release]; +} // tearDown + + +- (void)testCreation { + + // Make sure initializers work. + GTMLoggerRingBufferWriter *writer = + [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:32 + writer:countingWriter_]; + STAssertEquals([writer capacity], (NSUInteger)32, nil); + STAssertTrue([writer writer] == countingWriter_, nil); + STAssertEquals([writer count], (NSUInteger)0, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([writer totalLogged], (NSUInteger)0, nil); + + // Try with invalid arguments. Should always get nil back. + writer = + [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:0 + writer:countingWriter_]; + STAssertNil(writer, nil); + + writer = [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:32 + writer:nil]; + STAssertNil(writer, nil); + + writer = [[GTMLoggerRingBufferWriter alloc] init]; + STAssertNil(writer, nil); + +} // testCreation + + +- (void)testLogging { + GTMLoggerRingBufferWriter *writer = + [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:4 + writer:countingWriter_]; + [logger_ setWriter:writer]; + + // Shouldn't do anything if there are no contents. + [writer dumpContents]; + STAssertEquals([writer count], (NSUInteger)0, nil); + STAssertEquals([countingWriter_ count], (NSUInteger)0, nil); + + // Log a single item. Make sure the counts are accurate. + [logger_ logDebug:@"oop"]; + STAssertEquals([writer count], (NSUInteger)1, nil); + STAssertEquals([writer totalLogged], (NSUInteger)1, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([countingWriter_ count], (NSUInteger)0, nil); + + // Log a second item. Also make sure counts are accurate. + [logger_ logDebug:@"ack"]; + STAssertEquals([writer count], (NSUInteger)2, nil); + STAssertEquals([writer totalLogged], (NSUInteger)2, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([countingWriter_ count], (NSUInteger)0, nil); + + // Print them, and make sure the countingWriter sees the right stuff. + [writer dumpContents]; + STAssertEquals([countingWriter_ count], (NSUInteger)2, nil); + STAssertEquals([writer count], (NSUInteger)2, nil); // Should not be zeroed. + STAssertEquals([writer totalLogged], (NSUInteger)2, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"oop",@"ack", nil] + line:__LINE__]; + + + // Wipe the slates clean. + [writer reset]; + [countingWriter_ reset]; + STAssertEquals([writer count], (NSUInteger)0, nil); + STAssertEquals([writer totalLogged], (NSUInteger)0, nil); + + // An error log level should print the buffer and empty it. + [logger_ logDebug:@"oop"]; + [logger_ logInfo:@"ack"]; + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([writer totalLogged], (NSUInteger)2, nil); + + [logger_ logError:@"blargh"]; + STAssertEquals([countingWriter_ count], (NSUInteger)3, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"ack", + @"blargh", nil] + line:__LINE__]; + + + // An assert log level should do the same. This also fills the + // buffer to its limit without wrapping. + [countingWriter_ reset]; + [logger_ logDebug:@"oop"]; + [logger_ logInfo:@"ack"]; + [logger_ logDebug:@"blargh"]; + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([writer count], (NSUInteger)3, nil); + STAssertEquals([writer totalLogged], (NSUInteger)3, nil); + + [logger_ logAssert:@"ouch"]; + STAssertEquals([countingWriter_ count], (NSUInteger)4, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"ack", + @"blargh", @"ouch", nil] + line:__LINE__]; + + + // Try with exactly one wrap around. + [countingWriter_ reset]; + [logger_ logInfo:@"ack"]; + [logger_ logDebug:@"oop"]; + [logger_ logDebug:@"blargh"]; + [logger_ logDebug:@"flong"]; // Fills buffer + STAssertEquals([writer droppedLogCount], (NSUInteger)0, nil); + STAssertEquals([writer count], (NSUInteger)4, nil); + + [logger_ logAssert:@"ouch"]; // should drop "ack" + STAssertEquals([countingWriter_ count], (NSUInteger)4, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"blargh", + @"flong", @"ouch", nil] + line:__LINE__]; + + + // Try with more than one wrap around. + [countingWriter_ reset]; + [logger_ logInfo:@"ack"]; + [logger_ logDebug:@"oop"]; + [logger_ logDebug:@"blargh"]; + [logger_ logDebug:@"flong"]; // Fills buffer + [logger_ logDebug:@"bloogie"]; // should drop "ack" + STAssertEquals([writer droppedLogCount], (NSUInteger)1, nil); + STAssertEquals([writer count], (NSUInteger)4, nil); + + [logger_ logAssert:@"ouch"]; // should drop "oop" + STAssertEquals([countingWriter_ count], (NSUInteger)4, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"blargh", + @"flong", @"bloogie", @"ouch", nil] + line:__LINE__]; +} // testBasics + + +- (void)testCornerCases { + // make sure we work with small buffer sizes. + + GTMLoggerRingBufferWriter *writer = + [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:1 + writer:countingWriter_]; + [logger_ setWriter:writer]; + + [logger_ logInfo:@"ack"]; + STAssertEquals([countingWriter_ count], (NSUInteger)0, nil); + STAssertEquals([writer count], (NSUInteger)1, nil); + [writer dumpContents]; + STAssertEquals([countingWriter_ count], (NSUInteger)1, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"ack", nil] + line:__LINE__]; + + [logger_ logDebug:@"oop"]; // should drop "ack" + STAssertEquals([writer count], (NSUInteger)1, nil); + STAssertEquals([writer droppedLogCount], (NSUInteger)1, nil); + + [countingWriter_ reset]; + [logger_ logError:@"snoogy"]; // should drop "oop" + STAssertEquals([countingWriter_ count], (NSUInteger)1, nil); + + [self compareWriter:countingWriter_ + withExpectedLogging:[NSArray arrayWithObjects:@"snoogy", nil] + line:__LINE__]; + +} // testCornerCases + + + +// Run 10 threads, all logging through the same logger. + +static volatile NSUInteger gStoppedThreads = 0; // Total number that have stopped. + +- (void)bangMe:(id)info { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + GTMLogger *logger = (GTMLogger *)info; + + // Log a string. + for (int i = 0; i < 27; i++) { + [logger logDebug:@"oop"]; + } + + // log another string which should push the first string out. + // if we see any "oop"s in the logger output, then we know it got + // confused. + for (int i = 0; i < 15; i++) { + [logger logDebug:@"ack"]; + } + + [pool release]; + @synchronized ([self class]) { + gStoppedThreads++; + } + +} // bangMe + + +- (void)testThreading { + const NSUInteger kThreadCount = 10; + const NSUInteger kCapacity = 10; + + GTMLoggerRingBufferWriter *writer = + [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:kCapacity + writer:countingWriter_]; + [logger_ setWriter:writer]; + + for (NSUInteger i = 0; i < kThreadCount; i++) { + [NSThread detachNewThreadSelector:@selector(bangMe:) + toTarget:self + withObject:logger_]; + } + + // The threads are running, so wait for them all to finish. + while (1) { + NSDate *quick = [NSDate dateWithTimeIntervalSinceNow:0.2]; + [[NSRunLoop currentRunLoop] runUntilDate:quick]; + @synchronized ([self class]) { + if (gStoppedThreads == kThreadCount) break; + } + } + + // Now make sure we get back what's expected. + STAssertEquals([writer count], kThreadCount, nil); + STAssertEquals([countingWriter_ count], (NSUInteger)0, nil); // Nothing should be logged + STAssertEquals([writer totalLogged], (NSUInteger)420, nil); + + [logger_ logError:@"bork"]; + STAssertEquals([countingWriter_ count], kCapacity, nil); + + NSArray *expected = [NSArray arrayWithObjects: + @"ack", @"ack", @"ack", @"ack", @"ack", + @"ack", @"ack", @"ack", @"ack", @"bork", + nil]; + [self compareWriter:countingWriter_ + withExpectedLogging:expected + line:__LINE__]; + +} // testThreading + +@end // GTMLoggerRingBufferWriterTest diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerTest.m new file mode 100644 index 00000000..86ced5ef --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMLoggerTest.m @@ -0,0 +1,451 @@ +// +// GTMLoggerTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMLogger.h" +#import "GTMRegex.h" +#import "GTMSenTestCase.h" + + +// A test writer that stores log messages in an array for easy retrieval. +@interface ArrayWriter : NSObject { + @private + NSMutableArray *messages_; +} +- (NSArray *)messages; +- (void)clear; +@end +@implementation ArrayWriter +- (id)init { + if ((self = [super init])) { + messages_ = [[NSMutableArray alloc] init]; + } + return self; +} +- (void)dealloc { + [messages_ release]; + [super dealloc]; +} +- (NSArray *)messages { + return messages_; +} +- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { + [messages_ addObject:msg]; +} +- (void)clear { + [messages_ removeAllObjects]; +} +@end // ArrayWriter + + +// A formatter for testing that prepends the word DUMB to log messages, along +// with the log level number. +@interface DumbFormatter : GTMLogBasicFormatter +@end +@implementation DumbFormatter +- (NSString *)stringForFunc:(NSString *)func + withFormat:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level { + return [NSString stringWithFormat:@"DUMB [%d] %@", level, + [super stringForFunc:nil withFormat:fmt valist:args level:level]]; +} +@end // DumbFormatter + + +// A test filter that ignores messages with the string "ignore". +@interface IgnoreFilter : NSObject +@end +@implementation IgnoreFilter +- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { + NSRange range = [msg rangeOfString:@"ignore"]; + return (range.location == NSNotFound); +} +@end // IgnoreFilter + +// +// Begin test harness +// + +@interface GTMLoggerTest : GTMTestCase { + @private + NSString *path_; +} +@end + +@implementation GTMLoggerTest + +- (void)setUp { + path_ = [[NSTemporaryDirectory() stringByAppendingPathComponent: + @"GTMLoggerUnitTest.log"] retain]; + STAssertNotNil(path_, nil); + // Make sure we're cleaned up from the last run +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [[NSFileManager defaultManager] removeFileAtPath:path_ handler:nil]; +#else + [[NSFileManager defaultManager] removeItemAtPath:path_ error:NULL]; +#endif +} + +- (void)tearDown { + STAssertNotNil(path_, nil); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [[NSFileManager defaultManager] removeFileAtPath:path_ handler:nil]; +#else + [[NSFileManager defaultManager] removeItemAtPath:path_ error:NULL]; +#endif + [path_ release]; + path_ = nil; +} + +- (void)testCreation { + GTMLogger *logger1 = nil, *logger2 = nil; + + logger1 = [GTMLogger sharedLogger]; + logger2 = [GTMLogger sharedLogger]; + + STAssertTrue(logger1 == logger2, nil); + + STAssertNotNil([logger1 writer], nil); + STAssertNotNil([logger1 formatter], nil); + STAssertNotNil([logger1 filter], nil); + + // Get a new instance; not the shared instance + logger2 = [GTMLogger standardLogger]; + + STAssertTrue(logger1 != logger2, nil); + STAssertNotNil([logger2 writer], nil); + STAssertNotNil([logger2 formatter], nil); + STAssertNotNil([logger2 filter], nil); + + // Set the new instance to be the shared logger. + [GTMLogger setSharedLogger:logger2]; + STAssertTrue(logger2 == [GTMLogger sharedLogger], nil); + STAssertTrue(logger1 != [GTMLogger sharedLogger], nil); + + // Set the shared logger to nil, which should reset it to a new "standard" + // logger. + [GTMLogger setSharedLogger:nil]; + STAssertNotNil([GTMLogger sharedLogger], nil); + STAssertTrue(logger2 != [GTMLogger sharedLogger], nil); + STAssertTrue(logger1 != [GTMLogger sharedLogger], nil); + + GTMLogger *logger = [GTMLogger logger]; + STAssertNotNil(logger, nil); + + logger = [GTMLogger standardLoggerWithStderr]; + STAssertNotNil(logger, nil); + + logger = [GTMLogger standardLoggerWithPath:path_]; + STAssertNotNil(logger, nil); +} + +- (void)testAccessors { + GTMLogger *logger = [GTMLogger standardLogger]; + STAssertNotNil(logger, nil); + + STAssertNotNil([logger writer], nil); + STAssertNotNil([logger formatter], nil); + STAssertNotNil([logger filter], nil); + + [logger setWriter:nil]; + [logger setFormatter:nil]; + [logger setFilter:nil]; + + // These attributes should NOT be nil. They should be set to their defaults. + STAssertNotNil([logger writer], nil); + STAssertNotNil([logger formatter], nil); + STAssertNotNil([logger filter], nil); +} + +- (void)testLogger { + ArrayWriter *writer = [[[ArrayWriter alloc] init] autorelease]; + IgnoreFilter *filter = [[[IgnoreFilter alloc] init] autorelease]; + + // We actually only need the array writer instance for this unit test to pass, + // but we combine that writer with a stdout writer for two reasons: + // + // 1. To test the NSArray composite writer object + // 2. To make debugging easier by sending output to stdout + // + // We also include in the array an object that is not a GTMLogWriter to make + // sure that we don't crash when presented with an array of non-GTMLogWriters. + NSArray *writers = [NSArray arrayWithObjects:writer, + [NSFileHandle fileHandleWithStandardOutput], + @"blah", nil]; + + GTMLogger *logger = [GTMLogger loggerWithWriter:writers + formatter:nil // basic formatter + filter:filter]; + + STAssertNotNil(logger, nil); + + // Log a few messages to test with + [logger logInfo:@"hi"]; + [logger logDebug:@"foo"]; + [logger logError:@"blah"]; + [logger logAssert:@"baz"]; + + // Makes sure the messages got logged + NSArray *messages = [writer messages]; + STAssertNotNil(messages, nil); + STAssertEquals([messages count], (NSUInteger)4, nil); + STAssertEqualObjects([messages objectAtIndex:0], @"hi", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"foo", nil); + STAssertEqualObjects([messages objectAtIndex:2], @"blah", nil); + STAssertEqualObjects([messages objectAtIndex:3], @"baz", nil); + + // Log a message that should be ignored, and make sure it did NOT get logged + [logger logInfo:@"please ignore this"]; + messages = [writer messages]; + STAssertNotNil(messages, nil); + STAssertEquals([messages count], (NSUInteger)4, nil); + STAssertEqualObjects([messages objectAtIndex:0], @"hi", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"foo", nil); + STAssertEqualObjects([messages objectAtIndex:2], @"blah", nil); + STAssertEqualObjects([messages objectAtIndex:3], @"baz", nil); + + // Change the formatter to our "dumb formatter" + id formatter = [[[DumbFormatter alloc] init] autorelease]; + [logger setFormatter:formatter]; + + [logger logInfo:@"bleh"]; + messages = [writer messages]; + STAssertNotNil(messages, nil); + STAssertEquals([messages count], (NSUInteger)5, nil); // Message count should increase + // The previously logged messages should not change + STAssertEqualObjects([messages objectAtIndex:0], @"hi", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"foo", nil); + STAssertEqualObjects([messages objectAtIndex:2], @"blah", nil); + STAssertEqualObjects([messages objectAtIndex:3], @"baz", nil); + STAssertEqualObjects([messages objectAtIndex:4], @"DUMB [2] bleh", nil); +} + +- (void)testConvenienceMacros { + ArrayWriter *writer = [[[ArrayWriter alloc] init] autorelease]; + NSArray *writers = [NSArray arrayWithObjects:writer, + [NSFileHandle fileHandleWithStandardOutput], nil]; + + [[GTMLogger sharedLogger] setWriter:writers]; + + // Here we log a message using a convenience macro, which should log the + // message along with the name of the function it was called from. Here we + // test to make sure the logged message does indeed contain the name of the + // current function "testConvenienceMacros". + GTMLoggerError(@"test ========================"); + STAssertEquals([[writer messages] count], (NSUInteger)1, nil); + NSRange rangeOfFuncName = + [[[writer messages] objectAtIndex:0] rangeOfString:@"testConvenienceMacros"]; + STAssertTrue(rangeOfFuncName.location != NSNotFound, nil); + [writer clear]; + + [[GTMLogger sharedLogger] setFormatter:nil]; + + GTMLoggerInfo(@"test %d", 1); + GTMLoggerDebug(@"test %d", 2); + GTMLoggerError(@"test %d", 3); + GTMLoggerAssert(@"test %d", 4); + + NSArray *messages = [writer messages]; + STAssertNotNil(messages, nil); + +#ifdef DEBUG + STAssertEquals([messages count], (NSUInteger)4, nil); + STAssertEqualObjects([messages objectAtIndex:0], @"test 1", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"test 2", nil); + STAssertEqualObjects([messages objectAtIndex:2], @"test 3", nil); + STAssertEqualObjects([messages objectAtIndex:3], @"test 4", nil); +#else + // In Release builds, only the Error and Assert messages will be logged + STAssertEquals([messages count], (NSUInteger)2, nil); + STAssertEqualObjects([messages objectAtIndex:0], @"test 3", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"test 4", nil); +#endif + +} + +- (void)testFileHandleWriter { + NSFileHandle *fh = nil; + + fh = [NSFileHandle fileHandleForWritingAtPath:path_]; + STAssertNil(fh, nil); + + fh = [NSFileHandle fileHandleForLoggingAtPath:path_ mode:0644]; + STAssertNotNil(fh, nil); + + [fh logMessage:@"test 0" level:kGTMLoggerLevelUnknown]; + [fh logMessage:@"test 1" level:kGTMLoggerLevelDebug]; + [fh logMessage:@"test 2" level:kGTMLoggerLevelInfo]; + [fh logMessage:@"test 3" level:kGTMLoggerLevelError]; + [fh logMessage:@"test 4" level:kGTMLoggerLevelAssert]; + [fh closeFile]; + + NSString *contents = [NSString stringWithContentsOfFile:path_]; + + STAssertEqualObjects(@"test 0\ntest 1\ntest 2\ntest 3\ntest 4\n", contents, nil); +} + +- (void)testLoggerAdapterWriter { + ArrayWriter *writer = [[[ArrayWriter alloc] init] autorelease]; + STAssertNotNil(writer, nil); + + GTMLogger *sublogger = [GTMLogger loggerWithWriter:writer + formatter:nil + filter:nil]; + STAssertNotNil(sublogger, nil); + + GTMLogger *logger = [GTMLogger loggerWithWriter:sublogger + formatter:nil + filter:nil]; + + STAssertNotNil(logger, nil); + + // Log a few messages to test with + [logger logInfo:@"hi"]; + [logger logDebug:@"foo"]; + [logger logError:@"blah"]; + [logger logAssert:@"assert"]; + + // Makes sure the messages got logged + NSArray *messages = [writer messages]; + STAssertNotNil(messages, nil); + STAssertEquals([messages count], (NSUInteger)4, nil); + STAssertEqualObjects([messages objectAtIndex:0], @"hi", nil); + STAssertEqualObjects([messages objectAtIndex:1], @"foo", nil); + STAssertEqualObjects([messages objectAtIndex:2], @"blah", nil); + STAssertEqualObjects([messages objectAtIndex:3], @"assert", nil); +} + +// Helper method to help testing GTMLogFormatters +- (NSString *)stringFromFormatter:(id)formatter + level:(GTMLoggerLevel)level + format:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + NSString *msg = [formatter stringForFunc:nil + withFormat:fmt + valist:args + level:level]; + va_end(args); + return msg; +} + +- (void)testBasicFormatter { + id fmtr = [[[GTMLogBasicFormatter alloc] init] autorelease]; + STAssertNotNil(fmtr, nil); + NSString *msg = nil; + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@"test"]; + STAssertEqualObjects(msg, @"test", nil); + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@"test %d", 1]; + STAssertEqualObjects(msg, @"test 1", nil); + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@"test %@", @"foo"]; + STAssertEqualObjects(msg, @"test foo", nil); + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@""]; + STAssertEqualObjects(msg, @"", nil); + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@" ", 1]; + STAssertEqualObjects(msg, @" ", nil); +} + +- (void)testStandardFormatter { + id fmtr = [[[GTMLogStandardFormatter alloc] init] autorelease]; + STAssertNotNil(fmtr, nil); + + // E.g. 2008-01-04 09:16:26.906 otest[5567/0xa07d0f60] [lvl=1] (no func) test + NSString * kFormatBasePattern = + @"[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3} ((otest)|(GTMiPhoneTest))\\[[0-9]+/0x[0-9a-f]+\\] \\[lvl=[0-3]\\] \\(no func\\) "; + NSString *msg = nil; + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelDebug + format:@"test"]; + STAssertTrue([msg gtm_matchesPattern:[kFormatBasePattern stringByAppendingString:@"test"]], nil); + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelError + format:@"test %d", 1]; + STAssertTrue([msg gtm_matchesPattern:[kFormatBasePattern stringByAppendingString:@"test 1"]], nil); + + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelInfo + format:@"test %@", @"hi"]; + STAssertTrue([msg gtm_matchesPattern:[kFormatBasePattern stringByAppendingString:@"test hi"]], nil); + + + msg = [self stringFromFormatter:fmtr + level:kGTMLoggerLevelUnknown + format:@"test"]; + STAssertTrue([msg gtm_matchesPattern:[kFormatBasePattern stringByAppendingString:@"test"]], nil); +} + +- (void)testNoFilter { + id filter = [[[GTMLogNoFilter alloc] init] autorelease]; + STAssertNotNil(filter, nil); + + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], nil); + STAssertTrue([filter filterAllowsMessage:@"" level:kGTMLoggerLevelDebug], nil); + STAssertTrue([filter filterAllowsMessage:nil level:kGTMLoggerLevelDebug], nil); +} + +- (void)testFileHandleCreation { + NSFileHandle *fh = nil; + + fh = [NSFileHandle fileHandleForLoggingAtPath:nil mode:0644]; + STAssertNil(fh, nil); + + fh = [NSFileHandle fileHandleForLoggingAtPath:path_ mode:0644]; + STAssertNotNil(fh, nil); + + [fh logMessage:@"test 1" level:kGTMLoggerLevelInfo]; + [fh logMessage:@"test 2" level:kGTMLoggerLevelInfo]; + [fh logMessage:@"test 3" level:kGTMLoggerLevelInfo]; + [fh closeFile]; + + // Re-open file and make sure our log messages get appended + fh = [NSFileHandle fileHandleForLoggingAtPath:path_ mode:0644]; + STAssertNotNil(fh, nil); + + [fh logMessage:@"test 4" level:kGTMLoggerLevelInfo]; + [fh logMessage:@"test 5" level:kGTMLoggerLevelInfo]; + [fh logMessage:@"test 6" level:kGTMLoggerLevelInfo]; + [fh closeFile]; + + NSString *contents = [NSString stringWithContentsOfFile:path_]; + STAssertNotNil(contents, nil); + STAssertEqualObjects(@"test 1\ntest 2\ntest 3\ntest 4\ntest 5\ntest 6\n", contents, nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEvent+HandlerTest.applescript b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEvent+HandlerTest.applescript new file mode 100644 index 00000000..377d7338 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEvent+HandlerTest.applescript @@ -0,0 +1,60 @@ +-- +-- Copyright 2008 Google Inc. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); you may not +-- use this file except in compliance with the License. You may obtain a copy +-- of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +-- License for the specific language governing permissions and limitations under +-- the License. +-- + +script parentTestScript + property parentTestScriptProperty : 6 + on parentTestScriptFunc() + return "parent" + end parentTestScriptFunc +end script + +script testScript + property parent : parentTestScript + property testScriptProperty : 5 + on testScriptFunc() + return "child" + end testScriptFunc + on open foo + end open +end script + +property foo : 1 + +on test() +end test + +on testReturnOne() + return 1 +end testReturnOne + +on testReturnParam(param) + return param +end testReturnParam + +on testAddParams(param1, param2) + return param1 + param2 +end testAddParams + +on testAdd of a onto b given otherValue:d + return a + b + d +end testAdd + +on testGetScript() + return testScript +end testGetScript + +on print +end print diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.h new file mode 100644 index 00000000..fe3e1f02 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.h @@ -0,0 +1,100 @@ +// +// GTMNSAppleEventDescriptor+Foundation.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" +#import "GTMFourCharCode.h" + +// A category for dealing with NSAppleEventDescriptors and NSArrays. +@interface NSAppleEventDescriptor (GTMAppleEventDescriptorArrayAdditions) +// Used to register the types you know how to convert into +// NSAppleEventDescriptors. +// See examples in GTMNSAppleEventDescriptor+Foundation. +// Args: +// selector - selector to call for any of the types in |types| +// -(NSAppleEventDesc *)selector_name; +// types - an std c array of types of length |count| +// count - number of types in |types| ++ (void)gtm_registerSelector:(SEL)selector + forTypes:(DescType*)types + count:(NSUInteger)count; + +// Returns an NSObject for any NSAppleEventDescriptor +// Uses types registerd by registerSelector:forTypes:count: to determine +// what type of object to create. If it doesn't know a type, it attempts +// to return [self stringValue]. +- (id)gtm_objectValue; + +// Return an NSArray for an AEList +// Returns nil on failure. +- (NSArray*)gtm_arrayValue; + +// Return an NSDictionary for an AERecord +// Returns nil on failure. +- (NSDictionary*)gtm_dictionaryValue; + +// Return an NSNull for a desc of typeNull +// Returns nil on failure. +- (NSNull*)gtm_nullValue; + +// Return a NSAppleEventDescriptor for a double value. ++ (NSAppleEventDescriptor*)gtm_descriptorWithDouble:(double)real; + +// Return a NSAppleEventDescriptor for a float value. ++ (NSAppleEventDescriptor*)gtm_descriptorWithFloat:(float)real; + +// Return a NSAppleEventDescriptor for a CGFloat value. ++ (NSAppleEventDescriptor*)gtm_descriptorWithCGFloat:(CGFloat)real; + +// Attempt to extract a double value. Returns NAN on error. +- (double)gtm_doubleValue; + +// Attempt to extract a float value. Returns NAN on error. +- (float)gtm_floatValue; + +// Attempt to extract a CGFloat value. Returns NAN on error. +- (CGFloat)gtm_cgFloatValue; + +// Attempt to extract a NSNumber. Returns nil on error. +- (NSNumber*)gtm_numberValue; + +@end + +@interface NSObject (GTMAppleEventDescriptorObjectAdditions) +// A informal protocol that objects can override to return appleEventDescriptors +// for their type. The default is to return [self description] rolled up +// in an NSAppleEventDescriptor. Built in support for: +// NSArray, NSDictionary, NSNull, NSString, NSNumber and NSProcessInfo +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor; +@end + +@interface NSAppleEventDescriptor (GTMAppleEventDescriptorAdditions) +// Allows you to send events. +// Returns YES if send was successful. +- (BOOL)gtm_sendEventWithMode:(AESendMode)mode + timeOut:(NSTimeInterval)timeout + reply:(NSAppleEventDescriptor**)reply; +@end + +@interface GTMFourCharCode (GTMAppleEventDescriptorObjectAdditions) + +// if you call gtm_appleEventDescriptor on GTMFourCharCode it will be of +// type typeType. If you need something different (like typeProperty) this +// allows you to define the type you want. +- (NSAppleEventDescriptor*)gtm_appleEventDescriptorOfType:(DescType)type; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.m new file mode 100644 index 00000000..b3556074 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Foundation.m @@ -0,0 +1,536 @@ +// +// GTMNSAppleEventDescriptor+Foundation.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMDebugSelectorValidation.h" +#import // Needed Solely For keyASUserRecordFields + +// Map of types to selectors. +static NSMutableDictionary *gTypeMap = nil; + +@implementation NSAppleEventDescriptor (GTMAppleEventDescriptorArrayAdditions) + ++ (void)gtm_registerSelector:(SEL)selector + forTypes:(DescType*)types + count:(NSUInteger)count { + if (selector && types && count > 0) { +#if DEBUG + NSAppleEventDescriptor *desc + = [[[NSAppleEventDescriptor alloc] initListDescriptor] autorelease]; + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(desc, + selector, + @encode(id), + NULL); +#endif + @synchronized(self) { + if (!gTypeMap) { + gTypeMap = [[NSMutableDictionary alloc] init]; + } + NSString *selString = NSStringFromSelector(selector); + for (NSUInteger i = 0; i < count; ++i) { + NSNumber *key = [NSNumber numberWithUnsignedInt:types[i]]; + NSString *exists = [gTypeMap objectForKey:key]; + if (exists) { + _GTMDevLog(@"%@ being replaced with %@ exists for type: %@", + exists, selString, key); + } + [gTypeMap setObject:selString forKey:key]; + } + } + } +} + +- (id)gtm_objectValue { + id value = nil; + + // Check our registered types to see if we have anything + if (gTypeMap) { + @synchronized(gTypeMap) { + DescType type = [self descriptorType]; + NSNumber *key = [NSNumber numberWithUnsignedInt:type]; + NSString *selectorString = [gTypeMap objectForKey:key]; + if (selectorString) { + SEL selector = NSSelectorFromString(selectorString); + value = [self performSelector:selector]; + } else { + value = [self stringValue]; + } + } + } + return value; +} + +- (NSArray*)gtm_arrayValue { + NSUInteger count = [self numberOfItems]; + NSAppleEventDescriptor *workingDesc = self; + if (count == 0) { + // Create a list to work with. + workingDesc = [self coerceToDescriptorType:typeAEList]; + count = [workingDesc numberOfItems]; + } + NSMutableArray *items = [NSMutableArray arrayWithCapacity:count]; + for (NSUInteger i = 1; i <= count; ++i) { + NSAppleEventDescriptor *desc = [workingDesc descriptorAtIndex:i]; + id value = [desc gtm_objectValue]; + if (!value) { + _GTMDevLog(@"Unknown type of descriptor %@", [desc description]); + return nil; + } + [items addObject:value]; + } + return items; +} + +- (NSDictionary*)gtm_dictionaryValue { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + NSAppleEventDescriptor *userRecord = [self descriptorForKeyword:keyASUserRecordFields]; + if (userRecord) { + NSArray *userItems = [userRecord gtm_arrayValue]; + NSString *key = nil; + NSString *item; + GTM_FOREACH_OBJECT(item, userItems) { + if (key) { + // Save the pair and reset our state + [dictionary setObject:item forKey:key]; + key = nil; + } else { + // Save it for the next pair + key = item; + } + } + if (key) { + _GTMDevLog(@"Got a key %@ with no value in %@", key, userItems); + return nil; + } + } else { + NSUInteger count = [self numberOfItems]; + for (NSUInteger i = 1; i <= count; ++i) { + AEKeyword key = [self keywordForDescriptorAtIndex:i]; + NSAppleEventDescriptor *desc = [self descriptorForKeyword:key]; + id value = [desc gtm_objectValue]; + if (!value) { + _GTMDevLog(@"Unknown type of descriptor %@", [desc description]); + return nil; + } + [dictionary setObject:value + forKey:[GTMFourCharCode fourCharCodeWithFourCharCode:key]]; + } + } + return dictionary; +} + +- (NSNull*)gtm_nullValue { + return [NSNull null]; +} + ++ (NSAppleEventDescriptor*)gtm_descriptorWithDouble:(double)real { + return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint + bytes:&real + length:sizeof(real)]; +} + ++ (NSAppleEventDescriptor*)gtm_descriptorWithFloat:(float)real { + return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE32BitFloatingPoint + bytes:&real + length:sizeof(real)]; +} + + ++ (NSAppleEventDescriptor*)gtm_descriptorWithCGFloat:(CGFloat)real { +#if CGFLOAT_IS_DOUBLE + return [self gtm_descriptorWithDouble:real]; +#else + return [self gtm_descriptorWithFloat:real]; +#endif +} + +- (double)gtm_doubleValue { + double value = NAN; + NSNumber *number = [self gtm_numberValue]; + if (number) { + value = [number doubleValue]; + } + return value; +} + +- (float)gtm_floatValue { + float value = NAN; + NSNumber *number = [self gtm_numberValue]; + if (number) { + value = [number floatValue]; + } + return value; +} + +- (CGFloat)gtm_cgFloatValue { +#if CGFLOAT_IS_DOUBLE + return [self gtm_doubleValue]; +#else + return [self gtm_floatValue]; +#endif +} + +- (NSNumber*)gtm_numberValue { + typedef struct { + DescType type; + SEL selector; + } TypeSelectorMap; + TypeSelectorMap typeSelectorMap[] = { + { typeFalse, @selector(numberWithBool:) }, + { typeTrue, @selector(numberWithBool:) }, + { typeBoolean, @selector(numberWithBool:) }, + { typeSInt16, @selector(numberWithShort:) }, + { typeSInt32, @selector(numberWithInt:) }, + { typeUInt32, @selector(numberWithUnsignedInt:) }, + { typeSInt64, @selector(numberWithLongLong:) }, + { typeIEEE32BitFloatingPoint, @selector(numberWithFloat:) }, + { typeIEEE64BitFloatingPoint, @selector(numberWithDouble:) } + }; + DescType type = [self descriptorType]; + SEL selector = nil; + for (size_t i = 0; i < sizeof(typeSelectorMap) / sizeof(TypeSelectorMap); ++i) { + if (type == typeSelectorMap[i].type) { + selector = typeSelectorMap[i].selector; + break; + } + } + NSAppleEventDescriptor *desc = self; + if (!selector) { + // COV_NF_START - Don't know how to force this in a unittest + _GTMDevLog(@"Didn't get a valid selector?"); + desc = [self coerceToDescriptorType:typeIEEE64BitFloatingPoint]; + selector = @selector(numberWithDouble:); + // COV_NF_END + } + NSData *descData = [desc data]; + const void *bytes = [descData bytes]; + if (!bytes) { + // COV_NF_START - Don't know how to force this in a unittest + _GTMDevLog(@"Unable to get bytes from %@", desc); + return nil; + // COV_NF_END + } + Class numberClass = [NSNumber class]; + NSMethodSignature *signature = [numberClass methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:selector]; + [invocation setArgument:(void*)bytes atIndex:2]; + [invocation setTarget:numberClass]; + [invocation invoke]; + NSNumber *value = nil; + [invocation getReturnValue:&value]; + return value; +} + +- (GTMFourCharCode*)gtm_fourCharCodeValue { + return [GTMFourCharCode fourCharCodeWithFourCharCode:[self typeCodeValue]]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return self; +} + +@end + +@implementation NSObject (GTMAppleEventDescriptorObjectAdditions) +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return [NSAppleEventDescriptor descriptorWithString:[self description]]; +} +@end + +@implementation NSArray (GTMAppleEventDescriptorObjectAdditions) + ++ (void)load { + DescType types[] = { + typeAEList, + }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_arrayValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + NSAppleEventDescriptor *desc = [NSAppleEventDescriptor listDescriptor]; + NSUInteger count = [self count]; + for (NSUInteger i = 1; i <= count; ++i) { + id item = [self objectAtIndex:i-1]; + NSAppleEventDescriptor *itemDesc = [item gtm_appleEventDescriptor]; + if (!itemDesc) { + _GTMDevLog(@"Unable to create Apple Event Descriptor for %@", [self description]); + return nil; + } + [desc insertDescriptor:itemDesc atIndex:i]; + } + return desc; +} +@end + +@implementation NSDictionary (GTMAppleEventDescriptorObjectAdditions) + ++ (void)load { + DescType types[] = { + typeAERecord, + }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_dictionaryValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + Class keyClass = nil; + id key = nil; + GTM_FOREACH_KEY(key, self) { + if (!keyClass) { + if ([key isKindOfClass:[GTMFourCharCode class]]) { + keyClass = [GTMFourCharCode class]; + } else if ([key isKindOfClass:[NSString class]]) { + keyClass = [NSString class]; + } else { + _GTMDevLog(@"Keys must be of type NSString or GTMFourCharCode: %@", key); + return nil; + } + } + if (![key isKindOfClass:keyClass]) { + _GTMDevLog(@"Keys must be homogenous (first key was of type %@) " + "and of type NSString or GTMFourCharCode: %@", keyClass, key); + return nil; + } + } + NSAppleEventDescriptor *desc = [NSAppleEventDescriptor recordDescriptor]; + if ([keyClass isEqual:[NSString class]]) { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count] * 2]; + GTM_FOREACH_KEY(key, self) { + [array addObject:key]; + [array addObject:[self objectForKey:key]]; + } + NSAppleEventDescriptor *userRecord = [array gtm_appleEventDescriptor]; + if (!userRecord) { + return nil; + } + [desc setDescriptor:userRecord forKeyword:keyASUserRecordFields]; + } else { + GTM_FOREACH_KEY(key, self) { + id value = [self objectForKey:key]; + NSAppleEventDescriptor *valDesc = [value gtm_appleEventDescriptor]; + if (!valDesc) { + return nil; + } + [desc setDescriptor:valDesc forKeyword:[key fourCharCode]]; + } + } + return desc; +} + +@end + +@implementation NSNull (GTMAppleEventDescriptorObjectAdditions) ++ (void)load { + DescType types[] = { + typeNull + }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_nullValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return [NSAppleEventDescriptor nullDescriptor]; +} +@end + +@implementation NSString (GTMAppleEventDescriptorObjectAdditions) + ++ (void)load { + DescType types[] = { + typeUTF16ExternalRepresentation, + typeUnicodeText, + typeUTF8Text, + typeCString, + typePString, + typeChar, + typeIntlText }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(stringValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return [NSAppleEventDescriptor descriptorWithString:self]; +} +@end + +@implementation NSNumber (GTMAppleEventDescriptorObjectAdditions) + ++ (void)load { + DescType types[] = { + typeTrue, + typeFalse, + typeBoolean, + typeSInt16, + typeSInt32, + typeUInt32, + typeSInt64, + typeIEEE32BitFloatingPoint, + typeIEEE64BitFloatingPoint }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_numberValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + const char *type = [self objCType]; + if (!type || strlen(type) != 1) return nil; + + DescType desiredType = typeNull; + NSAppleEventDescriptor *desc = nil; + switch (type[0]) { + // COV_NF_START + // I can't seem to convince objcType to return something of this type + case 'B': + desc = [NSAppleEventDescriptor descriptorWithBoolean:[self boolValue]]; + break; + // COV_NF_END + + case 'c': + case 'C': + case 's': + case 'S': + desiredType = typeSInt16; + break; + + case 'i': + case 'l': + desiredType = typeSInt32; + break; + + // COV_NF_START + // I can't seem to convince objcType to return something of this type + case 'I': + case 'L': + desiredType = typeUInt32; + break; + // COV_NF_END + + case 'q': + case 'Q': + desiredType = typeSInt64; + break; + + case 'f': + desiredType = typeIEEE32BitFloatingPoint; + break; + + case 'd': + default: + desiredType = typeIEEE64BitFloatingPoint; + break; + } + + if (!desc) { + desc = [NSAppleEventDescriptor gtm_descriptorWithDouble:[self doubleValue]]; + if (desc && desiredType != typeIEEE64BitFloatingPoint) { + desc = [desc coerceToDescriptorType:desiredType]; + } + } + return desc; +} + +@end + +@implementation NSProcessInfo (GTMAppleEventDescriptorObjectAdditions) + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + return [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber + bytes:&psn + length:sizeof(ProcessSerialNumber)]; +} + +@end + +@implementation GTMFourCharCode (GTMAppleEventDescriptorObjectAdditions) + ++ (void)load { + DescType types[] = { + typeType, + typeKeyword, + typeApplSignature, + typeEnumerated, + }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_fourCharCodeValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return [self gtm_appleEventDescriptorOfType:typeType]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptorOfType:(DescType)type { + FourCharCode code = [self fourCharCode]; + return [NSAppleEventDescriptor descriptorWithDescriptorType:type + bytes:&code + length:sizeof(code)]; +} +@end + +@implementation NSAppleEventDescriptor (GTMAppleEventDescriptorAdditions) + +- (BOOL)gtm_sendEventWithMode:(AESendMode)mode + timeOut:(NSTimeInterval)timeout + reply:(NSAppleEventDescriptor**)reply { + BOOL isGood = YES; + AppleEvent replyEvent = { typeNull, NULL }; + OSStatus err = AESendMessage([self aeDesc], &replyEvent, mode, timeout * 60); + NSAppleEventDescriptor *replyDesc + = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&replyEvent] autorelease]; + if (err) { + isGood = NO; + _GTMDevLog(@"Unable to send message: %@ %d", self, err); + } + if (isGood) { + NSAppleEventDescriptor *errorDesc = [replyDesc descriptorForKeyword:keyErrorNumber]; + if (errorDesc && [errorDesc int32Value]) { + isGood = NO; + } + } + if (reply) { + *reply = replyDesc; + } + return isGood; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+FoundationTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+FoundationTest.m new file mode 100644 index 00000000..f346e992 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+FoundationTest.m @@ -0,0 +1,643 @@ +// +// GTMNSAppleEventDescriptor+FoundationTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMFourCharCode.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMNSAppleEventDescriptor_TestObject : NSObject +@end + +@implementation GTMNSAppleEventDescriptor_TestObject + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + return nil; +} + +@end + +@interface GTMNSAppleEventDescriptor_FoundationTest : GTMTestCase { + BOOL gotEvent_; +} +- (void)handleEvent:(NSAppleEventDescriptor*)event + withReply:(NSAppleEventDescriptor*)reply; +- (void)handleEvent:(NSAppleEventDescriptor*)event + withError:(NSAppleEventDescriptor*)reply; + +@end + +@implementation GTMNSAppleEventDescriptor_FoundationTest +- (void)testRegisterSelectorForTypesCount { + // Weird edge casey stuff. + // + (void)registerSelector:(SEL)selector + // forTypes:(DescType*)types count:(int)count + // is tested heavily by the other NSAppleEventDescriptor+foo categories. + DescType type; + [NSAppleEventDescriptor gtm_registerSelector:nil + forTypes:&type count:1]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(initListDescriptor) + forTypes:nil count:1]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(initListDescriptor) + forTypes:&type count:0]; + // Test the duplicate case + [NSAppleEventDescriptor gtm_registerSelector:@selector(initListDescriptor) + forTypes:&type count:1]; + [GTMUnitTestDevLog expectPattern:@"initListDescriptor being replaced with " + "initListDescriptor exists for type: [0-9]+"]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(initListDescriptor) + forTypes:&type count:1]; +} + +- (void)testObjectValue { + // - (void)testObjectValue is tested heavily by the other + // NSAppleEventDescriptor+foo categories. + long data = 1; + // v@#f is just a bogus descriptor type that we don't recognize. + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor descriptorWithDescriptorType:'v@#f' + bytes:&data + length:sizeof(data)]; + id value = [desc gtm_objectValue]; + STAssertNil(value, nil); +} + +- (void)testAppleEventDescriptor { + // - (NSAppleEventDescriptor*)appleEventDescriptor is tested heavily by the + // other NSAppleEventDescriptor+foo categories. + NSAppleEventDescriptor *desc = [self gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + STAssertEquals([desc descriptorType], (DescType)typeUnicodeText, nil); +} + +- (void)testDescriptorWithArrayAndArrayValue { + // Test empty array + NSAppleEventDescriptor *desc = [[NSArray array] gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + STAssertEquals([desc numberOfItems], (NSInteger)0, nil); + + // Complex array + NSArray *array = [NSArray arrayWithObjects: + [NSNumber numberWithInt:4], + @"foo", + [NSNumber numberWithInt:2], + @"bar", + [NSArray arrayWithObjects: + @"bam", + [NSArray arrayWithObject:[NSNumber numberWithFloat:4.2f]], + nil], + nil]; + STAssertNotNil(array, nil); + desc = [array gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + NSArray *array2 = [desc gtm_objectValue]; + STAssertNotNil(array2, nil); + NSArray *array3 = [desc gtm_arrayValue]; + STAssertNotNil(array3, nil); + STAssertTrue([array isEqualToArray:array2], + @"array: %@\narray2: %@\ndesc: %@", + [array description], [array2 description], [desc description]); + STAssertTrue([array2 isEqualToArray:array3], + @"array: %@\narray2: %@\ndesc: %@", + [array description], [array2 description], [desc description]); + + // Test a single object + array = [NSArray arrayWithObject:@"foo"]; + desc = [NSAppleEventDescriptor descriptorWithString:@"foo"]; + STAssertNotNil(desc, nil); + array2 = [desc gtm_arrayValue]; + STAssertTrue([array isEqualToArray:array2], + @"array: %@\narray2: %@\ndesc: %@", + [array description], [array2 description], [desc description]); + + // Something that doesn't know how to register itself. + GTMNSAppleEventDescriptor_TestObject *obj + = [[[GTMNSAppleEventDescriptor_TestObject alloc] init] autorelease]; + [GTMUnitTestDevLog expectPattern:@"Unable to create Apple Event Descriptor for .*"]; + desc = [[NSArray arrayWithObject:obj] gtm_appleEventDescriptor]; + STAssertNil(desc, @"Should be nil"); + + // A list containing something we don't know how to deal with + desc = [NSAppleEventDescriptor listDescriptor]; + NSAppleEventDescriptor *desc2 + = [NSAppleEventDescriptor descriptorWithDescriptorType:'@!@#' + bytes:&desc + length:sizeof(desc)]; + [GTMUnitTestDevLog expectPattern:@"Unknown type of descriptor " + ""]; + [desc insertDescriptor:desc2 atIndex:0]; + array = [desc gtm_objectValue]; + STAssertEquals([array count], (NSUInteger)0, @"Should have 0 items"); +} + +- (void)testDescriptorWithDictionaryAndDictionaryValue { + // Test empty dictionary + NSAppleEventDescriptor *desc + = [[NSDictionary dictionary] gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + STAssertEquals([desc numberOfItems], (NSInteger)0, nil); + + // Complex dictionary + NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: + @"fooobject", + @"fookey", + @"barobject", + @"barkey", + [NSDictionary dictionaryWithObjectsAndKeys: + @"january", + [GTMFourCharCode fourCharCodeWithFourCharCode:cJanuary], + @"february", + [GTMFourCharCode fourCharCodeWithFourCharCode:cFebruary], + nil], + @"dictkey", + nil]; + STAssertNotNil(dictionary, nil); + desc = [dictionary gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + NSDictionary *dictionary2 = [desc gtm_objectValue]; + STAssertNotNil(dictionary2, nil); + NSDictionary *dictionary3 = [desc gtm_dictionaryValue]; + STAssertNotNil(dictionary3, nil); + STAssertEqualObjects(dictionary, dictionary2, + @"desc: %@", [desc description]); + STAssertEqualObjects(dictionary2, dictionary3, + @"desc: %@", [desc description]); + + // Something that doesn't know how to register itself. + GTMNSAppleEventDescriptor_TestObject *obj + = [[[GTMNSAppleEventDescriptor_TestObject alloc] init] autorelease]; + [GTMUnitTestDevLog expectPattern:@"Unable to create Apple Event Descriptor for .*"]; + desc = [[NSDictionary dictionaryWithObject:obj + forKey:@"foo"] gtm_appleEventDescriptor]; + STAssertNil(desc, @"Should be nil"); + + GTMFourCharCode *fcc = [GTMFourCharCode fourCharCodeWithFourCharCode:cJanuary]; + desc = [[NSDictionary dictionaryWithObject:obj + forKey:fcc] gtm_appleEventDescriptor]; + STAssertNil(desc, @"Should be nil"); + + // A list containing something we don't know how to deal with + desc = [NSAppleEventDescriptor recordDescriptor]; + NSAppleEventDescriptor *desc2 + = [NSAppleEventDescriptor descriptorWithDescriptorType:'@!@#' + bytes:&desc + length:sizeof(desc)]; + [desc setDescriptor:desc2 forKeyword:cJanuary]; + [GTMUnitTestDevLog expectPattern:@"Unknown type of descriptor " + ""]; + dictionary = [desc gtm_objectValue]; + STAssertEquals([dictionary count], (NSUInteger)0, @"Should have 0 items"); + + // A bad dictionary + dictionary = [NSDictionary dictionaryWithObjectsAndKeys: + @"foo", + [GTMFourCharCode fourCharCodeWithFourCharCode:'APPL'], + @"bam", + @"bar", + nil]; + STAssertNotNil(dictionary, nil); + // I cannot use expectString here to the exact string because interestingly + // dictionaries in 64 bit enumerate in a different order from dictionaries + // on 32 bit. This is the closest pattern I can match. + [GTMUnitTestDevLog expectPattern:@"Keys must be homogenous .*"]; + desc = [dictionary gtm_appleEventDescriptor]; + STAssertNil(desc, nil); + + // Another bad dictionary + dictionary = [NSDictionary dictionaryWithObjectsAndKeys: + @"foo", + [NSNumber numberWithInt:4], + @"bam", + @"bar", + nil]; + STAssertNotNil(dictionary, nil); + // I cannot use expectString here to the exact string because interestingly + // dictionaries in 64 bit enumerate in a different order from dictionaries + // on 32 bit. This is the closest pattern I can match. + [GTMUnitTestDevLog expectPattern:@"Keys must be .*"]; + desc = [dictionary gtm_appleEventDescriptor]; + STAssertNil(desc, nil); + + // A bad descriptor + desc = [NSAppleEventDescriptor recordDescriptor]; + STAssertNotNil(desc, @""); + NSArray *array = [NSArray arrayWithObjects:@"foo", @"bar", @"bam", nil]; + STAssertNotNil(array, @""); + NSAppleEventDescriptor *userRecord = [array gtm_appleEventDescriptor]; + STAssertNotNil(userRecord, @""); + [desc setDescriptor:userRecord forKeyword:keyASUserRecordFields]; + [GTMUnitTestDevLog expectPattern:@"Got a key bam with no value in \\(.*"]; + dictionary = [desc gtm_objectValue]; + STAssertNil(dictionary, @"Should be nil"); +} + +- (void)testDescriptorWithNull { + // Test Null + NSNull *null = [NSNull null]; + NSAppleEventDescriptor *desc = [null gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + NSNull *null2 = [desc gtm_objectValue]; + STAssertNotNil(null2, nil); + NSNull *null3 = [desc gtm_nullValue]; + STAssertNotNil(null2, nil); + STAssertEqualObjects(null, null2, + @"null: %@\null2: %@\ndesc: %@", + [null description], [null2 description], + [desc description]); + STAssertEqualObjects(null, null3, + @"null: %@\null3: %@\ndesc: %@", + [null description], [null3 description], + [desc description]); +} + +- (void)testDescriptorWithString { + // Test empty String + NSAppleEventDescriptor *desc = [[NSString string] gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + + // Test String + NSString *string = @"Ratatouille!"; + desc = [string gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + NSString *string2 = [desc gtm_objectValue]; + STAssertNotNil(string2, nil); + STAssertEqualObjects(string, string2, + @"string: %@\nstring: %@\ndesc: %@", + [string description], [string2 description], [desc description]); + +} + +- (void)testDescriptorWithNumberAndNumberValue { + // There's really no good way to make this into a loop sadly due + // to me having to pass a pointer of bytes to NSInvocation as an argument. + // I want the compiler to convert my int to the appropriate type. + + NSNumber *original = [NSNumber numberWithBool:YES]; + STAssertNotNil(original, @"Value: YES"); + NSAppleEventDescriptor *desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: YES"); + id returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: YES"); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: YES"); + STAssertEqualObjects(original, returned, @"Value: YES"); + desc = [desc coerceToDescriptorType:typeBoolean]; + NSNumber *number = [desc gtm_numberValue]; + STAssertEqualObjects(number, original, @"Value: YES"); + + original = [NSNumber numberWithBool:NO]; + STAssertNotNil(original, @"Value: NO"); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: NO"); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: NO"); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: NO"); + STAssertEqualObjects(original, returned, @"Value: NO"); + + sranddev(); + double value = rand(); + + original = [NSNumber numberWithChar:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithUnsignedChar:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithShort:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithUnsignedShort:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithInt:(int)value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithUnsignedInt:(unsigned int)value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithLong:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithUnsignedLong:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithLongLong:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithUnsignedLongLong:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + float floatA = rand(); + float floatB = rand(); + value = floatA / floatB; + original = [NSNumber numberWithFloat:(float)value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + double doubleA = rand(); + double doubleB = rand(); + value = doubleA / doubleB; + original = [NSNumber numberWithDouble:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = rand(); + original = [NSNumber numberWithBool:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = NAN; + original = [NSNumber numberWithDouble:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = INFINITY; + original = [NSNumber numberWithDouble:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = -0.0; + original = [NSNumber numberWithDouble:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); + + value = -INFINITY; + original = [NSNumber numberWithDouble:value]; + STAssertNotNil(original, @"Value: %g", value); + desc = [original gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Value: %g", value); + returned = [desc gtm_objectValue]; + STAssertNotNil(returned, @"Value: %g", value); + STAssertTrue([returned isKindOfClass:[NSNumber class]], @"Value: %g", value); + STAssertEqualObjects(original, returned, @"Value: %g", value); +} + +- (void)testDescriptorWithDoubleAndDoubleValue { + sranddev(); + for (int i = 0; i < 1000; ++i) { + double value1 = rand(); + double value2 = rand(); + double value = value1 / value2; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithDouble:value]; + STAssertNotNil(desc, @"Value: %g", value); + double returnedValue = [desc gtm_doubleValue]; + STAssertEquals(value, returnedValue, @"Value: %g", value); + } + + double specialCases[] = { 0.0f, __DBL_MIN__, __DBL_EPSILON__, INFINITY, NAN }; + for (size_t i = 0; i < sizeof(specialCases) / sizeof(double); ++i) { + double value = specialCases[i]; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithDouble:value]; + STAssertNotNil(desc, @"Value: %g", value); + double returnedValue = [desc gtm_doubleValue]; + STAssertEquals(value, returnedValue, @"Value: %g", value); + } +} + +- (void)testDescriptorWithFloatAndFloatValue { + sranddev(); + for (int i = 0; i < 1000; ++i) { + float value1 = rand(); + float value2 = rand(); + float value = value1 / value2; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithFloat:value]; + STAssertNotNil(desc, @"Value: %f", value); + float returnedValue = [desc gtm_floatValue]; + STAssertEquals(value, returnedValue, @"Value: %f", value); + } + + float specialCases[] = { 0.0f, FLT_MIN, FLT_MAX, FLT_EPSILON, INFINITY, NAN }; + for (size_t i = 0; i < sizeof(specialCases) / sizeof(float); ++i) { + float value = specialCases[i]; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithFloat:value]; + STAssertNotNil(desc, @"Value: %f", value); + float returnedValue = [desc gtm_floatValue]; + STAssertEquals(value, returnedValue, @"Value: %f", value); + } +} + +- (void)testDescriptorWithCGFloatAndCGFloatValue { + sranddev(); + for (int i = 0; i < 1000; ++i) { + CGFloat value1 = rand(); + CGFloat value2 = rand(); + CGFloat value = value1 / value2; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithCGFloat:value]; + STAssertNotNil(desc, @"Value: %g", (double)value); + CGFloat returnedValue = [desc gtm_cgFloatValue]; + STAssertEquals(value, returnedValue, @"Value: %g", (double)value); + } + + CGFloat specialCases[] = { 0.0f, CGFLOAT_MIN, CGFLOAT_MAX, NAN }; + for (size_t i = 0; i < sizeof(specialCases) / sizeof(CGFloat); ++i) { + CGFloat value = specialCases[i]; + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithCGFloat:value]; + STAssertNotNil(desc, @"Value: %g", (double)value); + CGFloat returnedValue = [desc gtm_cgFloatValue]; + STAssertEquals(value, returnedValue, @"Value: %g", (double)value); + } +} + +- (void)testDescriptorWithGTMFourCharCode { + GTMFourCharCode *fcc = [GTMFourCharCode fourCharCodeWithFourCharCode:'APPL']; + STAssertNotNil(fcc, nil); + NSAppleEventDescriptor *desc = [fcc gtm_appleEventDescriptor]; + STAssertNotNil(desc, nil); + GTMFourCharCode *fcc2 = [desc gtm_objectValue]; + STAssertNotNil(fcc2, nil); + STAssertEqualObjects(fcc, fcc2, nil); + STAssertEquals([desc descriptorType], (DescType)typeType, nil); + desc = [fcc gtm_appleEventDescriptorOfType:typeKeyword]; + STAssertNotNil(desc, nil); + fcc2 = [desc gtm_objectValue]; + STAssertNotNil(fcc2, nil); + STAssertEqualObjects(fcc, fcc2, nil); + STAssertEquals([desc descriptorType], (DescType)typeKeyword, nil); +} + +- (void)testDescriptorWithDescriptor { + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor descriptorWithString:@"foo"]; + NSAppleEventDescriptor *desc2 = [desc gtm_appleEventDescriptor]; + STAssertEqualObjects(desc, desc2, nil); +} + +- (void)handleEvent:(NSAppleEventDescriptor*)event + withReply:(NSAppleEventDescriptor*)reply { + gotEvent_ = YES; + NSAppleEventDescriptor *answer = [NSAppleEventDescriptor descriptorWithInt32:1]; + [reply setDescriptor:answer forKeyword:keyDirectObject]; +} + +- (void)handleEvent:(NSAppleEventDescriptor*)event + withError:(NSAppleEventDescriptor*)error { + gotEvent_ = YES; + NSAppleEventDescriptor *answer = [NSAppleEventDescriptor descriptorWithInt32:1]; + [error setDescriptor:answer forKeyword:keyErrorNumber]; +} + +- (void)testSend { + const AEEventClass eventClass = 'Fooz'; + const AEEventID eventID = 'Ball'; + NSAppleEventManager *mgr = [NSAppleEventManager sharedAppleEventManager]; + [mgr setEventHandler:self + andSelector:@selector(handleEvent:withReply:) + forEventClass:eventClass + andEventID:'Ball']; + NSAppleEventDescriptor *currentProcess + = [[NSProcessInfo processInfo] gtm_appleEventDescriptor]; + NSAppleEventDescriptor *event + = [NSAppleEventDescriptor appleEventWithEventClass:eventClass + eventID:eventID + targetDescriptor:currentProcess + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID]; + gotEvent_ = NO; + NSAppleEventDescriptor *reply; + BOOL goodEvent = [event gtm_sendEventWithMode:kAEWaitReply timeOut:60 reply:&reply]; + [mgr removeEventHandlerForEventClass:eventClass andEventID:eventID]; + STAssertTrue(goodEvent, @"bad event?"); + STAssertTrue(gotEvent_, @"Handler not called"); + NSAppleEventDescriptor *value = [reply descriptorForKeyword:keyDirectObject]; + STAssertEquals([value int32Value], (SInt32)1, @"didn't get reply"); + + + gotEvent_ = NO; + [GTMUnitTestDevLog expectString:@"Unable to send message: " + " -1708"]; + goodEvent = [event gtm_sendEventWithMode:kAEWaitReply timeOut:60 reply:&reply]; + STAssertFalse(goodEvent, @"good event?"); + STAssertFalse(gotEvent_, @"Handler called?"); + + [mgr setEventHandler:self + andSelector:@selector(handleEvent:withError:) + forEventClass:eventClass + andEventID:eventID]; + gotEvent_ = NO; + goodEvent = [event gtm_sendEventWithMode:kAEWaitReply timeOut:60 reply:&reply]; + STAssertFalse(goodEvent, @"good event?"); + STAssertTrue(gotEvent_, @"Handler not called?"); + [mgr removeEventHandlerForEventClass:eventClass andEventID:eventID]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.h new file mode 100644 index 00000000..f2ac8800 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.h @@ -0,0 +1,40 @@ +// +// GTMNSAppleEventDescriptor+Handler.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +@interface NSAppleEventDescriptor (GTMAppleEventDescriptorHandlerAdditions) ++ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler + parametersArray:(NSArray*)params; ++ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler + parametersDescriptor:(NSAppleEventDescriptor*)params; ++ (id)gtm_descriptorWithLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count; + +- (id)gtm_initWithPositionalHandler:(NSString*)handler + parametersArray:(NSArray*)params; +- (id)gtm_initWithPositionalHandler:(NSString*)handler + parametersDescriptor:(NSAppleEventDescriptor*)params; +- (id)gtm_initWithLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.m new file mode 100644 index 00000000..76b6e858 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+Handler.m @@ -0,0 +1,130 @@ +// +// GTMNSAppleEventDescriptor+Handler.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSAppleEventDescriptor+Handler.h" +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMMethodCheck.h" +#import + +@implementation NSAppleEventDescriptor (GTMAppleEventDescriptorHandlerAdditions) +GTM_METHOD_CHECK(NSProcessInfo, gtm_appleEventDescriptor); + ++ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler + parametersArray:(NSArray*)params { + return [[[self alloc] gtm_initWithPositionalHandler:handler + parametersArray:params] autorelease]; +} + ++ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler + parametersDescriptor:(NSAppleEventDescriptor*)params { + return [[[self alloc] gtm_initWithPositionalHandler:handler + parametersDescriptor:params] autorelease]; +} + ++ (id)gtm_descriptorWithLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count { + return [[[self alloc] gtm_initWithLabeledHandler:handler + labels:labels + parameters:params + count:count] autorelease]; +} + +- (id)gtm_initWithPositionalHandler:(NSString*)handler + parametersArray:(NSArray*)params { + return [self gtm_initWithPositionalHandler:handler + parametersDescriptor:[params gtm_appleEventDescriptor]]; +} + +- (id)gtm_initWithPositionalHandler:(NSString*)handler + parametersDescriptor:(NSAppleEventDescriptor*)params { + if ((self = [self initWithEventClass:kASAppleScriptSuite + eventID:kASSubroutineEvent + targetDescriptor:[[NSProcessInfo processInfo] gtm_appleEventDescriptor] + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID])) { + // Create an NSAppleEventDescriptor with the method handler. Note that the + // name must be lowercase (even if it is uppercase in AppleScript). + // http://developer.apple.com/qa/qa2001/qa1111.html + // has details. + handler = [handler lowercaseString]; + if (!handler) { + [self release]; + return nil; + } + NSAppleEventDescriptor *handlerDesc + = [NSAppleEventDescriptor descriptorWithString:handler]; + [self setParamDescriptor:handlerDesc forKeyword:keyASSubroutineName]; + if (params) { + [self setParamDescriptor:params forKeyword:keyDirectObject]; + } + } + return self; +} + + +- (id)gtm_initWithLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count { + if ((self = [self initWithEventClass:kASAppleScriptSuite + eventID:kASSubroutineEvent + targetDescriptor:[[NSProcessInfo processInfo] gtm_appleEventDescriptor] + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID])) { + if (!handler) { + [self release]; + return nil; + } + // Create an NSAppleEventDescriptor with the method handler. Note that the + // name must be lowercase (even if it is uppercase in AppleScript). + NSAppleEventDescriptor *handlerDesc + = [NSAppleEventDescriptor descriptorWithString:[handler lowercaseString]]; + [self setParamDescriptor:handlerDesc forKeyword:keyASSubroutineName]; + for (NSUInteger i = 0; i < count; i++) { + NSAppleEventDescriptor *paramDesc = [params[i] gtm_appleEventDescriptor]; + if(labels[i] == keyASPrepositionGiven) { + if (![params[i] isKindOfClass:[NSDictionary class]]) { + _GTMDevLog(@"Must pass in dictionary for keyASPrepositionGiven " + "(got %@)", params[i]); + [self release]; + self = nil; + break; + } + NSAppleEventDescriptor *userDesc + = [paramDesc descriptorForKeyword:keyASUserRecordFields]; + if (!userDesc) { + _GTMDevLog(@"Dictionary for keyASPrepositionGiven must be a user " + "record field dictionary (got %@)", params[i]); + [self release]; + self = nil; + break; + } + [self setParamDescriptor:userDesc + forKeyword:keyASUserRecordFields]; + } else { + [self setParamDescriptor:paramDesc + forKeyword:labels[i]]; + } + } + } + return self; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+HandlerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+HandlerTest.m new file mode 100644 index 00000000..a137d8a8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleEventDescriptor+HandlerTest.m @@ -0,0 +1,70 @@ +// +// GTNNSAppleEventDescriptor+HandlerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMSenTestCase.h" +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMNSAppleEventDescriptor+Handler.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMNSAppleEventDescriptor_HandlerTest : GTMTestCase +@end + +@implementation GTMNSAppleEventDescriptor_HandlerTest +// Most of this gets tested by the NSAppleScript+Handler tests. +- (void)testPositionalHandlers { + NSAppleEventDescriptor *desc + = [NSAppleEventDescriptor gtm_descriptorWithPositionalHandler:nil + parametersArray:[NSArray array]]; + STAssertNil(desc, @"got a desc?"); + + desc = [NSAppleEventDescriptor gtm_descriptorWithPositionalHandler:@"happy" + parametersDescriptor:nil]; + STAssertNotNil(desc, @"didn't get a desc?"); + + desc = [NSAppleEventDescriptor gtm_descriptorWithLabeledHandler:nil + labels:nil + parameters:nil + count:0]; + STAssertNil(desc, @"got a desc?"); + + AEKeyword keys[] = { keyASPrepositionGiven }; + NSString *string = @"foo"; + [GTMUnitTestDevLog expectString:@"Must pass in dictionary for " + "keyASPrepositionGiven (got foo)"]; + desc = [NSAppleEventDescriptor gtm_descriptorWithLabeledHandler:@"happy" + labels:keys + parameters:&string + count:1]; + STAssertNil(desc, @"got a desc?"); + + NSDictionary *dict = [NSDictionary dictionaryWithObject:@"bart" + forKey:[NSNumber numberWithInt:4]]; + [GTMUnitTestDevLog expectString:@"Keys must be of type NSString or " + "GTMFourCharCode: 4"]; + [GTMUnitTestDevLog expectPattern:@"Dictionary for keyASPrepositionGiven must " + "be a user record field dictionary \\(got .*"]; + desc = [NSAppleEventDescriptor gtm_descriptorWithLabeledHandler:@"happy" + labels:keys + parameters:&dict + count:1]; + STAssertNil(desc, @"got a desc?"); + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.h new file mode 100644 index 00000000..65f57c56 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.h @@ -0,0 +1,126 @@ +// +// GTMNSAppleScript+Handler.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// :::WARNING::: NSAppleScript and Garbage Collect (GC) +// +// As of 10.5.6 (and below) Apple has bugs in NSAppleScript when running with +// GC; ie-things crash that have nothing to do w/ this or your code. See +// http://rails.wincent.com/issues/640 for a good amount of detail about the +// problems and simple cases that show it. + +// A category for calling handlers in NSAppleScript + +enum { + // Data type is OSAID. These will generally be representing + // scripts. + typeGTMOSAID = 'GTMO' +}; + +@interface NSAppleScript(GTMAppleScriptHandlerAdditions) +// Allows us to call a specific handler in an AppleScript. +// parameters are passed in left-right order 0-n. +// +// Args: +// handler - name of the handler to call in the Applescript +// params - the parameters to pass to the handler +// error - in non-nil returns any error that may have occurred. +// +// Returns: +// The result of the handler being called. nil on failure. +- (NSAppleEventDescriptor*)gtm_executePositionalHandler:(NSString*)handler + parameters:(NSArray*)params + error:(NSDictionary**)error; + + +// Allows us to call a specific labeled handler in an AppleScript. +// Parameters for a labeled handler can be in any order, as long as the +// order of the params array corresponds to the order of the labels array +// such that labels are associated with their correct parameter values. +// +// Args: +// handler - name of the handler to call in the Applescript +// labels - the labels to associate with the parameters +// params - the parameters to pass to the handler +// count - number of labels/parameters +// error - in non-nil returns any error that may have occurred. +// +// Returns: +// The result of the handler being called. nil on failure. +- (NSAppleEventDescriptor*)gtm_executeLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count + error:(NSDictionary **)error; + +// Same as executeAppleEvent:error: except that it handles return values of +// script correctly. Return values containing scripts will have the +// typeGTMOSAID. Calling gtm_objectValue on a NSAppleEventDescriptor of +// typeGTMOSAID will resolve correctly to a script value. We don't use +// typeScript because that actually copies the script instead of returning the +// actual value. Therefore if you called executeAppleEvent:error: (instead of +// the GTM version) to execute an event that returns a script, you will +// get a completely new Applescript, instead of the actual script you wanted. If +// you are working with script information, use gtm_executeAppleEvent:error +// instead of executeAppleEvent:error: to avoid the problem. +- (NSAppleEventDescriptor *)gtm_executeAppleEvent:(NSAppleEventDescriptor *)event + error:(NSDictionary **)error; + +// The set of all handlers that are defined in this script and its parents. +// Remember that handlers that are defined in an sdef will have their +// eventclass/eventid as their handler instead of the name seen in the script. +// So: +// on open(a) +// blah +// end open +// won't be "open" it will be "aevtodoc". +- (NSSet*)gtm_handlers; + +// The set of all properties that are defined in this script and its parents. +// Note that properties can be strings or GTMNSFourCharCodes, so expect both +// coming back in the set. +- (NSSet*)gtm_properties; + +// Return a value for a property. Will look up the inheritence tree. +// Property must be an NSString or a GTMFourCharCode. +- (id)gtm_valueForProperty:(id)property; + +// Return a value for a property by type (eg pASParent). Will look up the +// inheritence tree +- (id)gtm_valueForPropertyEnum:(DescType)property; + +// Set a script property value. Returns YES/NO on success/failure. +// Property must be of kind NSString or GTMFourCharCode. +// If addingDefinition is YES, it will add a definition to the script +// if the value doesn't exist in the script or one of it's parents. +- (BOOL)gtm_setValue:(id)value + forProperty:(id)property + addingDefinition:(BOOL)adding; + +// Set a value for a property by type (eg pASParent). See note above +// for gtm_setValue:forProperty. +- (BOOL)gtm_setValue:(id)value + forPropertyEnum:(DescType)property + addingDefinition:(BOOL)adding; + +// Return YES if the script has an open documents (odoc) handler +// Does not require script compilation, so it's a fast check. +- (BOOL)gtm_hasOpenDocumentsHandler; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.m new file mode 100644 index 00000000..8c236495 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+Handler.m @@ -0,0 +1,518 @@ +// +// GTMNSAppleScript+Handler.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMNSAppleScript+Handler.h" +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMNSAppleEventDescriptor+Handler.h" +#import "GTMFourCharCode.h" +#import "GTMMethodCheck.h" +#import "GTMDebugThreadValidation.h" + +// Some private methods that we need to call +@interface NSAppleScript (NSPrivate) ++ (ComponentInstance)_defaultScriptingComponent; +- (OSAID) _compiledScriptID; +- (id)_initWithData:(NSData*)data error:(NSDictionary**)error; +- (id)_initWithScriptIDNoCopy:(OSAID)osaID; ++ (id)_infoForOSAError:(OSAError)error; +@end + +@interface NSMethodSignature (NSPrivate) ++ (id)signatureWithObjCTypes:(const char *)fp8; +@end + +// Our own private interfaces. +@interface NSAppleScript (GTMAppleScriptHandlerAdditionsPrivate) + +// Return an descriptor for a property. Properties are only supposed to be +// of type NSString or GTMFourCharCode. GTMFourCharCode's need special handling +// as they must be turned into NSAppleEventDescriptors of typeProperty. +- (NSAppleEventDescriptor*)gtm_descriptorForPropertyValue:(id)property; + +// Return an NSAppleEventDescriptor for a given property. +// |property| must be kind of class GTMFourCharCode +- (NSAppleEventDescriptor*)gtm_valueDescriptorForProperty:(id)property; + +// Utility routine for extracting multiple values in scripts and their +// parents. +- (NSSet*)gtm_allValuesUsingSelector:(SEL)selector; + +// Utility routine for extracting the handlers for a specific script without +// referring to parent scripts. +- (NSSet*)gtm_scriptHandlers; + +// Utility routine for extracting the properties for a specific script without +// referring to parent scripts. +- (NSSet*)gtm_scriptProperties; + +// Handles creating an NSAppleEventDescriptor from an OSAID +- (NSAppleEventDescriptor*)descForScriptID:(OSAID)scriptID + component:(ComponentInstance)component; + +// Utility methods for converting between real and generic OSAIDs. +- (OSAID)gtm_genericID:(OSAID)osaID forComponent:(ComponentInstance)component; +- (OSAID)gtm_realIDAndComponent:(ComponentInstance*)component; +@end + +@implementation NSAppleScript(GTMAppleScriptHandlerAdditions) +GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithPositionalHandler:parametersArray:); +GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithLabeledHandler:labels:parameters:count:); +GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:); + ++ (void)load { + DescType types[] = { + typeScript + }; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_scriptValue) + forTypes:types + count:sizeof(types)/sizeof(DescType)]; + + DescType types2[] = { + 'evnt' // No type code for this one + }; + + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_eventValue) + forTypes:types2 + count:sizeof(types2)/sizeof(DescType)]; + + DescType types3[] = { + typeGTMOSAID + }; + + [NSAppleEventDescriptor gtm_registerSelector:@selector(gtm_osaIDValue) + forTypes:types3 + count:sizeof(types3)/sizeof(DescType)]; + [pool release]; +} + +- (NSAppleEventDescriptor *)gtm_executeAppleEvent:(NSAppleEventDescriptor *)event + error:(NSDictionary **)error { + GTMAssertRunningOnMainThread(); + if (![self isCompiled]) { + if (![self compileAndReturnError:error]) { + return nil; + } + } + NSAppleEventDescriptor *desc = nil; + ComponentInstance component; + OSAID scriptID = [self gtm_realIDAndComponent:&component]; + OSAID valueID; + OSAError err = OSAExecuteEvent(component, [event aeDesc], scriptID, + kOSAModeNull, &valueID); + if (err == noErr) { + // descForScriptID:component: is what sets this apart from the + // standard executeAppelEvent:error: in that it handles + // taking script results and turning them into AEDescs of typeGTMOSAID + // instead of typeScript. + desc = [self descForScriptID:valueID component:component]; + } + if (err && error) { + *error = [NSAppleScript _infoForOSAError:err]; + } + return desc; +} + +- (NSAppleEventDescriptor*)gtm_executePositionalHandler:(NSString*)handler + parameters:(NSArray*)params + error:(NSDictionary**)error { + NSAppleEventDescriptor *event + = [NSAppleEventDescriptor gtm_descriptorWithPositionalHandler:handler + parametersArray:params]; + return [self gtm_executeAppleEvent:event error:error]; +} + +- (NSAppleEventDescriptor*)gtm_executeLabeledHandler:(NSString*)handler + labels:(AEKeyword*)labels + parameters:(id*)params + count:(NSUInteger)count + error:(NSDictionary **)error { + NSAppleEventDescriptor *event + = [NSAppleEventDescriptor gtm_descriptorWithLabeledHandler:handler + labels:labels + parameters:params + count:count]; + return [self gtm_executeAppleEvent:event error:error]; +} + +- (NSSet*)gtm_handlers { + return [self gtm_allValuesUsingSelector:@selector(gtm_scriptHandlers)]; +} + +- (NSSet*)gtm_properties { + return [self gtm_allValuesUsingSelector:@selector(gtm_scriptProperties)]; +} + +// Set a value for a property by type (eg pASTopLevelScript) +- (BOOL)gtm_setValue:(id)value + forPropertyEnum:(DescType)property + addingDefinition:(BOOL)adding { + GTMFourCharCode *fcc + = [GTMFourCharCode fourCharCodeWithFourCharCode:property]; + return [self gtm_setValue:value forProperty:fcc addingDefinition:adding]; +} + +- (BOOL)gtm_setValue:(id)value + forProperty:(id)property + addingDefinition:(BOOL)adding{ + OSAError error = paramErr; + BOOL wasGood = NO; + NSAppleEventDescriptor *propertyName + = [self gtm_descriptorForPropertyValue:property]; + NSAppleEventDescriptor *desc = [value gtm_appleEventDescriptor]; + if (propertyName && desc) { + NSAppleScript *script = self; + OSAID valueID = kOSANullScript; + ComponentInstance component; + OSAID scriptID = [script gtm_realIDAndComponent:&component]; + error = OSACoerceFromDesc(component, + [desc aeDesc], + kOSAModeNull, + &valueID); + if (error == noErr) { + error = OSASetProperty(component, + adding ? kOSAModeNull : kOSAModeDontDefine, + scriptID, + [propertyName aeDesc], + valueID); + if (error == noErr) { + wasGood = YES; + } + } + } + if (!wasGood) { + _GTMDevLog(@"Unable to setValue:%@ forProperty:%@ from %@ (%d)", + value, property, self, error); + } + return wasGood; +} + +- (id)gtm_valueForProperty:(id)property { + return [[self gtm_valueDescriptorForProperty:property] gtm_objectValue]; +} + +- (id)gtm_valueForPropertyEnum:(DescType)property { + GTMFourCharCode *fcc = [GTMFourCharCode fourCharCodeWithFourCharCode:property]; + return [self gtm_valueForProperty:fcc]; +} + +- (NSAppleEventDescriptor*)gtm_appleEventDescriptor { + ComponentInstance component; + OSAID osaID = [self gtm_realIDAndComponent:&component]; + AEDesc result = { typeNull, NULL }; + NSAppleEventDescriptor *desc = nil; + OSAError error = OSACoerceToDesc(component, + osaID, + typeScript, + kOSAModeNull, + &result); + if (error == noErr) { + desc = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&result] + autorelease]; + } else { + _GTMDevLog(@"Unable to coerce script %d", error); + } + return desc; +} + +- (BOOL)gtm_hasOpenDocumentsHandler { + ComponentInstance component; + OSAID osaID = [self gtm_realIDAndComponent:&component]; + long value = 0; + OSAError error = OSAGetScriptInfo(component, + osaID, + kASHasOpenHandler, + &value); + if (error) { + _GTMDevLog(@"Unable to get script info about open handler %d", error); + value = 0; + } + return value != 0; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { + NSMethodSignature *signature = [super methodSignatureForSelector:aSelector]; + if (!signature) { + NSMutableString *types = [NSMutableString stringWithString:@"@@:"]; + NSString *selName = NSStringFromSelector(aSelector); + NSArray *selArray = [selName componentsSeparatedByString:@":"]; + NSUInteger count = [selArray count]; + for (NSUInteger i = 1; i < count; i++) { + [types appendString:@"@"]; + } + signature = [NSMethodSignature signatureWithObjCTypes:[types UTF8String]]; + } + return signature; +} + +- (void)forwardInvocation:(NSInvocation *)invocation { + SEL sel = [invocation selector]; + NSMutableString *handlerName + = [NSMutableString stringWithString:NSStringFromSelector(sel)]; + NSUInteger handlerOrigLength = [handlerName length]; + [handlerName replaceOccurrencesOfString:@":" + withString:@"" + options:0 + range:NSMakeRange(0,handlerOrigLength)]; + NSUInteger argCount = handlerOrigLength - [handlerName length]; + NSMutableArray *args = [NSMutableArray arrayWithCapacity:argCount]; + for (NSUInteger i = 0; i < argCount; ++i) { + id arg; + // +2 to ignore _sel and _cmd + [invocation getArgument:&arg atIndex:i + 2]; + [args addObject:arg]; + } + NSDictionary *error = nil; + NSAppleEventDescriptor *desc = [self gtm_executePositionalHandler:handlerName + parameters:args + error:&error]; + if ([[invocation methodSignature] methodReturnLength] > 0) { + id returnValue = [desc gtm_objectValue]; + [invocation setReturnValue:&returnValue]; + } +} +@end + +@implementation NSAppleScript (GTMAppleScriptHandlerAdditionsPrivate) + +- (NSAppleEventDescriptor*)gtm_descriptorForPropertyValue:(id)property { + NSAppleEventDescriptor *propDesc = nil; + if ([property isKindOfClass:[GTMFourCharCode class]]) { + propDesc = [property gtm_appleEventDescriptorOfType:typeProperty]; + } else if ([property isKindOfClass:[NSString class]]) { + propDesc = [property gtm_appleEventDescriptor]; + } + return propDesc; +} + +- (NSAppleEventDescriptor*)gtm_valueDescriptorForProperty:(id)property { + GTMAssertRunningOnMainThread(); + OSAError error = paramErr; + NSAppleEventDescriptor *desc = nil; + NSAppleEventDescriptor *propertyName + = [self gtm_descriptorForPropertyValue:property]; + if (propertyName) { + ComponentInstance component; + OSAID scriptID = [self gtm_realIDAndComponent:&component]; + OSAID valueID = kOSANullScript; + error = OSAGetProperty(component, + kOSAModeNull, + scriptID, + [propertyName aeDesc], + &valueID); + if (error == noErr) { + desc = [self descForScriptID:valueID component:component]; + } + } + if (error) { + _GTMDevLog(@"Unable to get valueForProperty:%@ from %@ (%d)", + property, self, error); + } + return desc; +} + +- (NSSet*)gtm_allValuesUsingSelector:(SEL)selector { + NSMutableSet *resultSet = [NSMutableSet set]; + NSAppleEventDescriptor *scriptDesc = [self gtm_appleEventDescriptor]; + NSMutableSet *scriptDescsWeveSeen = [NSMutableSet set]; + GTMFourCharCode *fcc = [GTMFourCharCode fourCharCodeWithFourCharCode:pASParent]; + Class appleScriptClass = [NSAppleScript class]; + while (scriptDesc) { + NSAppleScript *script = [scriptDesc gtm_objectValue]; + if ([script isKindOfClass:appleScriptClass]) { + NSData *data = [scriptDesc data]; + if (!data || [scriptDescsWeveSeen containsObject:data]) { + break; + } else { + [scriptDescsWeveSeen addObject:data]; + } + NSSet *newSet = [script performSelector:selector]; + [resultSet unionSet:newSet]; + scriptDesc = [script gtm_valueDescriptorForProperty:fcc]; + } else { + break; + } + } + return resultSet; +} + +- (NSSet*)gtm_scriptHandlers { + GTMAssertRunningOnMainThread(); + AEDescList names = { typeNull, NULL }; + NSArray *array = nil; + ComponentInstance component; + OSAID osaID = [self gtm_realIDAndComponent:&component]; + OSAError error = OSAGetHandlerNames(component, kOSAModeNull, osaID, &names); + if (error == noErr) { + NSAppleEventDescriptor *desc + = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&names] + autorelease]; + array = [desc gtm_objectValue]; + } + if (error != noErr) { + _GTMDevLog(@"Error getting handlers: %d", error); // COV_NF_LINE + } + return [NSSet setWithArray:array]; +} + +- (NSSet*)gtm_scriptProperties { + GTMAssertRunningOnMainThread(); + AEDescList names = { typeNull, NULL }; + NSArray *array = nil; + ComponentInstance component; + OSAID osaID = [self gtm_realIDAndComponent:&component]; + OSAError error = OSAGetPropertyNames(component, kOSAModeNull, osaID, &names); + if (error == noErr) { + NSAppleEventDescriptor *desc + = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&names] + autorelease]; + array = [desc gtm_objectValue]; + } + if (error != noErr) { + _GTMDevLog(@"Error getting properties: %d", error); // COV_NF_LINE + } + return [NSSet setWithArray:array]; +} + +- (OSAID)gtm_genericID:(OSAID)osaID forComponent:(ComponentInstance)component { + GTMAssertRunningOnMainThread(); + ComponentInstance genericComponent = [NSAppleScript _defaultScriptingComponent]; + OSAID exactID = osaID; + OSAError error = OSARealToGenericID(genericComponent, &exactID, component); + if (error != noErr) { + _GTMDevLog(@"Unable to get real id script: %@ %d", self, error); // COV_NF_LINE + exactID = kOSANullScript; // COV_NF_LINE + } + return exactID; +} + +- (NSAppleEventDescriptor*)descForScriptID:(OSAID)osaID + component:(ComponentInstance)component { + GTMAssertRunningOnMainThread(); + NSAppleEventDescriptor *desc = nil; + // If we have a script, return a typeGTMOSAID, otherwise convert it to + // it's default AEDesc using OSACoerceToDesc with typeWildCard. + long value = 0; + OSAError err = noErr; + if (osaID == 0) { + desc = [NSAppleEventDescriptor nullDescriptor]; + } else { + err = OSAGetScriptInfo(component, + osaID, + kOSAScriptBestType, + &value); + if (err == noErr) { + if (value == typeScript) { + osaID = [self gtm_genericID:osaID forComponent:component]; + desc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeGTMOSAID + bytes:&osaID + length:sizeof(osaID)]; + } else { + AEDesc aeDesc; + err = OSACoerceToDesc(component, + osaID, + typeWildCard, + kOSAModeNull, + &aeDesc); + if (err == noErr) { + desc = [[[NSAppleEventDescriptor alloc] + initWithAEDescNoCopy:&aeDesc] autorelease]; + } + } + } + } + if (err != noErr) { + _GTMDevLog(@"Unable to create desc for id:%d (%d)", osaID, err); // COV_NF_LINE + } + return desc; +} + +- (OSAID)gtm_realIDAndComponent:(ComponentInstance*)component { + GTMAssertRunningOnMainThread(); + if (![self isCompiled]) { + NSDictionary *error; + if (![self compileAndReturnError:&error]) { + _GTMDevLog(@"Unable to compile script: %@ %@", self, error); + return kOSANullScript; + } + } + OSAID genericID = [self _compiledScriptID]; + ComponentInstance genericComponent = [NSAppleScript _defaultScriptingComponent]; + OSAError error = OSAGenericToRealID(genericComponent, &genericID, component); + if (error != noErr) { + _GTMDevLog(@"Unable to get real id script: %@ %d", self, error); // COV_NF_LINE + genericID = kOSANullScript; // COV_NF_LINE + } + return genericID; +} + +@end + +// Private methods for dealing with Scripts/Events and NSAppleEventDescriptors +@interface NSAppleEventDescriptor (GTMAppleEventDescriptorScriptAdditions) + +// Return an NSAppleScript for a desc of typeScript. This will create a new +// Applescript that is a copy of the script that you want. +// Returns nil on failure. +- (NSAppleScript*)gtm_scriptValue; + +// Return an NSAppleScript for a desc of typeGTMOSAID. This will not copy the +// script, but will create an NSAppleScript wrapping the script represented +// by the OSAID. +// Returns nil on failure. +- (NSAppleScript*)gtm_osaIDValue; + +// Return a NSString with [eventClass][eventID] for typeEvent 'evnt' +- (NSString*)gtm_eventValue; +@end + + +@implementation NSAppleEventDescriptor (GMAppleEventDescriptorScriptAdditions) + +- (NSAppleScript*)gtm_scriptValue { + NSDictionary *error; + NSAppleScript *script = [[[NSAppleScript alloc] _initWithData:[self data] + error:&error] autorelease]; + if (!script) { + _GTMDevLog(@"Unable to create script: %@", error); // COV_NF_LINE + } + return script; +} + +- (NSAppleScript*)gtm_osaIDValue { + _GTMDevAssert([[self data] length] == sizeof(OSAID), nil); + OSAID osaID = *(const OSAID*)[[self data] bytes]; + return [[[NSAppleScript alloc] _initWithScriptIDNoCopy:osaID] autorelease]; +} + +- (NSString*)gtm_eventValue { + struct AEEventRecordStruct { + AEEventClass eventClass; + AEEventID eventID; + }; + NSData *data = [self data]; + const struct AEEventRecordStruct *record + = (const struct AEEventRecordStruct*)[data bytes]; + NSString *eClass = [GTMFourCharCode stringWithFourCharCode:record->eventClass]; + NSString *eID = [GTMFourCharCode stringWithFourCharCode:record->eventID]; + return [eClass stringByAppendingString:eID]; +} +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+HandlerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+HandlerTest.m new file mode 100644 index 00000000..44d0a0c6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSAppleScript+HandlerTest.m @@ -0,0 +1,506 @@ +// +// GTMNSAppleScript+HandlerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import +#import "GTMNSAppleScript+Handler.h" +#import "GTMNSAppleEventDescriptor+Foundation.h" +#import "GTMUnitTestDevLog.h" +#import "GTMGarbageCollection.h" +#import "GTMSystemVersion.h" +#import "GTMFourCharCode.h" + +@interface GTMNSAppleScript_HandlerTest : GTMTestCase { + NSAppleScript *script_; +} +@end + +@implementation GTMNSAppleScript_HandlerTest +- (void)invokeTest { + // NOTE: These tests are disabled in GC is on. See the comment/warning in the + // GTMNSAppleScript+Handler.h for more details, but we disable them to avoid + // the tests failing (crashing) when it's Apple's bug. Please bump the system + // check as appropriate when new systems are tested. Currently broken on + // 10.5.6 and below. Radar 6126682. + SInt32 major, minor, bugfix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix]; + if (!(GTMIsGarbageCollectionEnabled() + && major <= 10 && minor <= 5 && bugfix <= 6)) { + [super invokeTest]; + } else { + NSLog(@"--- %@ NOT run because of GC incompatibilites ---", [self name]); + } +} + +- (void)setUp { + NSBundle *bundle + = [NSBundle bundleForClass:[GTMNSAppleScript_HandlerTest class]]; + STAssertNotNil(bundle, nil); + NSString *path = [bundle pathForResource:@"GTMNSAppleEvent+HandlerTest" + ofType:@"scpt" + inDirectory:@"Scripts"]; + STAssertNotNil(path, [bundle description]); + NSDictionary *error = nil; + script_ + = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] + error:&error]; + STAssertNotNil(script_, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); +} + +- (void)tearDown { + [script_ release]; + script_ = nil; +} + +- (void)testExecuteAppleEvent { + NSString *source = @"on test()\nreturn 1\nend test"; + NSAppleScript *script + = [[[NSAppleScript alloc] initWithSource:source] autorelease]; + STAssertNotNil(script, nil); + NSDictionary *error = nil; + NSAppleEventDescriptor *desc = [script gtm_executePositionalHandler:@"test" + parameters:nil + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc gtm_objectValue], [NSNumber numberWithInt:1], nil); + + // bogus script + source = @"adf872345ba asdf asdf gr"; + script = [[[NSAppleScript alloc] initWithSource:source] autorelease]; + STAssertNotNil(script, nil); + desc = [script gtm_executePositionalHandler:@"test" + parameters:nil + error:&error]; + STAssertNil(desc, nil); + STAssertNotNil(error, @"Error should not be nil"); +} + +- (void)testHandlerNoParamsNoReturn { + NSDictionary *error = nil; + NSAppleEventDescriptor *desc = [script_ gtm_executePositionalHandler:@"test" + parameters:nil + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeNull, nil); + desc = [script_ gtm_executePositionalHandler:@"test" + parameters:[NSArray array] + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeNull, nil); + + //Applescript doesn't appear to get upset about extra params + desc = [script_ gtm_executePositionalHandler:@"test" + parameters:[NSArray arrayWithObject:@"foo"] + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeNull, nil); +} + +- (void)testHandlerNoParamsWithReturn { + NSDictionary *error = nil; + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"testReturnOne" + parameters:nil + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)1, nil); + desc = [script_ gtm_executePositionalHandler:@"testReturnOne" + parameters:[NSArray array] + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)1, nil); + + //Applescript doesn't appear to get upset about extra params + desc = [script_ gtm_executePositionalHandler:@"testReturnOne" + parameters:[NSArray arrayWithObject:@"foo"] + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)1, nil); +} + +- (void)testHandlerOneParamWithReturn { + NSDictionary *error = nil; + // Note case change in executeHandler call + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"testreturnParam" + parameters:nil + error:&error]; + STAssertNil(desc, @"Desc should by nil %@", desc); + STAssertNotNil(error, nil); + error = nil; + + desc = [script_ gtm_executePositionalHandler:@"testReturnParam" + parameters:[NSArray array] + error:&error]; + STAssertNil(desc, @"Desc should by nil %@", desc); + STAssertNotNil(error, nil); + error = nil; + + desc = [script_ gtm_executePositionalHandler:@"testReturnParam" + parameters:[NSArray arrayWithObject:@"foo"] + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeUnicodeText, nil); + STAssertEqualObjects([desc gtm_objectValue], @"foo", nil); +} + +- (void)testHandlerTwoParamsWithReturn { + NSDictionary *error = nil; + // Note case change in executeHandler call + // Test case and empty params + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"testADDPArams" + parameters:nil + error:&error]; + STAssertNil(desc, @"Desc should by nil %@", desc); + STAssertNotNil(error, nil); + + // Test empty params + error = nil; + desc = [script_ gtm_executePositionalHandler:@"testAddParams" + parameters:[NSArray array] + error:&error]; + STAssertNil(desc, @"Desc should by nil %@", desc); + STAssertNotNil(error, nil); + + error = nil; + NSArray *args = [NSArray arrayWithObjects: + [NSNumber numberWithInt:1], + [NSNumber numberWithInt:2], + nil]; + desc = [script_ gtm_executePositionalHandler:@"testAddParams" + parameters:args + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)3, nil); + + // Test bad params + error = nil; + args = [NSArray arrayWithObjects: + @"foo", + @"bar", + nil]; + desc = [script_ gtm_executePositionalHandler:@"testAddParams" + parameters:args + error:&error]; + STAssertNil(desc, @"Desc should by nil %@", desc); + STAssertNotNil(error, nil); + + // Test too many params. Currently Applescript allows this so it should pass + error = nil; + args = [NSArray arrayWithObjects: + [NSNumber numberWithInt:1], + [NSNumber numberWithInt:2], + [NSNumber numberWithInt:3], + nil]; + desc = [script_ gtm_executePositionalHandler:@"testAddParams" + parameters:args + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)3, nil);} + +- (void)testLabeledHandler { + NSDictionary *error = nil; + AEKeyword labels[] = { keyDirectObject, + keyASPrepositionOnto, + keyASPrepositionGiven }; + id params[3]; + params[0] = [NSNumber numberWithInt:1]; + params[1] = [NSNumber numberWithInt:3]; + params[2] = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:4] + forKey:@"othervalue"]; + + NSAppleEventDescriptor *desc + = [script_ gtm_executeLabeledHandler:@"testAdd" + labels:labels + parameters:params + count:sizeof(params) / sizeof(id) + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)8, nil); + + // Test too many params. Currently Applescript allows this so it should pass + AEKeyword labels2[] = { keyDirectObject, + keyASPrepositionOnto, + keyASPrepositionBetween, + keyASPrepositionGiven }; + id params2[4]; + params2[0] = [NSNumber numberWithInt:1]; + params2[1] = [NSNumber numberWithInt:3]; + params2[2] = [NSNumber numberWithInt:5]; + params2[3] = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:4] + forKey:@"othervalue"]; + + error = nil; + desc = [script_ gtm_executeLabeledHandler:@"testAdd" + labels:labels2 + parameters:params2 + count:sizeof(params2) / sizeof(id) + error:&error]; + STAssertNotNil(desc, [error description]); + STAssertNil(error, @"Error should be nil. Error = %@", [error description]); + STAssertEquals([desc descriptorType], (DescType)typeSInt32, nil); + STAssertEquals([desc int32Value], (SInt32)8, nil);} + +- (void)testHandlers { + NSSet *handlers = [script_ gtm_handlers]; + NSSet *expected = [NSSet setWithObjects: + @"aevtpdoc", + @"test", + @"testreturnone", + @"testreturnparam", + @"testaddparams", + @"testadd", + @"testgetscript", + nil]; + if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // Workaround for bug in SnowLeopard + // rdar://66688601 OSAGetHandlersNames returns names in camelcase instead + // of smallcaps. + handlers = [handlers valueForKey:@"lowercaseString"]; + } + STAssertEqualObjects(handlers, expected, @"Unexpected handlers?"); +} + +- (void)testInheritedHandlers { + NSDictionary *error = nil; + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"testGetScript" + parameters:nil + error:&error]; + STAssertNil(error, nil); + STAssertNotNil(desc, nil); + NSAppleScript *script = [desc gtm_objectValue]; + STAssertTrue([script isKindOfClass:[NSAppleScript class]], nil); + error = nil; + desc = [script gtm_executePositionalHandler:@"parentTestScriptFunc" + parameters:nil error:&error]; + STAssertNil(error, nil); + STAssertNotNil(desc, nil); + NSString *value = [desc gtm_objectValue]; + STAssertEqualObjects(value, @"parent", nil); +} + +- (void)testProperties { + NSDictionary *error = nil; + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"testGetScript" + parameters:nil + error:&error]; + STAssertNil(error, nil); + STAssertNotNil(desc, nil); + NSAppleScript *script = [desc gtm_objectValue]; + STAssertTrue([script isKindOfClass:[NSAppleScript class]], nil); + + NSSet *properties = [script gtm_properties]; + NSSet *expected + = [NSSet setWithObjects: + @"testscriptproperty", + @"parenttestscriptproperty", + @"foo", + @"testscript", + @"parenttestscript", + @"asdscriptuniqueidentifier", + [GTMFourCharCode fourCharCodeWithFourCharCode:pVersion], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASPrintDepth], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASTopLevelScript], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASResult], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASMinutes], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASDays], + // No constant for linefeed in the 10.5 sdk + // Radar 6132775 Need a constant for the Applescript Property 'lnfd' + [GTMFourCharCode fourCharCodeWithFourCharCode:'lnfd'], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASPi], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASReturn], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASSpace], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASPrintLength], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASQuote], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASWeeks], + [GTMFourCharCode fourCharCodeWithFourCharCode:pTextItemDelimiters], + // Applescript properties should be pASSeconds, but + // on 10.5.4/10.5.5 it is actually using cSeconds. + // Radar 6132696 Applescript root level property is cSeconds + // instead of pASSeconds + [GTMFourCharCode fourCharCodeWithFourCharCode:cSeconds], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASHours], + [GTMFourCharCode fourCharCodeWithFourCharCode:pASTab], + nil]; + if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // Workaround for bug in SnowLeopard + // rdar://6289077 OSAGetPropertyNames returns names in camelcase instead + // of lowercase. + properties = [properties valueForKey:@"lowercaseString"]; + } + STAssertEqualObjects(properties, expected, @"Unexpected properties?"); + id value = [script gtm_valueForProperty:@"testScriptProperty"]; + STAssertEqualObjects(value, [NSNumber numberWithInt:5], @"bad property?"); + BOOL goodSet = [script gtm_setValue:@"bar" + forProperty:@"foo" + addingDefinition:NO]; + STAssertTrue(goodSet, @"Couldn't set property"); + + // Test local set + value = [script gtm_valueForProperty:@"foo"]; + STAssertEqualObjects(value, @"bar", @"bad property?"); + + // Test inherited set + value = [script_ gtm_valueForProperty:@"foo"]; + STAssertEqualObjects(value, @"bar", @"bad property?"); + + [GTMUnitTestDevLog expectPattern:@"Unable to setValue:bar forProperty:" + "\\(null\\) from \\(-50\\)"]; + goodSet = [script gtm_setValue:@"bar" + forProperty:nil + addingDefinition:NO]; + STAssertFalse(goodSet, @"Set property?"); + + [GTMUnitTestDevLog expectPattern:@"Unable to setValue:bar forProperty:3" + " from \\(-50\\)"]; + goodSet = [script gtm_setValue:@"bar" + forProperty:[NSNumber numberWithInt:3] + addingDefinition:YES]; + STAssertFalse(goodSet, @"Set property?"); + + + [GTMUnitTestDevLog expectPattern:@"Unable to get valueForProperty:gargle " + "from \\(-1753\\)"]; + value = [script gtm_valueForProperty:@"gargle"]; + STAssertNil(value, @"Property named gargle?"); + + goodSet = [script_ gtm_setValue:@"wow" + forProperty:@"addedProperty" + addingDefinition:YES]; + STAssertTrue(goodSet, @"Unable to addProperty"); + + value = [script gtm_valueForProperty:@"addedProperty"]; + STAssertNotNil(value, nil); + STAssertEqualObjects(value, @"wow", nil); + + // http://www.straightdope.com/classics/a3_341.html + NSNumber *newPI = [NSNumber numberWithInt:3]; + goodSet = [script gtm_setValue:newPI + forPropertyEnum:pASPi + addingDefinition:NO]; + STAssertTrue(goodSet, @"Unable to set property"); + value = [script_ gtm_valueForPropertyEnum:pASPi]; + STAssertNotNil(value, nil); + STAssertEqualObjects(value, newPI, @"bad property"); +} + +- (void)testFailures { + NSDictionary *error = nil; + NSAppleEventDescriptor *desc + = [script_ gtm_executePositionalHandler:@"noSuchTest" + parameters:nil + error:&error]; + STAssertNil(desc, nil); + STAssertNotNil(error, nil); + + // Test with empty handler name + error = nil; + desc = [script_ gtm_executePositionalHandler:@"" + parameters:[NSArray array] + error:&error]; + STAssertNil(desc, nil); + STAssertNotNil(error, nil); + + // Test with nil handler + error = nil; + desc = [script_ gtm_executePositionalHandler:nil + parameters:[NSArray array] + error:&error]; + STAssertNil(desc, nil); + STAssertNotNil(error, nil); + + // Test with nil handler and nil error + desc = [script_ gtm_executePositionalHandler:nil + parameters:nil + error:nil]; + STAssertNil(desc, nil); + + // Test with a bad script + NSAppleScript *script + = [[[NSAppleScript alloc] initWithSource:@"david hasselhoff"] autorelease]; + [GTMUnitTestDevLog expectPattern:@"Unable to compile script: .*"]; + [GTMUnitTestDevLog expectString:@"Unable to coerce script -2147450879"]; + NSSet *handlers = [script gtm_handlers]; + STAssertEquals([handlers count], (NSUInteger)0, @"Should have no handlers"); + [GTMUnitTestDevLog expectPattern:@"Unable to compile script: .*"]; + [GTMUnitTestDevLog expectString:@"Unable to coerce script -2147450879"]; + NSSet *properties = [script gtm_properties]; + STAssertEquals([properties count], + (NSUInteger)0, + @"Should have no properties"); + [GTMUnitTestDevLog expectPattern:@"Unable to compile script: .*"]; + [GTMUnitTestDevLog expectString:@"Unable to get script info about " + @"open handler -2147450879"]; + STAssertFalse([script gtm_hasOpenDocumentsHandler], + @"Has an opendoc handler?"); +} + +- (void)testScriptDescriptors { + NSAppleEventDescriptor *desc = [script_ gtm_appleEventDescriptor]; + STAssertNotNil(desc, @"Couldn't make a script desc"); + NSAppleScript *script = [desc gtm_objectValue]; + STAssertNotNil(script, @"Couldn't get a script back"); + NSSet *handlers = [script gtm_handlers]; + STAssertNotNil(handlers, @"Couldn't get handlers"); +} + +- (void)testOpenHandler { + STAssertFalse([script_ gtm_hasOpenDocumentsHandler], nil); + id script = [script_ gtm_valueForProperty:@"testscript"]; + STAssertNotNil(script, nil); + STAssertTrue([script gtm_hasOpenDocumentsHandler], nil); +} + + +@protocol ScriptInterface +- (id)test; +- (id)testReturnParam:(id)param; +- (id)testAddParams:(id)param1 :(id)param2; +@end + +- (void)testForwarding { + id foo = (id)script_; + [foo test]; + NSNumber *val = [foo testReturnParam:[NSNumber numberWithInt:2]]; + STAssertEquals([val intValue], 2, @"should be 2"); + val = [foo testAddParams:[NSNumber numberWithInt:2] + :[NSNumber numberWithInt:3]]; + STAssertEquals([val intValue], 5, @"should be 5"); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.h new file mode 100644 index 00000000..8140f804 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.h @@ -0,0 +1,47 @@ +// +// GTMNSArray+Merge.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// Extension to NSArray to allow merging of arrays. +// +@interface NSArray (GTMNSArrayMergingAdditions) + +// Merge our array with |newArray| by sorting each array then merging the +// two arrays. If |merger| is provided then call that method on any old +// items that compare as equal to a new item, passing the new item as +// the only argument. If |merger| is not provided, then insert new items +// in front of matching old items. If neither array has any items then +// nil is returned. +// +// The signature of the |merger| is: +// - (id)merge:(id)newItem; +// +// Returns a new, sorted array. +- (NSArray *)gtm_mergeArray:(NSArray *)newArray + mergeSelector:(SEL)merger; + +// Same as above, only |comparer| is used to sort/compare the objects, just like +// -[NSArray sortedArrayUsingSelector]. If |comparer| is nil, nil is returned. +- (NSArray *)gtm_mergeArray:(NSArray *)newArray + compareSelector:(SEL)comparer + mergeSelector:(SEL)merger; + +@end + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.m new file mode 100644 index 00000000..5bf07c8f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.m @@ -0,0 +1,111 @@ +// +// GTMNSArray+Merge.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// + +#import "GTMNSArray+Merge.h" + +#import "GTMDefines.h" + +#if GTM_IPHONE_SDK +#import +#else // GTM_IPHONE_SDK +#import +#endif // GTM_IPHONE_SDK + +@implementation NSArray (GTMNSArrayMergingAdditions) + +- (NSArray *)gtm_mergeArray:(NSArray *)newArray + mergeSelector:(SEL)merger { + return [self gtm_mergeArray:newArray + compareSelector:@selector(compare:) + mergeSelector:merger]; +} + +- (NSArray *)gtm_mergeArray:(NSArray *)newArray + compareSelector:(SEL)comparer + mergeSelector:(SEL)merger { + // must have a compare selector + if (!comparer) return nil; + + // Sort and merge the contents of |self| with |newArray|. + NSArray *sortedMergedArray = nil; + if ([self count] && [newArray count]) { + NSMutableArray *mergingArray = [NSMutableArray arrayWithArray:self]; + [mergingArray sortUsingSelector:comparer]; + NSArray *sortedNewArray + = [newArray sortedArrayUsingSelector:comparer]; + + NSUInteger oldIndex = 0; + NSUInteger oldCount = [mergingArray count]; + id oldItem = (oldIndex < oldCount) + ? [mergingArray objectAtIndex:0] + : nil; + + id newItem = nil; + GTM_FOREACH_OBJECT(newItem, sortedNewArray) { + BOOL stillLooking = YES; + while (oldIndex < oldCount && stillLooking) { + // We must take care here, since Intel leaves junk in high bytes of + // return register for predicates that return BOOL. + // For details see: + // http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html + // and + // http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187 + NSComparisonResult result + = ((NSComparisonResult (*)(id, SEL, id))objc_msgSend)(newItem, comparer, oldItem); + if (result == NSOrderedSame && merger) { + // It's a match! + id repItem = [oldItem performSelector:merger + withObject:newItem]; + [mergingArray replaceObjectAtIndex:oldIndex + withObject:repItem]; + ++oldIndex; + oldItem = (oldIndex < oldCount) + ? [mergingArray objectAtIndex:oldIndex] + : nil; + stillLooking = NO; + } else if (result == NSOrderedAscending + || (result == NSOrderedSame && !merger)) { + // This is either a new item and belongs right here, or it's + // a match to an existing item but we're not merging. + [mergingArray insertObject:newItem + atIndex:oldIndex]; + ++oldIndex; + ++oldCount; + stillLooking = NO; + } else { + ++oldIndex; + oldItem = (oldIndex < oldCount) + ? [mergingArray objectAtIndex:oldIndex] + : nil; + } + } + if (stillLooking) { + // Once we get here, the rest of the new items get appended. + [mergingArray addObject:newItem]; + } + } + sortedMergedArray = mergingArray; + } else if ([self count]) { + sortedMergedArray = [self sortedArrayUsingSelector:comparer]; + } else if ([newArray count]) { + sortedMergedArray = [newArray sortedArrayUsingSelector:comparer]; + } + return sortedMergedArray; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+MergeTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+MergeTest.m new file mode 100644 index 00000000..0d8eb81f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSArray+MergeTest.m @@ -0,0 +1,219 @@ +// +// GTMNSArray+MergeTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSArray+Merge.h" + +@interface GTMNSArray_MergeTest : GTMTestCase +@end + + +@interface NSString (GTMStringMergingTestAdditions) + +- (NSString *)mergeString:(NSString *)stringB; + +@end + + +@implementation GTMNSArray_MergeTest + +- (void)testMergingTwoEmptyArrays { + NSArray *emptyArrayA = [NSArray array]; + NSArray *emptyArrayB = [NSArray array]; + NSArray *mergedArray = [emptyArrayA gtm_mergeArray:emptyArrayB + mergeSelector:nil]; + STAssertNil(mergedArray, + @"merge of two empty arrays with no merger should render nil"); +} + +- (void)testMergingTwoEmptyArraysWithMerger { + NSArray *emptyArrayA = [NSArray array]; + NSArray *emptyArrayB = [NSArray array]; + NSArray *mergedArray + = [emptyArrayA gtm_mergeArray:emptyArrayB + mergeSelector:@selector(mergeString:)]; + STAssertNil(mergedArray, + @"merge of two empty arrays with merger should render nil"); +} + +- (void)testMergingEmptyWithNilArray { + NSArray *emptyArrayA = [NSArray array]; + NSArray *nilArrayB = nil; + NSArray *mergedArray = [emptyArrayA gtm_mergeArray:nilArrayB + mergeSelector:nil]; + STAssertNil(mergedArray, + @"merge of empty with nil array with no merger should render nil"); +} + +- (void)testMergingEmptyWithNilArrayWithMerger { + NSArray *emptyArrayA = [NSArray array]; + NSArray *nilArrayB = nil; + NSArray *mergedArray + = [emptyArrayA gtm_mergeArray:nilArrayB + mergeSelector:@selector(mergeObject:)]; + STAssertNil(mergedArray, + @"merge of empty with nil array with merger should render nil"); +} + +- (void)testMergingTwoOneItemArraysThatDontMatch { + NSArray *arrayA = [NSArray arrayWithObject:@"abc.def"]; + NSArray *arrayB = [NSArray arrayWithObject:@"abc.ghi"]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:nil]; + STAssertNotNil(mergedArray, + @"merge of two non empty arrays with no merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)2, + @"merged array should have two items"); + STAssertEqualObjects([mergedArray objectAtIndex:0], @"abc.def", nil); + STAssertEqualObjects([mergedArray objectAtIndex:1], @"abc.ghi", nil); +} + +- (void)testMergingTwoOneItemArraysThatDontMatchWithMerger { + NSArray *arrayA = [NSArray arrayWithObject:@"abc.def"]; + NSArray *arrayB = [NSArray arrayWithObject:@"abc.ghi"]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:@selector(mergeString:)]; + STAssertNotNil(mergedArray, + @"merge of two non empty arrays with merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)2, + @"merged array should have two items"); + STAssertEqualObjects([mergedArray objectAtIndex:0], @"abc.def", nil); + STAssertEqualObjects([mergedArray objectAtIndex:1], @"abc.ghi", nil); +} + +- (void)testMergingTwoOneItemArraysThatMatch { + NSArray *arrayA = [NSArray arrayWithObject:@"abc.def"]; + NSArray *arrayB = [NSArray arrayWithObject:@"abc.def"]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:nil]; + STAssertNotNil(mergedArray, + @"merge of two matching arrays with no merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)2, + @"merged array with no merger should have two items"); + STAssertEqualObjects([mergedArray objectAtIndex:0], @"abc.def", nil); + STAssertEqualObjects([mergedArray objectAtIndex:1], @"abc.def", nil); +} + +- (void)testMergingTwoOneItemArraysThatMatchWithMerger { + NSArray *arrayA = [NSArray arrayWithObject:@"abc.def"]; + NSArray *arrayB = [NSArray arrayWithObject:@"abc.def"]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:@selector(mergeString:)]; + STAssertNotNil(mergedArray, + @"merge of two matching arrays with merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)1, + @"merged array with merger should have one items"); + STAssertEqualObjects([mergedArray objectAtIndex:0], @"abc.def", nil); +} + +- (void)testMergingMultipleItemArray { + NSArray *arrayA = [NSArray arrayWithObjects: + @"Kansas", + @"Arkansas", + @"Wisconson", + @"South Carolina", + nil]; + NSArray *arrayB = [NSArray arrayWithObjects: + @"South Carolina", + @"Quebec", + @"British Columbia", + @"Arkansas", + @"South Hamptom", + nil]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:nil]; + STAssertNotNil(mergedArray, + @"merge of two non empty arrays with no merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)9, + @"merged array should have 9 items"); +} + +- (void)testMergingMultipleItemArrayWithMerger { + NSArray *arrayA = [NSArray arrayWithObjects: + @"Kansas", + @"Arkansas", + @"Wisconson", + @"South Carolina", + nil]; + NSArray *arrayB = [NSArray arrayWithObjects: + @"South Carolina", + @"Quebec", + @"British Columbia", + @"Arkansas", + @"South Hamptom", + nil]; + NSArray *mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:@selector(mergeString:)]; + STAssertNotNil(mergedArray, + @"merge of two non empty arrays with merger should render " + @"an array"); + STAssertEquals([mergedArray count], (NSUInteger)7, + @"merged array should have 7 items"); +} + +- (void)testMergeWithEmptyArrays { + NSArray *arrayA = [NSArray arrayWithObjects:@"xyz", @"abc", @"mno", nil]; + NSArray *arrayB = [NSArray array]; + NSArray *expected = [NSArray arrayWithObjects:@"abc", @"mno", @"xyz", nil]; + STAssertNotNil(arrayA, nil); + STAssertNotNil(arrayB, nil); + STAssertNotNil(expected, nil); + NSArray *mergedArray; + + // no merger + mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:nil]; + STAssertNotNil(mergedArray, nil); + STAssertEqualObjects(mergedArray, expected, nil); + + // w/ merger + mergedArray = [arrayA gtm_mergeArray:arrayB + mergeSelector:@selector(mergeString:)]; + STAssertNotNil(mergedArray, nil); + STAssertEqualObjects(mergedArray, expected, nil); + + // no merger and array args reversed + mergedArray = [arrayB gtm_mergeArray:arrayA + mergeSelector:nil]; + STAssertNotNil(mergedArray, nil); + STAssertEqualObjects(mergedArray, expected, nil); + + // w/ merger and array args reversed + mergedArray = [arrayB gtm_mergeArray:arrayA + mergeSelector:@selector(mergeString:)]; + STAssertNotNil(mergedArray, nil); + STAssertEqualObjects(mergedArray, expected, nil); + +} + +@end + + +@implementation NSString (GTMStringMergingTestAdditions) + +- (NSString *)mergeString:(NSString *)stringB { + return stringB; +} + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.h new file mode 100644 index 00000000..df31d24c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.h @@ -0,0 +1,84 @@ +// +// GTMNSData+zlib.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +/// Helpers for dealing w/ zlib inflate/deflate calls. +@interface NSData (GTMZLibAdditions) + +/// Return an autoreleased NSData w/ the result of gzipping the bytes. +// +// Uses the default compression level. ++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes + length:(NSUInteger)length; + +/// Return an autoreleased NSData w/ the result of gzipping the payload of |data|. +// +// Uses the default compression level. ++ (NSData *)gtm_dataByGzippingData:(NSData *)data; + +/// Return an autoreleased NSData w/ the result of gzipping the bytes using |level| compression level. +// +// |level| can be 1-9, any other values will be clipped to that range. ++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level; + +/// Return an autoreleased NSData w/ the result of gzipping the payload of |data| using |level| compression level. ++ (NSData *)gtm_dataByGzippingData:(NSData *)data + compressionLevel:(int)level; + +// NOTE: deflate is *NOT* gzip. deflate is a "zlib" stream. pick which one +// you really want to create. (the inflate api will handle either) + +/// Return an autoreleased NSData w/ the result of deflating the bytes. +// +// Uses the default compression level. ++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes + length:(NSUInteger)length; + +/// Return an autoreleased NSData w/ the result of deflating the payload of |data|. +// +// Uses the default compression level. ++ (NSData *)gtm_dataByDeflatingData:(NSData *)data; + +/// Return an autoreleased NSData w/ the result of deflating the bytes using |level| compression level. +// +// |level| can be 1-9, any other values will be clipped to that range. ++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level; + +/// Return an autoreleased NSData w/ the result of deflating the payload of |data| using |level| compression level. ++ (NSData *)gtm_dataByDeflatingData:(NSData *)data + compressionLevel:(int)level; + + +/// Return an autoreleased NSData w/ the result of decompressing the bytes. +// +// The bytes to decompress can be zlib or gzip payloads. ++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes + length:(NSUInteger)length; + +/// Return an autoreleased NSData w/ the result of decompressing the payload of |data|. +// +// The data to decompress can be zlib or gzip payloads. ++ (NSData *)gtm_dataByInflatingData:(NSData *)data; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.m new file mode 100644 index 00000000..8ba1ddca --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlib.m @@ -0,0 +1,267 @@ +// +// GTMNSData+zlib.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSData+zlib.h" +#import +#import "GTMDefines.h" + +#define kChunkSize 1024 + +@interface NSData (GTMZlibAdditionsPrivate) ++ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level + useGzip:(BOOL)useGzip; +@end + +@implementation NSData (GTMZlibAdditionsPrivate) ++ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level + useGzip:(BOOL)useGzip { + if (!bytes || !length) { + return nil; + } + + // TODO: support 64bit inputs + // avail_in is a uInt, so if length > UINT_MAX we actually need to loop + // feeding the data until we've gotten it all in. not supporting this + // at the moment. + _GTMDevAssert(length <= UINT_MAX, @"Currently don't support >32bit lengths"); + + if (level == Z_DEFAULT_COMPRESSION) { + // the default value is actually outside the range, so we have to let it + // through specifically. + } else if (level < Z_BEST_SPEED) { + level = Z_BEST_SPEED; + } else if (level > Z_BEST_COMPRESSION) { + level = Z_BEST_COMPRESSION; + } + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int windowBits = 15; // the default + int memLevel = 8; // the default + if (useGzip) { + windowBits += 16; // enable gzip header instead of zlib header + } + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, + memLevel, Z_DEFAULT_STRATEGY)) != Z_OK) { + // COV_NF_START - no real way to force this in a unittest (we guard all args) + _GTMDevLog(@"Failed to init for deflate w/ level %d, error %d", + level, retCode); + return nil; + // COV_NF_END + } + + // hint the size at 1/4 the input size + NSMutableData *result = [NSMutableData dataWithCapacity:(length/4)]; + unsigned char output[kChunkSize]; + + // setup the input + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char*)bytes; + + // loop to collect the data + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + // COV_NF_START - no real way to force this in a unittest + // (in inflate, we can feed bogus/truncated data to test, but an error + // here would be some internal issue w/in zlib, and there isn't any real + // way to test it) + _GTMDevLog(@"Error trying to deflate some of the payload, error %d", + retCode); + deflateEnd(&strm); + return nil; + // COV_NF_END + } + // collect what we got + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // if the loop exits, we used all input and the stream ended + _GTMDevAssert(strm.avail_in == 0, + @"thought we finished deflate w/o using all input, %u bytes left", + strm.avail_in); + _GTMDevAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", + retCode); + + // clean up + deflateEnd(&strm); + + return result; +} // gtm_dataByCompressingBytes:length:compressionLevel:useGzip: + + +@end + + +@implementation NSData (GTMZLibAdditions) + ++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes + length:(NSUInteger)length { + return [self gtm_dataByCompressingBytes:bytes + length:length + compressionLevel:Z_DEFAULT_COMPRESSION + useGzip:YES]; +} // gtm_dataByGzippingBytes:length: + ++ (NSData *)gtm_dataByGzippingData:(NSData *)data { + return [self gtm_dataByCompressingBytes:[data bytes] + length:[data length] + compressionLevel:Z_DEFAULT_COMPRESSION + useGzip:YES]; +} // gtm_dataByGzippingData: + ++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level { + return [self gtm_dataByCompressingBytes:bytes + length:length + compressionLevel:level + useGzip:YES]; +} // gtm_dataByGzippingBytes:length:level: + ++ (NSData *)gtm_dataByGzippingData:(NSData *)data + compressionLevel:(int)level { + return [self gtm_dataByCompressingBytes:[data bytes] + length:[data length] + compressionLevel:level + useGzip:YES]; +} // gtm_dataByGzippingData:level: + ++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes + length:(NSUInteger)length { + return [self gtm_dataByCompressingBytes:bytes + length:length + compressionLevel:Z_DEFAULT_COMPRESSION + useGzip:NO]; +} // gtm_dataByDeflatingBytes:length: + ++ (NSData *)gtm_dataByDeflatingData:(NSData *)data { + return [self gtm_dataByCompressingBytes:[data bytes] + length:[data length] + compressionLevel:Z_DEFAULT_COMPRESSION + useGzip:NO]; +} // gtm_dataByDeflatingData: + ++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes + length:(NSUInteger)length + compressionLevel:(int)level { + return [self gtm_dataByCompressingBytes:bytes + length:length + compressionLevel:level + useGzip:NO]; +} // gtm_dataByDeflatingBytes:length:level: + ++ (NSData *)gtm_dataByDeflatingData:(NSData *)data + compressionLevel:(int)level { + return [self gtm_dataByCompressingBytes:[data bytes] + length:[data length] + compressionLevel:level + useGzip:NO]; +} // gtm_dataByDeflatingData:level: + ++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes + length:(NSUInteger)length { + if (!bytes || !length) { + return nil; + } + + // TODO: support 64bit inputs + // avail_in is a uInt, so if length > UINT_MAX we actually need to loop + // feeding the data until we've gotten it all in. not supporting this + // at the moment. + _GTMDevAssert(length <= UINT_MAX, @"Currently don't support >32bit lengths"); + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // setup the input + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char*)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + // COV_NF_START - no real way to force this in a unittest (we guard all args) + _GTMDevLog(@"Failed to init for inflate, error %d", retCode); + return nil; + // COV_NF_END + } + + // hint the size at 4x the input size + NSMutableData *result = [NSMutableData dataWithCapacity:(length*4)]; + unsigned char output[kChunkSize]; + + // loop to collect the data + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + _GTMDevLog(@"Error trying to inflate some of the payload, error %d", + retCode); + inflateEnd(&strm); + return nil; + } + // collect what we got + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // make sure there wasn't more data tacked onto the end of a valid compressed + // stream. + if (strm.avail_in != 0) { + _GTMDevLog(@"thought we finished inflate w/o using all input, %u bytes left", + strm.avail_in); + result = nil; + } + // the only way out of the loop was by hitting the end of the stream + _GTMDevAssert(retCode == Z_STREAM_END, + @"thought we finished inflate w/o getting a result of stream end, code %d", + retCode); + + // clean up + inflateEnd(&strm); + + return result; +} // gtm_dataByInflatingBytes:length: + ++ (NSData *)gtm_dataByInflatingData:(NSData *)data { + return [self gtm_dataByInflatingBytes:[data bytes] + length:[data length]]; +} // gtm_dataByInflatingData: + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlibTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlibTest.m new file mode 100644 index 00000000..0d868864 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSData+zlibTest.m @@ -0,0 +1,360 @@ +// +// GTMNSData+zlibTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMUnitTestDevLog.h" +#import "GTMNSData+zlib.h" +#import // for randiom/srandomdev +#import + +@interface GTMNSData_zlibTest : GTMTestCase +@end + +// NOTE: we don't need to test the actually compressor/inflation (we're using +// zlib, it works), we just need to test our wrapper. So we can use canned +// data, etc. (and yes, when using random data, things once failed because +// we generated a random block of data that was valid compressed data?!) + +static unsigned char randomDataLarge[] = { + // openssl rand -rand /dev/random 512 | xxd -i + 0xe1, 0xa6, 0xe2, 0xa2, 0x0b, 0xf7, 0x8d, 0x6b, 0x31, 0xfe, 0xaa, 0x64, + 0x50, 0xbe, 0x52, 0x7e, 0x83, 0x74, 0x00, 0x8f, 0x62, 0x96, 0xc7, 0xe9, + 0x20, 0x59, 0x78, 0xc6, 0xea, 0x10, 0xd5, 0xdb, 0x3f, 0x6b, 0x13, 0xd9, + 0x44, 0x18, 0x24, 0x17, 0x63, 0xc8, 0x74, 0xa5, 0x37, 0x6c, 0x9c, 0x00, + 0xe5, 0xcf, 0x0a, 0xdf, 0xb9, 0x66, 0xb1, 0xbd, 0x04, 0x8f, 0x55, 0x9e, + 0xb0, 0x24, 0x4e, 0xf0, 0xc4, 0x69, 0x2c, 0x1f, 0x63, 0x9f, 0x41, 0xa8, + 0x89, 0x9b, 0x98, 0x00, 0xb6, 0x78, 0xf7, 0xe4, 0x4c, 0x72, 0x14, 0x84, + 0xaa, 0x3d, 0xc1, 0x42, 0x9f, 0x12, 0x85, 0xdd, 0x16, 0x8b, 0x8f, 0x67, + 0xe0, 0x26, 0x5b, 0x5e, 0xaa, 0xe7, 0xd3, 0x67, 0xfe, 0x21, 0x77, 0xa6, + 0x52, 0xde, 0x33, 0x8b, 0x96, 0x49, 0x6a, 0xd6, 0x58, 0x58, 0x36, 0x00, + 0x23, 0xd2, 0x45, 0x13, 0x9f, 0xd9, 0xc7, 0x2d, 0x55, 0x12, 0xb4, 0xfe, + 0x53, 0x27, 0x1f, 0x14, 0x71, 0x9b, 0x7e, 0xcc, 0x5e, 0x8c, 0x59, 0xef, + 0x80, 0xac, 0x89, 0xf4, 0x45, 0x8d, 0x98, 0x6d, 0x97, 0xfd, 0x53, 0x5f, + 0x19, 0xd6, 0x11, 0xf7, 0xcb, 0x5d, 0xca, 0xab, 0xe1, 0x01, 0xf1, 0xe9, + 0x1f, 0x1f, 0xf3, 0x53, 0x76, 0xa2, 0x59, 0x8e, 0xb3, 0x91, 0xff, 0xe8, + 0x1b, 0xc0, 0xc0, 0xda, 0xdd, 0x93, 0xb5, 0x9d, 0x62, 0x13, 0xb8, 0x07, + 0xf2, 0xf5, 0xb9, 0x4b, 0xe1, 0x09, 0xed, 0xdb, 0xe6, 0xd9, 0x2d, 0xc4, + 0x0d, 0xb6, 0xbd, 0xfc, 0xdb, 0x5c, 0xcc, 0xf6, 0x53, 0x4e, 0x01, 0xa4, + 0x03, 0x95, 0x4a, 0xa4, 0xaa, 0x4f, 0x45, 0xaf, 0xbf, 0xf1, 0x7e, 0x60, + 0x1d, 0x86, 0x93, 0x65, 0x7b, 0x24, 0x0c, 0x09, 0xe0, 0xd1, 0xd8, 0x60, + 0xd9, 0xd9, 0x55, 0x2a, 0xec, 0xd5, 0xdc, 0xd0, 0xc6, 0x5e, 0x2c, 0x22, + 0xf5, 0x19, 0x0b, 0xc3, 0xa1, 0x38, 0x11, 0x67, 0x6f, 0x6c, 0x0e, 0x34, + 0x44, 0x83, 0xee, 0xd3, 0xf2, 0x4b, 0x7b, 0x03, 0x68, 0xfe, 0xc5, 0x76, + 0xb2, 0x2e, 0x26, 0xeb, 0x1f, 0x66, 0x02, 0xa4, 0xd9, 0xda, 0x28, 0x3a, + 0xc3, 0x94, 0x03, 0xe8, 0x29, 0x7e, 0xfe, 0x3d, 0xc8, 0xc1, 0x0a, 0x74, + 0xc7, 0xaf, 0xa6, 0x84, 0x86, 0x85, 0xc3, 0x8c, 0x00, 0x38, 0xd4, 0xb5, + 0xb2, 0xe0, 0xf0, 0xc4, 0x8d, 0x10, 0x0d, 0xf1, 0xcd, 0x05, 0xdb, 0xd0, + 0xcf, 0x17, 0x4f, 0xa8, 0xe5, 0xf0, 0x53, 0x55, 0x62, 0xc7, 0x55, 0xe5, + 0xbe, 0x18, 0x2f, 0xda, 0x48, 0xf1, 0xaa, 0x85, 0x46, 0x80, 0x15, 0x70, + 0x82, 0xd2, 0xa6, 0xb0, 0x3d, 0x31, 0xb5, 0xcc, 0x23, 0x95, 0x5e, 0x15, + 0x35, 0x32, 0xd0, 0x86, 0xd1, 0x6e, 0x2d, 0xc0, 0xfe, 0x45, 0xae, 0x28, + 0x24, 0xa7, 0x14, 0xf4, 0xe9, 0xb5, 0x6f, 0xac, 0x25, 0xf9, 0x88, 0xf6, + 0x60, 0x5d, 0x6b, 0x5c, 0xf2, 0x38, 0xe8, 0xdc, 0xbd, 0xa6, 0x13, 0xc0, + 0xa4, 0xc8, 0xe9, 0x7a, 0xc6, 0xb6, 0x88, 0x26, 0x98, 0x9f, 0xe3, 0x9a, + 0xd9, 0x5b, 0xd4, 0xd0, 0x02, 0x1f, 0x55, 0x30, 0xbe, 0xde, 0x9c, 0xd1, + 0x53, 0x93, 0x72, 0xe6, 0x19, 0x79, 0xe9, 0xf1, 0x70, 0x78, 0x92, 0x31, + 0xf6, 0x17, 0xc0, 0xdd, 0x99, 0xc8, 0x97, 0x67, 0xdc, 0xf6, 0x67, 0x6b, + 0x9b, 0x1c, 0x90, 0xea, 0x1a, 0x9e, 0x26, 0x68, 0xc2, 0x13, 0x94, 0x3a, + 0x3e, 0x73, 0x61, 0x4e, 0x37, 0xa8, 0xa1, 0xfa, 0xf8, 0x22, 0xdd, 0x20, + 0x40, 0xc6, 0x52, 0x27, 0x47, 0x1a, 0x79, 0xfa, 0x40, 0xa6, 0x62, 0x6b, + 0xe6, 0xc7, 0x67, 0xb7, 0xa8, 0x2d, 0xd1, 0x9f, 0x17, 0xb8, 0x77, 0x5e, + 0x97, 0x1e, 0x92, 0xd7, 0xd2, 0x25, 0x04, 0x92, 0xf9, 0x41, 0x70, 0x93, + 0xe1, 0x13, 0x07, 0x94, 0x8e, 0x0b, 0x82, 0x98 +}; + +static unsigned char randomDataSmall[] = { + // openssl rand -rand /dev/random 24 | xxd -i + 0xd1, 0xec, 0x35, 0xc3, 0xa0, 0x4c, 0x73, 0x37, 0x2f, 0x5a, 0x12, 0x44, + 0xee, 0xe4, 0x22, 0x07, 0x29, 0xa8, 0x4a, 0xde, 0xc8, 0xbb, 0xe7, 0xdb +}; + + +static BOOL HasGzipHeader(NSData *data) { + // very simple check + const unsigned char *bytes = [data bytes]; + return ([data length] > 2) && + ((bytes[0] == 0x1f) && (bytes[1] == 0x8b)); +} + + +@implementation GTMNSData_zlibTest + +- (void)testBoundryValues { + // build some test data + NSData *data = [NSData dataWithBytes:randomDataLarge + length:sizeof(randomDataLarge)]; + STAssertNotNil(data, @"failed to alloc data block"); + + // bogus args to start + STAssertNil([NSData gtm_dataByDeflatingData:nil], nil); + STAssertNil([NSData gtm_dataByDeflatingBytes:nil length:666], nil); + STAssertNil([NSData gtm_dataByDeflatingBytes:[data bytes] length:0], nil); + STAssertNil([NSData gtm_dataByGzippingData:nil], nil); + STAssertNil([NSData gtm_dataByGzippingBytes:nil length:666], nil); + STAssertNil([NSData gtm_dataByGzippingBytes:[data bytes] length:0], nil); + STAssertNil([NSData gtm_dataByInflatingData:nil], nil); + STAssertNil([NSData gtm_dataByInflatingBytes:nil length:666], nil); + STAssertNil([NSData gtm_dataByInflatingBytes:[data bytes] length:0], nil); + + // test deflate w/ compression levels out of range + NSData *deflated = [NSData gtm_dataByDeflatingData:data + compressionLevel:-4]; + STAssertNotNil(deflated, nil); + STAssertFalse(HasGzipHeader(deflated), nil); + NSData *dataPrime = [NSData gtm_dataByInflatingData:deflated]; + STAssertNotNil(dataPrime, nil); + STAssertEqualObjects(data, dataPrime, nil); + deflated = [NSData gtm_dataByDeflatingData:data + compressionLevel:20]; + STAssertNotNil(deflated, nil); + STAssertFalse(HasGzipHeader(deflated), nil); + dataPrime = [NSData gtm_dataByInflatingData:deflated]; + STAssertNotNil(dataPrime, nil); + STAssertEqualObjects(data, dataPrime, nil); + + // test gzip w/ compression levels out of range + NSData *gzipped = [NSData gtm_dataByGzippingData:data + compressionLevel:-4]; + STAssertNotNil(gzipped, nil); + STAssertTrue(HasGzipHeader(gzipped), nil); + dataPrime = [NSData gtm_dataByInflatingData:gzipped]; + STAssertNotNil(dataPrime, nil); + STAssertEqualObjects(data, dataPrime, nil); + gzipped = [NSData gtm_dataByGzippingData:data + compressionLevel:20]; + STAssertNotNil(gzipped, nil); + STAssertTrue(HasGzipHeader(gzipped), nil); + dataPrime = [NSData gtm_dataByInflatingData:gzipped]; + STAssertNotNil(dataPrime, nil); + STAssertEqualObjects(data, dataPrime, nil); + + // test non-compressed data data itself + [GTMUnitTestDevLog expectString:@"Error trying to inflate some of the " + "payload, error -3"]; + STAssertNil([NSData gtm_dataByInflatingData:data], nil); + + // test deflated data runs that end before they are done + [GTMUnitTestDevLog expect:([deflated length] / 11) + 1 + casesOfString:@"Error trying to inflate some of the payload, " + "error -5"]; + for (NSUInteger x = 1 ; x < [deflated length] ; x += 11) { + STAssertNil([NSData gtm_dataByInflatingBytes:[deflated bytes] + length:x], nil); + } + + // test gzipped data runs that end before they are done + [GTMUnitTestDevLog expect:([gzipped length] / 11) + 1 + casesOfString:@"Error trying to inflate some of the payload, " + "error -5"]; + for (NSUInteger x = 1 ; x < [gzipped length] ; x += 11) { + STAssertNil([NSData gtm_dataByInflatingBytes:[gzipped bytes] + length:x], nil); + } + + // test extra data before the deflated/gzipped data (just to make sure we + // don't seek to the "real" data) + NSMutableData *prefixedDeflated = + [NSMutableData dataWithBytes:randomDataSmall length:sizeof(randomDataSmall)]; + STAssertNotNil(prefixedDeflated, @"failed to alloc data block"); + [prefixedDeflated appendData:deflated]; + [GTMUnitTestDevLog expectString:@"Error trying to inflate some of the " + "payload, error -3"]; + STAssertNil([NSData gtm_dataByInflatingData:prefixedDeflated], nil); + [GTMUnitTestDevLog expectString:@"Error trying to inflate some of the " + "payload, error -3"]; + STAssertNil([NSData gtm_dataByInflatingBytes:[prefixedDeflated bytes] + length:[prefixedDeflated length]], + nil); + NSMutableData *prefixedGzipped = + [NSMutableData dataWithBytes:randomDataSmall length:sizeof(randomDataSmall)]; + STAssertNotNil(prefixedDeflated, @"failed to alloc data block"); + [prefixedGzipped appendData:gzipped]; + [GTMUnitTestDevLog expectString:@"Error trying to inflate some of the " + "payload, error -3"]; + STAssertNil([NSData gtm_dataByInflatingData:prefixedGzipped], nil); + [GTMUnitTestDevLog expectString:@"Error trying to inflate some of the " + "payload, error -3"]; + STAssertNil([NSData gtm_dataByInflatingBytes:[prefixedGzipped bytes] + length:[prefixedGzipped length]], + nil); + + // test extra data after the deflated/gzipped data (just to make sure we + // don't ignore some of the data) + NSMutableData *suffixedDeflated = [NSMutableData data]; + STAssertNotNil(suffixedDeflated, @"failed to alloc data block"); + [suffixedDeflated appendData:deflated]; + [suffixedDeflated appendBytes:[data bytes] length:20]; + [GTMUnitTestDevLog expectString:@"thought we finished inflate w/o using " + "all input, 20 bytes left"]; + STAssertNil([NSData gtm_dataByInflatingData:suffixedDeflated], nil); + [GTMUnitTestDevLog expectString:@"thought we finished inflate w/o using " + "all input, 20 bytes left"]; + STAssertNil([NSData gtm_dataByInflatingBytes:[suffixedDeflated bytes] + length:[suffixedDeflated length]], + nil); + NSMutableData *suffixedGZipped = [NSMutableData data]; + STAssertNotNil(suffixedGZipped, @"failed to alloc data block"); + [suffixedGZipped appendData:gzipped]; + [suffixedGZipped appendBytes:[data bytes] length:20]; + [GTMUnitTestDevLog expectString:@"thought we finished inflate w/o using " + "all input, 20 bytes left"]; + STAssertNil([NSData gtm_dataByInflatingData:suffixedGZipped], nil); + [GTMUnitTestDevLog expectString:@"thought we finished inflate w/o using " + "all input, 20 bytes left"]; + STAssertNil([NSData gtm_dataByInflatingBytes:[suffixedGZipped bytes] + length:[suffixedGZipped length]], + nil); +} + +- (void)testInflateDeflate { + NSData *data = [NSData dataWithBytes:randomDataLarge + length:sizeof(randomDataLarge)]; + STAssertNotNil(data, @"failed to alloc data block"); + + // w/ *Bytes apis, default level + NSData *deflated = [NSData gtm_dataByDeflatingBytes:[data bytes] + length:[data length]]; + STAssertNotNil(deflated, @"failed to deflate data block"); + STAssertGreaterThan([deflated length], + (NSUInteger)0, @"failed to deflate data block"); + STAssertFalse(HasGzipHeader(deflated), @"has gzip header on zlib data"); + NSData *dataPrime = [NSData gtm_dataByInflatingBytes:[deflated bytes] + length:[deflated length]]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Bytes apis"); + + // w/ *Data apis, default level + deflated = [NSData gtm_dataByDeflatingData:data]; + STAssertNotNil(deflated, @"failed to deflate data block"); + STAssertGreaterThan([deflated length], + (NSUInteger)0, @"failed to deflate data block"); + STAssertFalse(HasGzipHeader(deflated), @"has gzip header on zlib data"); + dataPrime = [NSData gtm_dataByInflatingData:deflated]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Data apis"); + + // loop over the compression levels + for (int level = 1 ; level < 9 ; ++level) { + // w/ *Bytes apis, using our level + deflated = [NSData gtm_dataByDeflatingBytes:[data bytes] + length:[data length] + compressionLevel:level]; + STAssertNotNil(deflated, @"failed to deflate data block"); + STAssertGreaterThan([deflated length], + (NSUInteger)0, @"failed to deflate data block"); + STAssertFalse(HasGzipHeader(deflated), @"has gzip header on zlib data"); + dataPrime = [NSData gtm_dataByInflatingBytes:[deflated bytes] + length:[deflated length]]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Bytes apis"); + + // w/ *Data apis, using our level + deflated = [NSData gtm_dataByDeflatingData:data compressionLevel:level]; + STAssertNotNil(deflated, @"failed to deflate data block"); + STAssertGreaterThan([deflated length], + (NSUInteger)0, @"failed to deflate data block"); + STAssertFalse(HasGzipHeader(deflated), @"has gzip header on zlib data"); + dataPrime = [NSData gtm_dataByInflatingData:deflated]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Data apis"); + } +} + +- (void)testInflateGzip { + NSData *data = [NSData dataWithBytes:randomDataLarge + length:sizeof(randomDataLarge)]; + STAssertNotNil(data, @"failed to alloc data block"); + + // w/ *Bytes apis, default level + NSData *gzipped = [NSData gtm_dataByGzippingBytes:[data bytes] + length:[data length]]; + STAssertNotNil(gzipped, @"failed to gzip data block"); + STAssertGreaterThan([gzipped length], + (NSUInteger)0, @"failed to gzip data block"); + STAssertTrue(HasGzipHeader(gzipped), + @"doesn't have gzip header on gzipped data"); + NSData *dataPrime = [NSData gtm_dataByInflatingBytes:[gzipped bytes] + length:[gzipped length]]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Bytes apis"); + + // w/ *Data apis, default level + gzipped = [NSData gtm_dataByGzippingData:data]; + STAssertNotNil(gzipped, @"failed to gzip data block"); + STAssertGreaterThan([gzipped length], + (NSUInteger)0, @"failed to gzip data block"); + STAssertTrue(HasGzipHeader(gzipped), + @"doesn't have gzip header on gzipped data"); + dataPrime = [NSData gtm_dataByInflatingData:gzipped]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Data apis"); + + // loop over the compression levels + for (int level = 1 ; level < 9 ; ++level) { + // w/ *Bytes apis, using our level + gzipped = [NSData gtm_dataByGzippingBytes:[data bytes] + length:[data length] + compressionLevel:level]; + STAssertNotNil(gzipped, @"failed to gzip data block"); + STAssertGreaterThan([gzipped length], + (NSUInteger)0, @"failed to gzip data block"); + STAssertTrue(HasGzipHeader(gzipped), + @"doesn't have gzip header on gzipped data"); + dataPrime = [NSData gtm_dataByInflatingBytes:[gzipped bytes] + length:[gzipped length]]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, dataPrime, + @"failed to round trip via *Bytes apis"); + + // w/ *Data apis, using our level + gzipped = [NSData gtm_dataByGzippingData:data compressionLevel:level]; + STAssertNotNil(gzipped, @"failed to gzip data block"); + STAssertGreaterThan([gzipped length], + (NSUInteger)0, @"failed to gzip data block"); + STAssertTrue(HasGzipHeader(gzipped), + @"doesn't have gzip header on gzipped data"); + dataPrime = [NSData gtm_dataByInflatingData:gzipped]; + STAssertNotNil(dataPrime, @"failed to inflate data block"); + STAssertGreaterThan([dataPrime length], + (NSUInteger)0, @"failed to inflate data block"); + STAssertEqualObjects(data, + dataPrime, @"failed to round trip via *Data apis"); + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.h new file mode 100644 index 00000000..4bc896d0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.h @@ -0,0 +1,30 @@ +// +// GTMNSDictionary+URLArguments.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Utility for building a URL or POST argument string. +@interface NSDictionary (GTMNSDictionaryURLArgumentsAdditions) + +/// Gets a string representation of the dictionary in the form +/// key1=value1&key2&value2&...&keyN=valueN, suitable for use as either +/// URL arguments (after a '?') or POST body. Keys and values will be escaped +/// automatically, so should be unescaped in the dictionary. +- (NSString *)gtm_httpArgumentsString; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.m new file mode 100644 index 00000000..89610e48 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArguments.m @@ -0,0 +1,40 @@ +// +// GTMNSDictionary+URLArguments.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSDictionary+URLArguments.h" +#import "GTMNSString+URLArguments.h" +#import "GTMMethodCheck.h" +#import "GTMDefines.h" + +@implementation NSDictionary (GTMNSDictionaryURLArgumentsAdditions) + +GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument); + +- (NSString *)gtm_httpArgumentsString { + NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]]; + NSString* key; + GTM_FOREACH_KEY(key, self) { + [arguments addObject:[NSString stringWithFormat:@"%@=%@", + [key gtm_stringByEscapingForURLArgument], + [[[self objectForKey:key] description] gtm_stringByEscapingForURLArgument]]]; + } + + return [arguments componentsJoinedByString:@"&"]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArgumentsTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArgumentsTest.m new file mode 100644 index 00000000..f01519e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+URLArgumentsTest.m @@ -0,0 +1,54 @@ +// +// GTMNSDictionary+URLArgumentsTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSDictionary+URLArguments.h" +#import "GTMDefines.h" + +@interface GTMNSDictionary_URLArgumentsTest : GTMTestCase +@end + +@implementation GTMNSDictionary_URLArgumentsTest + +- (void)testArgumentsString { + STAssertEqualObjects([[NSDictionary dictionary] gtm_httpArgumentsString], @"", + @"- empty dictionary should give an empty string"); + STAssertEqualObjects([[NSDictionary dictionaryWithObject:@"123" forKey:@"abc"] gtm_httpArgumentsString], + @"abc=123", + @"- simple one-pair dictionary should work"); + NSDictionary* arguments = [NSDictionary dictionaryWithObjectsAndKeys: + @"1+1!=3 & 2*6/3=4", @"complex", + @"specialkey", @"a+b", + nil]; + NSString* argumentString = [arguments gtm_httpArgumentsString]; + // check for individual pieces since order is not guaranteed + NSString* component1 = @"a%2Bb=specialkey"; + NSString* component2 = @"complex=1%2B1%21%3D3%20%26%202%2A6%2F3%3D4"; + STAssertNotEquals([argumentString rangeOfString:component1].location, (NSUInteger)NSNotFound, + @"- '%@' not found in '%@'", component1, argumentString); + STAssertNotEquals([argumentString rangeOfString:component2].location, (NSUInteger)NSNotFound, + @"- '%@' not found in '%@'", component2, argumentString); + STAssertNotEquals([argumentString rangeOfString:@"&"].location, (NSUInteger)NSNotFound, + @"- special characters should be escaped"); + STAssertNotEquals([argumentString characterAtIndex:0], (unichar)'&', + @"- there should be no & at the beginning of the string"); + STAssertNotEquals([argumentString characterAtIndex:([argumentString length] - 1)], (unichar)'&', + @"- there should be no & at the end of the string"); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.h new file mode 100644 index 00000000..8e10d937 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.h @@ -0,0 +1,53 @@ +// +// GTMNSEnumerator+Filter.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// A generic category for methods that allow us to filter enumeratable +/// containers, inspired by C++ Standard Library's use of iterators. +/// Like in C++, these assume the underlying container is not modified during +/// the lifetime of the iterator. +/// +@interface NSEnumerator (GTMEnumeratorFilterAdditions) + +/// @argument predicate - the function return BOOL. will be applied to each element +/// @argument argument - optional argument to pass to predicate +/// @returns an enumerator that contains only elements where [element sel:argument] is true +- (NSEnumerator *)gtm_filteredEnumeratorByMakingEachObjectPerformSelector:(SEL)predicate + withObject:(id)argument; + +/// @argument selector - the function return a transformed object. will be applied to each element +/// @argument argument - optional argument to pass to transformer +/// @returns an enumerator that contains the transformed elements +- (NSEnumerator *)gtm_enumeratorByMakingEachObjectPerformSelector:(SEL)selector + withObject:(id)argument; + +/// @argument target - receiver for each method +/// @argument predicate - as in, [target predicate: [self nextObject]], return a BOOL +/// @returns an enumerator that contains only elements where [element sel:argument] is true +- (NSEnumerator *)gtm_filteredEnumeratorByTarget:(id)target + performOnEachSelector:(SEL)predicate; + +/// @argument target - receiver for each method +/// @argument sel - as in, [target selector: [self nextObject]], return a transformed object +/// @returns an enumerator that contains the transformed elements +- (NSEnumerator *)gtm_enumeratorByTarget:(id)target + performOnEachSelector:(SEL)selector; + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.m new file mode 100644 index 00000000..51d56f8b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+Filter.m @@ -0,0 +1,179 @@ +// +// GTMNSEnumerator+Filter.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSEnumerator+Filter.h" +#import "GTMDebugSelectorValidation.h" +#import "GTMDefines.h" +#if GTM_IPHONE_SDK +#import +#import +#else +#import +#endif + +// a private subclass of NSEnumerator that does all the work. +// public interface just returns one of these. +// This top level class contains all the additional boilerplate. Specific +// behavior is in the subclasses. +@interface GTMEnumeratorPrivateBase : NSEnumerator { + @protected + NSEnumerator *base_; // STRONG + SEL operation_; // either a predicate or a transform depending on context. + id other_; // STRONG, may be nil +} +@end + +@interface GTMEnumeratorPrivateBase (SubclassesMustProvide) +- (BOOL)filterObject:(id)obj returning:(id *)resultp; +@end + +@implementation GTMEnumeratorPrivateBase +- (id)initWithBase:(NSEnumerator *)base + sel:(SEL)filter + object:(id)optionalOther { + self = [super init]; + if (self) { + + // someone would have to subclass or directly create an object of this + // class, and this class is private to this impl. + _GTMDevAssert(base, @"can't initWithBase: a nil base enumerator"); + base_ = [base retain]; + operation_ = filter; + other_ = [optionalOther retain]; + } + return self; +} + +// we don't provide an init because this base class is private to this +// impl, and no one would be able to create it (if they do, they get whatever +// they happens...). + +- (void)dealloc { + [base_ release]; + [other_ release]; + [super dealloc]; +} + +- (id)nextObject { + for (id obj = [base_ nextObject]; obj; obj = [base_ nextObject]) { + id result = nil; + if ([self filterObject:obj returning:&result]) { + return result; + } + } + return nil; +} +@end + +// a transformer, for each item in the enumerator, returns a f(item). +@interface GTMEnumeratorTransformer : GTMEnumeratorPrivateBase +@end +@implementation GTMEnumeratorTransformer +- (BOOL)filterObject:(id)obj returning:(id *)resultp { + *resultp = [obj performSelector:operation_ withObject:other_]; + return nil != *resultp; +} +@end + +// a transformer, for each item in the enumerator, returns a f(item). +// a target transformer swaps the target and the argument. +@interface GTMEnumeratorTargetTransformer : GTMEnumeratorPrivateBase +@end +@implementation GTMEnumeratorTargetTransformer +- (BOOL)filterObject:(id)obj returning:(id *)resultp { + *resultp = [other_ performSelector:operation_ withObject:obj]; + return nil != *resultp; +} +@end + +// a filter, for each item in the enumerator, if(f(item)) { returns item. } +@interface GTMEnumeratorFilter : GTMEnumeratorPrivateBase +@end +@implementation GTMEnumeratorFilter +// We must take care here, since Intel leaves junk in high bytes of return register +// for predicates that return BOOL. +// For details see: +// http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html +// and +// http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187 +- (BOOL)filterObject:(id)obj returning:(id *)resultp { + *resultp = obj; + return ((BOOL (*)(id, SEL, id))objc_msgSend)(obj, operation_, other_); +} +@end + +// a target filter, for each item in the enumerator, if(f(item)) { returns item. } +// a target transformer swaps the target and the argument. +@interface GTMEnumeratorTargetFilter : GTMEnumeratorPrivateBase +@end +@implementation GTMEnumeratorTargetFilter +// We must take care here, since Intel leaves junk in high bytes of return register +// for predicates that return BOOL. +// For details see: +// http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html +// and +// http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187 +- (BOOL)filterObject:(id)obj returning:(id *)resultp { + *resultp = obj; + return ((BOOL (*)(id, SEL, id))objc_msgSend)(other_, operation_, obj); +} +@end + +@implementation NSEnumerator (GTMEnumeratorFilterAdditions) + +- (NSEnumerator *)gtm_filteredEnumeratorByMakingEachObjectPerformSelector:(SEL)selector + withObject:(id)argument { + return [[[GTMEnumeratorFilter alloc] initWithBase:self + sel:selector + object:argument] autorelease]; +} + +- (NSEnumerator *)gtm_enumeratorByMakingEachObjectPerformSelector:(SEL)selector + withObject:(id)argument { + return [[[GTMEnumeratorTransformer alloc] initWithBase:self + sel:selector + object:argument] autorelease]; +} + + +- (NSEnumerator *)gtm_filteredEnumeratorByTarget:(id)target + performOnEachSelector:(SEL)selector { + // make sure the object impls this selector taking an object as an arg. + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target, selector, + @encode(BOOL), + @encode(id), + NULL); + return [[[GTMEnumeratorTargetFilter alloc] initWithBase:self + sel:selector + object:target] autorelease]; +} + +- (NSEnumerator *)gtm_enumeratorByTarget:(id)target + performOnEachSelector:(SEL)selector { + // make sure the object impls this selector taking an object as an arg. + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target, selector, + @encode(id), + @encode(id), + NULL); + return [[[GTMEnumeratorTargetTransformer alloc] initWithBase:self + sel:selector + object:target] autorelease]; +} + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+FilterTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+FilterTest.m new file mode 100644 index 00000000..ef0d9556 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSEnumerator+FilterTest.m @@ -0,0 +1,133 @@ +// +// GTMNSEnumerator+FilterTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSEnumerator+Filter.h" + +@interface GTMNSEnumerator_FilterTest : GTMTestCase +@end + +@implementation GTMNSEnumerator_FilterTest + +- (void)testEnumeratorByMakingEachObjectPerformSelector { + // test w/ a set of strings + NSSet *numbers = [NSSet setWithObjects: @"1", @"2", @"3", nil]; + NSEnumerator *e = [[numbers objectEnumerator] + gtm_enumeratorByMakingEachObjectPerformSelector:@selector(stringByAppendingString:) + withObject:@" "]; + NSMutableSet *trailingSpaces = [NSMutableSet set]; + id obj; + while (nil != (obj = [e nextObject])) { + [trailingSpaces addObject:obj]; + } + NSSet *trailingSpacesGood = [NSSet setWithObjects: @"1 ", @"2 ", @"3 ", nil]; + STAssertEqualObjects(trailingSpaces, trailingSpacesGood, @""); + + // test an empty set + NSSet *empty = [NSSet set]; + e = [[empty objectEnumerator] + gtm_enumeratorByMakingEachObjectPerformSelector:@selector(stringByAppendingString:) + withObject:@" "]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); +} + +- (void)testFilteredEnumeratorByMakingEachObjectPerformSelector { + // test with a dict of strings + NSDictionary *testDict = [NSDictionary dictionaryWithObjectsAndKeys: + @"foo", @"1", + @"bar", @"2", + @"foobar", @"3", + nil]; + // test those that have prefixes + NSEnumerator *e = [[testDict objectEnumerator] + gtm_filteredEnumeratorByMakingEachObjectPerformSelector:@selector(hasPrefix:) + withObject:@"foo"]; + // since the dictionary iterates in any order, compare as sets + NSSet *filteredValues = [NSSet setWithArray:[e allObjects]]; + NSSet *expectedValues = [NSSet setWithObjects:@"foo", @"foobar", nil]; + STAssertEqualObjects(filteredValues, expectedValues, @""); + + // test an empty set + NSSet *empty = [NSSet set]; + e = [[empty objectEnumerator] + gtm_filteredEnumeratorByMakingEachObjectPerformSelector:@selector(hasPrefix:) + withObject:@"foo"]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); + + // test an set that will filter out + NSSet *filterAway = [NSSet setWithObjects:@"bar", @"baz", nil]; + e = [[filterAway objectEnumerator] + gtm_filteredEnumeratorByMakingEachObjectPerformSelector:@selector(hasPrefix:) + withObject:@"foo"]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); +} + +- (void)testEnumeratorByTargetPerformOnEachSelector { + // test w/ a set of strings + NSSet *numbers = [NSSet setWithObjects: @"1", @"2", @"3", nil]; + NSString *target = @"foo"; + NSEnumerator *e = [[numbers objectEnumerator] + gtm_enumeratorByTarget:target + performOnEachSelector:@selector(stringByAppendingString:)]; + // since the set iterates in any order, compare as sets + NSSet *collectedValues = [NSSet setWithArray:[e allObjects]]; + NSSet *expectedValues = [NSSet setWithObjects:@"foo1", @"foo2", @"foo3", nil]; + STAssertEqualObjects(collectedValues, expectedValues, @""); + + // test an empty set + NSSet *empty = [NSSet set]; + e = [[empty objectEnumerator] + gtm_enumeratorByTarget:target + performOnEachSelector:@selector(stringByAppendingString:)]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); +} + +- (void)testFilteredEnumeratorByTargetPerformOnEachSelector { + // test w/ a set of strings + NSSet *numbers = [NSSet setWithObjects:@"1", @"2", @"3", @"4", nil]; + NSSet *target = [NSSet setWithObjects:@"2", @"4", @"6", nil]; + NSEnumerator *e = [[numbers objectEnumerator] + gtm_filteredEnumeratorByTarget:target + performOnEachSelector:@selector(containsObject:)]; + // since the set iterates in any order, compare as sets + NSSet *filteredValues = [NSSet setWithArray:[e allObjects]]; + NSSet *expectedValues = [NSSet setWithObjects:@"2", @"4", nil]; + STAssertEqualObjects(filteredValues, expectedValues, @""); + + // test an empty set + NSSet *empty = [NSSet set]; + e = [[empty objectEnumerator] + gtm_filteredEnumeratorByTarget:target + performOnEachSelector:@selector(containsObject:)]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); + + // test an set that will filter out + NSSet *filterAway = [NSSet setWithObjects:@"bar", @"baz", nil]; + e = [[filterAway objectEnumerator] + gtm_filteredEnumeratorByTarget:target + performOnEachSelector:@selector(containsObject:)]; + STAssertNil([e nextObject], + @"shouldn't have gotten anything from first advance of enumerator"); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.h new file mode 100644 index 00000000..86215eaf --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.h @@ -0,0 +1,60 @@ +// +// GTMNSFileManager+Carbon.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + + +// A few useful methods for dealing with paths and carbon structures +@interface NSFileManager (GTMFileManagerCarbonAdditions) + +// Converts a path to an alias +// Args: +// path - the path to convert +// +// Returns: +// An alias wrapped up in an autoreleased NSData. Nil on failure. +// +- (NSData *)gtm_aliasDataForPath:(NSString *)path; + +// Converts an alias to a path +// Args: +// alias - an alias wrapped up in an NSData +// +// Returns: +// The path. Nil on failure. +// +- (NSString *)gtm_pathFromAliasData:(NSData *)alias; + +// Converts a path to an FSRef * +// Args: +// path - the path to convert +// +// Returns: +// An autoreleased FSRef *. Nil on failure. +// +- (FSRef *)gtm_FSRefForPath:(NSString *)path; + +// Converts an FSRef to a path +// Args: +// fsRef - the FSRef to convert +// +// Returns: +// The path. Nil on failure. +// +- (NSString *)gtm_pathFromFSRef:(FSRef *)fsRef; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.m new file mode 100644 index 00000000..4f8ba8bd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Carbon.m @@ -0,0 +1,99 @@ +// +// GTMNSFileManager+Carbon.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSFileManager+Carbon.h" +#import +#import +#import "GTMDefines.h" + +@implementation NSFileManager (GTMFileManagerCarbonAdditions) + +- (NSData *)gtm_aliasDataForPath:(NSString *)path { + NSData *data = nil; + FSRef ref; + AliasHandle alias = NULL; + + require_quiet([path length], CantUseParams); + require_noerr(FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], + &ref, NULL), CantMakeRef); + require_noerr(FSNewAlias(NULL, &ref, &alias), CantMakeAlias); + + Size length = GetAliasSize(alias); + data = [NSData dataWithBytes:*alias length:length]; + + DisposeHandle((Handle)alias); + +CantMakeAlias: +CantMakeRef: +CantUseParams: + return data; +} + +- (NSString *)gtm_pathFromAliasData:(NSData *)data { + NSString *path = nil; + require_quiet(data, CantUseParams); + + AliasHandle alias; + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + require_noerr(PtrToHand(bytes, (Handle *)&alias, length), CantMakeHandle); + + FSRef ref; + Boolean wasChanged; + // we don't use a require here because it is quite legitimate for an alias + // resolve to fail. + if (FSResolveAlias(NULL, alias, &ref, &wasChanged) == noErr) { + path = [self gtm_pathFromFSRef:&ref]; + } + DisposeHandle((Handle)alias); +CantMakeHandle: +CantUseParams: + return path; +} + +- (FSRef *)gtm_FSRefForPath:(NSString *)path { + FSRef* fsRef = NULL; + require_quiet([path length], CantUseParams); + NSMutableData *fsRefData = [NSMutableData dataWithLength:sizeof(FSRef)]; + require(fsRefData, CantAllocateFSRef); + fsRef = (FSRef*)[fsRefData mutableBytes]; + Boolean isDir = FALSE; + const UInt8 *filePath = (const UInt8 *)[path fileSystemRepresentation]; + require_noerr_action(FSPathMakeRef(filePath, fsRef, &isDir), + CantMakeRef, fsRef = NULL); +CantMakeRef: +CantAllocateFSRef: +CantUseParams: + return fsRef; +} + +- (NSString *)gtm_pathFromFSRef:(FSRef *)fsRef { + NSString *nsPath = nil; + require_quiet(fsRef, CantUseParams); + + char path[MAXPATHLEN]; + require_noerr(FSRefMakePath(fsRef, (UInt8 *)path, MAXPATHLEN), CantMakePath); + nsPath = [self stringWithFileSystemRepresentation:path length:strlen(path)]; + nsPath = [nsPath stringByStandardizingPath]; + +CantMakePath: +CantUseParams: + return nsPath; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+CarbonTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+CarbonTest.m new file mode 100644 index 00000000..76692b0e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+CarbonTest.m @@ -0,0 +1,69 @@ +// +// GTMNSFileManager+CarbonTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSFileManager+Carbon.h" +#import "GTMUnitTestDevLog.h" +#import + +@interface GTMNSFileManager_CarbonTest : GTMTestCase +@end + +@implementation GTMNSFileManager_CarbonTest + +- (void)testAliasPathFSRefConversion { + NSString *path = NSHomeDirectory(); + STAssertNotNil(path, nil); + NSFileManager *fileManager = [NSFileManager defaultManager]; + FSRef *fsRef = [fileManager gtm_FSRefForPath:path]; + STAssertNotNULL(fsRef, nil); + AliasHandle alias; + STAssertNoErr(FSNewAlias(nil, fsRef, &alias), nil); + STAssertNotNULL(alias, nil); + NSData *aliasData = [NSData dataWithBytes:*alias + length:GetAliasSize(alias)]; + STAssertNotNil(aliasData, nil); + NSString *path2 = [fileManager gtm_pathFromAliasData:aliasData]; + STAssertEqualObjects(path, path2, nil); + NSData *aliasData2 = [fileManager gtm_aliasDataForPath:path2]; + STAssertNotNil(aliasData2, nil); + NSString *path3 = [fileManager gtm_pathFromAliasData:aliasData2]; + STAssertEqualObjects(path2, path3, nil); + NSString *path4 = [fileManager gtm_pathFromFSRef:fsRef]; + STAssertEqualObjects(path, path4, nil); + + // Failure cases + [GTMUnitTestDevLogDebug expectPattern:@"DebugAssert: " + @"GoogleToolboxForMac: FSPathMakeRef.*"]; + STAssertNULL([fileManager gtm_FSRefForPath:@"/ptah/taht/dosent/esixt/"], + nil); + + STAssertNULL([fileManager gtm_FSRefForPath:@""], nil); + STAssertNULL([fileManager gtm_FSRefForPath:nil], nil); + STAssertNil([fileManager gtm_pathFromFSRef:nil], nil); + STAssertNil([fileManager gtm_pathFromAliasData:nil], nil); + STAssertNil([fileManager gtm_pathFromAliasData:[NSData data]], nil); + + [GTMUnitTestDevLogDebug expectPattern:@"DebugAssert: " + @"GoogleToolboxForMac: FSPathMakeRef.*"]; + STAssertNil([fileManager gtm_aliasDataForPath:@"/ptah/taht/dosent/esixt/"], nil); + STAssertNil([fileManager gtm_aliasDataForPath:@""], nil); + STAssertNil([fileManager gtm_aliasDataForPath:nil], nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.h new file mode 100644 index 00000000..f3772154 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.h @@ -0,0 +1,75 @@ +// +// GTMNSFileManager+Path.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + + +/// A few useful methods for dealing with paths. +@interface NSFileManager (GMFileManagerPathAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +/// For the Unix-y at heart, this is "mkdir -p". It tries to create +/// the directory specified by |path|, and any intervening directories that +/// are needed. Each directory that is created is created with |attributes| +/// (see other NSFileManager doco for the details on |attributes|). +/// +/// If you are building for 10.5 or later, you should just use the new api: +/// createDirectoryAtPath:withIntermediateDirectories:attributes:error: +/// +/// Also if you need more control over the creation of paths and their +/// attributes, look into using GTMPath. +/// +/// Args: +/// path - the path of the directory to create. +/// attributes - these are defined in the "Constants" section of Apple's +/// NSFileManager doco +/// +/// Returns: +/// YES if |path| exists or was able to be created successfully +/// NO otherwise +/// +- (BOOL)gtm_createFullPathToDirectory:(NSString *)path + attributes:(NSDictionary *)attributes; + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +/// Return an the paths for all resources in |directoryPath| that have the +/// |extension| file extension. +/// +/// Args: +/// extension - the file extension (excluding the leading ".") to match. +/// If nil, all files are matched. +/// directoryPath - the directory to look in. NOTE: Subdirectories are NOT +/// traversed. +/// +/// Returns: +/// An NSArray of absolute file paths that have |extension|. nil is returned +/// if |directoryPath| doesn't exist or can't be opened, and returns an empty +/// array if |directoryPath| is empty. ".", "..", and resource forks are never returned. +/// +- (NSArray *)gtm_filePathsWithExtension:(NSString *)extension + inDirectory:(NSString *)directoryPath; + +/// Same as -filePathsWithExtension:inDirectory: except |extensions| is an +/// NSArray of extensions to match. +/// +- (NSArray *)gtm_filePathsWithExtensions:(NSArray *)extensions + inDirectory:(NSString *)directoryPath; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.m new file mode 100644 index 00000000..195cd9ee --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+Path.m @@ -0,0 +1,101 @@ +// +// GTMNSFileManager+Path.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSFileManager+Path.h" +#import "GTMDefines.h" + +@implementation NSFileManager (GMFileManagerPathAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (BOOL)gtm_createFullPathToDirectory:(NSString *)path + attributes:(NSDictionary *)attributes { + if (!path) return NO; + + BOOL isDir; + BOOL exists = [self fileExistsAtPath:path isDirectory:&isDir]; + + // Quick check for the case where we have nothing to do. + if (exists && isDir) + return YES; + + NSString *actualPath = @"/"; + NSString *directory; + + GTM_FOREACH_OBJECT(directory, [path pathComponents]) { + actualPath = [actualPath stringByAppendingPathComponent:directory]; + + if ([self fileExistsAtPath:actualPath isDirectory:&isDir] && isDir) { + continue; + } else if ([self createDirectoryAtPath:actualPath attributes:attributes]) { + continue; + } else { + return NO; + } + } + + return YES; +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (NSArray *)gtm_filePathsWithExtension:(NSString *)extension + inDirectory:(NSString *)directoryPath { + NSArray *extensions = nil; + + // Treat no extension and an empty extension as the user requesting all files + if (extension != nil && ![extension isEqualToString:@""]) + extensions = [NSArray arrayWithObject:extension]; + + return [self gtm_filePathsWithExtensions:extensions + inDirectory:directoryPath]; +} + +- (NSArray *)gtm_filePathsWithExtensions:(NSArray *)extensions + inDirectory:(NSString *)directoryPath { + if (directoryPath == nil) + return nil; + + // |basenames| will contain only the matching file names, not their full paths. + NSArray *basenames = [self directoryContentsAtPath:directoryPath]; + + // Check if dir doesn't exist or couldn't be opened. + if (basenames == nil) + return nil; + + // Check if dir is empty. + if ([basenames count] == 0) + return basenames; + + NSMutableArray *paths = [NSMutableArray arrayWithCapacity:[basenames count]]; + NSString *basename; + + // Convert all the |basenames| to full paths. + GTM_FOREACH_OBJECT(basename, basenames) { + NSString *fullPath = [directoryPath stringByAppendingPathComponent:basename]; + [paths addObject:fullPath]; + } + + // Check if caller wants all files, regardless of extension. + if (extensions == nil || [extensions count] == 0) + return paths; + + return [paths pathsMatchingExtensions:extensions]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+PathTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+PathTest.m new file mode 100644 index 00000000..db40c68d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSFileManager+PathTest.m @@ -0,0 +1,249 @@ +// +// GTMNSFileManager+PathTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSFileManager+Path.h" + +@interface GTMNSFileManager_PathTest : GTMTestCase { + NSString *baseDir_; +} +@end + +@implementation GTMNSFileManager_PathTest + +- (void)setUp { + // make a directory to scribble in + baseDir_ = + [[NSTemporaryDirectory() + stringByAppendingPathComponent:@"GTMNSFileManager_PathTest"] retain]; + if (baseDir_) { + NSFileManager *fm = [NSFileManager defaultManager]; + if (![fm fileExistsAtPath:baseDir_] && + ![fm createDirectoryAtPath:baseDir_ attributes:nil]) { + // COV_NF_START + // if the dir exists or we failed to create it, drop the baseDir_ + [baseDir_ release]; + baseDir_ = nil; + // COV_NF_END + } + } +} + +- (void)tearDown { + if (baseDir_) { + // clean up our directory + NSFileManager *fm = [NSFileManager defaultManager]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + NSError *error = nil; + [fm removeItemAtPath:baseDir_ error:&error]; + STAssertNil(error, + @"Unable to delete %@: %@", baseDir_, [error description]); +#else + [fm removeFileAtPath:baseDir_ handler:nil]; +#endif + + [baseDir_ release]; + baseDir_ = nil; + } +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (void)testCreateFullPathToDirectoryAttributes { + STAssertNotNil(baseDir_, @"setUp failed"); + + NSString *testPath = + [baseDir_ stringByAppendingPathComponent:@"/foo/bar/baz"]; + STAssertNotNil(testPath, nil); + NSFileManager *fm = [NSFileManager defaultManager]; + + STAssertFalse([fm fileExistsAtPath:testPath], + @"You must delete '%@' before running this test", testPath); + + STAssertFalse([fm gtm_createFullPathToDirectory:nil attributes:nil], + @"didn't fail on nil input"); + + STAssertTrue([fm gtm_createFullPathToDirectory:testPath attributes:nil], + @"Failed to create nested testPath"); + STAssertTrue([fm gtm_createFullPathToDirectory:testPath attributes:nil], + @"Failed to succeed on second create of testPath"); + + NSString *pathToFail = [@"/etc" stringByAppendingPathComponent:testPath]; + STAssertFalse([fm gtm_createFullPathToDirectory:pathToFail attributes:nil], + @"We were allowed to create a dir in '/etc'?!"); + + STAssertFalse([fm gtm_createFullPathToDirectory:nil attributes:nil], + @"Should have failed when passed (nil)"); +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (void)testfilePathsWithExtensionsInDirectory { + STAssertNotNil(baseDir_, @"setUp failed"); + + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *bogusPath = @"/some/place/that/does/not/exist"; + + // -------------------------------------------------------------------------- + // test fail cases first + + // single + STAssertNil([fm gtm_filePathsWithExtension:nil inDirectory:nil], + @"shouldn't have gotten anything for nil dir"); + STAssertNil([fm gtm_filePathsWithExtension:@"txt" inDirectory:nil], + @"shouldn't have gotten anything for nil dir"); + STAssertNil([fm gtm_filePathsWithExtension:@"txt" inDirectory:bogusPath], + @"shouldn't have gotten anything for a bogus dir"); + // array + STAssertNil([fm gtm_filePathsWithExtensions:nil inDirectory:nil], + @"shouldn't have gotten anything for nil dir"); + STAssertNil([fm gtm_filePathsWithExtensions:[NSArray array] inDirectory:nil], + @"shouldn't have gotten anything for nil dir"); + STAssertNil([fm gtm_filePathsWithExtensions:[NSArray arrayWithObject:@"txt"] + inDirectory:nil], + @"shouldn't have gotten anything for nil dir"); + STAssertNil([fm gtm_filePathsWithExtensions:[NSArray arrayWithObject:@"txt"] + inDirectory:bogusPath], + @"shouldn't have gotten anything for a bogus dir"); + + // -------------------------------------------------------------------------- + // create some test data + + NSString *testDirs[] = { + @"", @"/foo", // mave a subdir to make sure we don't match w/in it + }; + NSString *testFiles[] = { + @"a.txt", @"b.txt", @"c.rtf", @"d.m", + }; + + for (size_t i = 0; i < sizeof(testDirs) / sizeof(NSString*); i++) { + NSString *testDir = nil; + if ([testDirs[i] length]) { + testDir = [baseDir_ stringByAppendingPathComponent:testDirs[i]]; + STAssertTrue([fm createDirectoryAtPath:testDir attributes:nil], nil); + } else { + testDir = baseDir_; + } + for (size_t j = 0; j < sizeof(testFiles) / sizeof(NSString*); j++) { + NSString *testFile = [testDir stringByAppendingPathComponent:testFiles[j]]; + STAssertTrue([@"test" writeToFile:testFile atomically:YES], nil); + } + } + + // build set of the top level items + NSMutableArray *allFiles = [NSMutableArray array]; + for (size_t i = 0; i < sizeof(testDirs) / sizeof(NSString*); i++) { + if ([testDirs[i] length]) { + NSString *testDir = [baseDir_ stringByAppendingPathComponent:testDirs[i]]; + [allFiles addObject:testDir]; + } + } + for (size_t j = 0; j < sizeof(testFiles) / sizeof(NSString*); j++) { + NSString *testFile = [baseDir_ stringByAppendingPathComponent:testFiles[j]]; + [allFiles addObject:testFile]; + } + + NSArray *matches = nil; + NSArray *expectedMatches = nil; + NSArray *extensions = nil; + + // NOTE: we do all compares w/ sets so order doesn't matter + + // -------------------------------------------------------------------------- + // test match all + + // single + matches = [fm gtm_filePathsWithExtension:nil inDirectory:baseDir_]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:allFiles], + @"didn't get all files for nil extension"); + matches = [fm gtm_filePathsWithExtension:@"" inDirectory:baseDir_]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:allFiles], + @"didn't get all files for nil extension"); + // array + matches = [fm gtm_filePathsWithExtensions:nil inDirectory:baseDir_]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:allFiles], + @"didn't get all files for nil extension"); + matches = [fm gtm_filePathsWithExtensions:[NSArray array] + inDirectory:baseDir_]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:allFiles], + @"didn't get all files for nil extension"); + + // -------------------------------------------------------------------------- + // test match something + + // single + extensions = [NSArray arrayWithObject:@"txt"]; + matches = [fm gtm_filePathsWithExtension:@"txt" inDirectory:baseDir_]; + expectedMatches = [allFiles pathsMatchingExtensions:extensions]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:expectedMatches], + @"didn't get expected files"); + // array + matches = [fm gtm_filePathsWithExtensions:extensions inDirectory:baseDir_]; + expectedMatches = [allFiles pathsMatchingExtensions:extensions]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:expectedMatches], + @"didn't get expected files"); + extensions = [NSArray arrayWithObjects:@"txt", @"rtf", @"xyz", nil]; + matches = [fm gtm_filePathsWithExtensions:extensions inDirectory:baseDir_]; + expectedMatches = [allFiles pathsMatchingExtensions:extensions]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:expectedMatches], + @"didn't get expected files"); + + // -------------------------------------------------------------------------- + // test match nothing + + // single + extensions = [NSArray arrayWithObject:@"xyz"]; + matches = [fm gtm_filePathsWithExtension:@"xyz" inDirectory:baseDir_]; + expectedMatches = [allFiles pathsMatchingExtensions:extensions]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:expectedMatches], + @"didn't get expected files"); + // array + matches = [fm gtm_filePathsWithExtensions:extensions inDirectory:baseDir_]; + expectedMatches = [allFiles pathsMatchingExtensions:extensions]; + STAssertEqualObjects([NSSet setWithArray:matches], + [NSSet setWithArray:expectedMatches], + @"didn't get expected files"); + + // -------------------------------------------------------------------------- + // test match an empty dir + + // create the empty dir + NSString *emptyDir = [baseDir_ stringByAppendingPathComponent:@"emptyDir"]; + STAssertTrue([fm createDirectoryAtPath:emptyDir attributes:nil], nil); + + // single + matches = [fm gtm_filePathsWithExtension:@"txt" inDirectory:emptyDir]; + STAssertEqualObjects([NSSet setWithArray:matches], [NSSet set], + @"expected empty dir"); + // array + matches = [fm gtm_filePathsWithExtensions:[NSArray arrayWithObject:@"txt"] + inDirectory:emptyDir]; + STAssertEqualObjects([NSSet setWithArray:matches], [NSSet set], + @"expected empty dir"); + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.h new file mode 100644 index 00000000..de11aeb7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.h @@ -0,0 +1,70 @@ +// +// GTMNSObject+KeyValueObserving.h +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// +// MAKVONotificationCenter.h +// MAKVONotificationCenter +// +// Created by Michael Ash on 10/15/08. +// + +// This code is based on code by Michael Ash. +// Please see his excellent writeup at +// http://www.mikeash.com/?page=pyblog/key-value-observing-done-right.html +// You may also be interested in this writeup: +// http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/ +// and the discussion on cocoa-dev that is linked to at the end of it. + +#import + +// If you read the articles above you will see that doing KVO correctly +// is actually pretty tricky, and that Apple's documentation may not be +// completely clear as to how things should be used. Use the methods below +// to make things a little easier instead of the stock addObserver, +// removeObserver methods. +// Selector should have the following signature: +// - (void)observeNotification:(GTMKeyValueChangeNotification *)notification +@interface NSObject (GTMKeyValueObservingAdditions) + +// Use this instead of [NSObject addObserver:forKeyPath:options:context:] +- (void)gtm_addObserver:(id)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options; +// Use this instead of [NSObject removeObserver:forKeyPath:] +- (void)gtm_removeObserver:(id)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector; +@end + +// This is the class that is sent to your notification selector as an +// argument. +@interface GTMKeyValueChangeNotification : NSObject { + @private + NSString *keyPath_; + id object_; + id userInfo_; + NSDictionary *change_; +} + +- (NSString *)keyPath; +- (id)object; +- (id)userInfo; +- (NSDictionary *)change; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.m new file mode 100644 index 00000000..dc6883d5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObserving.m @@ -0,0 +1,350 @@ +// +// GTMNSObject+KeyValueObserving.h +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// +// MAKVONotificationCenter.m +// MAKVONotificationCenter +// +// Created by Michael Ash on 10/15/08. +// + +// This code is based on code by Michael Ash. +// See comment in header. + +#import "GTMNSObject+KeyValueObserving.h" + +#import +#import "GTMDefines.h" +#import "GTMDebugSelectorValidation.h" +#import "GTMObjC2Runtime.h" + +// A singleton that works as a dispatch center for KVO +// -[NSObject observeValueForKeyPath:ofObject:change:context:] and turns them +// into selector dispatches. It stores a collection of +// GTMKeyValueObservingHelpers, and keys them via the key generated by +// -dictionaryKeyForObserver:ofObject:forKeyPath:selector. +@interface GTMKeyValueObservingCenter : NSObject { +@private + NSMutableDictionary *observerHelpers_; +} + ++ (id)defaultCenter; + +- (void)addObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options; +- (void)removeObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector; +- (id)dictionaryKeyForObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector; +@end + +@interface GTMKeyValueObservingHelper : NSObject { + @private + __weak id observer_; + SEL selector_; + id userInfo_; + id target_; + NSString* keyPath_; +} + +- (id)initWithObserver:(id)observer + object:(id)target + keyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options; +- (void)deregister; + +@end + +@interface GTMKeyValueChangeNotification () +- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object + userInfo:(id)userInfo change:(NSDictionary *)change; +@end + +@implementation GTMKeyValueObservingHelper + +// For info how and why we use these statics: +// http://lists.apple.com/archives/cocoa-dev/2006/Jul/msg01038.html +static char GTMKeyValueObservingHelperContextData; +static char* GTMKeyValueObservingHelperContext + = >MKeyValueObservingHelperContextData; + +- (id)initWithObserver:(id)observer + object:(id)target + keyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options { + if((self = [super init])) { + observer_ = observer; + selector_ = selector; + userInfo_ = [userInfo retain]; + + target_ = target; + keyPath_ = [keyPath retain]; + + [target addObserver:self + forKeyPath:keyPath + options:options + context:GTMKeyValueObservingHelperContext]; + } + return self; +} + +- (void)dealloc { + [userInfo_ release]; + [keyPath_ release]; + [super dealloc]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if(context == GTMKeyValueObservingHelperContext) { + GTMKeyValueChangeNotification *notification + = [[GTMKeyValueChangeNotification alloc] initWithKeyPath:keyPath + ofObject:object + userInfo:userInfo_ + change:change]; + [observer_ performSelector:selector_ withObject:notification]; + [notification release]; + } else { + // COV_NF_START + // There's no way this should ever be called. + // If it is, the call will go up to NSObject which will assert. + [super observeValueForKeyPath:keyPath + ofObject:object + change:change + context:context]; + // COV_NF_END + } +} + +- (void)deregister { + [target_ removeObserver:self forKeyPath:keyPath_]; +} + +@end + +@implementation GTMKeyValueObservingCenter + ++ (id)defaultCenter { + static GTMKeyValueObservingCenter *center = nil; + if(!center) { + // do a bit of clever atomic setting to make this thread safe + // if two threads try to set simultaneously, one will fail + // and the other will set things up so that the failing thread + // gets the shared center + GTMKeyValueObservingCenter *newCenter = [[self alloc] init]; + if(!objc_atomicCompareAndSwapGlobalBarrier(nil, + newCenter, + (void *)¢er)) { + [newCenter release]; // COV_NF_LINE no guarantee we'll hit this line + } + } + return center; +} + +- (id)init { + if((self = [super init])) { + observerHelpers_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +// COV_NF_START +// Singletons don't get deallocated +- (void)dealloc { + [observerHelpers_ release]; + [super dealloc]; +} +// COV_NF_END + +- (id)dictionaryKeyForObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector { + NSString *key = [NSString stringWithFormat:@"%p:%p:%@:%p", + observer, target, keyPath, selector]; + return key; +} + +- (void)addObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options { + GTMKeyValueObservingHelper *helper + = [[GTMKeyValueObservingHelper alloc] initWithObserver:observer + object:target + keyPath:keyPath + selector:selector + userInfo:userInfo + options:options]; + id key = [self dictionaryKeyForObserver:observer + ofObject:target + forKeyPath:keyPath + selector:selector]; + @synchronized(self) { +#if DEBUG + GTMKeyValueObservingHelper *oldHelper = [observerHelpers_ objectForKey:key]; + if (oldHelper) { + _GTMDevLog(@"%@ already observing %@ forKeyPath %@", + observer, target, keyPath); + } +#endif // DEBUG + [observerHelpers_ setObject:helper forKey:key]; + } + [helper release]; +} + +- (void)removeObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector { + id key = [self dictionaryKeyForObserver:observer + ofObject:target + forKeyPath:keyPath + selector:selector]; + GTMKeyValueObservingHelper *helper = nil; + @synchronized(self) { + helper = [[observerHelpers_ objectForKey:key] retain]; +#if DEBUG + if (!helper) { + _GTMDevLog(@"%@ was not observing %@ with keypath %@", + observer, target, keyPath); + } +#endif // DEBUG + [observerHelpers_ removeObjectForKey:key]; + } + [helper deregister]; + [helper release]; +} + +@end + +@implementation NSObject (GTMKeyValueObservingAdditions) + +- (void)gtm_addObserver:(id)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo + options:(NSKeyValueObservingOptions)options { + _GTMDevAssert(observer && [keyPath length] && selector, + @"Missing observer, keyPath, or selector"); + GTMKeyValueObservingCenter *center + = [GTMKeyValueObservingCenter defaultCenter]; + GTMAssertSelectorNilOrImplementedWithArguments(observer, + selector, + @encode(GTMKeyValueChangeNotification *), + NULL); + [center addObserver:observer + ofObject:self + forKeyPath:keyPath + selector:selector + userInfo:userInfo + options:options]; +} + +- (void)gtm_removeObserver:(id)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector { + _GTMDevAssert(observer && [keyPath length] && selector, + @"Missing observer, keyPath, or selector"); + GTMKeyValueObservingCenter *center + = [GTMKeyValueObservingCenter defaultCenter]; + GTMAssertSelectorNilOrImplementedWithArguments(observer, + selector, + @encode(GTMKeyValueChangeNotification *), + NULL); + [center removeObserver:observer + ofObject:self + forKeyPath:keyPath + selector:selector]; +} + +@end + + +@implementation GTMKeyValueChangeNotification + +- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object + userInfo:(id)userInfo change:(NSDictionary *)change { + if ((self = [super init])) { + keyPath_ = [keyPath copy]; + object_ = [object retain]; + userInfo_ = [userInfo retain]; + change_ = [change retain]; + } + return self; +} + +- (void)dealloc { + [keyPath_ release]; + [object_ release]; + [userInfo_ release]; + [change_ release]; + [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithKeyPath:keyPath_ + ofObject:object_ + userInfo:userInfo_ + change:change_]; +} + +- (BOOL)isEqual:(id)object { + return ([keyPath_ isEqualToString:[object keyPath]] + && [object_ isEqual:[object object]] + && [userInfo_ isEqual:[object userInfo]] + && [change_ isEqual:[object change]]); +} + +- (NSUInteger)hash { + return [keyPath_ hash] + [object_ hash] + [userInfo_ hash] + [change_ hash]; +} + +- (NSString *)keyPath { + return keyPath_; +} + +- (id)object { + return object_; +} + +- (id)userInfo { + return userInfo_; +} + +- (NSDictionary *)change { + return change_; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObservingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObservingTest.m new file mode 100644 index 00000000..b97f7ff7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSObject+KeyValueObservingTest.m @@ -0,0 +1,106 @@ +// +// GTMNSObject+KeyValueObservingTest.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// +// Tester.m +// MAKVONotificationCenter +// +// Created by Michael Ash on 10/15/08. +// + +// This code is based on code by Michael Ash. +// See comment in header. + +#import "GTMSenTestCase.h" +#import "GTMNSObject+KeyValueObserving.h" +#import "GTMDefines.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMNSObject_KeyValueObservingTest : GTMTestCase { + int32_t count_; + NSMutableDictionary *dict_; + __weak NSString *expectedValue_; +} +@end + +@implementation GTMNSObject_KeyValueObservingTest +- (void)setUp { + dict_ = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + @"foo", @"key", + nil]; +} + +- (void)tearDown { + [dict_ release]; +} + +- (void)testSingleChange { + [dict_ gtm_addObserver:self + forKeyPath:@"key" + selector:@selector(observeValueChange:) + userInfo:@"userInfo" + options:NSKeyValueObservingOptionNew]; + expectedValue_ = @"bar"; + [dict_ setObject:expectedValue_ forKey:@"key"]; + STAssertEquals(count_, (int32_t)1, nil); + [dict_ gtm_removeObserver:self + forKeyPath:@"key" + selector:@selector(observeValueChange:)]; + [dict_ setObject:@"foo" forKey:@"key"]; + STAssertEquals(count_, (int32_t)1, nil); +} + +- (void)testRemoving { + [GTMUnitTestDevLogDebug expectPattern:@"-\\[GTMNSObject_KeyValueObservingTest" + @" testRemoving\\] was not observing.*"]; + + [dict_ gtm_removeObserver:self + forKeyPath:@"key" + selector:@selector(observeValueChange:)]; +} + +- (void)testAdding { + [dict_ gtm_addObserver:self + forKeyPath:@"key" + selector:@selector(observeValueChange:) + userInfo:@"userInfo" + options:NSKeyValueObservingOptionNew]; + [GTMUnitTestDevLogDebug expectPattern:@"-\\[GTMNSObject_KeyValueObservingTest" + @" testAdding\\] already observing.*"]; + [dict_ gtm_addObserver:self + forKeyPath:@"key" + selector:@selector(observeValueChange:) + userInfo:@"userInfo" + options:NSKeyValueObservingOptionNew]; +} + +- (void)observeValueChange:(GTMKeyValueChangeNotification *)notification { + STAssertEqualObjects([notification userInfo], @"userInfo", nil); + STAssertEqualObjects([notification keyPath], @"key", nil); + STAssertEqualObjects([notification object], dict_, nil); + NSDictionary *change = [notification change]; + NSString *value = [change objectForKey:NSKeyValueChangeNewKey]; + STAssertEqualObjects(value, expectedValue_, nil); + ++count_; + + GTMKeyValueChangeNotification *copy = [[notification copy] autorelease]; + STAssertEqualObjects(notification, copy, nil); + STAssertEquals([notification hash], [copy hash], nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.h new file mode 100644 index 00000000..1b4d362f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.h @@ -0,0 +1,55 @@ +// +// GTMNSString+FindFolder.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +@interface NSString (GTMStringFindFolderAdditions) + +// Create a path to a folder located with FindFolder +// +// Args: +// theFolderType: one of the folder types in Folders.h +// (kPreferencesFolderType, etc) +// theDomain: one of the domains in Folders.h (kLocalDomain, kUserDomain, etc) +// doCreate: create the folder if it does not already exist +// +// Returns: +// full path to folder, or nil if the folder doesn't exist or can't be created +// ++ (NSString *)gtm_stringWithPathForFolder:(OSType)theFolderType + inDomain:(short)theDomain + doCreate:(BOOL)doCreate; + +// Create a path to a folder inside a folder located with FindFolder +// +// Args: +// theFolderType: one of the folder types in Folders.h +// (kPreferencesFolderType, etc) +// subfolderName: name of directory inside the Apple folder to be located or created +// theDomain: one of the domains in Folders.h (kLocalDomain, kUserDomain, etc) +// doCreate: create the folder if it does not already exist +// +// Returns: +// full path to subdirectory, or nil if the folder doesn't exist or can't be created +// ++ (NSString *)gtm_stringWithPathForFolder:(OSType)theFolderType + subfolderName:(NSString *)subfolderName + inDomain:(short)theDomain + doCreate:(BOOL)doCreate; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.m new file mode 100644 index 00000000..3a44174f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolder.m @@ -0,0 +1,78 @@ +// +// GTMNSString+FindFolder.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSString+FindFolder.h" +#import "GTMGarbageCollection.h" + +@implementation NSString (GTMStringFindFolderAdditions) + ++ (NSString *)gtm_stringWithPathForFolder:(OSType)theFolderType + inDomain:(short)theDomain + doCreate:(BOOL)doCreate { + + NSString* folderPath = nil; + FSRef folderRef; + + OSErr err = FSFindFolder(theDomain, theFolderType, doCreate, &folderRef); + if (err == noErr) { + + CFURLRef folderURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, + &folderRef); + if (folderURL) { + folderPath = GTMCFAutorelease(CFURLCopyFileSystemPath(folderURL, + kCFURLPOSIXPathStyle)); + CFRelease(folderURL); + } + } + return folderPath; +} + ++ (NSString *)gtm_stringWithPathForFolder:(OSType)theFolderType + subfolderName:(NSString *)subfolderName + inDomain:(short)theDomain + doCreate:(BOOL)doCreate { + NSString *resultPath = nil; + NSString *subdirPath = nil; + NSString *parentFolderPath = [self gtm_stringWithPathForFolder:theFolderType + inDomain:theDomain + doCreate:doCreate]; + if (parentFolderPath) { + + // find the path to the subdirectory + subdirPath = [parentFolderPath stringByAppendingPathComponent:subfolderName]; + + NSFileManager* fileMgr = [NSFileManager defaultManager]; + BOOL isDir = NO; + if ([fileMgr fileExistsAtPath:subdirPath isDirectory:&isDir] && isDir) { + // it already exists + resultPath = subdirPath; + } else if (doCreate) { + + // create the subdirectory with the parent folder's attributes + NSDictionary* attrs = [fileMgr fileAttributesAtPath:parentFolderPath + traverseLink:YES]; + if ([fileMgr createDirectoryAtPath:subdirPath + attributes:attrs]) { + resultPath = subdirPath; + } + } + } + return resultPath; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolderTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolderTest.m new file mode 100644 index 00000000..66fd329e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+FindFolderTest.m @@ -0,0 +1,77 @@ +// +// GTMNSString+FindFolderTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSString+FindFolder.h" + +@interface GTMNSString_FindFolderTest : GTMTestCase +@end + +@implementation GTMNSString_FindFolderTest + +- (void)testStringWithPathForFolder { + // for gtm_stringWithPathForFolder:inDomain:doCreate: + // the parameters all get passed through to FSFindFolder so there's no point testing + // other combinations; our semantics will match FSFindFolder's + NSString *prefsPath = [NSString gtm_stringWithPathForFolder:kPreferencesFolderType + inDomain:kUserDomain + doCreate:NO]; + NSString *realPrefsPath = [@"~/Library/Preferences" stringByExpandingTildeInPath]; + STAssertEqualObjects(realPrefsPath, prefsPath, @"Found incorrect prefs path"); + + + // test the subfolder method; it should return nil if we pass NO and the + // subfolder doesn't already exist + + NSString *googCacheNoCreatePath = [NSString gtm_stringWithPathForFolder:kCachedDataFolderType + subfolderName:@"GTMUnitTestDuzntExist" + inDomain:kUserDomain + doCreate:NO]; + STAssertNil(googCacheNoCreatePath, @"Should not exist: %@", googCacheNoCreatePath); + + // test creating ~/Library/Cache/GTMUnitTestCreated + + NSString *folderName = @"GTMUnitTestCreated"; + NSString *gtmCachePath = [NSString gtm_stringWithPathForFolder:kCachedDataFolderType + subfolderName:folderName + inDomain:kUserDomain + doCreate:YES]; + NSString *testPath = [NSString gtm_stringWithPathForFolder:kCachedDataFolderType + inDomain:kUserDomain + doCreate:NO]; + NSString *testPathAppended = [testPath stringByAppendingPathComponent:folderName]; + STAssertEqualObjects(gtmCachePath, testPathAppended, @"Unexpected path name"); + + NSFileManager* fileMgr = [NSFileManager defaultManager]; + BOOL isDir = NO; + BOOL pathExists = [fileMgr fileExistsAtPath:gtmCachePath isDirectory:&isDir] && isDir; + STAssertTrue(pathExists, @"Path %@ is not existing like it should", gtmCachePath); + + // test finding it again w/o having to create it + NSString *gtmCachePath2 = [NSString gtm_stringWithPathForFolder:kCachedDataFolderType + subfolderName:folderName + inDomain:kUserDomain + doCreate:NO]; + STAssertEqualObjects(gtmCachePath2, gtmCachePath, nil); + + BOOL didRemove = [fileMgr removeFileAtPath:gtmCachePath + handler:nil]; + STAssertTrue(didRemove, @"Error removing %@", gtmCachePath); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.h new file mode 100644 index 00000000..1273cc3b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.h @@ -0,0 +1,66 @@ +// +// GTMNSString+HTML.h +// Dealing with NSStrings that contain HTML +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Utilities for NSStrings containing HTML +@interface NSString (GTMNSStringHTMLAdditions) + +/// Get a string where internal characters that need escaping for HTML are escaped +// +/// For example, '&' become '&'. This will only cover characters from table +/// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters +/// which is what you want for a unicode encoded webpage. If you have a ascii +/// or non-encoded webpage, please use stringByEscapingAsciiHTML which will +/// encode all characters. +/// +/// For obvious reasons this call is only safe once. +// +// Returns: +// Autoreleased NSString +// +- (NSString *)gtm_stringByEscapingForHTML; + +/// Get a string where internal characters that need escaping for HTML are escaped +// +/// For example, '&' become '&' +/// All non-mapped characters (unicode that don't have a &keyword; mapping) +/// will be converted to the appropriate &#xxx; value. If your webpage is +/// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is +/// faster, and produces less bloated and more readable HTML (as long as you +/// are using a unicode compliant HTML reader). +/// +/// For obvious reasons this call is only safe once. +// +// Returns: +// Autoreleased NSString +// +- (NSString *)gtm_stringByEscapingForAsciiHTML; + +/// Get a string where internal characters that are escaped for HTML are unescaped +// +/// For example, '&' becomes '&' +/// Handles and 2 cases as well +/// +// Returns: +// Autoreleased NSString +// +- (NSString *)gtm_stringByUnescapingFromHTML; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.m new file mode 100644 index 00000000..6853df07 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTML.m @@ -0,0 +1,522 @@ +// +// GTMNSString+HTML.m +// Dealing with NSStrings that contain HTML +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import "GTMNSString+HTML.h" + +typedef struct { + NSString *escapeSequence; + unichar uchar; +} HTMLEscapeMap; + +// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters +// Ordered by uchar lowest to highest for bsearching +static HTMLEscapeMap gAsciiHTMLEscapeMap[] = { + // A.2.2. Special characters + { @""", 34 }, + { @"&", 38 }, + { @"'", 39 }, + { @"<", 60 }, + { @">", 62 }, + + // A.2.1. Latin-1 characters + { @" ", 160 }, + { @"¡", 161 }, + { @"¢", 162 }, + { @"£", 163 }, + { @"¤", 164 }, + { @"¥", 165 }, + { @"¦", 166 }, + { @"§", 167 }, + { @"¨", 168 }, + { @"©", 169 }, + { @"ª", 170 }, + { @"«", 171 }, + { @"¬", 172 }, + { @"­", 173 }, + { @"®", 174 }, + { @"¯", 175 }, + { @"°", 176 }, + { @"±", 177 }, + { @"²", 178 }, + { @"³", 179 }, + { @"´", 180 }, + { @"µ", 181 }, + { @"¶", 182 }, + { @"·", 183 }, + { @"¸", 184 }, + { @"¹", 185 }, + { @"º", 186 }, + { @"»", 187 }, + { @"¼", 188 }, + { @"½", 189 }, + { @"¾", 190 }, + { @"¿", 191 }, + { @"À", 192 }, + { @"Á", 193 }, + { @"Â", 194 }, + { @"Ã", 195 }, + { @"Ä", 196 }, + { @"Å", 197 }, + { @"Æ", 198 }, + { @"Ç", 199 }, + { @"È", 200 }, + { @"É", 201 }, + { @"Ê", 202 }, + { @"Ë", 203 }, + { @"Ì", 204 }, + { @"Í", 205 }, + { @"Î", 206 }, + { @"Ï", 207 }, + { @"Ð", 208 }, + { @"Ñ", 209 }, + { @"Ò", 210 }, + { @"Ó", 211 }, + { @"Ô", 212 }, + { @"Õ", 213 }, + { @"Ö", 214 }, + { @"×", 215 }, + { @"Ø", 216 }, + { @"Ù", 217 }, + { @"Ú", 218 }, + { @"Û", 219 }, + { @"Ü", 220 }, + { @"Ý", 221 }, + { @"Þ", 222 }, + { @"ß", 223 }, + { @"à", 224 }, + { @"á", 225 }, + { @"â", 226 }, + { @"ã", 227 }, + { @"ä", 228 }, + { @"å", 229 }, + { @"æ", 230 }, + { @"ç", 231 }, + { @"è", 232 }, + { @"é", 233 }, + { @"ê", 234 }, + { @"ë", 235 }, + { @"ì", 236 }, + { @"í", 237 }, + { @"î", 238 }, + { @"ï", 239 }, + { @"ð", 240 }, + { @"ñ", 241 }, + { @"ò", 242 }, + { @"ó", 243 }, + { @"ô", 244 }, + { @"õ", 245 }, + { @"ö", 246 }, + { @"÷", 247 }, + { @"ø", 248 }, + { @"ù", 249 }, + { @"ú", 250 }, + { @"û", 251 }, + { @"ü", 252 }, + { @"ý", 253 }, + { @"þ", 254 }, + { @"ÿ", 255 }, + + // A.2.2. Special characters cont'd + { @"Œ", 338 }, + { @"œ", 339 }, + { @"Š", 352 }, + { @"š", 353 }, + { @"Ÿ", 376 }, + + // A.2.3. Symbols + { @"ƒ", 402 }, + + // A.2.2. Special characters cont'd + { @"ˆ", 710 }, + { @"˜", 732 }, + + // A.2.3. Symbols cont'd + { @"Α", 913 }, + { @"Β", 914 }, + { @"Γ", 915 }, + { @"Δ", 916 }, + { @"Ε", 917 }, + { @"Ζ", 918 }, + { @"Η", 919 }, + { @"Θ", 920 }, + { @"Ι", 921 }, + { @"Κ", 922 }, + { @"Λ", 923 }, + { @"Μ", 924 }, + { @"Ν", 925 }, + { @"Ξ", 926 }, + { @"Ο", 927 }, + { @"Π", 928 }, + { @"Ρ", 929 }, + { @"Σ", 931 }, + { @"Τ", 932 }, + { @"Υ", 933 }, + { @"Φ", 934 }, + { @"Χ", 935 }, + { @"Ψ", 936 }, + { @"Ω", 937 }, + { @"α", 945 }, + { @"β", 946 }, + { @"γ", 947 }, + { @"δ", 948 }, + { @"ε", 949 }, + { @"ζ", 950 }, + { @"η", 951 }, + { @"θ", 952 }, + { @"ι", 953 }, + { @"κ", 954 }, + { @"λ", 955 }, + { @"μ", 956 }, + { @"ν", 957 }, + { @"ξ", 958 }, + { @"ο", 959 }, + { @"π", 960 }, + { @"ρ", 961 }, + { @"ς", 962 }, + { @"σ", 963 }, + { @"τ", 964 }, + { @"υ", 965 }, + { @"φ", 966 }, + { @"χ", 967 }, + { @"ψ", 968 }, + { @"ω", 969 }, + { @"ϑ", 977 }, + { @"ϒ", 978 }, + { @"ϖ", 982 }, + + // A.2.2. Special characters cont'd + { @" ", 8194 }, + { @" ", 8195 }, + { @" ", 8201 }, + { @"‌", 8204 }, + { @"‍", 8205 }, + { @"‎", 8206 }, + { @"‏", 8207 }, + { @"–", 8211 }, + { @"—", 8212 }, + { @"‘", 8216 }, + { @"’", 8217 }, + { @"‚", 8218 }, + { @"“", 8220 }, + { @"”", 8221 }, + { @"„", 8222 }, + { @"†", 8224 }, + { @"‡", 8225 }, + // A.2.3. Symbols cont'd + { @"•", 8226 }, + { @"…", 8230 }, + + // A.2.2. Special characters cont'd + { @"‰", 8240 }, + + // A.2.3. Symbols cont'd + { @"′", 8242 }, + { @"″", 8243 }, + + // A.2.2. Special characters cont'd + { @"‹", 8249 }, + { @"›", 8250 }, + + // A.2.3. Symbols cont'd + { @"‾", 8254 }, + { @"⁄", 8260 }, + + // A.2.2. Special characters cont'd + { @"€", 8364 }, + + // A.2.3. Symbols cont'd + { @"ℑ", 8465 }, + { @"℘", 8472 }, + { @"ℜ", 8476 }, + { @"™", 8482 }, + { @"ℵ", 8501 }, + { @"←", 8592 }, + { @"↑", 8593 }, + { @"→", 8594 }, + { @"↓", 8595 }, + { @"↔", 8596 }, + { @"↵", 8629 }, + { @"⇐", 8656 }, + { @"⇑", 8657 }, + { @"⇒", 8658 }, + { @"⇓", 8659 }, + { @"⇔", 8660 }, + { @"∀", 8704 }, + { @"∂", 8706 }, + { @"∃", 8707 }, + { @"∅", 8709 }, + { @"∇", 8711 }, + { @"∈", 8712 }, + { @"∉", 8713 }, + { @"∋", 8715 }, + { @"∏", 8719 }, + { @"∑", 8721 }, + { @"−", 8722 }, + { @"∗", 8727 }, + { @"√", 8730 }, + { @"∝", 8733 }, + { @"∞", 8734 }, + { @"∠", 8736 }, + { @"∧", 8743 }, + { @"∨", 8744 }, + { @"∩", 8745 }, + { @"∪", 8746 }, + { @"∫", 8747 }, + { @"∴", 8756 }, + { @"∼", 8764 }, + { @"≅", 8773 }, + { @"≈", 8776 }, + { @"≠", 8800 }, + { @"≡", 8801 }, + { @"≤", 8804 }, + { @"≥", 8805 }, + { @"⊂", 8834 }, + { @"⊃", 8835 }, + { @"⊄", 8836 }, + { @"⊆", 8838 }, + { @"⊇", 8839 }, + { @"⊕", 8853 }, + { @"⊗", 8855 }, + { @"⊥", 8869 }, + { @"⋅", 8901 }, + { @"⌈", 8968 }, + { @"⌉", 8969 }, + { @"⌊", 8970 }, + { @"⌋", 8971 }, + { @"⟨", 9001 }, + { @"⟩", 9002 }, + { @"◊", 9674 }, + { @"♠", 9824 }, + { @"♣", 9827 }, + { @"♥", 9829 }, + { @"♦", 9830 } +}; + +// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters +// This is table A.2.2 Special Characters +static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = { + // C0 Controls and Basic Latin + { @""", 34 }, + { @"&", 38 }, + { @"'", 39 }, + { @"<", 60 }, + { @">", 62 }, + + // Latin Extended-A + { @"Œ", 338 }, + { @"œ", 339 }, + { @"Š", 352 }, + { @"š", 353 }, + { @"Ÿ", 376 }, + + // Spacing Modifier Letters + { @"ˆ", 710 }, + { @"˜", 732 }, + + // General Punctuation + { @" ", 8194 }, + { @" ", 8195 }, + { @" ", 8201 }, + { @"‌", 8204 }, + { @"‍", 8205 }, + { @"‎", 8206 }, + { @"‏", 8207 }, + { @"–", 8211 }, + { @"—", 8212 }, + { @"‘", 8216 }, + { @"’", 8217 }, + { @"‚", 8218 }, + { @"“", 8220 }, + { @"”", 8221 }, + { @"„", 8222 }, + { @"†", 8224 }, + { @"‡", 8225 }, + { @"‰", 8240 }, + { @"‹", 8249 }, + { @"›", 8250 }, + { @"€", 8364 }, +}; + + +// Utility function for Bsearching table above +static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) { + const unichar *uchar = (const unichar*)ucharVoid; + const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid; + int val; + if (*uchar > map->uchar) { + val = 1; + } else if (*uchar < map->uchar) { + val = -1; + } else { + val = 0; + } + return val; +} + +@implementation NSString (GTMNSStringHTMLAdditions) + +- (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table + ofSize:(NSUInteger)size + escapingUnicode:(BOOL)escapeUnicode { + NSUInteger length = [self length]; + if (!length) { + return self; + } + + NSMutableString *finalString = [NSMutableString string]; + NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length]; + + // this block is common between GTMNSString+HTML and GTMNSString+XML but + // it's so short that it isn't really worth trying to share. + const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self); + if (!buffer) { + // We want this buffer to be autoreleased. + NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)]; + if (!data) { + // COV_NF_START - Memory fail case + _GTMDevLog(@"couldn't alloc buffer"); + return nil; + // COV_NF_END + } + [self getCharacters:[data mutableBytes]]; + buffer = [data bytes]; + } + + if (!buffer || !data2) { + // COV_NF_START + _GTMDevLog(@"Unable to allocate buffer or data2"); + return nil; + // COV_NF_END + } + + unichar *buffer2 = (unichar *)[data2 mutableBytes]; + + NSUInteger buffer2Length = 0; + + for (NSUInteger i = 0; i < length; ++i) { + HTMLEscapeMap *val = bsearch(&buffer[i], table, + size / sizeof(HTMLEscapeMap), + sizeof(HTMLEscapeMap), EscapeMapCompare); + if (val || (escapeUnicode && buffer[i] > 127)) { + if (buffer2Length) { + CFStringAppendCharacters((CFMutableStringRef)finalString, + buffer2, + buffer2Length); + buffer2Length = 0; + } + if (val) { + [finalString appendString:val->escapeSequence]; + } + else { + _GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character"); + [finalString appendFormat:@"&#%d;", buffer[i]]; + } + } else { + buffer2[buffer2Length] = buffer[i]; + buffer2Length += 1; + } + } + if (buffer2Length) { + CFStringAppendCharacters((CFMutableStringRef)finalString, + buffer2, + buffer2Length); + } + return finalString; +} + +- (NSString *)gtm_stringByEscapingForHTML { + return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap + ofSize:sizeof(gUnicodeHTMLEscapeMap) + escapingUnicode:NO]; +} // gtm_stringByEscapingHTML + +- (NSString *)gtm_stringByEscapingForAsciiHTML { + return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap + ofSize:sizeof(gAsciiHTMLEscapeMap) + escapingUnicode:YES]; +} // gtm_stringByEscapingAsciiHTML + +- (NSString *)gtm_stringByUnescapingFromHTML { + NSRange range = NSMakeRange(0, [self length]); + NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]; + + // if no ampersands, we've got a quick way out + if (subrange.length == 0) return self; + NSMutableString *finalString = [NSMutableString stringWithString:self]; + do { + NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location); + semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange]; + range = NSMakeRange(0, subrange.location); + // if we don't find a semicolon in the range, we don't have a sequence + if (semiColonRange.location == NSNotFound) { + continue; + } + NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1); + NSString *escapeString = [self substringWithRange:escapeRange]; + NSUInteger length = [escapeString length]; + // a squence must be longer than 3 (<) and less than 11 (ϑ) + if (length > 3 && length < 11) { + if ([escapeString characterAtIndex:1] == '#') { + unichar char2 = [escapeString characterAtIndex:2]; + if (char2 == 'x' || char2 == 'X') { + // Hex escape squences £ + NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)]; + NSScanner *scanner = [NSScanner scannerWithString:hexSequence]; + unsigned value; + if ([scanner scanHexInt:&value] && + value < USHRT_MAX && + value > 0 + && [scanner scanLocation] == length - 4) { + unichar uchar = value; + NSString *charString = [NSString stringWithCharacters:&uchar length:1]; + [finalString replaceCharactersInRange:escapeRange withString:charString]; + } + + } else { + // Decimal Sequences { + NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)]; + NSScanner *scanner = [NSScanner scannerWithString:numberSequence]; + int value; + if ([scanner scanInt:&value] && + value < USHRT_MAX && + value > 0 + && [scanner scanLocation] == length - 3) { + unichar uchar = value; + NSString *charString = [NSString stringWithCharacters:&uchar length:1]; + [finalString replaceCharactersInRange:escapeRange withString:charString]; + } + } + } else { + // "standard" sequences + for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) { + if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) { + [finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]]; + break; + } + } + } + } + } while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0); + return finalString; +} // gtm_stringByUnescapingHTML + + + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTMLTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTMLTest.m new file mode 100644 index 00000000..1c7baf01 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+HTMLTest.m @@ -0,0 +1,242 @@ +// +// GTMNSString+HTMLTest.m +// +// Copyright 2005-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSString+HTML.h" + +@interface GTMNSString_HTMLTest : GTMTestCase +@end + +@implementation GTMNSString_HTMLTest + +- (void)testStringByEscapingHTML { + unichar chars[] = + { 34, 38, 39, 60, 62, 338, 339, 352, 353, 376, 710, 732, + 8194, 8195, 8201, 8204, 8205, 8206, 8207, 8211, 8212, 8216, 8217, 8218, + 8220, 8221, 8222, 8224, 8225, 8240, 8249, 8250, 8364, }; + + NSString *string1 = [NSString stringWithCharacters:chars + length:sizeof(chars) / sizeof(unichar)]; + NSString *string2 = + @""&'<>ŒœŠšŸ" + "ˆ˜   ‌‍‎‏–" + "—‘’‚“”„†‡" + "‰‹›€"; + + STAssertEqualObjects([string1 gtm_stringByEscapingForHTML], + string2, + @"HTML escaping failed"); + + STAssertEqualObjects([@"" gtm_stringByEscapingForHTML], + @"<this & that>", + @"HTML escaping failed"); + NSString *string = [NSString stringWithUTF8String:"パン・&ド・カンパーニュ"]; + NSString *escapeStr = [NSString stringWithUTF8String:"パン・&ド・カンパーニュ"]; + STAssertEqualObjects([string gtm_stringByEscapingForHTML], + escapeStr, + @"HTML escaping failed"); + + string = [NSString stringWithUTF8String:"abcا1ب<تdef&"]; + STAssertEqualObjects([string gtm_stringByEscapingForHTML], + [NSString stringWithUTF8String:"abcا1ب<تdef&"], + @"HTML escaping failed"); + + // test empty string + STAssertEqualObjects([@"" gtm_stringByEscapingForHTML], @"", nil); +} // testStringByEscapingHTML + +- (void)testStringByEscapingAsciiHTML { + unichar chars[] = + { 34, 38, 39, 60, 62, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 338, 339, 352, 353, 376, + 402, 710, 732, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, + 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 945, 946, 947, + 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, + 963, 964, 965, 966, 967, 968, 969, 977, 978, 982, 8194, 8195, 8201, 8204, + 8205, 8206, 8207, 8211, 8212, 8216, 8217, 8218, 8220, 8221, 8222, 8224, 8225, + 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8254, 8260, 8364, 8472, 8465, 8476, + 8482, 8501, 8592, 8593, 8594, 8595, 8596, 8629, 8656, 8657, 8658, 8659, 8660, + 8704, 8706, 8707, 8709, 8711, 8712, 8713, 8715, 8719, 8721, 8722, 8727, 8730, + 8733, 8734, 8736, 8743, 8744, 8745, 8746, 8747, 8756, 8764, 8773, 8776, 8800, + 8801, 8804, 8805, 8834, 8835, 8836, 8838, 8839, 8853, 8855, 8869, 8901, 8968, + 8969, 8970, 8971, 9001, 9002, 9674, 9824, 9827, 9829, 9830 }; + + NSString *string1 = [NSString stringWithCharacters:chars + length:sizeof(chars) / sizeof(unichar)]; + NSString *string2 = + @""&'<> ¡¢£¤¥" + "¦§¨©ª«¬­®¯°" + "±²³´µ¶·¸¹" + "º»¼½¾¿ÀÁ" + "ÂÃÄÅÆÇÈÉ" + "ÊËÌÍÎÏÐÑÒ" + "ÓÔÕÖ×ØÙÚ" + "ÛÜÝÞßàáâã" + "äåæçèéêëì" + "íîïðñòóôõ" + "ö÷øùúûüýþ" + "ÿŒœŠšŸƒˆ˜" + "ΑΒΓΔΕΖΗΘΙ" + "ΚΛΜΝΞΟΠΡΣΤ" + "ΥΦΧΨΩαβγδ" + "εζηθικλμνξ" + "οπρςστυφχψ" + "ωϑϒϖ   ‌‍" + "‎‏–—‘’‚“”" + "„†‡•…‰′″" + "‹›‾⁄€℘ℑℜ™" + "ℵ←↑→↓↔↵⇐⇑⇒" + "⇓⇔∀∂∃∅∇∈∉∋" + "∏∑−∗√∝∞∠∧∨" + "∩∪∫∴∼≅≈≠≡≤≥" + "⊂⊃⊄⊆⊇⊕⊗⊥⋅⌈" + "⌉⌊⌋⟨⟩◊♠♣♥" + "♦"; + + STAssertEqualObjects([string1 gtm_stringByEscapingForAsciiHTML], + string2, + @"HTML escaping failed"); + + STAssertEqualObjects([@"" gtm_stringByEscapingForAsciiHTML], + @"<this & that>", + @"HTML escaping failed"); + NSString *string = [NSString stringWithUTF8String:"パン・ド・カンパーニュ"]; + STAssertEqualObjects([string gtm_stringByEscapingForAsciiHTML], + @"パン・ド・カ" + "ンパーニュ", + @"HTML escaping failed"); + + // Mix in some right - to left + string = [NSString stringWithUTF8String:"abcا1ب<تdef&"]; + STAssertEqualObjects([string gtm_stringByEscapingForAsciiHTML], + @"abcا1ب<تdef&", + @"HTML escaping failed"); +} // stringByEscapingAsciiHTML + +- (void)testStringByUnescapingHTML { + NSString *string1 = + @""&'<> ¡¢£¤¥" + "¦§¨©ª«¬­®¯°" + "±²³´µ¶·¸¹" + "º»¼½¾¿ÀÁ" + "ÂÃÄÅÆÇÈÉ" + "ÊËÌÍÎÏÐÑÒ" + "ÓÔÕÖ×ØÙÚ" + "ÛÜÝÞßàáâã" + "äåæçèéêëì" + "íîïðñòóôõ" + "ö÷øùúûüýþ" + "ÿŒœŠšŸƒˆ˜" + "ΑΒΓΔΕΖΗΘΙ" + "ΚΛΜΝΞΟΠΡΣΤ" + "ΥΦΧΨΩαβγδ" + "εζηθικλμνξ" + "οπρςστυφχψ" + "ωϑϒϖ   ‌‍" + "‎‏–—‘’‚“”" + "„†‡•…‰′″" + "‹›‾⁄€℘ℑℜ™" + "ℵ←↑→↓↔↵⇐⇑⇒" + "⇓⇔∀∂∃∅∇∈∉∋" + "∏∑−∗√∝∞∠∧∨" + "∩∪∫∴∼≅≈≠≡≤≥" + "⊂⊃⊄⊆⊇⊕⊗⊥⋅⌈" + "⌉⌊⌋⟨⟩◊♠♣♥" + "♦"; + + unichar chars[] = + { 34, 38, 39, 60, 62, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 338, 339, 352, 353, 376, + 402, 710, 732, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, + 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 945, 946, 947, + 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, + 963, 964, 965, 966, 967, 968, 969, 977, 978, 982, 8194, 8195, 8201, 8204, + 8205, 8206, 8207, 8211, 8212, 8216, 8217, 8218, 8220, 8221, 8222, 8224, 8225, + 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8254, 8260, 8364, 8472, 8465, 8476, + 8482, 8501, 8592, 8593, 8594, 8595, 8596, 8629, 8656, 8657, 8658, 8659, 8660, + 8704, 8706, 8707, 8709, 8711, 8712, 8713, 8715, 8719, 8721, 8722, 8727, 8730, + 8733, 8734, 8736, 8743, 8744, 8745, 8746, 8747, 8756, 8764, 8773, 8776, 8800, + 8801, 8804, 8805, 8834, 8835, 8836, 8838, 8839, 8853, 8855, 8869, 8901, 8968, + 8969, 8970, 8971, 9001, 9002, 9674, 9824, 9827, 9829, 9830 }; + + NSString *string2 = [NSString stringWithCharacters:chars + length:sizeof(chars) / sizeof(unichar)]; + STAssertEqualObjects([string1 gtm_stringByUnescapingFromHTML], + string2, + @"HTML unescaping failed"); + + STAssertEqualObjects([@"ABC" gtm_stringByUnescapingFromHTML], + @"ABC", @"HTML unescaping failed"); + + STAssertEqualObjects([@"" gtm_stringByUnescapingFromHTML], + @"", @"HTML unescaping failed"); + + STAssertEqualObjects([@"A&Bang;C" gtm_stringByUnescapingFromHTML], + @"A&Bang;C", @"HTML unescaping failed"); + + STAssertEqualObjects([@"A&Bang;C" gtm_stringByUnescapingFromHTML], + @"A&Bang;C", @"HTML unescaping failed"); + + STAssertEqualObjects([@"A&Bang;C" gtm_stringByUnescapingFromHTML], + @"A&Bang;C", @"HTML unescaping failed"); + + STAssertEqualObjects([@"AA;" gtm_stringByUnescapingFromHTML], + @"AA;", @"HTML unescaping failed"); + + STAssertEqualObjects([@"&" gtm_stringByUnescapingFromHTML], + @"&", @"HTML unescaping failed"); + + STAssertEqualObjects([@"&;" gtm_stringByUnescapingFromHTML], + @"&;", @"HTML unescaping failed"); + + STAssertEqualObjects([@"&x;" gtm_stringByUnescapingFromHTML], + @"&x;", @"HTML unescaping failed"); + + STAssertEqualObjects([@"&X;" gtm_stringByUnescapingFromHTML], + @"&X;", @"HTML unescaping failed"); + + STAssertEqualObjects([@";" gtm_stringByUnescapingFromHTML], + @";", @"HTML unescaping failed"); + + STAssertEqualObjects([@"<this & that>" gtm_stringByUnescapingFromHTML], + @"", @"HTML unescaping failed"); + + +} // testStringByUnescapingHTML + +- (void)testStringRoundtrippingEscapedHTML { + NSString *string = [NSString stringWithUTF8String:"This test ©™®๒०᠐٧"]; + STAssertEqualObjects(string, + [[string gtm_stringByEscapingForHTML] gtm_stringByUnescapingFromHTML], + @"HTML Roundtripping failed"); + string = [NSString stringWithUTF8String:"This test ©™®๒०᠐٧"]; + STAssertEqualObjects(string, + [[string gtm_stringByEscapingForAsciiHTML] gtm_stringByUnescapingFromHTML], + @"HTML Roundtripping failed"); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.h new file mode 100644 index 00000000..71a98c5f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.h @@ -0,0 +1,45 @@ +// +// GTMNSString+Replace.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Give easy search-n-replace functionality to NSString. +@interface NSString (GTMStringReplaceAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +// 10.5 has stringByReplacingOccurrencesOfString:withString:, use that directly. + +/// Returns a new autoreleased string by replacing all occurrences of +// |oldString| with |newString| (case sensitive). If |oldString| is nil or +// @"" nothing is done and |self| is returned. If |newString| is nil, it's +// treated as if |newString| were the empty string, thus effectively +// deleting all occurrences of |oldString| from |self|. +// +// Args: +// target - the NSString to search for +// replacement - the NSString to replace |oldString| with +// +// Returns: +// A new autoreleased NSString +// +- (NSString *)gtm_stringByReplacingString:(NSString *)target + withString:(NSString *)replacement; + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.m new file mode 100644 index 00000000..ddaad5ed --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+Replace.m @@ -0,0 +1,53 @@ +// +// GTMNSString+Replace.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSString+Replace.h" + + +@implementation NSString (GTMStringReplaceAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +// 10.5 has stringByReplacingOccurrencesOfString:withString:, use that directly. + +- (NSString *)gtm_stringByReplacingString:(NSString *)target + withString:(NSString *)replacement { + // If |target| was nil, then do nothing and return |self| + // + // We do the retain+autorelease dance here because of this use case: + // NSString *s1 = [[NSString alloc] init...]; + // NSString *s2 = [s1 stringByReplacingString:@"foo" withString:@"bar"]; + // [s1 release]; // |s2| still needs to be valid after this line + if (!target) + return [[self retain] autorelease]; + + // If |replacement| is nil we want it to be treated as if @"" was specified + // ... effectively removing |target| from self + if (!replacement) + replacement = @""; + + NSMutableString *result = [[self mutableCopy] autorelease]; + [result replaceOccurrencesOfString:target + withString:replacement + options:0 + range:NSMakeRange(0, [result length])]; + return result; +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+ReplaceTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+ReplaceTest.m new file mode 100644 index 00000000..4561af66 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+ReplaceTest.m @@ -0,0 +1,59 @@ +// +// GTMNSString+ReplaceTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSString+Replace.h" + +@interface GTMNSString_ReplaceTest : GTMTestCase +@end + +@implementation GTMNSString_ReplaceTest + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (void)testStringByReplacingStringWithString { + NSString *testString = @"a bc debc gh"; + NSString *result; + + result = [testString gtm_stringByReplacingString:@"bc" withString:@"BC"]; + STAssertEqualObjects(@"a BC deBC gh", result, + @"'bc' wasn't replaced with 'BC'"); + + result = [testString gtm_stringByReplacingString:@"bc" withString:@""]; + STAssertEqualObjects(@"a de gh", result, @"'bc' wasn't replaced with ''"); + + result = [testString gtm_stringByReplacingString:@"bc" withString:nil]; + STAssertEqualObjects(@"a de gh", result, @"'bc' wasn't replaced with (nil)"); + + result = [testString gtm_stringByReplacingString:@" " withString:@"S"]; + STAssertEqualObjects(@"aSbcSdebcSgh", result, @"' ' wasn't replaced with 'S'"); + + result = [testString gtm_stringByReplacingString:nil withString:@"blah"]; + STAssertEqualObjects(testString, result, @"(nil) wasn't replaced with 'blah'"); + + result = [testString gtm_stringByReplacingString:nil withString:nil]; + STAssertEqualObjects(testString, result, @"(nil) wasn't replaced with (nil)"); + + result = [testString gtm_stringByReplacingString:@"" withString:@"X"]; + STAssertEqualObjects(testString, result, + @"replacing '' with anything should yield the original string"); +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.h new file mode 100644 index 00000000..d4c7e09a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.h @@ -0,0 +1,41 @@ +// +// GTMNSString+URLArguments.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Utilities for encoding and decoding URL arguments. +@interface NSString (GTMNSStringURLArgumentsAdditions) + +/// Returns a string that is escaped properly to be a URL argument. +// +/// This differs from stringByAddingPercentEscapesUsingEncoding: in that it +/// will escape all the reserved characters (per RFC 3986 +/// ) which +/// stringByAddingPercentEscapesUsingEncoding would leave. +/// +/// This will also escape '%', so this should not be used on a string that has +/// already been escaped unless double-escaping is the desired result. +- (NSString*)gtm_stringByEscapingForURLArgument; + +/// Returns the unescaped version of a URL argument +// +/// This has the same behavior as stringByReplacingPercentEscapesUsingEncoding:, +/// except that it will also convert '+' to space. +- (NSString*)gtm_stringByUnescapingFromURLArgument; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.m new file mode 100644 index 00000000..46d2c99e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArguments.m @@ -0,0 +1,45 @@ +// +// GTMNSString+URLArguments.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSString+URLArguments.h" +#import "GTMGarbageCollection.h" + +@implementation NSString (GTMNSStringURLArgumentsAdditions) + +- (NSString*)gtm_stringByEscapingForURLArgument { + // Encode all the reserved characters, per RFC 3986 + // () + CFStringRef escaped = + CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + (CFStringRef)self, + NULL, + (CFStringRef)@"!*'();:@&=+$,/?%#[]", + kCFStringEncodingUTF8); + return GTMCFAutorelease(escaped); +} + +- (NSString*)gtm_stringByUnescapingFromURLArgument { + NSMutableString *resultString = [NSMutableString stringWithString:self]; + [resultString replaceOccurrencesOfString:@"+" + withString:@" " + options:NSLiteralSearch + range:NSMakeRange(0, [resultString length])]; + return [resultString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArgumentsTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArgumentsTest.m new file mode 100644 index 00000000..90a5a813 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+URLArgumentsTest.m @@ -0,0 +1,94 @@ +// +// GTMNSString+URLArgumentsTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMNSString+URLArguments.h" + +@interface GTMNSString_URLArgumentsTest : GTMTestCase +@end + +@implementation GTMNSString_URLArgumentsTest + + +- (void)testEscaping { + // should be done already by the basic code + STAssertEqualObjects([@"this that" gtm_stringByEscapingForURLArgument], @"this%20that", @"- space should be escaped"); + STAssertEqualObjects([@"this\"that" gtm_stringByEscapingForURLArgument], @"this%22that", @"- double quote should be escaped"); + // make sure our additions are handled + STAssertEqualObjects([@"this!that" gtm_stringByEscapingForURLArgument], @"this%21that", @"- exclamation mark should be escaped"); + STAssertEqualObjects([@"this*that" gtm_stringByEscapingForURLArgument], @"this%2Athat", @"- asterisk should be escaped"); + STAssertEqualObjects([@"this'that" gtm_stringByEscapingForURLArgument], @"this%27that", @"- single quote should be escaped"); + STAssertEqualObjects([@"this(that" gtm_stringByEscapingForURLArgument], @"this%28that", @"- left paren should be escaped"); + STAssertEqualObjects([@"this)that" gtm_stringByEscapingForURLArgument], @"this%29that", @"- right paren should be escaped"); + STAssertEqualObjects([@"this;that" gtm_stringByEscapingForURLArgument], @"this%3Bthat", @"- semi-colon should be escaped"); + STAssertEqualObjects([@"this:that" gtm_stringByEscapingForURLArgument], @"this%3Athat", @"- colon should be escaped"); + STAssertEqualObjects([@"this@that" gtm_stringByEscapingForURLArgument], @"this%40that", @"- at sign should be escaped"); + STAssertEqualObjects([@"this&that" gtm_stringByEscapingForURLArgument], @"this%26that", @"- ampersand should be escaped"); + STAssertEqualObjects([@"this=that" gtm_stringByEscapingForURLArgument], @"this%3Dthat", @"- equals should be escaped"); + STAssertEqualObjects([@"this+that" gtm_stringByEscapingForURLArgument], @"this%2Bthat", @"- plus should be escaped"); + STAssertEqualObjects([@"this$that" gtm_stringByEscapingForURLArgument], @"this%24that", @"- dollar-sign should be escaped"); + STAssertEqualObjects([@"this,that" gtm_stringByEscapingForURLArgument], @"this%2Cthat", @"- comma should be escaped"); + STAssertEqualObjects([@"this/that" gtm_stringByEscapingForURLArgument], @"this%2Fthat", @"- slash should be escaped"); + STAssertEqualObjects([@"this?that" gtm_stringByEscapingForURLArgument], @"this%3Fthat", @"- question mark should be escaped"); + STAssertEqualObjects([@"this%that" gtm_stringByEscapingForURLArgument], @"this%25that", @"- percent should be escaped"); + STAssertEqualObjects([@"this#that" gtm_stringByEscapingForURLArgument], @"this%23that", @"- pound should be escaped"); + STAssertEqualObjects([@"this[that" gtm_stringByEscapingForURLArgument], @"this%5Bthat", @"- left bracket should be escaped"); + STAssertEqualObjects([@"this]that" gtm_stringByEscapingForURLArgument], @"this%5Dthat", @"- right bracket should be escaped"); + // make sure plus and space are handled in the right order + STAssertEqualObjects([@"this that+the other" gtm_stringByEscapingForURLArgument], @"this%20that%2Bthe%20other", @"- pluses and spaces should be different"); + // high char test + NSString *tester = [NSString stringWithUTF8String:"caf\xC3\xA9"]; + STAssertNotNil(tester, @"failed to create from utf8 run"); + STAssertEqualObjects([tester gtm_stringByEscapingForURLArgument], @"caf%C3%A9", @"- high chars should work"); +} + +- (void)testUnescaping { + // should be done already by the basic code + STAssertEqualObjects([@"this%20that" gtm_stringByUnescapingFromURLArgument], @"this that", @"- space should be unescaped"); + STAssertEqualObjects([@"this%22that" gtm_stringByUnescapingFromURLArgument], @"this\"that", @"- double quote should be unescaped"); + // make sure our additions are handled + STAssertEqualObjects([@"this%21that" gtm_stringByUnescapingFromURLArgument], @"this!that", @"- exclamation mark should be unescaped"); + STAssertEqualObjects([@"this%2Athat" gtm_stringByUnescapingFromURLArgument], @"this*that", @"- asterisk should be unescaped"); + STAssertEqualObjects([@"this%27that" gtm_stringByUnescapingFromURLArgument], @"this'that", @"- single quote should be unescaped"); + STAssertEqualObjects([@"this%28that" gtm_stringByUnescapingFromURLArgument], @"this(that", @"- left paren should be unescaped"); + STAssertEqualObjects([@"this%29that" gtm_stringByUnescapingFromURLArgument], @"this)that", @"- right paren should be unescaped"); + STAssertEqualObjects([@"this%3Bthat" gtm_stringByUnescapingFromURLArgument], @"this;that", @"- semi-colon should be unescaped"); + STAssertEqualObjects([@"this%3Athat" gtm_stringByUnescapingFromURLArgument], @"this:that", @"- colon should be unescaped"); + STAssertEqualObjects([@"this%40that" gtm_stringByUnescapingFromURLArgument], @"this@that", @"- at sign should be unescaped"); + STAssertEqualObjects([@"this%26that" gtm_stringByUnescapingFromURLArgument], @"this&that", @"- ampersand should be unescaped"); + STAssertEqualObjects([@"this%3Dthat" gtm_stringByUnescapingFromURLArgument], @"this=that", @"- equals should be unescaped"); + STAssertEqualObjects([@"this%2Bthat" gtm_stringByUnescapingFromURLArgument], @"this+that", @"- plus should be unescaped"); + STAssertEqualObjects([@"this%24that" gtm_stringByUnescapingFromURLArgument], @"this$that", @"- dollar-sign should be unescaped"); + STAssertEqualObjects([@"this%2Cthat" gtm_stringByUnescapingFromURLArgument], @"this,that", @"- comma should be unescaped"); + STAssertEqualObjects([@"this%2Fthat" gtm_stringByUnescapingFromURLArgument], @"this/that", @"- slash should be unescaped"); + STAssertEqualObjects([@"this%3Fthat" gtm_stringByUnescapingFromURLArgument], @"this?that", @"- question mark should be unescaped"); + STAssertEqualObjects([@"this%25that" gtm_stringByUnescapingFromURLArgument], @"this%that", @"- percent should be unescaped"); + STAssertEqualObjects([@"this%23that" gtm_stringByUnescapingFromURLArgument], @"this#that", @"- pound should be unescaped"); + STAssertEqualObjects([@"this%5Bthat" gtm_stringByUnescapingFromURLArgument], @"this[that", @"- left bracket should be unescaped"); + STAssertEqualObjects([@"this%5Dthat" gtm_stringByUnescapingFromURLArgument], @"this]that", @"- right bracket should be unescaped"); + // make sure a plus come back out as a space + STAssertEqualObjects([[NSString stringWithString:@"this+that"] gtm_stringByUnescapingFromURLArgument], @"this that", @"- plus should be unescaped"); + // make sure plus and %2B are handled in the right order + STAssertEqualObjects([@"this+that%2Bthe%20other" gtm_stringByUnescapingFromURLArgument], @"this that+the other", @"- pluses and spaces should be different"); + // high char test + NSString *tester = [NSString stringWithUTF8String:"caf\xC3\xA9"]; + STAssertNotNil(tester, @"failed to create from utf8 run"); + STAssertEqualObjects([[NSString stringWithString:@"caf%C3%A9"] gtm_stringByUnescapingFromURLArgument], tester, @"- high chars should work"); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.h new file mode 100644 index 00000000..6ef54d71 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.h @@ -0,0 +1,51 @@ +// +// GTMNSString+XML.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Utilities for NSStrings containing XML +@interface NSString (GTMNSStringXMLAdditions) + +/// Get a string where characters that need escaping for XML are escaped and invalid characters removed +// +/// This call escapes '&', '<, '>', '\'', '"' per the xml spec and removes all +/// invalid characters as defined by Section 2.2 of the xml spec. +/// +/// For obvious reasons this call is only safe once. +// +// Returns: +// Autoreleased NSString +// +- (NSString *)gtm_stringBySanitizingAndEscapingForXML; + +/// Get a string where characters that invalid characters per the XML spec have been removed +// +/// This call removes all invalid characters as defined by Section 2.2 of the +/// xml spec. If you are writing XML yourself, you probably was to use the +/// above api (gtm_stringBySanitizingAndEscapingForXML) so any entities also +/// get escaped. +// +// Returns: +// Autoreleased NSString +// +- (NSString *)gtm_stringBySanitizingToXMLSpec; + +// There is no stringByUnescapingFromXML because the XML parser will do this. +// The above api is here just incase you need to create XML yourself. + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.m new file mode 100644 index 00000000..0e16ddba --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XML.m @@ -0,0 +1,182 @@ +// +// GTMNSString+XML.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import "GTMNSString+XML.h" +#import "GTMGarbageCollection.h" + +enum { + kGTMXMLCharModeEncodeQUOT = 0, + kGTMXMLCharModeEncodeAMP = 1, + kGTMXMLCharModeEncodeAPOS = 2, + kGTMXMLCharModeEncodeLT = 3, + kGTMXMLCharModeEncodeGT = 4, + kGTMXMLCharModeValid = 99, + kGTMXMLCharModeInvalid = 100, +}; +typedef NSUInteger GTMXMLCharMode; + +static NSString *gXMLEntityList[] = { + // this must match the above order + @""", + @"&", + @"'", + @"<", + @">", +}; + +GTM_INLINE GTMXMLCharMode XMLModeForUnichar(UniChar c) { + + // Per XML spec Section 2.2 Characters + // ( http://www.w3.org/TR/REC-xml/#charsets ) + // + // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | + // [#x10000-#x10FFFF] + + if (c <= 0xd7ff) { + if (c >= 0x20) { + switch (c) { + case 34: + return kGTMXMLCharModeEncodeQUOT; + case 38: + return kGTMXMLCharModeEncodeAMP; + case 39: + return kGTMXMLCharModeEncodeAPOS; + case 60: + return kGTMXMLCharModeEncodeLT; + case 62: + return kGTMXMLCharModeEncodeGT; + default: + return kGTMXMLCharModeValid; + } + } else { + if (c == '\n') + return kGTMXMLCharModeValid; + if (c == '\r') + return kGTMXMLCharModeValid; + if (c == '\t') + return kGTMXMLCharModeValid; + return kGTMXMLCharModeInvalid; + } + } + + if (c < 0xE000) + return kGTMXMLCharModeInvalid; + + if (c <= 0xFFFD) + return kGTMXMLCharModeValid; + + // UniChar can't have the following values + // if (c < 0x10000) + // return kGTMXMLCharModeInvalid; + // if (c <= 0x10FFFF) + // return kGTMXMLCharModeValid; + + return kGTMXMLCharModeInvalid; +} // XMLModeForUnichar + + +static NSString *AutoreleasedCloneForXML(NSString *src, BOOL escaping) { + // + // NOTE: + // We don't use CFXMLCreateStringByEscapingEntities because it's busted in + // 10.3 (http://lists.apple.com/archives/Cocoa-dev/2004/Nov/msg00059.html) and + // it doesn't do anything about the chars that are actually invalid per the + // xml spec. + // + + // we can't use the CF call here because it leaves the invalid chars + // in the string. + NSUInteger length = [src length]; + if (!length) { + return src; + } + + NSMutableString *finalString = [NSMutableString string]; + + // this block is common between GTMNSString+HTML and GTMNSString+XML but + // it's so short that it isn't really worth trying to share. + const UniChar *buffer = CFStringGetCharactersPtr((CFStringRef)src); + if (!buffer) { + // We want this buffer to be autoreleased. + NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)]; + if (!data) { + // COV_NF_START - Memory fail case + _GTMDevLog(@"couldn't alloc buffer"); + return nil; + // COV_NF_END + } + [src getCharacters:[data mutableBytes]]; + buffer = [data bytes]; + } + + const UniChar *goodRun = buffer; + NSUInteger goodRunLength = 0; + + for (NSUInteger i = 0; i < length; ++i) { + + GTMXMLCharMode cMode = XMLModeForUnichar(buffer[i]); + + // valid chars go as is, and if we aren't doing entities, then + // everything goes as is. + if ((cMode == kGTMXMLCharModeValid) || + (!escaping && (cMode != kGTMXMLCharModeInvalid))) { + // goes as is + goodRunLength += 1; + } else { + // it's something we have to encode or something invalid + + // start by adding what we already collected (if anything) + if (goodRunLength) { + CFStringAppendCharacters((CFMutableStringRef)finalString, + goodRun, + goodRunLength); + goodRunLength = 0; + } + + // if it wasn't invalid, add the encoded version + if (cMode != kGTMXMLCharModeInvalid) { + // add this encoded + [finalString appendString:gXMLEntityList[cMode]]; + } + + // update goodRun to point to the next UniChar + goodRun = buffer + i + 1; + } + } + + // anything left to add? + if (goodRunLength) { + CFStringAppendCharacters((CFMutableStringRef)finalString, + goodRun, + goodRunLength); + } + return finalString; +} // AutoreleasedCloneForXML + +@implementation NSString (GTMNSStringXMLAdditions) + +- (NSString *)gtm_stringBySanitizingAndEscapingForXML { + return AutoreleasedCloneForXML(self, YES); +} // gtm_stringBySanitizingAndEscapingForXML + +- (NSString *)gtm_stringBySanitizingToXMLSpec { + return AutoreleasedCloneForXML(self, NO); +} // gtm_stringBySanitizingToXMLSpec + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XMLTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XMLTest.m new file mode 100644 index 00000000..4788690f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMNSString+XMLTest.m @@ -0,0 +1,93 @@ +// +// GTMNSString+XMLTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#import "GTMSenTestCase.h" +#import "GTMNSString+XML.h" + + +@interface GTMNSString_XMLTest : GTMTestCase +@end + +@implementation GTMNSString_XMLTest + +- (void)testStringBySanitizingAndEscapingForXML { + // test the substitutions cases + UniChar chars[] = { + 'z', 0, 'z', 1, 'z', 4, 'z', 5, 'z', 34, 'z', 38, 'z', 39, 'z', + 60, 'z', 62, 'z', ' ', 'z', 0xd800, 'z', 0xDFFF, 'z', 0xE000, + 'z', 0xFFFE, 'z', 0xFFFF, 'z', '\n', 'z', '\r', 'z', '\t', 'z' }; + + NSString *string1 = [NSString stringWithCharacters:chars + length:sizeof(chars) / sizeof(UniChar)]; + NSString *string2 = + [NSString stringWithFormat:@"zzzzz"z&z'z<z>z zzz%Czzz\nz\rz\tz", + 0xE000]; + + STAssertEqualObjects([string1 gtm_stringBySanitizingAndEscapingForXML], + string2, + @"Sanitize and Escape for XML failed"); + + // force the backing store of the NSString to test extraction paths + char ascBuffer[] = "a\01bcde\nf"; + NSString *ascString = + [[[NSString alloc] initWithBytesNoCopy:ascBuffer + length:sizeof(ascBuffer) / sizeof(char) + encoding:NSASCIIStringEncoding + freeWhenDone:NO] autorelease]; + STAssertEqualObjects([ascString gtm_stringBySanitizingAndEscapingForXML], + @"abcde\nf", + @"Sanitize and Escape for XML from asc buffer failed"); + + // test empty string + STAssertEqualObjects([@"" gtm_stringBySanitizingAndEscapingForXML], @"", nil); +} + +- (void)testStringBySanitizingToXMLSpec { + // test the substitutions cases + UniChar chars[] = { + 'z', 0, 'z', 1, 'z', 4, 'z', 5, 'z', 34, 'z', 38, 'z', 39, 'z', + 60, 'z', 62, 'z', ' ', 'z', 0xd800, 'z', 0xDFFF, 'z', 0xE000, + 'z', 0xFFFE, 'z', 0xFFFF, 'z', '\n', 'z', '\r', 'z', '\t', 'z' }; + + NSString *string1 = [NSString stringWithCharacters:chars + length:sizeof(chars) / sizeof(UniChar)]; + NSString *string2 = + [NSString stringWithFormat:@"zzzzz\"z&z'zz zzz%Czzz\nz\rz\tz", + 0xE000]; + + STAssertEqualObjects([string1 gtm_stringBySanitizingToXMLSpec], + string2, + @"Sanitize for XML failed"); + + // force the backing store of the NSString to test extraction paths + char ascBuffer[] = "a\01bcde\nf"; + NSString *ascString = + [[[NSString alloc] initWithBytesNoCopy:ascBuffer + length:sizeof(ascBuffer) / sizeof(char) + encoding:NSASCIIStringEncoding + freeWhenDone:NO] autorelease]; + STAssertEqualObjects([ascString gtm_stringBySanitizingToXMLSpec], + @"abcde\nf", + @"Sanitize and Escape for XML from asc buffer failed"); + + // test empty string + STAssertEqualObjects([@"" gtm_stringBySanitizingToXMLSpec], @"", nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.h new file mode 100644 index 00000000..2c258419 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.h @@ -0,0 +1,106 @@ +// +// GTMObjC2Runtime.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// These functions exist for code that we want to compile on both the < 10.5 +// sdks and on the >= 10.5 sdks without warnings. It basically reimplements +// certain parts of the objc2 runtime in terms of the objc1 runtime. It is not +// a complete implementation as I've only implemented the routines I know we +// use. Feel free to add more as necessary. +// These functions are not documented because they conform to the documentation +// for the ObjC2 Runtime. + +#if OBJC_API_VERSION >= 2 // Only have optional and req'd keywords in ObjC2. +#define AT_OPTIONAL @optional +#define AT_REQUIRED @required +#else +#define AT_OPTIONAL +#define AT_REQUIRED +#endif + +// The file objc-runtime.h was moved to runtime.h and in Leopard, objc-runtime.h +// was just a wrapper around runtime.h. For the iPhone SDK, this objc-runtime.h +// is removed in the iPhoneOS2.0 SDK. +// +// The |Object| class was removed in the iPhone2.0 SDK too. +#if GTM_IPHONE_SDK +#import +#else +#import +#import +#endif + +#import + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +#import "objc/Protocol.h" + +OBJC_EXPORT Class object_getClass(id obj); +OBJC_EXPORT const char *class_getName(Class cls); +OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol); +OBJC_EXPORT Class class_getSuperclass(Class cls); +OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount); +OBJC_EXPORT SEL method_getName(Method m); +OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2); +OBJC_EXPORT IMP method_getImplementation(Method method); +OBJC_EXPORT IMP method_setImplementation(Method method, IMP imp); +OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p, + SEL aSel, + BOOL isRequiredMethod, + BOOL isInstanceMethod); + +// If building for 10.4 but using the 10.5 SDK, don't include these. +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +// atomics +// On Leopard these are GC aware +// Intentionally did not include the non-barrier versions, because I couldn't +// come up with a case personally where you wouldn't want to use the +// barrier versions. +GTM_INLINE bool OSAtomicCompareAndSwapPtrBarrier(void *predicate, + void *replacement, + volatile void *theValue) { +#if defined(__LP64__) && __LP64__ + return OSAtomicCompareAndSwap64Barrier((int64_t)predicate, + (int64_t)replacement, + (int64_t *)theValue); +#else // defined(__LP64__) && __LP64__ + return OSAtomicCompareAndSwap32Barrier((int32_t)predicate, + (int32_t)replacement, + (int32_t *)theValue); +#endif // defined(__LP64__) && __LP64__ +} + +GTM_INLINE BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate, + id replacement, + volatile id *objectLocation) { + return OSAtomicCompareAndSwapPtrBarrier(predicate, + replacement, + objectLocation); +} +GTM_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate, + id replacement, + volatile id *objectLocation) { + return OSAtomicCompareAndSwapPtrBarrier(predicate, + replacement, + objectLocation); +} +#endif + +#endif // OBJC2_UNAVAILABLE diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.m new file mode 100644 index 00000000..98356549 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2Runtime.m @@ -0,0 +1,156 @@ +// +// GTMObjC2Runtime.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMObjC2Runtime.h" + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +#import +#import + +Class object_getClass(id obj) { + if (!obj) return NULL; + return obj->isa; +} + +const char *class_getName(Class cls) { + if (!cls) return "nil"; + return cls->name; +} + +BOOL class_conformsToProtocol(Class cls, Protocol *protocol) { + // We intentionally don't check cls as it crashes on Leopard so we want + // to crash on Tiger as well. + // I logged + // Radar 5572978 class_conformsToProtocol crashes when arg1 is passed as nil + // because it seems odd that this API won't accept nil for cls considering + // all the other apis will accept nil args. + // If this does get fixed, remember to enable the unit tests. + if (!protocol) return NO; + + struct objc_protocol_list *protos; + for (protos = cls->protocols; protos != NULL; protos = protos->next) { + for (long i = 0; i < protos->count; i++) { + if ([protos->list[i] conformsTo:protocol]) { + return YES; + } + } + } + return NO; +} + +Class class_getSuperclass(Class cls) { + if (!cls) return NULL; + return cls->super_class; +} + +Method *class_copyMethodList(Class cls, unsigned int *outCount) { + if (!cls) return NULL; + + unsigned int count = 0; + void *iterator = NULL; + struct objc_method_list *mlist; + Method *methods = NULL; + if (outCount) *outCount = 0; + + while ( (mlist = class_nextMethodList(cls, &iterator)) ) { + if (mlist->method_count == 0) continue; + methods = (Method *)realloc(methods, + sizeof(Method) * (count + mlist->method_count + 1)); + if (!methods) { + //Memory alloc failed, so what can we do? + return NULL; // COV_NF_LINE + } + for (int i = 0; i < mlist->method_count; i++) { + methods[i + count] = &mlist->method_list[i]; + } + count += mlist->method_count; + } + + // List must be NULL terminated + if (methods) { + methods[count] = NULL; + } + if (outCount) *outCount = count; + return methods; +} + +SEL method_getName(Method method) { + if (!method) return NULL; + return method->method_name; +} + +IMP method_getImplementation(Method method) { + if (!method) return NULL; + return method->method_imp; +} + +IMP method_setImplementation(Method method, IMP imp) { + // We intentionally don't test method for nil. + // Leopard fails here, so should we. + // I logged this as Radar: + // 5572981 method_setImplementation crashes if you pass nil for the + // method arg (arg 1) + // because it seems odd that this API won't accept nil for method considering + // all the other apis will accept nil args. + // If this does get fixed, remember to enable the unit tests. + // This method works differently on SnowLeopard than + // on Leopard. If you pass in a nil for IMP on SnowLeopard + // it doesn't change anything. On Leopard it will. Since + // attempting to change a sel to nil is probably an error + // we follow the SnowLeopard way of doing things. + IMP oldImp = NULL; + if (imp) { + oldImp = method->method_imp; + method->method_imp = imp; + } + return oldImp; +} + +void method_exchangeImplementations(Method m1, Method m2) { + if (m1 == m2) return; + if (!m1 || !m2) return; + IMP imp2 = method_getImplementation(m2); + IMP imp1 = method_setImplementation(m1, imp2); + method_setImplementation(m2, imp1); +} + +struct objc_method_description protocol_getMethodDescription(Protocol *p, + SEL aSel, + BOOL isRequiredMethod, + BOOL isInstanceMethod) { + struct objc_method_description *descPtr = NULL; + // No such thing as required in ObjC1. + if (isInstanceMethod) { + descPtr = [p descriptionForInstanceMethod:aSel]; + } else { + descPtr = [p descriptionForClassMethod:aSel]; + } + + struct objc_method_description desc; + if (descPtr) { + desc = *descPtr; + } else { + bzero(&desc, sizeof(desc)); + } + return desc; +} + + +#endif + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2RuntimeTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2RuntimeTest.m new file mode 100644 index 00000000..7344a0f8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjC2RuntimeTest.m @@ -0,0 +1,424 @@ +// +// GTMObjC2RuntimeTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMObjC2Runtime.h" +#import "GTMSenTestCase.h" +#import "GTMSystemVersion.h" + + + +#import + +@protocol GTMObjC2Runtime_TestProtocol +@end + +@protocol GTMObjC2Runtime_Test2Protocol +AT_OPTIONAL +- (NSString*)optional; +AT_REQUIRED +- (NSString*)required; +AT_OPTIONAL ++ (NSString*)class_optional; +AT_REQUIRED ++ (NSString*)class_required; +@end + +@interface GTMObjC2RuntimeTest : GTMTestCase { + Class cls_; +} +@end + +@interface GTMObjC2Runtime_TestClass : NSObject +- (NSString*)kwyjibo; + +@end + +@interface GTMObjC2Runtime_TestClass (GMObjC2Runtime_TestClassCategory) +- (NSString*)eatMyShorts; +@end + +@implementation GTMObjC2Runtime_TestClass + ++ (NSString*)dontHaveACow { + return @"dontHaveACow"; +} + +- (NSString*)kwyjibo { + return @"kwyjibo"; +} +@end + +@implementation GTMObjC2Runtime_TestClass (GMObjC2Runtime_TestClassCategory) +- (NSString*)eatMyShorts { + return @"eatMyShorts"; +} + ++ (NSString*)brokeHisBrain { + return @"brokeHisBrain"; +} + +@end + +@interface GTMObjC2NotificationWatcher : NSObject +@end + +@implementation GTMObjC2NotificationWatcher +- (id)init { + if ((self = [super init])) { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + // We release ourselves when we are notified. + [self retain]; + [nc addObserver:self + selector:@selector(startedTest:) + name:SenTestSuiteDidStartNotification + object:nil]; + + } + return self; +} + +- (void)startedTest:(NSNotification *)notification { + // Logs if we are testing on Tiger or Leopard runtime. + NSString *testName = [(SenTest*)[[notification object] test] name]; + NSString *className = NSStringFromClass([GTMObjC2RuntimeTest class]); + if ([testName isEqualToString:className]) { + NSString *runtimeString; +#ifndef OBJC2_UNAVAILABLE + runtimeString = @"ObjC1"; +#else + runtimeString = @"ObjC2"; +#endif + NSLog(@"Running GTMObjC2RuntimeTests using %@ runtime.", runtimeString); + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self]; + [self autorelease]; + } +} +@end + +@implementation GTMObjC2RuntimeTest + ++ (void)initialize { + // This allows us to track which runtime we are actually testing. + [[[GTMObjC2NotificationWatcher alloc] init] autorelease]; +} + +- (void)setUp { + cls_ = [[GTMObjC2Runtime_TestClass class] retain]; +} + +- (void)tearDown { + [cls_ release]; +} + +- (void)test_object_getClass { + // Nil Checks + STAssertNil(object_getClass(nil), nil); + + // Standard use check + GTMObjC2Runtime_TestClass *test = [[[cls_ alloc] init] autorelease]; + Class cls = object_getClass(test); + STAssertEqualObjects(cls, cls_, nil); +} + +- (void)test_class_getName { + // Nil Checks + const char *name = class_getName(nil); + STAssertEqualCStrings(name, "nil", nil); + + // Standard use check + STAssertEqualCStrings(class_getName(cls_), "GTMObjC2Runtime_TestClass", nil); +} + +- (void)test_class_conformsToProtocol { + // Nil Checks + STAssertFalse(class_conformsToProtocol(cls_, @protocol(NSObject)), nil); + STAssertFalse(class_conformsToProtocol(cls_, nil), nil); + // The following two tests intentionally commented out as they fail on + // Leopard with a crash, so we fail on Tiger intentionally as well. + // STAssertFalse(class_conformsToProtocol(nil, @protocol(NSObject)), nil); + // STAssertFalse(class_conformsToProtocol(nil, nil), nil); + + // Standard use check + STAssertTrue(class_conformsToProtocol(cls_, + @protocol(GTMObjC2Runtime_TestProtocol)), + nil); +} + +- (void)test_class_getSuperclass { + // Nil Checks + STAssertNil(class_getSuperclass(nil), nil); + + // Standard use check + STAssertEqualObjects(class_getSuperclass(cls_), [NSObject class], nil); +} + +- (void)test_class_copyMethodList { + // Nil Checks + Method *list = class_copyMethodList(nil, nil); + STAssertNULL(list, nil); + + // Standard use check + list = class_copyMethodList(cls_, nil); + STAssertNotNULL(list, nil); + free(list); + unsigned int count = 0; + list = class_copyMethodList(cls_, &count); + STAssertNotNULL(list, nil); + STAssertEquals(count, 2U, nil); + STAssertNULL(list[count], nil); + free(list); + + // Now test meta class + count = 0; + list = class_copyMethodList((Class)objc_getMetaClass(class_getName(cls_)), + &count); + STAssertNotNULL(list, nil); + STAssertEquals(count, 2U, nil); + STAssertNULL(list[count], nil); + free(list); +} + +- (void)test_method_getName { + // Nil Checks + STAssertNULL(method_getName(nil), nil); + + // Standard use check + Method *list = class_copyMethodList(cls_, nil); + STAssertNotNULL(list, nil); + const char* selName1 = sel_getName(method_getName(list[0])); + const char* selName2 = sel_getName(@selector(kwyjibo)); + const char* selName3 = sel_getName(@selector(eatMyShorts)); + BOOL isGood = ((strcmp(selName1, selName2)) == 0 || (strcmp(selName1, selName3) == 0)); + STAssertTrue(isGood, nil); + free(list); +} + +- (void)test_method_exchangeImplementations { + // nil checks + method_exchangeImplementations(nil, nil); + + // Standard use check + GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init]; + STAssertNotNil(test, nil); + + // Get initial values + NSString *val1 = [test kwyjibo]; + STAssertNotNil(val1, nil); + NSString *val2 = [test eatMyShorts]; + STAssertNotNil(val2, nil); + NSString *val3 = [GTMObjC2Runtime_TestClass dontHaveACow]; + STAssertNotNil(val3, nil); + NSString *val4 = [GTMObjC2Runtime_TestClass brokeHisBrain]; + STAssertNotNil(val4, nil); + + // exchange the imps + Method *list = class_copyMethodList(cls_, nil); + STAssertNotNULL(list, nil); + method_exchangeImplementations(list[0], list[1]); + + // test against initial values + NSString *val5 = [test kwyjibo]; + STAssertNotNil(val5, nil); + NSString *val6 = [test eatMyShorts]; + STAssertNotNil(val6, nil); + STAssertEqualStrings(val1, val6, nil); + STAssertEqualStrings(val2, val5, nil); + + // Check that other methods not affected + STAssertEqualStrings([GTMObjC2Runtime_TestClass dontHaveACow], val3, nil); + STAssertEqualStrings([GTMObjC2Runtime_TestClass brokeHisBrain], val4, nil); + + // exchange the imps back + method_exchangeImplementations(list[0], list[1]); + + // and test against initial values again + NSString *val7 = [test kwyjibo]; + STAssertNotNil(val7, nil); + NSString *val8 = [test eatMyShorts]; + STAssertNotNil(val8, nil); + STAssertEqualStrings(val1, val7, nil); + STAssertEqualStrings(val2, val8, nil); + + method_exchangeImplementations(list[0], nil); + method_exchangeImplementations(nil, list[0]); + + val7 = [test kwyjibo]; + STAssertNotNil(val7, nil); + val8 = [test eatMyShorts]; + STAssertNotNil(val8, nil); + STAssertEqualStrings(val1, val7, nil); + STAssertEqualStrings(val2, val8, nil); + + free(list); + [test release]; +} + +- (void)test_method_getImplementation { + // Nil Checks + STAssertNULL(method_getImplementation(nil), nil); + + // Standard use check + Method *list = class_copyMethodList(cls_, nil); + STAssertNotNULL(list, nil); + STAssertNotNULL(method_getImplementation(list[0]), nil); + free(list); +} + +- (void)test_method_setImplementation { + // Standard use check + GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init]; + Method *list = class_copyMethodList(cls_, nil); + + // Get initial value + NSString *str1 = objc_msgSend(test, method_getName(list[0])); + STAssertNotNil(str1, nil); + + // set the imp to something else + IMP oldImp = method_setImplementation(list[0], method_getImplementation(list[1])); + STAssertNotNULL(oldImp, nil); + + // make sure they are different + NSString *str2 = objc_msgSend(test,method_getName(list[0])); + STAssertNotNil(str2, nil); + STAssertNotEqualStrings(str1, str2, nil); + + // reset the imp + IMP newImp = method_setImplementation(list[0], oldImp); + STAssertNotEquals(oldImp, newImp, nil); + + // test nils + // Apparently it was a bug that we could call setImplementation with a nil + // so we now test to make sure that setting to nil works as expected on + // all systems. +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + // Built for less then leopard gives us the behaviors we defined... + // (doesn't take nil) + IMP nullImp = method_setImplementation(list[0], nil); + STAssertNULL(nullImp, nil); + IMP testImp = method_setImplementation(list[0], newImp); + STAssertEquals(testImp, oldImp, nil); +#else + // Built for leopard or later means we get the os runtime behavior... + if ([GTMSystemVersion isLeopard]) { + // (takes nil) + oldImp = method_setImplementation(list[0], nil); + STAssertNotNULL(oldImp, nil); + newImp = method_setImplementation(list[0], oldImp); + STAssertNULL(newImp, nil); + } else { + // (doesn't take nil) + IMP nullImp = method_setImplementation(list[0], nil); + STAssertNULL(nullImp, nil); + IMP testImp = method_setImplementation(list[0], newImp); + STAssertEquals(testImp, oldImp, nil); + } +#endif + + // This case intentionally not tested. Passing nil to method_setImplementation + // on Leopard crashes. It does on Tiger as well. Half works on SnowLeopard. + // We made our Tiger implementation the same as the SnowLeopard + // implementation. + // Logged as radar 5572981. + if (![GTMSystemVersion isLeopard]) { + STAssertNULL(method_setImplementation(nil, nil), nil); + } + if ([GTMSystemVersion isBuildGreaterThan:kGTMSystemBuild10_6_0_WWDC]) { + STAssertNULL(method_setImplementation(nil, newImp), nil); + } + + [test release]; + free(list); +} + +- (void)test_protocol_getMethodDescription { + // Check nil cases + struct objc_method_description desc = protocol_getMethodDescription(nil, nil, + YES, YES); + STAssertNULL(desc.name, nil); + desc = protocol_getMethodDescription(nil, @selector(optional), YES, YES); + STAssertNULL(desc.name, nil); + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + nil, YES, YES); + STAssertNULL(desc.name, nil); + + // Instance Methods + // Check Required case. Only OBJC2 supports required. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(optional), YES, YES); +#if OBJC_API_VERSION >= 2 + STAssertNULL(desc.name, nil); +#else + STAssertNotNULL(desc.name, nil); +#endif + + // Check Required case. Only OBJC2 supports required. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(required), YES, YES); + + STAssertNotNULL(desc.name, nil); + + // Check Optional case. Only OBJC2 supports optional. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(optional), NO, YES); + + STAssertNotNULL(desc.name, nil); + + // Check Optional case. Only OBJC2 supports optional. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(required), NO, YES); +#if OBJC_API_VERSION >= 2 + STAssertNULL(desc.name, nil); +#else + STAssertNotNULL(desc.name, nil); +#endif + + // Class Methods + // Check Required case. Only OBJC2 supports required. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(class_optional), YES, NO); +#if OBJC_API_VERSION >= 2 + STAssertNULL(desc.name, nil); +#else + STAssertNotNULL(desc.name, nil); +#endif + + // Check Required case. Only OBJC2 supports required. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(class_required), YES, NO); + + STAssertNotNULL(desc.name, nil); + + // Check Optional case. Only OBJC2 supports optional. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(class_optional), NO, NO); + + STAssertNotNULL(desc.name, nil); + + // Check Optional case. Only OBJC2 supports optional. + desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol), + @selector(class_required), NO, NO); +#if OBJC_API_VERSION >= 2 + STAssertNULL(desc.name, nil); +#else + STAssertNotNULL(desc.name, nil); +#endif + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjectSingleton.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjectSingleton.h new file mode 100644 index 00000000..4763b687 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMObjectSingleton.h @@ -0,0 +1,71 @@ +// +// GTMObjectSingleton.h +// Macro to implement methods for a singleton +// +// Copyright 2005-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" + +/// This macro implements the various methods needed to make a safe singleton. +// +/// This Singleton pattern was taken from: +/// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html +/// +/// Sample usage: +/// +/// GTMOBJECT_SINGLETON_BOILERPLATE(SomeUsefulManager, sharedSomeUsefulManager) +/// (with no trailing semicolon) +/// +#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_) \ +static _object_name_ *z##_shared_obj_name_ = nil; \ ++ (_object_name_ *)_shared_obj_name_ { \ + @synchronized(self) { \ + if (z##_shared_obj_name_ == nil) { \ + /* Note that 'self' may not be the same as _object_name_ */ \ + /* first assignment done in allocWithZone but we must reassign in case init fails */ \ + z##_shared_obj_name_ = [[self alloc] init]; \ + _GTMDevAssert((z##_shared_obj_name_ != nil), @"didn't catch singleton allocation"); \ + } \ + } \ + return z##_shared_obj_name_; \ +} \ ++ (id)allocWithZone:(NSZone *)zone { \ + @synchronized(self) { \ + if (z##_shared_obj_name_ == nil) { \ + z##_shared_obj_name_ = [super allocWithZone:zone]; \ + return z##_shared_obj_name_; \ + } \ + } \ + \ + /* We can't return the shared instance, because it's been init'd */ \ + _GTMDevAssert(NO, @"use the singleton API, not alloc+init"); \ + return nil; \ +} \ +- (id)retain { \ + return self; \ +} \ +- (NSUInteger)retainCount { \ + return NSUIntegerMax; \ +} \ +- (void)release { \ +} \ +- (id)autorelease { \ + return self; \ +} \ +- (id)copyWithZone:(NSZone *)zone { \ + return self; \ +} \ + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.h new file mode 100644 index 00000000..6ac2347d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.h @@ -0,0 +1,132 @@ +// +// GTMPath.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + + +// GTMPath +// +// This class represents a single, absolute file system path. The represented +// path must exist at the time of creation. This class also allows you to easily +// create new paths (or full hierarchies) based on existing GTMPath instances. +// +// Given a GTMPath instance, new files and directories can be created inside +// that path providing the instance refers to a directory. It is an error to try +// to create a file/directory from a GTMPath that represents a file (this should +// be common sense: clearly mkdir /etc/passwd/foo won't work). +// +// === Examples === +// +// 1. This sample creates a GTMPath that references /tmp, then gets the +// attributes for that directory. +// +// GTMPath *tmp = [GTMPath pathWithFullPath:@"/tmp"]; +// NSDictionary *attr = [tmp attributes]; +// +// +// 2. This sample creates a new directory inside /tmp named "foo". +// +// GTMPath *tmp = [GTMPath pathWithFullPath:@"/tmp"]; +// GTMPath *foo = [tmp createDirectoryName:@"foo" mode:0755]; +// +// +// 3. This sample creates a GTMPath instance that represents a user's ~/Library +// folder. +// +// GTMPath *library = [GTMPath pathWithFullPath:@"/Users/bob/Library"]; +// ... +// +// +// 4. This sample creates a directory hierarchy, where each level has its own +// mode. Notice that the return value from these -create* methods is the +// GTMPath that was just created. This allows these creation calls to be +// chained together enabling easy creation of directory hierarchies. +// This is one of the big benefits of this class. +// +// GTMPath *tmp = [GTMPath pathWithFullPath:@"/tmp"]; +// GTMPath *baz = [[[tmp createDirectoryName:@"foo" mode:0755] +// createDirectoryName:@"bar" mode:0756] +// createDirectoryName:@"baz" mode:0757]; +// +@interface GTMPath : NSObject { + @private + NSString *fullPath_; +} + +// Returns a GTMPath instance that represents the full path specified by +// |fullPath|. Note that |fullPath| MUST be an absolute path. ++ (id)pathWithFullPath:(NSString *)fullPath; + +// Returns a GTMPath instance that represents the full path specified by +// |fullPath|. Note that |fullPath| MUST be an absolute path. This method is the +// designated initializer. +- (id)initWithFullPath:(NSString *)fullPath; + +// Returns the name of this GTMPath instance. This is not the full path. It is +// just the component name of this GTMPath instance. This is equivalent to +// the Unix basename(3) function. +- (NSString *)name; + +// Returns this path's parent GTMPath. This method will ONLY (and always) return +// nil when |name| is "/". In otherwords, parent will be nil IFF this GTMPath +// instance represents the root path, because "/" doesn't really have a parent. +- (GTMPath *)parent; + +// Returns YES if this GTMPath represents a directory. +- (BOOL)isDirectory; + +// Returns YES if this GTMPath instance represents the root path "/". +- (BOOL)isRoot; + +// Returns the file system attributes of the path represented by this GTMPath +// instance. See -[NSFileManager fileAttributesAtPath:...] for details. +- (NSDictionary *)attributes; + +// Returns a string representation of the absolute path represented by this +// GTMPath instance. +- (NSString *)fullPath; + +@end + + +// Methods for creating files and directories inside a GTMPath instance. These +// methods are only allowed to be called on GTMPath instances that represent +// directories. See the NSFileManager documentation for details about the +// |attributes| parameters. +@interface GTMPath (GTMPathGeneration) + +// Creates a new directory with the specified mode or attributes inside the +// current GTMPath instance. If the creation is successful, a GTMPath for the +// newly created directory is returned. Otherwise, nil is returned. +- (GTMPath *)createDirectoryName:(NSString *)name mode:(mode_t)mode; +- (GTMPath *)createDirectoryName:(NSString *)name + attributes:(NSDictionary *)attributes; + +// Creates a new file with the specified mode or attributes inside the +// current GTMPath instance. If the creation is successful, a GTMPath for the +// newly created file is returned. Otherwise, nil is returned. |data| is the +// data to put in the file when created. +- (GTMPath *)createFileName:(NSString *)name mode:(mode_t)mode; +- (GTMPath *)createFileName:(NSString *)name + attributes:(NSDictionary *)attributes; +- (GTMPath *)createFileName:(NSString *)name + attributes:(NSDictionary *)attributes + data:(NSData *)data; + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.m new file mode 100644 index 00000000..28ffad07 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPath.m @@ -0,0 +1,156 @@ +// +// GTMPath.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMPath.h" + + +@implementation GTMPath + ++ (id)pathWithFullPath:(NSString *)fullPath { + return [[[self alloc] initWithFullPath:fullPath] autorelease]; +} + +- (id)init { + return [self initWithFullPath:nil]; +} + +- (id)initWithFullPath:(NSString *)fullPath { + if ((self = [super init])) { + fullPath_ = [fullPath copy]; + if (![fullPath_ isAbsolutePath] || [self attributes] == nil) { + [self release]; + return nil; + } + } + + return self; +} + +- (void)dealloc { + [fullPath_ release]; + [super dealloc]; +} + +- (NSString *)description { + return [self fullPath]; +} + +- (NSString *)name { + return [fullPath_ lastPathComponent]; +} + +- (GTMPath *)parent { + if ([self isRoot]) return nil; + NSString *parentPath = [fullPath_ stringByDeletingLastPathComponent]; + return [[self class] pathWithFullPath:parentPath]; +} + +- (BOOL)isDirectory { + BOOL isDir = NO; + BOOL exists = [[NSFileManager defaultManager] + fileExistsAtPath:fullPath_ isDirectory:&isDir]; + return exists && isDir; +} + +- (BOOL)isRoot { + return [fullPath_ isEqualToString:@"/"]; +} + +- (NSDictionary *)attributes { + return [[NSFileManager defaultManager] + fileAttributesAtPath:fullPath_ + traverseLink:YES]; +} + +- (NSString *)fullPath { + return [[fullPath_ copy] autorelease]; +} + +@end + + +@implementation GTMPath (GTMPathGeneration) + +- (GTMPath *)createDirectoryName:(NSString *)name mode:(mode_t)mode { + NSDictionary *attributes = + [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:mode] + forKey:NSFilePosixPermissions]; + return [self createDirectoryName:name attributes:attributes]; +} + +- (GTMPath *)createDirectoryName:(NSString *)name + attributes:(NSDictionary *)attributes { + if ([name length] == 0) return nil; + + // We first check to see if the requested directory alread exists by trying + // to create a GTMPath from the desired new path string. Only if the path + // doesn't already exist do we attempt to create it. If the path already + // exists, we will end up returning a GTMPath for the pre-existing path. + NSString *newPath = [fullPath_ stringByAppendingPathComponent:name]; + GTMPath *nascentPath = [GTMPath pathWithFullPath:newPath]; + if (nascentPath != nil && ![nascentPath isDirectory]) { + return nil; // Return nil because the path exists, but it's not a dir + } + + if (nascentPath == nil) { + BOOL created = [[NSFileManager defaultManager] + createDirectoryAtPath:newPath + attributes:attributes]; + nascentPath = created ? [GTMPath pathWithFullPath:newPath] : nil; + } + + return nascentPath; +} + +- (GTMPath *)createFileName:(NSString *)name mode:(mode_t)mode { + NSDictionary *attributes = + [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:mode] + forKey:NSFilePosixPermissions]; + return [self createFileName:name attributes:attributes]; +} + +- (GTMPath *)createFileName:(NSString *)name + attributes:(NSDictionary *)attributes { + return [self createFileName:name attributes:attributes data:[NSData data]]; +} + +- (GTMPath *)createFileName:(NSString *)name + attributes:(NSDictionary *)attributes + data:(NSData *)data { + if ([name length] == 0) return nil; + + // See createDirectoryName:attribute: for some high-level notes about what and + // why this method does what it does. + NSString *newPath = [fullPath_ stringByAppendingPathComponent:name]; + GTMPath *nascentPath = [GTMPath pathWithFullPath:newPath]; + if (nascentPath != nil && [nascentPath isDirectory]) { + return nil; // Return nil because the path exists, but it's a dir + } + + if (nascentPath == nil) { + BOOL created = [[NSFileManager defaultManager] + createFileAtPath:newPath + contents:data + attributes:attributes]; + nascentPath = created ? [GTMPath pathWithFullPath:newPath] : nil; + } + + return nascentPath; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPathTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPathTest.m new file mode 100644 index 00000000..211206cb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMPathTest.m @@ -0,0 +1,236 @@ +// +// GTMPathTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMPath.h" +#import "GTMUnitTestDevLog.h" + + +@interface GTMPathTest : GTMTestCase { + @private + NSString *testDirectory_; +} +@end + +@implementation GTMPathTest + +- (void)setUp { + NSString *tmp = NSTemporaryDirectory(); + STAssertNotNil(tmp, nil); + + testDirectory_ = [[tmp stringByAppendingPathComponent:@"GTMPathTest"] retain]; + STAssertNotNil(testDirectory_, nil); + + BOOL created = [[NSFileManager defaultManager] + createDirectoryAtPath:testDirectory_ + attributes:nil]; + STAssertTrue(created, nil); +} + +- (void)tearDown { + // Make sure it's safe to remove this directory before nuking it. + STAssertNotNil(testDirectory_, nil); + STAssertNotEqualObjects(testDirectory_, @"/", nil); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [[NSFileManager defaultManager] removeFileAtPath:testDirectory_ handler:nil]; +#else + [[NSFileManager defaultManager] removeItemAtPath:testDirectory_ error:NULL]; +#endif + [testDirectory_ release]; +} + +- (void)testBasicCreation { + GTMPath *path = nil; + + path = [[[GTMPath alloc] init] autorelease]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"/"]; + STAssertNotNil(path, nil); + STAssertNil([path parent], nil); + STAssertTrue([path isRoot], nil); + STAssertTrue([path isDirectory], nil); + STAssertEqualObjects([path name], @"/", nil); + STAssertEqualObjects([path fullPath], @"/", nil); +} + +- (void)testRecursiveInitialization { + GTMPath *path = nil; + + path = [GTMPath pathWithFullPath:nil]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@""]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"etc"]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"/"]; + STAssertNotNil(path, nil); + STAssertNil([path parent], nil); + STAssertTrue([path isRoot], nil); + STAssertTrue([path isDirectory], nil); + STAssertEqualObjects([path name], @"/", nil); + STAssertEqualObjects([path fullPath], @"/", nil); + + path = [GTMPath pathWithFullPath:@"/etc"]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"etc", nil); + STAssertEqualObjects([path fullPath], @"/etc", nil); + STAssertTrue([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + STAssertNotNil([path parent], nil); + STAssertTrue([[path parent] isRoot], nil); + + path = [GTMPath pathWithFullPath:@"/etc/passwd"]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"passwd", nil); + STAssertEqualObjects([path fullPath], @"/etc/passwd", nil); + STAssertFalse([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + STAssertNotNil([path parent], nil); + STAssertFalse([[path parent] isRoot], nil); + STAssertTrue([[path parent] isDirectory], nil); + STAssertTrue([[[path parent] parent] isRoot], nil); + + STAssertTrue([[path description] length] > 1, nil); +} + +- (void)testCreationWithNonExistentPath { + GTMPath *path = nil; + + path = [GTMPath pathWithFullPath:@" "]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"/abcxyz"]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"/etc/foo"]; + STAssertNil(path, nil); + + path = [GTMPath pathWithFullPath:@"/foo/bar/baz"]; + STAssertNil(path, nil); +} + +- (void)testDirectoryCreation { + GTMPath *tmp = [GTMPath pathWithFullPath:testDirectory_]; + GTMPath *path = nil; + + NSString *fooPath = [[tmp fullPath] stringByAppendingPathComponent:@"foo"]; + path = [GTMPath pathWithFullPath:fooPath]; + STAssertNil(path, nil); + + path = [tmp createDirectoryName:@"foo" mode:0555]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"foo", nil); + // filePosixPermissions has odd return types in different SDKs, so we use + // STAssertTrue to avoid the macros type checks from choking us. + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertTrue([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + + // Trying to create a file where a dir already exists should fail + path = [tmp createFileName:@"foo" mode:0555]; + STAssertNil(path, nil); + + // Calling create again should succeed + path = [tmp createDirectoryName:@"foo" mode:0555]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertTrue([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + + GTMPath *foo = [GTMPath pathWithFullPath:fooPath]; + STAssertNotNil(foo, nil); + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertTrue([path isDirectory], nil); + STAssertFalse([path isRoot], nil); +} + +- (void)testFileCreation { + GTMPath *tmp = [GTMPath pathWithFullPath:testDirectory_]; + GTMPath *path = nil; + + NSString *fooPath = [[tmp fullPath] stringByAppendingPathComponent:@"foo"]; + path = [GTMPath pathWithFullPath:fooPath]; + STAssertNil(path, nil); + + path = [tmp createFileName:@"foo" mode:0555]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertFalse([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + + // Trying to create a dir where a file already exists should fail. + path = [tmp createDirectoryName:@"foo" mode:0555]; + STAssertNil(path, nil); + + // Calling create again should succeed + path = [tmp createFileName:@"foo" mode:0555]; + STAssertNotNil(path, nil); + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertFalse([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + + GTMPath *foo = [GTMPath pathWithFullPath:fooPath]; + STAssertNotNil(foo, nil); + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0555, nil); + STAssertFalse([path isDirectory], nil); + STAssertFalse([path isRoot], nil); + + // Make sure we can't create a file/directory rooted off of |foo|, since it's + // not a directory. + path = [foo createFileName:@"bar" mode:0555]; + STAssertNil(path, nil); + path = [foo createDirectoryName:@"bar" mode:0555]; + STAssertNil(path, nil); +} + +- (void)testHierarchyCreation { + GTMPath *tmp = [GTMPath pathWithFullPath:testDirectory_]; + NSString *fooPath = [[tmp fullPath] stringByAppendingPathComponent:@"foo"]; + GTMPath *path = [GTMPath pathWithFullPath:fooPath]; + STAssertNil(path, nil); + + path = [[[tmp createDirectoryName:@"foo" mode:0755] + createDirectoryName:@"bar" mode:0756] + createDirectoryName:@"baz" mode:0757]; + STAssertNotNil(path, nil); + + // Check "baz" + STAssertEqualObjects([path name], @"baz", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0757, nil); + + // Check "bar" + path = [path parent]; + STAssertEqualObjects([path name], @"bar", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0756, nil); + + // Check "foo" + path = [path parent]; + STAssertEqualObjects([path name], @"foo", nil); + STAssertTrue([[path attributes] filePosixPermissions] == 0755, nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMProgressMonitorInputStream.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMProgressMonitorInputStream.h new file mode 100644 index 00000000..5f779bc5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMProgressMonitorInputStream.h @@ -0,0 +1,22 @@ +// +// GTMProgressMonitorInputStream.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This class is no more. If you want something like it's functionality, look +// at using the version in the Objective-C GData Client +// (http://code.google.com/p/gdata-objectivec-client/). It provides the same +// functionality and will continue to be maintained. diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.h new file mode 100644 index 00000000..3ef5604c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.h @@ -0,0 +1,379 @@ +// +// GTMRegex.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import +#import "GTMDefines.h" + +/// Options for controlling the behavior of the matches +enum { + + kGTMRegexOptionIgnoreCase = 0x01, + // Ignore case in matching, ie: 'a' matches 'a' or 'A' + + kGTMRegexOptionSupressNewlineSupport = 0x02, + // By default (without this option), regular expressions are implicitly + // processed on a line by line basis, where "lines" are delimited by newline + // characters. In this mode '.' (dot) does NOT match newline characters, and + // '^' and '$' match at the beginning and end of the string as well as + // around newline characters. This behavior matches the default behavior for + // regular expressions in other languages including Perl and Python. For + // example, + // foo.*bar + // would match + // fooAAAbar + // but would NOT match + // fooAAA\nbar + // With the kGTMRegexOptionSupressNewlineSupport option, newlines are treated + // just like any other character which means that '.' will match them. In + // this mode, ^ and $ only match the beginning and end of the input string + // and do NOT match around the newline characters. For example, + // foo.*bar + // would match + // fooAAAbar + // and would also match + // fooAAA\nbar + +}; +typedef NSUInteger GTMRegexOptions; + +/// Global contants needed for errors from consuming patterns + +#undef _EXTERN +#undef _INITIALIZE_AS +#ifdef GTMREGEX_DEFINE_GLOBALS +#define _EXTERN +#define _INITIALIZE_AS(x) =x +#else +#define _EXTERN GTM_EXTERN +#define _INITIALIZE_AS(x) +#endif + +_EXTERN NSString* kGTMRegexErrorDomain _INITIALIZE_AS(@"com.google.mactoolbox.RegexDomain"); + +enum { + kGTMRegexPatternParseFailedError = -100 +}; + +// Keys for the userInfo from a kGTMRegexErrorDomain/kGTMRegexPatternParseFailedError error +_EXTERN NSString* kGTMRegexPatternErrorPattern _INITIALIZE_AS(@"pattern"); +_EXTERN NSString* kGTMRegexPatternErrorErrorString _INITIALIZE_AS(@"patternError"); + +/// Class for doing Extended Regex operations w/ libregex (see re_format(7)). +// +// NOTE: the docs for recomp/regexec make *no* claims about i18n. All work +// within this class is done w/ UTF-8 so Unicode should move through it safely, +// however, the character classes described in re_format(7) might not really +// be unicode "savvy", so use them and this class w/ that in mind. +// +// Example usage: +// +// NSArray *inputArrayOfStrings = ... +// NSArray *matches = [NSMutableArray array]; +// +// GTMRegex *regex = [GTMRegex regexWithPattern:@"foo.*bar"]; +// for (NSString *curStr in inputArrayOfStrings) { +// if ([regex matchesString:curStr]) +// [matches addObject:curStr]; +// } +// .... +// +// ------------- +// +// If you need to include something dynamic in a pattern: +// +// NSString *pattern = +// [NSString stringWithFormat:@"^foo:%@bar", +// [GTMRegex escapedPatternForString:inputStr]]; +// GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; +// .... +// +// ------------- +// +// GTMRegex *regex = [GTMRegex regexWithPattern:@"(foo+)(bar)"]; +// NSString *highlighted = +// [regex stringByReplacingMatchesInString:inputString +// withReplacement:@"\\1\\2"]; +// .... +// +@interface GTMRegex : NSObject { + @private + NSString *pattern_; + GTMRegexOptions options_; + regex_t regexData_; +} + +/// Create a new, autoreleased object w/ the given regex pattern with the default options ++ (id)regexWithPattern:(NSString *)pattern; + +/// Create a new, autoreleased object w/ the given regex pattern and specify the matching options ++ (id)regexWithPattern:(NSString *)pattern options:(GTMRegexOptions)options; + +/// Create a new, autoreleased object w/ the given regex pattern, specify the matching options and receive any error consuming the pattern. ++ (id)regexWithPattern:(NSString *)pattern + options:(GTMRegexOptions)options + withError:(NSError **)outErrorOrNULL; + +/// Returns a new, autoreleased copy of |str| w/ any pattern chars in it escaped so they have no meaning when used w/in a pattern. ++ (NSString *)escapedPatternForString:(NSString *)str; + +/// Initialize a new object w/ the given regex pattern with the default options +- (id)initWithPattern:(NSString *)pattern; + +/// Initialize a new object w/ the given regex pattern and specify the matching options +- (id)initWithPattern:(NSString *)pattern options:(GTMRegexOptions)options; + +/// Initialize a new object w/ the given regex pattern, specify the matching options, and receive any error consuming the pattern. +- (id)initWithPattern:(NSString *)pattern + options:(GTMRegexOptions)options + withError:(NSError **)outErrorOrNULL; + +/// Returns the number of sub patterns in the pattern +// +// Sub Patterns are basically the number of parenthesis blocks w/in the pattern. +// ie: The pattern "foo((bar)|(baz))" has 3 sub patterns. +// +- (NSUInteger)subPatternCount; + +/// Returns YES if the whole string |str| matches the pattern. +- (BOOL)matchesString:(NSString *)str; + +/// Returns a new, autoreleased array of string that contain the subpattern matches for the string. +// +// If the whole string does not match the pattern, nil is returned. +// +// The api follows the conventions of most regex engines, and index 0 (zero) is +// the full match, then the subpatterns are index 1, 2, ... going left to right. +// If the pattern has optional subpatterns, then anything that didn't match +// will have NSNull at that index. +// ie: The pattern "(fo(o+))((bar)|(baz))" has five subpatterns, and when +// applied to the string "foooooobaz" you'd get an array of: +// 0: "foooooobaz" +// 1: "foooooo" +// 2: "ooooo" +// 3: "baz" +// 4: NSNull +// 5: "baz" +// +- (NSArray *)subPatternsOfString:(NSString *)str; + +/// Returns the first match for this pattern in |str|. +- (NSString *)firstSubStringMatchedInString:(NSString *)str; + +/// Returns YES if this pattern some substring of |str|. +- (BOOL)matchesSubStringInString:(NSString *)str; + +/// Returns a new, autoreleased enumerator that will walk segments (GTMRegexStringSegment) of |str| based on the pattern. +// +// This will split the string into "segments" using the given pattern. You get +// both the matches and parts that are inbetween matches. ie-the entire string +// will eventually be returned. +// +// See GTMRegexStringSegment for more infomation and examples. +// +- (NSEnumerator *)segmentEnumeratorForString:(NSString *)str; + +/// Returns a new, autoreleased enumerator that will walk only the matching segments (GTMRegexStringSegment) of |str| based on the pattern. +// +// This extracts the "segments" of the string that used the pattern. So it can +// be used to collect all of the matching substrings from within a string. +// +// See GTMRegexStringSegment for more infomation and examples. +// +- (NSEnumerator *)matchSegmentEnumeratorForString:(NSString *)str; + +/// Returns a new, autoreleased string with all matches of the pattern in |str| replaced with |replacementPattern|. +// +// Replacement uses the SED substitution like syntax w/in |replacementPattern| +// to allow the use of matches in the replacment. The replacement pattern can +// make use of any number of match references by using a backslash followed by +// the match subexpression number (ie-"\2", "\0", ...), see subPatternsOfString: +// for details on the subexpression indexing. +// +// REMINDER: you need to double-slash since the slash has meaning to the +// compiler/preprocessor. ie: "\\0" +// +- (NSString *)stringByReplacingMatchesInString:(NSString *)str + withReplacement:(NSString *)replacementPattern; + +@end + +/// Class returned by the nextObject for the enumerators from GTMRegex +// +// The two enumerators on from GTMRegex return objects of this type. This object +// represents a "piece" of the string the enumerator is walking. It's the apis +// on this object allow you to figure out why each segment was returned and to +// act on it. +// +// The easiest way to under stand this how the enumerators and this class works +// is through and examples :: +// Pattern: "foo+" +// String: "fo bar foobar foofooo baz" +// If you walk this w/ -segmentEnumeratorForString you'll get: +// # nextObjects Calls -isMatch -string +// 1 NO "fo bar " +// 2 YES "foo" +// 3 NO "bar " +// 4 YES "foo" +// 5 YES "fooo" +// 6 NO " baz" +// And if you walk this w/ -matchSegmentEnumeratorForString you'll get: +// # nextObjects Calls -isMatch -string +// 1 YES "foo" +// 2 YES "foo" +// 3 YES "fooo" +// (see the comments on subPatternString for how it works) +// +// Example usage: +// +// NSMutableString processedStr = [NSMutableString string]; +// NSEnumerator *enumerator = +// [inputStr segmentEnumeratorForPattern:@"foo+((ba+r)|(ba+z))"]; +// GTMRegexStringSegment *segment = nil; +// while ((segment = [enumerator nextObject]) != nil) { +// if ([segment isMatch]) { +// if ([segment subPatterString:2] != nil) { +// // matched: "(ba+r)" +// [processStr appendFormat:@"%@", [segment string]]; +// } else { +// // matched: "(ba+z)" +// [processStr appendFormat:@"%@", [segment string]]; +// } +// } else { +// [processStr appendString:[segment string]]; +// } +// } +// // proccessedStr now has all the versions of foobar wrapped in bold tags, +// // and all the versons of foobaz in italics tags. +// // ie: " fooobar foobaaz " ==> " fooobar foobaaz " +// +@interface GTMRegexStringSegment : NSObject { + @private + NSData *utf8StrBuf_; + regmatch_t *regMatches_; // STRONG: ie-we call free + NSUInteger numRegMatches_; + BOOL isMatch_; +} + +/// Returns YES if this segment from from a match of the regex, false if it was a segment between matches. +// +// Use -isMatch to see if the segment from from a match of the pattern or if the +// segment is some text between matches. (NOTE: isMatch is always YES for +// matchSegmentEnumeratorForString) +// +- (BOOL)isMatch; + +/// Returns a new, autoreleased string w/ the full text segment from the original string. +- (NSString *)string; + +/// Returns a new, autoreleased string w/ the |index| sub pattern from this segment of the original string. +// +// This api follows the conventions of most regex engines, and index 0 (zero) is +// the full match, then the subpatterns are index 1, 2, ... going left to right. +// If the pattern has optional subpatterns, then anything that didn't match +// will return nil. +// ie: When using the pattern "(fo(o+))((bar)|(baz))" the following indexes +// fetch these values for a segment where -string is @"foooooobaz": +// 0: "foooooobaz" +// 1: "foooooo" +// 2: "ooooo" +// 3: "baz" +// 4: nil +// 5: "baz" +// +- (NSString *)subPatternString:(NSUInteger)index; + +@end + +/// Some helpers to streamline usage of GTMRegex +// +// Example usage: +// +// if ([inputStr matchesPattern:@"foo.*bar"]) { +// // act on match +// .... +// } +// +// ------------- +// +// NSString *subStr = [inputStr firstSubStringMatchedByPattern:@"^foo:.*$"]; +// if (subStr != nil) { +// // act on subStr +// .... +// } +// +// ------------- +// +// NSArray *headingList = +// [inputStr allSubstringsMatchedByPattern:@"^Heading:.*$"]; +// // act on the list of headings +// .... +// +// ------------- +// +// NSString *highlightedString = +// [inputString stringByReplacingMatchesOfPattern:@"(foo+)(bar)" +// withReplacement:@"\\1\\2"]; +// .... +// +@interface NSString (GTMRegexAdditions) + +/// Returns YES if the full string matches regex |pattern| using the default match options +- (BOOL)gtm_matchesPattern:(NSString *)pattern; + +/// Returns a new, autoreleased array of strings that contain the subpattern matches of |pattern| using the default match options +// +// See [GTMRegex subPatternsOfString:] for information about the returned array. +// +- (NSArray *)gtm_subPatternsOfPattern:(NSString *)pattern; + +/// Returns a new, autoreleased string w/ the first substring that matched the regex |pattern| using the default match options +- (NSString *)gtm_firstSubStringMatchedByPattern:(NSString *)pattern; + +/// Returns YES if a substring string matches regex |pattern| using the default match options +- (BOOL)gtm_subStringMatchesPattern:(NSString *)pattern; + +/// Returns a new, autoreleased array of substrings in the string that match the regex |pattern| using the default match options +// +// Note: if the string has no matches, you get an empty array. +- (NSArray *)gtm_allSubstringsMatchedByPattern:(NSString *)pattern; + +/// Returns a new, autoreleased segment enumerator that will break the string using pattern w/ the default match options +// +// The enumerator returns GTMRegexStringSegment options, see that class for more +// details and examples. +// +- (NSEnumerator *)gtm_segmentEnumeratorForPattern:(NSString *)pattern; + +/// Returns a new, autoreleased segment enumerator that will only return matching segments from the string using pattern w/ the default match options +// +// The enumerator returns GTMRegexStringSegment options, see that class for more +// details and examples. +// +- (NSEnumerator *)gtm_matchSegmentEnumeratorForPattern:(NSString *)pattern; + +/// Returns a new, autoreleased string with all matches for pattern |pattern| are replaced w/ |replacementPattern|. Uses the default match options. +// +// |replacemetPattern| has support for using any subExpression that matched, +// see [GTMRegex stringByReplacingMatchesInString:withReplacement:] above +// for details. +// +- (NSString *)gtm_stringByReplacingMatchesOfPattern:(NSString *)pattern + withReplacement:(NSString *)replacementPattern; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.m new file mode 100644 index 00000000..10272247 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegex.m @@ -0,0 +1,817 @@ +// +// GTMRegex.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#define GTMREGEX_DEFINE_GLOBALS 1 +#import "GTMRegex.h" +#import "GTMDefines.h" + +// This is the pattern to use for walking replacement text when doing +// substitutions. +// +// This pattern may look over-escaped, but remember the compiler will consume +// one layer of slashes, and then we have to escape the slashes for them to be +// seen as we want in the pattern. +static NSString *const kReplacementPattern = + @"((^|[^\\\\])(\\\\\\\\)*)(\\\\([0-9]+))"; +#define kReplacementPatternLeadingTextIndex 1 +#define kReplacementPatternSubpatternNumberIndex 5 + +@interface GTMRegex (PrivateMethods) +- (NSString *)errorMessage:(int)errCode; +- (BOOL)runRegexOnUTF8:(const char*)utf8Str + nmatch:(size_t)nmatch + pmatch:(regmatch_t *)pmatch + flags:(int)flags; +@end + +// private enumerator as impl detail +@interface GTMRegexEnumerator : NSEnumerator { + @private + GTMRegex *regex_; + NSData *utf8StrBuf_; + BOOL allSegments_; + BOOL treatStartOfNewSegmentAsBeginningOfString_; + regoff_t curParseIndex_; + __strong regmatch_t *savedRegMatches_; +} +- (id)initWithRegex:(GTMRegex *)regex + processString:(NSString *)str + allSegments:(BOOL)allSegments; +- (void)treatStartOfNewSegmentAsBeginningOfString:(BOOL)yesNo; +@end + +@interface GTMRegexStringSegment (PrivateMethods) +- (id)initWithUTF8StrBuf:(NSData *)utf8StrBuf + regMatches:(regmatch_t *)regMatches + numRegMatches:(NSUInteger)numRegMatches + isMatch:(BOOL)isMatch; +@end + +@implementation GTMRegex + ++ (id)regexWithPattern:(NSString *)pattern { + return [[[self alloc] initWithPattern:pattern] autorelease]; +} + ++ (id)regexWithPattern:(NSString *)pattern options:(GTMRegexOptions)options { + return [[[self alloc] initWithPattern:pattern + options:options] autorelease]; +} + ++ (id)regexWithPattern:(NSString *)pattern + options:(GTMRegexOptions)options + withError:(NSError **)outErrorOrNULL { + return [[[self alloc] initWithPattern:pattern + options:options + withError:outErrorOrNULL] autorelease]; +} + ++ (NSString *)escapedPatternForString:(NSString *)str { + if (str == nil) + return nil; + + // NOTE: this could be done more efficiently by fetching the whole string into + // a unichar buffer and scanning that, along w/ pushing the data over in + // chunks (when possible). + + NSUInteger len = [str length]; + NSMutableString *result = [NSMutableString stringWithCapacity:len]; + + for (NSUInteger x = 0; x < len; ++x) { + unichar ch = [str characterAtIndex:x]; + switch (ch) { + case '^': + case '.': + case '[': + case '$': + case '(': + case ')': + case '|': + case '*': + case '+': + case '?': + case '{': + case '\\': + [result appendFormat:@"\\%C", ch]; + break; + default: + [result appendFormat:@"%C", ch]; + break; + } + } + + return result; +} + +- (id)init { + return [self initWithPattern:nil]; +} + +- (id)initWithPattern:(NSString *)pattern { + return [self initWithPattern:pattern options:0]; +} + +- (id)initWithPattern:(NSString *)pattern options:(GTMRegexOptions)options { + return [self initWithPattern:pattern options:options withError:nil]; +} + +- (id)initWithPattern:(NSString *)pattern + options:(GTMRegexOptions)options + withError:(NSError **)outErrorOrNULL { + + self = [super init]; + if (!self) return nil; + + if (outErrorOrNULL) *outErrorOrNULL = nil; + + if ([pattern length] == 0) { + [self release]; + return nil; + } + + // figure out the flags + options_ = options; + int flags = REG_EXTENDED; + if (options_ & kGTMRegexOptionIgnoreCase) + flags |= REG_ICASE; + if ((options_ & kGTMRegexOptionSupressNewlineSupport) == 0) + flags |= REG_NEWLINE; + + // even if regcomp failes we need a flags that we did call regcomp so we'll + // call regfree (because the structure can get filled in some to allow better + // error info). we use pattern_ as this flag. + pattern_ = [pattern copy]; + if (!pattern_) { + // COV_NF_START - no real way to force this in a unittest + [self release]; + return nil; + // COV_NF_END + } + + // compile it + int compResult = regcomp(®exData_, [pattern_ UTF8String], flags); + if (compResult != 0) { + NSString *errorStr = [self errorMessage:compResult]; + if (outErrorOrNULL) { + // include the pattern and patternError message in the userInfo. + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + pattern_, kGTMRegexPatternErrorPattern, + errorStr, kGTMRegexPatternErrorErrorString, + nil]; + *outErrorOrNULL = [NSError errorWithDomain:kGTMRegexErrorDomain + code:kGTMRegexPatternParseFailedError + userInfo:userInfo]; + } else { + // if caller didn't get us an NSError to fill in, we log the error to help + // debugging. + _GTMDevLog(@"Invalid pattern \"%@\", error: \"%@\"", + pattern_, errorStr); + } + + [self release]; + return nil; + } + + return self; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + // we used pattern_ as our flag that we initialized the regex_t + if (pattern_) { + regfree(®exData_); + [pattern_ release]; + // play it safe and clear it since we use it as a flag for regexData_ + pattern_ = nil; + } + [super finalize]; +} +#endif + +- (void)dealloc { + // we used pattern_ as our flag that we initialized the regex_t + if (pattern_) { + regfree(®exData_); + [pattern_ release]; + // play it safe and clear it since we use it as a flag for regexData_ + pattern_ = nil; + } + [super dealloc]; +} + +- (NSUInteger)subPatternCount { + return regexData_.re_nsub; +} + +- (BOOL)matchesString:(NSString *)str { + regmatch_t regMatch; + if (![self runRegexOnUTF8:[str UTF8String] + nmatch:1 + pmatch:®Match + flags:0]) { + // no match + return NO; + } + + // make sure the match is the full string + return (regMatch.rm_so == 0) && + (regMatch.rm_eo == (regoff_t)[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); +} + +- (NSArray *)subPatternsOfString:(NSString *)str { + NSArray *result = nil; + + NSUInteger count = regexData_.re_nsub + 1; + regmatch_t *regMatches = malloc(sizeof(regmatch_t) * count); + if (!regMatches) + return nil; // COV_NF_LINE - no real way to force this in a unittest + + // wrap it all in a try so we don't leak the malloc + @try { + const char *utf8Str = [str UTF8String]; + if (![self runRegexOnUTF8:utf8Str + nmatch:count + pmatch:regMatches + flags:0]) { + // no match + return nil; + } + + // make sure the match is the full string + if ((regMatches[0].rm_so != 0) || + (regMatches[0].rm_eo != (regoff_t)[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding])) { + // only matched a sub part of the string + return nil; + } + + NSMutableArray *buildResult = [NSMutableArray arrayWithCapacity:count]; + + for (NSUInteger x = 0 ; x < count ; ++x) { + if ((regMatches[x].rm_so == -1) && (regMatches[x].rm_eo == -1)) { + // add NSNull since it wasn't used + [buildResult addObject:[NSNull null]]; + } else { + // fetch the string + const char *base = utf8Str + regMatches[x].rm_so; + regoff_t len = regMatches[x].rm_eo - regMatches[x].rm_so; + NSString *sub = + [[[NSString alloc] initWithBytes:base + length:(NSUInteger)len + encoding:NSUTF8StringEncoding] autorelease]; + [buildResult addObject:sub]; + } + } + + result = buildResult; + } // COV_NF_LINE - radar 5851992 only reachable w/ an uncaught exception which isn't testable + @finally { + free(regMatches); + } + + return result; +} + +- (NSString *)firstSubStringMatchedInString:(NSString *)str { + NSString *result = nil; + + regmatch_t regMatch; + const char *utf8Str = [str UTF8String]; + if ([self runRegexOnUTF8:utf8Str + nmatch:1 + pmatch:®Match + flags:0]) { + // fetch the string + const char *base = utf8Str + regMatch.rm_so; + regoff_t len = regMatch.rm_eo - regMatch.rm_so; + result = + [[[NSString alloc] initWithBytes:base + length:(NSUInteger)len + encoding:NSUTF8StringEncoding] autorelease]; + } + return result; +} + +- (BOOL)matchesSubStringInString:(NSString *)str { + regmatch_t regMatch; + if ([self runRegexOnUTF8:[str UTF8String] + nmatch:1 + pmatch:®Match + flags:0]) { + // don't really care what matched, just report the match + return YES; + } + return NO; +} + +- (NSEnumerator *)segmentEnumeratorForString:(NSString *)str { + return [[[GTMRegexEnumerator alloc] initWithRegex:self + processString:str + allSegments:YES] autorelease]; +} + +- (NSEnumerator *)matchSegmentEnumeratorForString:(NSString *)str { + return [[[GTMRegexEnumerator alloc] initWithRegex:self + processString:str + allSegments:NO] autorelease]; +} + +- (NSString *)stringByReplacingMatchesInString:(NSString *)str + withReplacement:(NSString *)replacementPattern { + if (!str) + return nil; + + // if we have a replacement, we go ahead and crack it now. if the replacement + // is just an empty string (or nil), just use the nil marker. + NSArray *replacements = nil; + if ([replacementPattern length]) { + // don't need newline support, just match the start of the pattern for '^' + GTMRegex *replacementRegex = + [GTMRegex regexWithPattern:kReplacementPattern + options:kGTMRegexOptionSupressNewlineSupport]; +#ifdef DEBUG + if (!replacementRegex) { + _GTMDevLog(@"failed to parse out replacement regex!!!"); // COV_NF_LINE + } +#endif + GTMRegexEnumerator *relacementEnumerator = + [[[GTMRegexEnumerator alloc] initWithRegex:replacementRegex + processString:replacementPattern + allSegments:YES] autorelease]; + // We turn on treatStartOfNewSegmentAsBeginningOfLine for this enumerator. + // As complex as kReplacementPattern is, it can't completely do what we want + // with the normal string walk. The problem is this, backreferences are a + // slash follow by a number ("\0"), but the replacement pattern might + // actually need to use backslashes (they have to be escaped). So if a + // replacement were "\\0", then there is no backreference, instead the + // replacement is a backslash and a zero. Generically this means an even + // number of backslashes are all escapes, and an odd are some number of + // literal backslashes followed by our backreference. Think of it as a "an + // odd number of slashes that comes after a non-backslash character." There + // is no way to rexpress this in re_format(7) extended expressions. Instead + // we look for a non-blackslash or string start followed by an optional even + // number of slashes followed by the backreference; and use the special + // flag; so after each match, we restart claiming it's the start of the + // string. (the problem match w/o this flag is a substition of "\2\1") + [relacementEnumerator treatStartOfNewSegmentAsBeginningOfString:YES]; + // pull them all into an array so we can walk this as many times as needed. + replacements = [relacementEnumerator allObjects]; + if (!replacements) { + // COV_NF_START - no real way to force this in a unittest + _GTMDevLog(@"failed to create the replacements for substitutions"); + return nil; + // COV_NF_END + } + } + + NSMutableString *result = [NSMutableString stringWithCapacity:[str length]]; + + NSEnumerator *enumerator = [self segmentEnumeratorForString:str]; + GTMRegexStringSegment *segment = nil; + while ((segment = [enumerator nextObject]) != nil) { + if (![segment isMatch]) { + // not a match, just move this chunk over + [result appendString:[segment string]]; + } else { + // match... + if (!replacements) { + // no replacements, they want to eat matches, nothing to do + } else { + // spin over the split up replacement + GTMRegexStringSegment *replacementSegment = nil; + GTM_FOREACH_OBJECT(replacementSegment, replacements) { + if (![replacementSegment isMatch]) { + // not a match, raw text to put in + [result appendString:[replacementSegment string]]; + } else { + // match... + + // first goes any leading text + NSString *leading = + [replacementSegment subPatternString:kReplacementPatternLeadingTextIndex]; + if (leading) + [result appendString:leading]; + // then use the subpattern number to find what goes in from the + // original string match. + int subPatternNum = + [[replacementSegment subPatternString:kReplacementPatternSubpatternNumberIndex] intValue]; + NSString *matchSubPatStr = [segment subPatternString:subPatternNum]; + // handle an unused subpattern (ie-nil result) + if (matchSubPatStr) + [result appendString:matchSubPatStr]; + } + } + } + } + } + return result; +} + +- (NSString *)description { + NSMutableString *result = + [NSMutableString stringWithFormat:@"%@<%p> { pattern=\"%@\", rawNumSubPatterns=%zd, options=(", + [self class], self, pattern_, regexData_.re_nsub]; + if (options_) { + if (options_ & kGTMRegexOptionIgnoreCase) + [result appendString:@" IgnoreCase"]; + if ((options_ & kGTMRegexOptionSupressNewlineSupport) == kGTMRegexOptionSupressNewlineSupport) + [result appendString:@" NoNewlineSupport"]; + } else { + [result appendString:@" None(Default)"]; + } + [result appendString:@" ) }"]; + return result; +} + +@end + +@implementation GTMRegex (PrivateMethods) + +- (NSString *)errorMessage:(int)errCode { + NSString *result = @"internal error"; + + // size the buffer we need + size_t len = regerror(errCode, ®exData_, NULL, 0); + char *buffer = (char*)malloc(sizeof(char) * len); + if (buffer) { + // fetch the error + if (len == regerror(errCode, ®exData_, buffer, len)) { + NSString *generatedError = [NSString stringWithUTF8String:buffer]; + if (generatedError) + result = generatedError; + } + free(buffer); + } + return result; +} + +// private helper to run the regex on a block +- (BOOL)runRegexOnUTF8:(const char*)utf8Str + nmatch:(size_t)nmatch + pmatch:(regmatch_t *)pmatch + flags:(int)flags { + if (!utf8Str) + return NO; + + int execResult = regexec(®exData_, utf8Str, nmatch, pmatch, flags); + if (execResult != 0) { +#ifdef DEBUG + if (execResult != REG_NOMATCH) { + // COV_NF_START - no real way to force this in a unittest + NSString *errorStr = [self errorMessage:execResult]; + _GTMDevLog(@"%@: matching string \"%.20s...\", had error: \"%@\"", + self, utf8Str, errorStr); + // COV_NF_END + } +#endif + return NO; + } + return YES; +} + +@end + +@implementation GTMRegexEnumerator + +// we don't block init because the class isn't exported, so no one can +// create one, or if they do, they get whatever happens... + +- (id)initWithRegex:(GTMRegex *)regex + processString:(NSString *)str + allSegments:(BOOL)allSegments { + self = [super init]; + if (!self) return nil; + + // collect args + regex_ = [regex retain]; + utf8StrBuf_ = [[str dataUsingEncoding:NSUTF8StringEncoding] retain]; + allSegments_ = allSegments; + + // arg check + if (!regex_ || !utf8StrBuf_) { + [self release]; + return nil; + } + + // parsing state initialized to zero for us by object creation + + return self; +} + +// Don't need a finalize because savedRegMatches_ is marked __strong +- (void)dealloc { + if (savedRegMatches_) { + free(savedRegMatches_); + savedRegMatches_ = nil; + } + [regex_ release]; + [utf8StrBuf_ release]; + [super dealloc]; +} + +- (void)treatStartOfNewSegmentAsBeginningOfString:(BOOL)yesNo { + // The way regexec works, it assumes the first char it's looking at to the + // start of the string. In normal use, this makes sense; but in this case, + // we're going to walk the entry string splitting it up by our pattern. That + // means for the first call, it is the string start, but for all future calls, + // it is NOT the string start, so we will pass regexec the flag to let it + // know. However, (you knew that was coming), there are some cases where you + // actually want the each pass to be considered as the start of the string + // (usually the cases are where a pattern can't express what's needed w/o + // this). There is no really good way to explain this behavior w/o all this + // text and lot of examples, so for now this is not in the public api, and + // just here. (Hint: see what w/in this file uses this for why we have it) + treatStartOfNewSegmentAsBeginningOfString_ = yesNo; +} + +- (id)nextObject { + + GTMRegexStringSegment *result = nil; + regmatch_t *nextMatches = nil; + BOOL isMatch = NO; + + // we do all this w/in a try, so if something throws, the memory we malloced + // will still get cleaned up + @try { + + // if we have a saved match, use that... + if (savedRegMatches_) { + nextMatches = savedRegMatches_; + savedRegMatches_ = nil; + isMatch = YES; // if we have something saved, it was a pattern match + } + // have we reached the end? + else if (curParseIndex_ >= (regoff_t)[utf8StrBuf_ length]) { + // done, do nothing, we'll return nil + } + // do the search. + else { + + // alloc the match structure (extra space for the zero (full) match) + size_t matchBufSize = ([regex_ subPatternCount] + 1) * sizeof(regmatch_t); + nextMatches = malloc(matchBufSize); + if (!nextMatches) + return nil; // COV_NF_LINE - no real way to force this in a unittest + + // setup our range to work on + nextMatches[0].rm_so = curParseIndex_; + nextMatches[0].rm_eo = [utf8StrBuf_ length]; + + // figure out our flags + int flags = REG_STARTEND; + if ((!treatStartOfNewSegmentAsBeginningOfString_) && + (curParseIndex_ != 0)) { + // see -treatStartOfNewSegmentAsBeginningOfString: for why we have + // this check here. + flags |= REG_NOTBOL; + } + + // call for the match + if ([regex_ runRegexOnUTF8:[utf8StrBuf_ bytes] + nmatch:([regex_ subPatternCount] + 1) + pmatch:nextMatches + flags:flags]) { + // match + + if (allSegments_ && + (nextMatches[0].rm_so != curParseIndex_)) { + // we should return all segments (not just matches), and there was + // something before this match. So safe off this match for later + // and create a range for this. + + savedRegMatches_ = nextMatches; + nextMatches = malloc(matchBufSize); + if (!nextMatches) + return nil; // COV_NF_LINE - no real way to force this in a unittest + + isMatch = NO; + // mark everything but the zero slot w/ not used + for (NSUInteger x = [regex_ subPatternCount]; x > 0; --x) { + nextMatches[x].rm_so = nextMatches[x].rm_eo = -1; + } + nextMatches[0].rm_so = curParseIndex_; + nextMatches[0].rm_eo = savedRegMatches_[0].rm_so; + + // advance our marker + curParseIndex_ = savedRegMatches_[0].rm_eo; + + } else { + // we only return matches or are pointed at a match + + // no real work to do, just fall through to return to return the + // current match. + isMatch = YES; + + // advance our marker + curParseIndex_ = nextMatches[0].rm_eo; + } + + } else { + // no match + + // should we return the last non matching segment? + if (allSegments_) { + isMatch = NO; + // mark everything but the zero slot w/ not used + for (NSUInteger x = [regex_ subPatternCount]; x > 0; --x) { + nextMatches[x].rm_so = nextMatches[x].rm_eo = -1; + } + nextMatches[0].rm_so = curParseIndex_; + nextMatches[0].rm_eo = [utf8StrBuf_ length]; + } else { + // drop match set, we don't want it + free(nextMatches); + nextMatches = nil; + } + + // advance our marker since we're done + curParseIndex_ = [utf8StrBuf_ length]; + + } + } + + // create the segment to return + if (nextMatches) { + result = + [[[GTMRegexStringSegment alloc] initWithUTF8StrBuf:utf8StrBuf_ + regMatches:nextMatches + numRegMatches:[regex_ subPatternCount] + isMatch:isMatch] autorelease]; + nextMatches = nil; + } + } @catch (id e) { // COV_NF_START - no real way to force this in a test + _GTMDevLog(@"Exceptions while trying to advance enumeration (%@)", e); + // if we still have something in our temp, free it + if (nextMatches) + free(nextMatches); + } // COV_NF_END + + return result; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@<%p> { regex=\"%@\", allSegments=%s, string=\"%.20s...\" }", + [self class], self, + regex_, + (allSegments_ ? "YES" : "NO"), + [utf8StrBuf_ bytes]]; +} + +@end + +@implementation GTMRegexStringSegment + +- (id)init { + // make sure init is never called, the class in in the header so someone + // could try to create it by mistake. + // Call super init and release so we don't leak + [[super init] autorelease]; + [self doesNotRecognizeSelector:_cmd]; + return nil; // COV_NF_LINE - return is just here to keep gcc happy +} + +- (void)dealloc { + if (regMatches_) { + free(regMatches_); + regMatches_ = nil; + } + [utf8StrBuf_ release]; + [super dealloc]; +} + +- (BOOL)isMatch { + return isMatch_; +} + +- (NSString *)string { + // fetch match zero + return [self subPatternString:0]; +} + +- (NSString *)subPatternString:(NSUInteger)patternIndex { + if (patternIndex > numRegMatches_) + return nil; + + // pick off when it wasn't found + if ((regMatches_[patternIndex].rm_so == -1) && + (regMatches_[patternIndex].rm_eo == -1)) + return nil; + + // fetch the string + const char *base = (const char*)[utf8StrBuf_ bytes] + + regMatches_[patternIndex].rm_so; + regoff_t len = regMatches_[patternIndex].rm_eo + - regMatches_[patternIndex].rm_so; + return [[[NSString alloc] initWithBytes:base + length:(NSUInteger)len + encoding:NSUTF8StringEncoding] autorelease]; +} + +- (NSString *)description { + NSMutableString *result = + [NSMutableString stringWithFormat:@"%@<%p> { isMatch=\"%s\", subPatterns=(", + [self class], self, (isMatch_ ? "YES" : "NO")]; + for (NSUInteger x = 0; x <= numRegMatches_; ++x) { + NSString *format = @", \"%.*s\""; + if (x == 0) + format = @" \"%.*s\""; + + [result appendFormat:format, + (int)(regMatches_[x].rm_eo - regMatches_[x].rm_so), + (((const char*)[utf8StrBuf_ bytes]) + regMatches_[x].rm_so)]; + } + [result appendString:@" ) }"]; + + return result; +} + +@end + +@implementation GTMRegexStringSegment (PrivateMethods) + +- (id)initWithUTF8StrBuf:(NSData *)utf8StrBuf + regMatches:(regmatch_t *)regMatches + numRegMatches:(NSUInteger)numRegMatches + isMatch:(BOOL)isMatch { + self = [super init]; + if (!self) return nil; + + utf8StrBuf_ = [utf8StrBuf retain]; + regMatches_ = regMatches; + numRegMatches_ = numRegMatches; + isMatch_ = isMatch; + + // check the args + if (!utf8StrBuf_ || !regMatches_) { + // COV_NF_START + // this could only happen something messed w/ our internal state. + [self release]; + return nil; + // COV_NF_END + } + + return self; +} + +@end + +@implementation NSString (GTMRegexAdditions) + +- (BOOL)gtm_matchesPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex matchesString:self]; +} + +- (NSArray *)gtm_subPatternsOfPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex subPatternsOfString:self]; +} + +- (NSString *)gtm_firstSubStringMatchedByPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex firstSubStringMatchedInString:self]; +} + +- (BOOL)gtm_subStringMatchesPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex matchesSubStringInString:self]; +} + +- (NSArray *)gtm_allSubstringsMatchedByPattern:(NSString *)pattern { + NSEnumerator *enumerator = [self gtm_matchSegmentEnumeratorForPattern:pattern]; + NSArray *allSegments = [enumerator allObjects]; + return [allSegments valueForKey:@"string"]; +} + +- (NSEnumerator *)gtm_segmentEnumeratorForPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex segmentEnumeratorForString:self]; +} + +- (NSEnumerator *)gtm_matchSegmentEnumeratorForPattern:(NSString *)pattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex matchSegmentEnumeratorForString:self]; +} + +- (NSString *)gtm_stringByReplacingMatchesOfPattern:(NSString *)pattern + withReplacement:(NSString *)replacementPattern { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + return [regex stringByReplacingMatchesInString:self + withReplacement:replacementPattern]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegexTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegexTest.m new file mode 100644 index 00000000..6f41d600 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMRegexTest.m @@ -0,0 +1,1245 @@ +// +// GTMRegexTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMRegex.h" +#import "GTMUnitTestDevLog.h" + +// +// NOTE: +// +// We don't really test any of the pattern matching since that's testing +// libregex, we just want to test our wrapper. +// + +@interface GTMRegexTest : GTMTestCase +@end + +@interface NSString_GTMRegexAdditions : GTMTestCase +@end + +@implementation GTMRegexTest + +- (void)testEscapedPatternForString { + STAssertEqualStrings([GTMRegex escapedPatternForString:@"abcdefghijklmnopqrstuvwxyz0123456789"], + @"abcdefghijklmnopqrstuvwxyz0123456789", + nil); + STAssertEqualStrings([GTMRegex escapedPatternForString:@"^.[$()|*+?{\\"], + @"\\^\\.\\[\\$\\(\\)\\|\\*\\+\\?\\{\\\\", + nil); + STAssertEqualStrings([GTMRegex escapedPatternForString:@"a^b.c[d$e(f)g|h*i+j?k{l\\m"], + @"a\\^b\\.c\\[d\\$e\\(f\\)g\\|h\\*i\\+j\\?k\\{l\\\\m", + nil); + + STAssertNil([GTMRegex escapedPatternForString:nil], nil); + STAssertEqualStrings([GTMRegex escapedPatternForString:@""], @"", nil); +} + + +- (void)testInit { + + // fail cases + STAssertNil([[[GTMRegex alloc] init] autorelease], nil); + STAssertNil([[[GTMRegex alloc] initWithPattern:nil] autorelease], nil); + STAssertNil([[[GTMRegex alloc] initWithPattern:nil + options:kGTMRegexOptionIgnoreCase] autorelease], nil); + [GTMUnitTestDevLog expectString:@"Invalid pattern \"(.\", error: \"parentheses not balanced\""]; + STAssertNil([[[GTMRegex alloc] initWithPattern:@"(."] autorelease], nil); + [GTMUnitTestDevLog expectString:@"Invalid pattern \"(.\", error: \"parentheses not balanced\""]; + STAssertNil([[[GTMRegex alloc] initWithPattern:@"(." + options:kGTMRegexOptionIgnoreCase] autorelease], nil); + // fail cases w/ error param + NSError *error = nil; + STAssertNil([[[GTMRegex alloc] initWithPattern:nil + options:kGTMRegexOptionIgnoreCase + withError:&error] autorelease], nil); + STAssertNil(error, @"no pattern, shouldn't get error object"); + STAssertNil([[[GTMRegex alloc] initWithPattern:@"(." + options:kGTMRegexOptionIgnoreCase + withError:&error] autorelease], nil); + STAssertNotNil(error, nil); + STAssertEqualObjects([error domain], kGTMRegexErrorDomain, nil); + STAssertEquals([error code], (NSInteger)kGTMRegexPatternParseFailedError, nil); + NSDictionary *userInfo = [error userInfo]; + STAssertNotNil(userInfo, @"failed to get userInfo from error"); + STAssertEqualObjects([userInfo objectForKey:kGTMRegexPatternErrorPattern], @"(.", nil); + STAssertNotNil([userInfo objectForKey:kGTMRegexPatternErrorErrorString], nil); + + // basic pattern w/ options + STAssertNotNil([[[GTMRegex alloc] initWithPattern:@"(.*)"] autorelease], nil); + STAssertNotNil([[[GTMRegex alloc] initWithPattern:@"(.*)" + options:0] autorelease], nil); + STAssertNotNil([[[GTMRegex alloc] initWithPattern:@"(.*)" + options:kGTMRegexOptionIgnoreCase] autorelease], nil); + error = nil; + STAssertNotNil([[[GTMRegex alloc] initWithPattern:@"(.*)" + options:kGTMRegexOptionIgnoreCase + withError:&error] autorelease], nil); + STAssertNil(error, @"shouldn't have been any error"); + + // fail cases (helper) + STAssertNil([GTMRegex regexWithPattern:nil], nil); + STAssertNil([GTMRegex regexWithPattern:nil + options:0], nil); + [GTMUnitTestDevLog expectString:@"Invalid pattern \"(.\", error: \"parentheses not balanced\""]; + STAssertNil([GTMRegex regexWithPattern:@"(."], nil); + [GTMUnitTestDevLog expectString:@"Invalid pattern \"(.\", error: \"parentheses not balanced\""]; + STAssertNil([GTMRegex regexWithPattern:@"(." + options:0], nil); + // fail cases (helper) w/ error param + STAssertNil([GTMRegex regexWithPattern:nil + options:kGTMRegexOptionIgnoreCase + withError:&error], nil); + STAssertNil(error, @"no pattern, shouldn't get error object"); + STAssertNil([GTMRegex regexWithPattern:@"(." + options:kGTMRegexOptionIgnoreCase + withError:&error], nil); + STAssertNotNil(error, nil); + STAssertEqualObjects([error domain], kGTMRegexErrorDomain, nil); + STAssertEquals([error code], (NSInteger)kGTMRegexPatternParseFailedError, nil); + userInfo = [error userInfo]; + STAssertNotNil(userInfo, @"failed to get userInfo from error"); + STAssertEqualObjects([userInfo objectForKey:kGTMRegexPatternErrorPattern], @"(.", nil); + STAssertNotNil([userInfo objectForKey:kGTMRegexPatternErrorErrorString], nil); + + // basic pattern w/ options (helper) + STAssertNotNil([GTMRegex regexWithPattern:@"(.*)"], nil); + STAssertNotNil([GTMRegex regexWithPattern:@"(.*)" + options:0], nil); + STAssertNotNil([GTMRegex regexWithPattern:@"(.*)" + options:kGTMRegexOptionIgnoreCase], nil); + error = nil; + STAssertNotNil([GTMRegex regexWithPattern:@"(.*)" + options:kGTMRegexOptionIgnoreCase + withError:&error], nil); + STAssertNil(error, @"shouldn't have been any error"); + + // not really a test on GTMRegex, but make sure we block attempts to directly + // alloc/init a GTMRegexStringSegment. + STAssertThrowsSpecificNamed([[[GTMRegexStringSegment alloc] init] autorelease], + NSException, NSInvalidArgumentException, + @"shouldn't have been able to alloc/init a GTMRegexStringSegment"); +} + +- (void)testOptions { + + NSString *testString = @"aaa AAA\nbbb BBB\n aaa aAa\n bbb BbB"; + + // default options + GTMRegex *regex = [GTMRegex regexWithPattern:@"a+"]; + STAssertNotNil(regex, nil); + NSEnumerator *enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa" + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " AAA\nbbb BBB\n " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" AAA\nbbb BBB\n ", nil); + // "aaa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" ", nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "A" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"A", nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "\n bbb BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\n bbb BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // kGTMRegexOptionIgnoreCase + regex = [GTMRegex regexWithPattern:@"a+" options:kGTMRegexOptionIgnoreCase]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" ", nil); + // "AAA" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"AAA", nil); + // "\nbbb BBB\n " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\nbbb BBB\n ", nil); + // "aaa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" ", nil); + // "aAa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aAa", nil); + // "\n bbb BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\n bbb BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // defaults w/ '^' + regex = [GTMRegex regexWithPattern:@"^a+"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " AAA\nbbb BBB\n aaa aAa\n bbb BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" AAA\nbbb BBB\n aaa aAa\n bbb BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // defaults w/ '$' + regex = [GTMRegex regexWithPattern:@"B+$"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa AAA\nbbb " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa AAA\nbbb ", nil); + // "BBB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"BBB", nil); + // "\n aaa aAa\n bbb Bb" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\n aaa aAa\n bbb Bb", nil); + // "B" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"B", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // kGTMRegexOptionIgnoreCase w/ '$' + regex = [GTMRegex regexWithPattern:@"B+$" + options:kGTMRegexOptionIgnoreCase]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa AAA\nbbb " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa AAA\nbbb ", nil); + // "BBB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"BBB", nil); + // "\n aaa aAa\n bbb " + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\n aaa aAa\n bbb ", nil); + // "BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test w/ kGTMRegexOptionSupressNewlineSupport and \n in the string + regex = [GTMRegex regexWithPattern:@"a.*b" options:kGTMRegexOptionSupressNewlineSupport]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa AAA\nbbb BBB\n aaa aAa\n bbb Bb" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa AAA\nbbb BBB\n aaa aAa\n bbb Bb", nil); + // "B" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"B", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test w/o kGTMRegexOptionSupressNewlineSupport and \n in the string + // (this is no match since it '.' can't match the '\n') + regex = [GTMRegex regexWithPattern:@"a.*b"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa AAA\nbbb BBB\n aaa aAa\n bbb BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa AAA\nbbb BBB\n aaa aAa\n bbb BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // kGTMRegexOptionSupressNewlineSupport w/ '^' + regex = [GTMRegex regexWithPattern:@"^a+" options:kGTMRegexOptionSupressNewlineSupport]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + // " AAA\nbbb BBB\n aaa aAa\n bbb BbB" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @" AAA\nbbb BBB\n aaa aAa\n bbb BbB", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // kGTMRegexOptionSupressNewlineSupport w/ '$' + regex = [GTMRegex regexWithPattern:@"B+$" options:kGTMRegexOptionSupressNewlineSupport]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:testString]; + STAssertNotNil(enumerator, nil); + // "aaa AAA\nbbb BBB\n aaa aAa\n bbb Bb" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa AAA\nbbb BBB\n aaa aAa\n bbb Bb", nil); + // "B" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"B", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); +} + +- (void)testSubPatternCount { + STAssertEquals((NSUInteger)0, [[GTMRegex regexWithPattern:@".*"] subPatternCount], nil); + STAssertEquals((NSUInteger)1, [[GTMRegex regexWithPattern:@"(.*)"] subPatternCount], nil); + STAssertEquals((NSUInteger)1, [[GTMRegex regexWithPattern:@"[fo]*(.*)[bar]*"] subPatternCount], nil); + STAssertEquals((NSUInteger)3, [[GTMRegex regexWithPattern:@"([fo]*)(.*)([bar]*)"] subPatternCount], nil); + STAssertEquals((NSUInteger)7, [[GTMRegex regexWithPattern:@"(([bar]*)|([fo]*))(.*)(([bar]*)|([fo]*))"] subPatternCount], nil); +} + +- (void)testMatchesString { + // simple pattern + GTMRegex *regex = [GTMRegex regexWithPattern:@"foo.*bar"]; + STAssertNotNil(regex, nil); + STAssertTrue([regex matchesString:@"foobar"], nil); + STAssertTrue([regex matchesString:@"foobydoo spambar"], nil); + STAssertFalse([regex matchesString:@"zzfoobarzz"], nil); + STAssertFalse([regex matchesString:@"zzfoobydoo spambarzz"], nil); + STAssertFalse([regex matchesString:@"abcdef"], nil); + STAssertFalse([regex matchesString:@""], nil); + STAssertFalse([regex matchesString:nil], nil); + // pattern w/ sub patterns + regex = [GTMRegex regexWithPattern:@"(foo)(.*)(bar)"]; + STAssertNotNil(regex, nil); + STAssertTrue([regex matchesString:@"foobar"], nil); + STAssertTrue([regex matchesString:@"foobydoo spambar"], nil); + STAssertFalse([regex matchesString:@"zzfoobarzz"], nil); + STAssertFalse([regex matchesString:@"zzfoobydoo spambarzz"], nil); + STAssertFalse([regex matchesString:@"abcdef"], nil); + STAssertFalse([regex matchesString:@""], nil); + STAssertFalse([regex matchesString:nil], nil); +} + +- (void)testSubPatternsOfString { + GTMRegex *regex = [GTMRegex regexWithPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNotNil(regex, nil); + STAssertEquals((NSUInteger)5, [regex subPatternCount], nil); + NSArray *subPatterns = [regex subPatternsOfString:@"foooooobaz"]; + STAssertNotNil(subPatterns, nil); + STAssertEquals((NSUInteger)6, [subPatterns count], nil); + STAssertEqualStrings(@"foooooobaz", [subPatterns objectAtIndex:0], nil); + STAssertEqualStrings(@"foooooo", [subPatterns objectAtIndex:1], nil); + STAssertEqualStrings(@"ooooo", [subPatterns objectAtIndex:2], nil); + STAssertEqualStrings(@"baz", [subPatterns objectAtIndex:3], nil); + STAssertEqualObjects([NSNull null], [subPatterns objectAtIndex:4], nil); + STAssertEqualStrings(@"baz", [subPatterns objectAtIndex:5], nil); + + // not there + subPatterns = [regex subPatternsOfString:@"aaa"]; + STAssertNil(subPatterns, nil); + + // not extra stuff on either end + subPatterns = [regex subPatternsOfString:@"ZZZfoooooobaz"]; + STAssertNil(subPatterns, nil); + subPatterns = [regex subPatternsOfString:@"foooooobazZZZ"]; + STAssertNil(subPatterns, nil); + subPatterns = [regex subPatternsOfString:@"ZZZfoooooobazZZZ"]; + STAssertNil(subPatterns, nil); +} + +- (void)testFirstSubStringMatchedInString { + // simple pattern + GTMRegex *regex = [GTMRegex regexWithPattern:@"foo.*bar"]; + STAssertNotNil(regex, nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"foobar"], + @"foobar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"foobydoo spambar"], + @"foobydoo spambar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"zzfoobarzz"], + @"foobar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"zzfoobydoo spambarzz"], + @"foobydoo spambar", nil); + STAssertNil([regex firstSubStringMatchedInString:@"abcdef"], nil); + STAssertNil([regex firstSubStringMatchedInString:@""], nil); + // pattern w/ sub patterns + regex = [GTMRegex regexWithPattern:@"(foo)(.*)(bar)"]; + STAssertNotNil(regex, nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"foobar"], + @"foobar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"foobydoo spambar"], + @"foobydoo spambar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"zzfoobarzz"], + @"foobar", nil); + STAssertEqualStrings([regex firstSubStringMatchedInString:@"zzfoobydoo spambarzz"], + @"foobydoo spambar", nil); + STAssertNil([regex firstSubStringMatchedInString:@"abcdef"], nil); + STAssertNil([regex firstSubStringMatchedInString:@""], nil); +} + +- (void)testMatchesSubStringInString { + // simple pattern + GTMRegex *regex = [GTMRegex regexWithPattern:@"foo.*bar"]; + STAssertNotNil(regex, nil); + STAssertTrue([regex matchesSubStringInString:@"foobar"], nil); + STAssertTrue([regex matchesSubStringInString:@"foobydoo spambar"], nil); + STAssertTrue([regex matchesSubStringInString:@"zzfoobarzz"], nil); + STAssertTrue([regex matchesSubStringInString:@"zzfoobydoo spambarzz"], nil); + STAssertFalse([regex matchesSubStringInString:@"abcdef"], nil); + STAssertFalse([regex matchesSubStringInString:@""], nil); + // pattern w/ sub patterns + regex = [GTMRegex regexWithPattern:@"(foo)(.*)(bar)"]; + STAssertNotNil(regex, nil); + STAssertTrue([regex matchesSubStringInString:@"foobar"], nil); + STAssertTrue([regex matchesSubStringInString:@"foobydoo spambar"], nil); + STAssertTrue([regex matchesSubStringInString:@"zzfoobarzz"], nil); + STAssertTrue([regex matchesSubStringInString:@"zzfoobydoo spambarzz"], nil); + STAssertFalse([regex matchesSubStringInString:@"abcdef"], nil); + STAssertFalse([regex matchesSubStringInString:@""], nil); +} + +- (void)testSegmentEnumeratorForString { + GTMRegex *regex = [GTMRegex regexWithPattern:@"foo+ba+r"]; + STAssertNotNil(regex, nil); + + // test odd input + NSEnumerator *enumerator = [regex segmentEnumeratorForString:@""]; + STAssertNotNil(enumerator, nil); + enumerator = [regex segmentEnumeratorForString:nil]; + STAssertNil(enumerator, nil); + + // on w/ the normal tests + enumerator = [regex segmentEnumeratorForString:@"afoobarbfooobaarfoobarzz"]; + STAssertNotNil(enumerator, nil); + // "a" + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "b" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"b", nil); + // "fooobaar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"fooobaar", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "zz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"zz", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test no match + enumerator = [regex segmentEnumeratorForString:@"aaa"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test only match + enumerator = [regex segmentEnumeratorForString:@"foobar"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // now test the saved sub segments + regex = [GTMRegex regexWithPattern:@"(foo)((bar)|(baz))"]; + STAssertNotNil(regex, nil); + STAssertEquals((NSUInteger)4, [regex subPatternCount], nil); + enumerator = [regex segmentEnumeratorForString:@"foobarxxfoobaz"]; + STAssertNotNil(enumerator, nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"bar", nil); + STAssertEqualStrings([seg subPatternString:3], @"bar", nil); + STAssertNil([seg subPatternString:4], nil); // nothing matched "(baz)" + STAssertNil([seg subPatternString:5], nil); + // "xx" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"xx", nil); + STAssertEqualStrings([seg subPatternString:0], @"xx", nil); + STAssertNil([seg subPatternString:1], nil); + // "foobaz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"baz", nil); + STAssertNil([seg subPatternString:3], nil); // (nothing matched "(bar)" + STAssertEqualStrings([seg subPatternString:4], @"baz", nil); + STAssertNil([seg subPatternString:5], nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test all objects + regex = [GTMRegex regexWithPattern:@"foo+ba+r"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:@"afoobarbfooobaarfoobarzz"]; + STAssertNotNil(enumerator, nil); + NSArray *allSegments = [enumerator allObjects]; + STAssertNotNil(allSegments, nil); + STAssertEquals((NSUInteger)6, [allSegments count], nil); + + // test we are getting the flags right for newline + regex = [GTMRegex regexWithPattern:@"^a"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:@"aa\naa"]; + STAssertNotNil(enumerator, nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "a\n" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a\n", nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test we are getting the flags right for newline, part 2 + regex = [GTMRegex regexWithPattern:@"^a*$"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:@"aa\naa\nbb\naa"]; + STAssertNotNil(enumerator, nil); + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // "\n" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\n", nil); + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // "\nbb\n" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"\nbb\n", nil); + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // make sure the enum cleans up if not walked to the end + regex = [GTMRegex regexWithPattern:@"b+"]; + STAssertNotNil(regex, nil); + enumerator = [regex segmentEnumeratorForString:@"aabbcc"]; + STAssertNotNil(enumerator, nil); + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // and done w/o walking the rest +} + +- (void)testMatchSegmentEnumeratorForString { + GTMRegex *regex = [GTMRegex regexWithPattern:@"foo+ba+r"]; + STAssertNotNil(regex, nil); + + // test odd input + NSEnumerator *enumerator = [regex matchSegmentEnumeratorForString:@""]; + STAssertNotNil(enumerator, nil); + enumerator = [regex matchSegmentEnumeratorForString:nil]; + STAssertNil(enumerator, nil); + + // on w/ the normal tests + enumerator = [regex matchSegmentEnumeratorForString:@"afoobarbfooobaarfoobarzz"]; + STAssertNotNil(enumerator, nil); + // "a" - skipped + // "foobar" + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "b" - skipped + // "fooobaar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"fooobaar", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "zz" - skipped + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test no match + enumerator = [regex matchSegmentEnumeratorForString:@"aaa"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); // should have gotten nothing + + // test only match + enumerator = [regex matchSegmentEnumeratorForString:@"foobar"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // now test the saved sub segments + regex = [GTMRegex regexWithPattern:@"(foo)((bar)|(baz))"]; + STAssertNotNil(regex, nil); + STAssertEquals((NSUInteger)4, [regex subPatternCount], nil); + enumerator = [regex matchSegmentEnumeratorForString:@"foobarxxfoobaz"]; + STAssertNotNil(enumerator, nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"bar", nil); + STAssertEqualStrings([seg subPatternString:3], @"bar", nil); + STAssertNil([seg subPatternString:4], nil); // nothing matched "(baz)" + STAssertNil([seg subPatternString:5], nil); + // "xx" - skipped + // "foobaz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"baz", nil); + STAssertNil([seg subPatternString:3], nil); // (nothing matched "(bar)" + STAssertEqualStrings([seg subPatternString:4], @"baz", nil); + STAssertNil([seg subPatternString:5], nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test all objects + regex = [GTMRegex regexWithPattern:@"foo+ba+r"]; + STAssertNotNil(regex, nil); + enumerator = [regex matchSegmentEnumeratorForString:@"afoobarbfooobaarfoobarzz"]; + STAssertNotNil(enumerator, nil); + NSArray *allSegments = [enumerator allObjects]; + STAssertNotNil(allSegments, nil); + STAssertEquals((NSUInteger)3, [allSegments count], nil); + + // test we are getting the flags right for newline + regex = [GTMRegex regexWithPattern:@"^a"]; + STAssertNotNil(regex, nil); + enumerator = [regex matchSegmentEnumeratorForString:@"aa\naa"]; + STAssertNotNil(enumerator, nil); + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "a\n" - skipped + // "a" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "a" - skipped + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test we are getting the flags right for newline, part 2 + regex = [GTMRegex regexWithPattern:@"^a*$"]; + STAssertNotNil(regex, nil); + enumerator = [regex matchSegmentEnumeratorForString:@"aa\naa\nbb\naa"]; + STAssertNotNil(enumerator, nil); + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // "\n" - skipped + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // "\nbb\n" - skipped + // "aa" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aa", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); +} + +- (void)testStringByReplacingMatchesInStringWithReplacement { + GTMRegex *regex = [GTMRegex regexWithPattern:@"(foo)(.*)(bar)"]; + STAssertNotNil(regex, nil); + // the basics + STAssertEqualStrings(@"weeZbarZbydoo spamZfooZdoggies", + [regex stringByReplacingMatchesInString:@"weefoobydoo spambardoggies" + withReplacement:@"Z\\3Z\\2Z\\1Z"], + nil); + // nil/empty replacement + STAssertEqualStrings(@"weedoggies", + [regex stringByReplacingMatchesInString:@"weefoobydoo spambardoggies" + withReplacement:nil], + nil); + STAssertEqualStrings(@"weedoggies", + [regex stringByReplacingMatchesInString:@"weefoobydoo spambardoggies" + withReplacement:@""], + nil); + STAssertEqualStrings(@"", + [regex stringByReplacingMatchesInString:@"" + withReplacement:@"abc"], + nil); + STAssertNil([regex stringByReplacingMatchesInString:nil + withReplacement:@"abc"], + nil); + // use optional and invale subexpression parts to confirm that works + regex = [GTMRegex regexWithPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNotNil(regex, nil); + STAssertEqualStrings(@"aaa baz bar bar foo baz aaa", + [regex stringByReplacingMatchesInString:@"aaa foooooobaz fooobar bar foo baz aaa" + withReplacement:@"\\4\\5"], + nil); + STAssertEqualStrings(@"aaa ZZZ ZZZ bar foo baz aaa", + [regex stringByReplacingMatchesInString:@"aaa foooooobaz fooobar bar foo baz aaa" + withReplacement:@"Z\\10Z\\12Z"], + nil); + // test slashes in replacement that aren't part of the subpattern reference + regex = [GTMRegex regexWithPattern:@"a+"]; + STAssertNotNil(regex, nil); + STAssertEqualStrings(@"z\\\\0 \\\\a \\\\\\\\0z", + [regex stringByReplacingMatchesInString:@"zaz" + withReplacement:@"\\\\0 \\\\\\0 \\\\\\\\0"], + nil); + STAssertEqualStrings(@"z\\\\a \\\\\\\\0 \\\\\\\\az", + [regex stringByReplacingMatchesInString:@"zaz" + withReplacement:@"\\\\\\0 \\\\\\\\0 \\\\\\\\\\0"], + nil); + STAssertEqualStrings(@"z\\\\\\\\0 \\\\\\\\a \\\\\\\\\\\\0z", + [regex stringByReplacingMatchesInString:@"zaz" + withReplacement:@"\\\\\\\\0 \\\\\\\\\\0 \\\\\\\\\\\\0"], + nil); +} + +- (void)testDescriptions { + // default options + GTMRegex *regex = [GTMRegex regexWithPattern:@"a+"]; + STAssertNotNil(regex, nil); + STAssertGreaterThan([[regex description] length], (NSUInteger)10, + @"failed to get a reasonable description for regex"); + // enumerator + NSEnumerator *enumerator = [regex segmentEnumeratorForString:@"aaabbbccc"]; + STAssertNotNil(enumerator, nil); + STAssertGreaterThan([[enumerator description] length], (NSUInteger)10, + @"failed to get a reasonable description for regex enumerator"); + // string segment + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertGreaterThan([[seg description] length], (NSUInteger)10, + @"failed to get a reasonable description for regex string segment"); + // regex w/ other options + regex = [GTMRegex regexWithPattern:@"a+" + options:(kGTMRegexOptionIgnoreCase | kGTMRegexOptionSupressNewlineSupport)]; + STAssertNotNil(regex, nil); + STAssertGreaterThan([[regex description] length], (NSUInteger)10, + @"failed to get a reasonable description for regex w/ options"); +} + +@end + +@implementation NSString_GTMRegexAdditions +// Only partial tests to test that the call get through correctly since the +// above really tests them. + +- (void)testMatchesPattern { + // simple pattern + STAssertTrue([@"foobar" gtm_matchesPattern:@"foo.*bar"], nil); + STAssertTrue([@"foobydoo spambar" gtm_matchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"zzfoobarzz" gtm_matchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"zzfoobydoo spambarzz" gtm_matchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"abcdef" gtm_matchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"" gtm_matchesPattern:@"foo.*bar"], nil); + // pattern w/ sub patterns + STAssertTrue([@"foobar" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertTrue([@"foobydoo spambar" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"zzfoobarzz" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"zzfoobydoo spambarzz" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"abcdef" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"" gtm_matchesPattern:@"(foo)(.*)(bar)"], nil); +} + +- (void)testSubPatternsOfPattern { + NSArray *subPatterns = [@"foooooobaz" gtm_subPatternsOfPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNotNil(subPatterns, nil); + STAssertEquals((NSUInteger)6, [subPatterns count], nil); + STAssertEqualStrings(@"foooooobaz", [subPatterns objectAtIndex:0], nil); + STAssertEqualStrings(@"foooooo", [subPatterns objectAtIndex:1], nil); + STAssertEqualStrings(@"ooooo", [subPatterns objectAtIndex:2], nil); + STAssertEqualStrings(@"baz", [subPatterns objectAtIndex:3], nil); + STAssertEqualObjects([NSNull null], [subPatterns objectAtIndex:4], nil); + STAssertEqualStrings(@"baz", [subPatterns objectAtIndex:5], nil); + + // not there + subPatterns = [@"aaa" gtm_subPatternsOfPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNil(subPatterns, nil); + + // not extra stuff on either end + subPatterns = [@"ZZZfoooooobaz" gtm_subPatternsOfPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNil(subPatterns, nil); + subPatterns = [@"foooooobazZZZ" gtm_subPatternsOfPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNil(subPatterns, nil); + subPatterns = [@"ZZZfoooooobazZZZ" gtm_subPatternsOfPattern:@"(fo(o+))((bar)|(baz))"]; + STAssertNil(subPatterns, nil); +} + +- (void)testFirstSubStringMatchedByPattern { + // simple pattern + STAssertEqualStrings([@"foobar" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], + @"foobar", nil); + STAssertEqualStrings([@"foobydoo spambar" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], + @"foobydoo spambar", nil); + STAssertEqualStrings([@"zzfoobarzz" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], + @"foobar", nil); + STAssertEqualStrings([@"zzfoobydoo spambarzz" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], + @"foobydoo spambar", nil); + STAssertNil([@"abcdef" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], nil); + STAssertNil([@"" gtm_firstSubStringMatchedByPattern:@"foo.*bar"], nil); + // pattern w/ sub patterns + STAssertEqualStrings([@"foobar" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], + @"foobar", nil); + STAssertEqualStrings([@"foobydoo spambar" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], + @"foobydoo spambar", nil); + STAssertEqualStrings([@"zzfoobarzz" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], + @"foobar", nil); + STAssertEqualStrings([@"zzfoobydoo spambarzz" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], + @"foobydoo spambar", nil); + STAssertNil([@"abcdef" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], nil); + STAssertNil([@"" gtm_firstSubStringMatchedByPattern:@"(foo)(.*)(bar)"], nil); +} + +- (void)testSubStringMatchesPattern { + // simple pattern + STAssertTrue([@"foobar" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + STAssertTrue([@"foobydoo spambar" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + STAssertTrue([@"zzfoobarzz" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + STAssertTrue([@"zzfoobydoo spambarzz" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"abcdef" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + STAssertFalse([@"" gtm_subStringMatchesPattern:@"foo.*bar"], nil); + // pattern w/ sub patterns + STAssertTrue([@"foobar" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertTrue([@"foobydoo spambar" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertTrue([@"zzfoobarzz" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertTrue([@"zzfoobydoo spambarzz" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"abcdef" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); + STAssertFalse([@"" gtm_subStringMatchesPattern:@"(foo)(.*)(bar)"], nil); +} + +- (void)testSegmentEnumeratorForPattern { + NSEnumerator *enumerator = + [@"afoobarbfooobaarfoobarzz" gtm_segmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + // "a" + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"a", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "b" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"b", nil); + // "fooobaar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"fooobaar", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "zz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"zz", nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test no match + enumerator = [@"aaa" gtm_segmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"aaa", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test only match + enumerator = [@"foobar" gtm_segmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // now test the saved sub segments + enumerator = + [@"foobarxxfoobaz" gtm_segmentEnumeratorForPattern:@"(foo)((bar)|(baz))"]; + STAssertNotNil(enumerator, nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"bar", nil); + STAssertEqualStrings([seg subPatternString:3], @"bar", nil); + STAssertNil([seg subPatternString:4], nil); // nothing matched "(baz)" + STAssertNil([seg subPatternString:5], nil); + // "xx" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertFalse([seg isMatch], nil); + STAssertEqualStrings([seg string], @"xx", nil); + STAssertEqualStrings([seg subPatternString:0], @"xx", nil); + STAssertNil([seg subPatternString:1], nil); + // "foobaz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"baz", nil); + STAssertNil([seg subPatternString:3], nil); // (nothing matched "(bar)" + STAssertEqualStrings([seg subPatternString:4], @"baz", nil); + STAssertNil([seg subPatternString:5], nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test all objects + enumerator = [@"afoobarbfooobaarfoobarzz" gtm_segmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + NSArray *allSegments = [enumerator allObjects]; + STAssertNotNil(allSegments, nil); + STAssertEquals((NSUInteger)6, [allSegments count], nil); +} + +- (void)testMatchSegmentEnumeratorForPattern { + NSEnumerator *enumerator = + [@"afoobarbfooobaarfoobarzz" gtm_matchSegmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + // "a" - skipped + // "foobar" + GTMRegexStringSegment *seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "b" - skipped + // "fooobaar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"fooobaar", nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + // "zz" - skipped + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test no match + enumerator = [@"aaa" gtm_matchSegmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test only match + enumerator = [@"foobar" gtm_matchSegmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // now test the saved sub segments + enumerator = + [@"foobarxxfoobaz" gtm_matchSegmentEnumeratorForPattern:@"(foo)((bar)|(baz))"]; + STAssertNotNil(enumerator, nil); + // "foobar" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobar", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"bar", nil); + STAssertEqualStrings([seg subPatternString:3], @"bar", nil); + STAssertNil([seg subPatternString:4], nil); // nothing matched "(baz)" + STAssertNil([seg subPatternString:5], nil); + // "xx" - skipped + // "foobaz" + seg = [enumerator nextObject]; + STAssertNotNil(seg, nil); + STAssertTrue([seg isMatch], nil); + STAssertEqualStrings([seg string], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:0], @"foobaz", nil); + STAssertEqualStrings([seg subPatternString:1], @"foo", nil); + STAssertEqualStrings([seg subPatternString:2], @"baz", nil); + STAssertNil([seg subPatternString:3], nil); // (nothing matched "(bar)" + STAssertEqualStrings([seg subPatternString:4], @"baz", nil); + STAssertNil([seg subPatternString:5], nil); + // (end) + seg = [enumerator nextObject]; + STAssertNil(seg, nil); + + // test all objects + enumerator = [@"afoobarbfooobaarfoobarzz" gtm_matchSegmentEnumeratorForPattern:@"foo+ba+r"]; + STAssertNotNil(enumerator, nil); + NSArray *allSegments = [enumerator allObjects]; + STAssertNotNil(allSegments, nil); + STAssertEquals((NSUInteger)3, [allSegments count], nil); +} + +- (void)testAllSubstringsMatchedByPattern { + NSArray *segments = + [@"afoobarbfooobaarfoobarzz" gtm_allSubstringsMatchedByPattern:@"foo+ba+r"]; + STAssertNotNil(segments, nil); + STAssertEquals((NSUInteger)3, [segments count], nil); + STAssertEqualStrings([segments objectAtIndex:0], @"foobar", nil); + STAssertEqualStrings([segments objectAtIndex:1], @"fooobaar", nil); + STAssertEqualStrings([segments objectAtIndex:2], @"foobar", nil); + + // test no match + segments = [@"aaa" gtm_allSubstringsMatchedByPattern:@"foo+ba+r"]; + STAssertNotNil(segments, nil); + STAssertEquals((NSUInteger)0, [segments count], nil); + + // test only match + segments = [@"foobar" gtm_allSubstringsMatchedByPattern:@"foo+ba+r"]; + STAssertNotNil(segments, nil); + STAssertEquals((NSUInteger)1, [segments count], nil); + STAssertEqualStrings([segments objectAtIndex:0], @"foobar", nil); +} + +- (void)testStringByReplacingMatchesOfPatternWithReplacement { + // the basics + STAssertEqualStrings(@"weeZbarZbydoo spamZfooZdoggies", + [@"weefoobydoo spambardoggies" gtm_stringByReplacingMatchesOfPattern:@"(foo)(.*)(bar)" + withReplacement:@"Z\\3Z\\2Z\\1Z"], + nil); + // nil/empty replacement + STAssertEqualStrings(@"weedoggies", + [@"weefoobydoo spambardoggies" gtm_stringByReplacingMatchesOfPattern:@"(foo)(.*)(bar)" + withReplacement:nil], + nil); + STAssertEqualStrings(@"weedoggies", + [@"weefoobydoo spambardoggies" gtm_stringByReplacingMatchesOfPattern:@"(foo)(.*)(bar)" + withReplacement:@""], + nil); + STAssertEqualStrings(@"", + [@"" gtm_stringByReplacingMatchesOfPattern:@"(foo)(.*)(bar)" + withReplacement:@"abc"], + nil); + // use optional and invale subexpression parts to confirm that works + STAssertEqualStrings(@"aaa baz bar bar foo baz aaa", + [@"aaa foooooobaz fooobar bar foo baz aaa" gtm_stringByReplacingMatchesOfPattern:@"(fo(o+))((bar)|(baz))" + withReplacement:@"\\4\\5"], + nil); + STAssertEqualStrings(@"aaa ZZZ ZZZ bar foo baz aaa", + [@"aaa foooooobaz fooobar bar foo baz aaa" gtm_stringByReplacingMatchesOfPattern:@"(fo(o+))((bar)|(baz))" + withReplacement:@"Z\\10Z\\12Z"], + nil); + // test slashes in replacement that aren't part of the subpattern reference + STAssertEqualStrings(@"z\\\\0 \\\\a \\\\\\\\0z", + [@"zaz" gtm_stringByReplacingMatchesOfPattern:@"a+" + withReplacement:@"\\\\0 \\\\\\0 \\\\\\\\0"], + nil); + STAssertEqualStrings(@"z\\\\a \\\\\\\\0 \\\\\\\\az", + [@"zaz" gtm_stringByReplacingMatchesOfPattern:@"a+" + withReplacement:@"\\\\\\0 \\\\\\\\0 \\\\\\\\\\0"], + nil); + STAssertEqualStrings(@"z\\\\\\\\0 \\\\\\\\a \\\\\\\\\\\\0z", + [@"zaz" gtm_stringByReplacingMatchesOfPattern:@"a+" + withReplacement:@"\\\\\\\\0 \\\\\\\\\\0 \\\\\\\\\\\\0"], + nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.h new file mode 100644 index 00000000..0697d5aa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.h @@ -0,0 +1,713 @@ +// +// GTMSQLite.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// +// +// This class is a convenience wrapper for SQLite storage with +// release/retain semantics. In its most basic form, that is all this +// class offers. You have the option of activating "CFAdditions" on +// init which patches or overrides the following SQLite functionality: +// +// - Strings you pass through the API layer will always be converted +// to precomposed UTF-8 with compatibility mapping +// (kCFStringNormalizationFormKC). This is done in an attempt to +// make SQLite correctly handle string equality for composed +// character sequences. This change applies only to +// NSStrings/CFStrings passed through the GTMSQLiteDatabase or +// GTMSQLiteStatement. Direct access to the database using the +// underlying sqlite3_* handles is not affected. +// +// - The SQL UPPER/LOWER functions are replaced with CFString-based +// implementations which (unlike SQLite's native implementation) +// handle case conversion outside the ASCII range. These +// implementations seem to be 20-30% slower than the SQLite +// implementations but may be worth it for accuracy. +// +// - The SQLite "NOCASE" collation is replaced with a CFString-based +// collation that is case insensitive but still uses literal +// comparison (composition-sensitive). +// +// - Additional collation sequences can be created by using these keywords +// separated by underscores. Each option corresponds to a CFStringCompareFlags +// option. +// NOCASE (kCFCompareCaseInsensitive) +// NONLITERAL (kCFCompareNonliteral) +// LOCALIZED (kCFCompareLocalized) +// NUMERIC (kCFCompareNumerically) + +// These additional options are available when linking with the 10.5 SDK: +// NODIACRITIC (kCFCompareDiacriticInsensitive) +// WIDTHINSENSITIVE (kCFCompareWidthInsensitive) +// +// Ordering of the above options can be changed by adding "REVERSE". +// +// Thus, for a case-insensitive, width-insensitive, composition-insensitive +// comparison that ignores diacritical marks and sorts in reverse use: +// +// NOCASE_NONLITERAL_NODIACRITIC_WIDTHINSENSITIVE_REVERSE +// +// - SQL LIKE and GLOB commands are implemented with CFString/CFCharacterSet +// comparisons. As with the other CF additions, this gives us better handling +// of case and composed character sequences. However, whereever reasonable, +// SQLite semantics have been retained. Specific notes: +// +// * LIKE is case insensitive and uses non-literal comparison +// (kCFCompareNonliteral) by default. It is possible to modify this +// behavior using the accessor methods. You must use those methods +// instead of the SQLite "PRAGMA case_sensitive_like" in order for them +// to interact properly with our CFString implementations. +// +// * ESCAPE clauses to LIKE are honored, but the escape character must +// be expressable as a single UniChar (UTF16). The escaped characters in +// LIKE only escape the following UniChar, not a composed character +// sequence. This is not viewed as a limitation since the use of ESCAPE +// is typically only for characters with meaning to SQL LIKE ('%', '_') +// all of which can be expressed as a single UniChar. +// +// * GLOB is by default case sensitive but non-literal. Again, accessor +// methods are available to change this behavior. +// +// * Single character pattern matches ('_' for LIKE, '?' for GLOB) will +// always consume a full composed character sequence. +// +// * As with the standard SQLite implementation, character set comparisons +// are only available for GLOB. +// +// * Character set comparisons are always literal and case sensitive and do +// not take into account composed character sequences. Essentially +// character sets should always be expressed as a set of single UniChars +// or ranges between single UniChars. +// + +// SQLite is preinstalled on 10.4 only. As long as we're using the OS version +// of the library, limit ourself to Tiger+ +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 +#error SQLite support is Tiger or later +#endif + +#import +#import + +/// Wrapper for SQLite with release/retain semantics and CFString convenience features +@interface GTMSQLiteDatabase : NSObject { + @protected + sqlite3 *db_; // strong + NSString *path_; // strong + int timeoutMS_; + BOOL hasCFAdditions_; + CFOptionFlags likeOptions_; + CFOptionFlags globOptions_; + NSMutableArray *userArgDataPool_; // strong +} + +// Get the numeric version number of the SQLite library (compiled in value +// for SQLITE_VERSION_NUMBER). +// +// Returns: +// Integer version number +// ++ (int)sqliteVersionNumber; + +// Get the string version number of the SQLite library. +// +// Returns: +// Autoreleased NSString version string +// ++ (NSString *)sqliteVersionString; + +// Create and open a database instance on a file-based database. +// +// Args: +// path: Path to the database. If it does not exist an empty database +// will be created. +// withCFAdditions: If true, the SQLite database will include CFString +// based string functions and collation sequences. See +// the class header for information on these differences +// and performance impact. +// err: Result code from SQLite. If nil is returned by this function +// check the result code for the error. If NULL no result code is +// reported. +// +- (id)initWithPath:(NSString *)path + withCFAdditions:(BOOL)additions + utf8:(BOOL)useUTF8 + errorCode:(int *)err; + +// Create and open a memory-based database. Memory-based databases +// cannot be shared amongst threads, and each instance is unique. See +// SQLite documentation for details. +// +// For argument details see [... initWithPath:withCFAdditions:errorCode:] +// +- (id)initInMemoryWithCFAdditions:(BOOL)additions + utf8:(BOOL)useUTF8 + errorCode:(int *)err; + +// Get the underlying SQLite database handle. In general you should +// never do this, if you do use this be careful with how you compose +// and decompse strings you pass to the database. +// +// Returns: +// sqlite3 pointer +// +- (sqlite3 *)sqlite3DB; + +// Enable/Disable the database synchronous mode. Disabling +// synchronous mode results in much faster insert throughput at the +// cost of safety. See the SQlite documentation for details. +// +// Args: +// enable: Boolean flag to determine mode. +// +- (void)synchronousMode:(BOOL)enable; + +// Check if this database instance has our CFString functions and collation +// sequences (see top of file for details). +// +// Returns: +// YES if the GTMSQLiteDatabase instance has our CF additions +// +- (BOOL)hasCFAdditions; + +// Set comparison options for the "LIKE" operator for databases with +// our CF addtions active. +// +// Args: +// options: CFStringCompareFlags value. Note that a limited list +// of options are supported. For example one cannot +// use kCFCompareBackwards as an option. +// +- (void)setLikeComparisonOptions:(CFOptionFlags)options; + +// Get current comparison options for the "LIKE" operator in a database +// with our CF additions active. +// +// Returns: +// Current comparison options or zero if CF additions are inactive. +// +- (CFOptionFlags)likeComparisonOptions; + +// Set comparison options for the "GLOB" operator for databases with +// our CF addtions active. +// +// Args: +// options: CFStringCompareFlags value. Note that a limited list +// of options are supported. For example one cannot +// use kCFCompareBackwards as an option. +// +- (void)setGlobComparisonOptions:(CFOptionFlags)options; + +// Get current comparison options for the "GLOB" operator in a database +// with our CF additions active. +// +// Returns: +// Current comparison options or zero if CF additions are inactive. +// +- (CFOptionFlags)globComparisonOptions; + +// Obtain the last error code from the database +// +// Returns: +// SQLite error code, if no error is pending returns SQLITE_OK +// +- (int)lastErrorCode; + +// Obtain an error string for the last error from the database +// +// Returns: +// Autoreleased NSString error message +// +- (NSString *)lastErrorString; + +// Obtain a count of rows added, mmodified or deleted by the most recent +// statement. See sqlite3_changes() for details and limitations. +// +// Returns: +// Row count +// +- (int)lastChangeCount; + +// Obtain a count of rows added, mmodified or deleted since the database +// was opened. See sqlite3_total_changes() for details and limitations. +// +// Returns: +// Row count +// +- (int)totalChangeCount; + +// Obtain the last insert row ID +// +// Returns: +// 64-bit row ID +// +- (unsigned long long)lastInsertRowID; + +// Interrupt any currently running database operations as soon as possible. +// Running operations will receive a SQLITE_INTERRUPT and will need to +// handle it correctly (this is the callers problem to deal with). +// +- (void)interrupt; + +// Set the timeout value in milliseconds. This is a database global affecting +// all running and future statements. +// +// Args: +// timeoutMS: Integer count in ms SQLite will wait for the database to +// unlock before giving up and returning SQLITE_BUSY. A value +// of 0 or less means the database always returns immediately. +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)setBusyTimeoutMS:(int)timeoutMS; + +// Get the current busy timeout in milliseconds. +// +// Returns: +// Current database busy timeout value in ms, 0 or less means no timeout. +// +- (int)busyTimeoutMS; + +// Execute a string containing one or more SQL statements. No returned data +// is available, use GTMSQLiteStatement for that usage. +// +// Args: +// sql: Raw SQL statement to prepare. It is the caller's responsibility +// to properly escape the SQL. +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)executeSQL:(NSString *)sql; + +// Convenience method to start a deferred transaction (most common case). +// +// Returns: +// YES if the transaction started successfully +// +- (BOOL)beginDeferredTransaction; + +// Convenience method to roll back a transaction. +// +// Returns: +// YES if the transaction rolled back successfully +// +- (BOOL)rollback; + +// Convenience method to commit a transaction. +// +// Returns: +// YES if the transaction committed successfully +// +- (BOOL)commit; + +@end + +// Wrapper class for SQLite statements with retain/release semantics. +// Attempts to behave like an NSEnumerator, however you should bind +// your values before beginning enumeration and unlike NSEnumerator, +// a reset is supported. +// +// The GTMSQLiteDatabase class has options to modify some SQL +// functions and force particular string representations. This class +// honors the database preferences for those options. See the +// GTMSQLiteDatabase header for details. + +/// Wrapper class for SQLite statements with retain/release +/// semantics. +@interface GTMSQLiteStatement : NSObject { + +@protected + sqlite3_stmt *statement_; + BOOL hasCFAdditions_; +} + +#pragma mark Creation, Access and Finalization + +// Create an autoreleased prepared statement, see initWithSQL: for arguments. +// +// NOTE: Even though this object is autoreleased you MUST call +// [finalizeStatement] on this when your done. See the init for explanation. +// +// Returns: +// Autoreleased GTMSQLiteStatement +// ++ (id)statementWithSQL:(NSString *)sql + inDatabase:(GTMSQLiteDatabase *)gtmdb + errorCode:(int *)err; + +// Designated initializer, create a prepared statement. Positional and named +// parameters are supported, see the SQLite documentation. +// +// NOTE: Although this object will clean up its statement when deallocated, +// you are REQUIRED to "finalize" the statement when you are +// through with it. Failing to do this will prevent the database from allowing +// new transactions or queries. In other words, leaving an instance on the +// autorelease pool unfinalized may interfere with other database usage if any +// caller sharing the database uses transactions. +// +// Args: +// sql: Raw SQL statement to prepare. It is the caller's responsibility +// to properly escape the SQL and make sure that the SQL contains +// only _one_ statement. Additional statements are silently ignored. +// db: The GTMSQLiteDatabase (not retained) +// err: Result code from SQLite. If nil is returned by this function +// check the result code for the error. If NULL no result code is +// reported. +// +- (id)initWithSQL:(NSString *)sql + inDatabase:(GTMSQLiteDatabase *)gtmdb + errorCode:(int *)err; + +// Get the underlying SQLite statement handle. In general you should never +// do this, if you do use this be careful with how you compose and +// decompse strings you pass to the database. +// +// Returns: +// sqlite3_stmt pointer +// +- (sqlite3_stmt *)sqlite3Statement; + +// Finalize the statement, allowing other transactions to start on the database +// This method MUST be called when you are done with a statement. Failure to +// do so means that the database will not be torn down properly when it's +// retain count drops to 0 or GC collects it. +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)finalizeStatement; + +#pragma mark Parameters and Binding + +// Get the number of parameters that can be bound in the prepared statement. +// +// Returns: +// Integer count of parameters or -1 on error +// +- (int)parameterCount; + +// Get the position of a parameter with a given name. +// +// Args: +// paramName: String name of the parameter, including any leading punctuation +// (see SQLite docs) +// +// Returns: +// 1-based parameter position index or -1 on error +// +- (int)positionOfParameterNamed:(NSString *)paramName; + +// Get the name of a parameter at a particular index. +// +// Args: +// position: Parameter position (1-based index) +// +// Returns: +// Autoreleased string name of the parameter, including any leading +// punctuation (see SQLite docs) or nil on error. +// +- (NSString *)nameOfParameterAtPosition:(int)position; + +// Bind a NULL at a given position +// +// Args: +// position: Parameter position (1-based index) +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindSQLNullAtPosition:(int)position; + +// Bind a blob parameter at a given position index to a raw pointer and +// length. The data will be copied by SQLite +// +// Args: +// position: Parameter position (1-based index) +// bytes: Raw pointer to the data to copy/bind +// length: Number of bytes in the blob +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindBlobAtPosition:(int)position bytes:(void *)bytes length:(int)length; + +// Bind an NSData as a blob at a given position. The data will be copied +// by SQLite. +// +// Args: +// position: Parameter position (1-based index) +// data: NSData to convert to blob +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindBlobAtPosition:(int)position data:(NSData *)data; + +// Bind a double at the given position (for floats convert to double). +// +// Args: +// position: Parameter position (1-based index) +// value: Double to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindDoubleAtPosition:(int)position value:(double)value; + +// Bind an NSNumber as a double value at the given position. +// +// Args: +// position: Parameter position (1-based index) +// number: NSNumber to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindNumberAsDoubleAtPosition:(int)position number:(NSNumber *)number; + +// Bind a 32-bit integer at the given position. +// +// Args: +// position: Parameter position (1-based index) +// value: Integer to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindInt32AtPosition:(int)position value:(int)value; + +// Bind an NSNumber as a 32-bit integer value at the given position. +// +// Args: +// position: Parameter position (1-based index) +// number: NSNumber to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindNumberAsInt32AtPosition:(int)position number:(NSNumber *)number; + +// Bind a 64-bit integer at the given position. +// +// Args: +// position: Parameter position (1-based index) +// value: Int64 value to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindLongLongAtPosition:(int)position value:(long long)value; + +// Bind an NSNumber as a 64-bit integer value at the given position. +// +// Args: +// position: Parameter position (1-based index) +// number: NSNumber to bind +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindNumberAsLongLongAtPosition:(int)position number:(NSNumber *)number; + +// Bind a string at the given position. +// +// Args: +// position: Parameter position (1-based index) +// string: String to bind (string will be converted to UTF8 and copied). +// NOTE: For bindings it is not necessary for you to SQL escape +// your strings. +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)bindStringAtPosition:(int)position string:(NSString *)string; + +#pragma mark Results + +// Get the number of result columns per row this statement will generate. +// +// Returns: +// Column count, 0 if no columns will be returned ("UPDATE.." etc.), +// -1 on error. +// +- (int)resultColumnCount; + +// Get the name of result colument at a given index. +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Autoreleased NSString column name or nil if no column exists at that +// position or error. +// +- (NSString *)resultColumnNameAtPosition:(int)position; + +// Get the number of data values in the current row of this statement. +// Generally this will be the same as resultColumnCount:, except when row +// iteration is done (see SQLite docs for sqlite3_data_count()). +// +// Returns: +// Data count or 0 if no data will be returned, -1 on error. +// +- (int)rowDataCount; + +// Get the SQLite type constant for a column in a row. Note that because +// SQLite does not enforce column type restrictions the type of a particular +// column in a row may not match the declared type of the column. +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// SQLite data type constant (i.e. SQLITE_INTEGER, SQLITE_FLOAT, etc.) or +// -1 on error. +// +- (int)resultColumnTypeAtPosition:(int)position; + +// Get the data for a result row blob column as an NSData +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Autoreleased NSData, nil on error +// +- (NSData *)resultBlobDataAtPosition:(int)position; + +// Get the data for a result row blob column as a double +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Double value +// +- (double)resultDoubleAtPosition:(int)position; + +// Get the data for a result row blob column as an integer +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Integer value +// +- (int)resultInt32AtPosition:(int)position; + +// Get the data for a result row blob column as a long long +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Long long value +// +- (long long)resultLongLongAtPosition:(int)position; + +// Get the data for a result row blob column as an NSNumber +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Autoreleased NSNumber value or nil on error +// +- (NSNumber *)resultNumberAtPosition:(int)position; + +// Get the data for a result row blob column as an NSString +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Autoreleased NSString value or nil on error +// +- (NSString *)resultStringAtPosition:(int)position; + +// Get a Foundation object (NSData, NSNumber, NSString, NSNull) for the column, +// autodetecting the most appropriate representation. +// +// Args: +// position: Column position (0-based index) +// +// Returns: +// Autoreleased Foundation type, nil on error +// +- (id)resultFoundationObjectAtPosition:(int)position; + +// Get an array of Foundation objects for the row in query column order. +// +// Returns: +// Autoreleased array of Foundation types or nil if there is no +// data in the row or error +// +- (NSArray *)resultRowArray; + +// Get a dictionary of Foundation objects for the row keyed by column name. +// +// Returns: +// Autoreleased dictionary of Foundation types or nil if there is no +// data in the row or error. +// +- (NSDictionary *)resultRowDictionary; + +#pragma mark Rows + +// Step the statement forward one row, potentially spinning forever till +// the row can be located (if database is SQLITE_BUSY). +// +// Returns: +// SQLite result code, SQLITE_ROW if a row was found or SQLITE_DONE if +// no further rows match the statement. +// +- (int)stepRow; + +// Step the statement forward one row, waiting at most the currrent database +// busy timeout (see [GTMSQLiteDatabase setBusyTimeoutMS]). +// +// Returns: +// SQLite result code, SQLITE_ROW if a row was found or SQLITE_DONE if +// no further rows match the statement. If SQLITE_BUSY is returned the +// database did not unlock during the timeout. +// +- (int)stepRowWithTimeout; + +// Reset the statement starting again at the first row +// +// Returns: +// SQLite result code, SQLITE_OK on no error +// +- (int)reset; + +// Check if the SQLite parser recognizes the receiver as one or more valid +// SQLite statements. +// +// Returns: +// YES if the string is a complete and valid SQLite statement +// ++ (BOOL)isCompleteStatement:(NSString *)string; + +// Quote and escape the receiver for SQL. +// Example: "This is wild! It's fun!" +// Becomes: "'This is wild! It''s fun!'" +// +// Returns: +// Autoreleased NSString ++ (NSString *)quoteAndEscapeString:(NSString *)string; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.m new file mode 100644 index 00000000..0225ff54 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLite.m @@ -0,0 +1,2012 @@ +// +// GTMSQLite.m +// +// Convenience wrapper for SQLite storage see the header for details. +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#import +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +#import +#endif +#import "GTMSQLite.h" +#import "GTMMethodCheck.h" +#import "GTMDefines.h" +#include +#import "GTMGarbageCollection.h" + +typedef struct { + BOOL upperCase; + int textRep; +} UpperLowerUserArgs; + +typedef struct { + BOOL reverse; + CFOptionFlags compareOptions; + int textRep; +} CollateUserArgs; + +typedef struct { + CFOptionFlags *compareOptionPtr; + int textRep; +} LikeGlobUserArgs; + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +// While we want to be compatible with Tiger, some operations are more +// efficient when implemented with Leopard APIs. We look those up dynamically. +// CFStringCreateWithBytesNoCopy +static const char* const kCFStringCreateWithBytesNoCopySymbolName = + "CFStringCreateWithBytesNoCopy"; + +typedef CFStringRef (*CFStringCreateWithBytesNoCopyPtrType)(CFAllocatorRef, + const UInt8 *, + CFIndex, + CFStringEncoding, + Boolean, + CFAllocatorRef); +static CFStringCreateWithBytesNoCopyPtrType gCFStringCreateWithBytesNoCopySymbol = NULL; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +// Helper inline for SQLite text type to CF endcoding +GTM_INLINE CFStringEncoding SqliteTextEncodingToCFStringEncoding(int enc) { + // Default should never happen, but assume UTF 8 + CFStringEncoding encoding = kCFStringEncodingUTF8; + _GTMDevAssert(enc == SQLITE_UTF16BE || + enc == SQLITE_UTF16LE, + @"Passed in encoding was not a UTF16 encoding"); + switch(enc) { + case SQLITE_UTF16BE: + encoding = kCFStringEncodingUTF16BE; + break; + case SQLITE_UTF16LE: + encoding = kCFStringEncodingUTF16LE; + break; + } + return encoding; +} + +// Helper inline for filtering CFStringCompareFlags +GTM_INLINE CFOptionFlags FilteredStringCompareFlags(CFOptionFlags inOptions) { + CFOptionFlags outOptions = 0; + if (inOptions & kCFCompareCaseInsensitive) { + outOptions |= kCFCompareCaseInsensitive; + } + if (inOptions & kCFCompareNonliteral) outOptions |= kCFCompareNonliteral; + if (inOptions & kCFCompareLocalized) outOptions |= kCFCompareLocalized; + if (inOptions & kCFCompareNumerically) outOptions |= kCFCompareNumerically; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + if (inOptions & kCFCompareDiacriticInsensitive) { + outOptions |= kCFCompareDiacriticInsensitive; + } + if (inOptions & kCFCompareWidthInsensitive) { + outOptions |= kCFCompareWidthInsensitive; + } +#endif + return outOptions; +} + +// Function prototypes for our custom implementations of UPPER/LOWER using +// CFString so that we handle Unicode and localization more cleanly than +// native SQLite. +static void UpperLower8(sqlite3_context *context, + int argc, + sqlite3_value **argv); +static void UpperLower16(sqlite3_context *context, + int argc, + sqlite3_value **argv); + +// Function prototypes for CFString-based collation sequences +static void CollateNeeded(void *userContext, sqlite3 *db, + int textRep, const char *name); +static int Collate8(void *userContext, int length1, const void *str1, + int length2, const void *str2); +static int Collate16(void *userContext, int length1, const void *str1, + int length2, const void *str2); + +// Function prototypes for CFString LIKE and GLOB +static void Like8(sqlite3_context *context, int argc, sqlite3_value **argv); +static void Like16(sqlite3_context *context, int argc, sqlite3_value **argv); +static void Glob8(sqlite3_context *context, int argc, sqlite3_value **argv); +static void Glob16(sqlite3_context *context, int argc, sqlite3_value **argv); + +// The CFLocale of the current user at process start +static CFLocaleRef gCurrentLocale = NULL; + +// Private methods +@interface GTMSQLiteDatabase (PrivateMethods) + +- (int)installCFAdditions; +- (void)collationArgumentRetain:(NSData *)collationArgs; +// Convenience method to clean up resources. Called from both +// dealloc & finalize +// +- (void)cleanupDB; +@end + +@implementation GTMSQLiteDatabase + ++ (void)initialize { + // Need the locale for some CFString enhancements + gCurrentLocale = CFLocaleCopyCurrent(); + +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + // Compiling pre-Leopard try to find some symbols dynamically + gCFStringCreateWithBytesNoCopySymbol = + (CFStringCreateWithBytesNoCopyPtrType)dlsym( + RTLD_DEFAULT, + kCFStringCreateWithBytesNoCopySymbolName); +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +} + ++ (int)sqliteVersionNumber { + return sqlite3_libversion_number(); +} + ++ (NSString *)sqliteVersionString { + return [NSString stringWithUTF8String:sqlite3_libversion()]; +} + +- (id)initWithPath:(NSString *)path + withCFAdditions:(BOOL)additions + utf8:(BOOL)useUTF8 + errorCode:(int *)err { + int rc = SQLITE_INTERNAL; + + if ((self = [super init])) { + path_ = [path copy]; + if (useUTF8) { + rc = sqlite3_open([path_ fileSystemRepresentation], &db_); + } else { + CFStringEncoding cfEncoding; +#if TARGET_RT_BIG_ENDIAN + cfEncoding = kCFStringEncodingUTF16BE; +#else + cfEncoding = kCFStringEncodingUTF16LE; +#endif + NSStringEncoding nsEncoding + = CFStringConvertEncodingToNSStringEncoding(cfEncoding); + NSData *data = [path dataUsingEncoding:nsEncoding]; + // Using -[NSString cStringUsingEncoding] causes sqlite3_open16 + // to fail because it expects 2 null-terminating bytes and + // cStringUsingEncoding only has 1 + NSMutableData *mutable = [NSMutableData dataWithData:data]; + [mutable increaseLengthBy:2]; + rc = sqlite3_open16([mutable bytes], &db_); + } + + if ((rc == SQLITE_OK) && db_) { + if (additions) { + userArgDataPool_ = [[NSMutableArray array] retain]; + if (!userArgDataPool_) { + // Leave *err as internal err + // COV_NF_START - not sure how to fail Cocoa initializers + [self release]; + return nil; + // COV_NF_END + } + rc = [self installCFAdditions]; + } + } + + if (err) *err = rc; + + if (rc != SQLITE_OK) { + // COV_NF_START + [self release]; + self = nil; + // COV_NF_END + } + } + + return self; +} + +- (id)initInMemoryWithCFAdditions:(BOOL)additions + utf8:(BOOL)useUTF8 + errorCode:(int *)err { + return [self initWithPath:@":memory:" + withCFAdditions:additions + utf8:useUTF8 + errorCode:err]; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + [self cleanupDB]; + [super finalize]; +} +#endif + +- (void)dealloc { + [self cleanupDB]; + [super dealloc]; +} + +- (void)cleanupDB { + if (db_) { + int rc = sqlite3_close(db_); + if (rc != SQLITE_OK) { + _GTMDevLog(@"Unable to close \"%@\", error code: %d\r" + @"Did you forget to call -[GTMSQLiteStatement" + @" finalizeStatement] on one of your statements?", + self, rc); + } + } + [path_ release]; + [userArgDataPool_ release]; +} + +// Private method to install our custom CoreFoundation additions to SQLite +// behavior +- (int)installCFAdditions { + int rc = SQLITE_OK; + // Install our custom functions for improved text handling + // UPPER/LOWER + const struct { + const char *sqlName; + UpperLowerUserArgs userArgs; + void *function; + } customUpperLower[] = { + { "upper", { YES, SQLITE_UTF8 }, &UpperLower8 }, + { "upper", { YES, SQLITE_UTF16 }, &UpperLower16 }, + { "upper", { YES, SQLITE_UTF16BE }, &UpperLower16 }, + { "upper", { YES, SQLITE_UTF16LE }, &UpperLower16 }, + { "lower", { NO, SQLITE_UTF8 }, &UpperLower8 }, + { "lower", { NO, SQLITE_UTF16 }, &UpperLower16 }, + { "lower", { NO, SQLITE_UTF16BE }, &UpperLower16 }, + { "lower", { NO, SQLITE_UTF16LE }, &UpperLower16 }, + }; + + for (size_t i = 0; + i < (sizeof(customUpperLower) / sizeof(customUpperLower[0])); + i++) { + rc = sqlite3_create_function(db_, + customUpperLower[i].sqlName, + 1, + customUpperLower[i].userArgs.textRep, + (void *)&customUpperLower[i].userArgs, + customUpperLower[i].function, + NULL, + NULL); + if (rc != SQLITE_OK) + return rc; // COV_NF_LINE because sqlite3_create_function is + // called with input defined at compile-time + } + + // Fixed collation sequences + const struct { + const char *sqlName; + CollateUserArgs userArgs; + void *function; + } customCollationSequence[] = { + { "nocase", { NO, kCFCompareCaseInsensitive, SQLITE_UTF8 }, &Collate8 }, + { "nocase", { NO, kCFCompareCaseInsensitive, SQLITE_UTF16 }, &Collate16 }, + { "nocase", { NO, kCFCompareCaseInsensitive, SQLITE_UTF16BE }, &Collate16 }, + { "nocase", { NO, kCFCompareCaseInsensitive, SQLITE_UTF16LE }, &Collate16 }, + }; + + for (size_t i = 0; + i < (sizeof(customCollationSequence) / sizeof(customCollationSequence[0])); + i++) { + rc = sqlite3_create_collation(db_, + customCollationSequence[i].sqlName, + customCollationSequence[i].userArgs.textRep, + (void *)&customCollationSequence[i].userArgs, + customCollationSequence[i].function); + if (rc != SQLITE_OK) + return rc; // COV_NF_LINE because the input to + // sqlite3_create_collation is set at compile time + } + + // Install handler for dynamic collation sequences + const struct { + const char *sqlName; + int numArgs; + int textRep; + void *function; + } customLike[] = { + { "like", 2, SQLITE_UTF8, &Like8 }, + { "like", 2, SQLITE_UTF16, &Like16 }, + { "like", 2, SQLITE_UTF16BE, &Like16 }, + { "like", 2, SQLITE_UTF16LE, &Like16 }, + { "like", 3, SQLITE_UTF8, &Like8 }, + { "like", 3, SQLITE_UTF16, &Like16 }, + { "like", 3, SQLITE_UTF16BE, &Like16 }, + { "like", 3, SQLITE_UTF16LE, &Like16 }, + }; + + rc = sqlite3_collation_needed(db_, self, &CollateNeeded); + if (rc != SQLITE_OK) + return rc; // COV_NF_LINE because input to + // sqlite3_collation_needed is static + + // Start LIKE as case-insensitive and non-literal + // (sqlite defaults LIKE to case-insensitive) + likeOptions_ = kCFCompareCaseInsensitive | kCFCompareNonliteral; + for (size_t i = 0; i < (sizeof(customLike) / sizeof(customLike[0])); i++) { + // Each implementation gets its own user args + NSMutableData *argsData + = [NSMutableData dataWithLength:sizeof(LikeGlobUserArgs)]; + if (!argsData) return SQLITE_INTERNAL; + [userArgDataPool_ addObject:argsData]; + LikeGlobUserArgs *args = (LikeGlobUserArgs *)[argsData bytes]; + args->compareOptionPtr = &likeOptions_; + args->textRep = customLike[i].textRep; + rc = sqlite3_create_function(db_, + customLike[i].sqlName, + customLike[i].numArgs, + customLike[i].textRep, + args, + customLike[i].function, + NULL, + NULL); + if (rc != SQLITE_OK) + return rc; // COV_NF_LINE because input to + // sqlite3_create_function is static + } + + // Start GLOB just non-literal but case-sensitive (same as SQLite defaults) + const struct { + const char *sqlName; + int textRep; + void *function; + } customGlob[] = { + { "glob", SQLITE_UTF8, &Glob8 }, + { "glob", SQLITE_UTF16, &Glob16 }, + { "glob", SQLITE_UTF16BE, &Glob16 }, + { "glob", SQLITE_UTF16LE, &Glob16 }, + }; + + globOptions_ = kCFCompareNonliteral; + for (size_t i = 0; i < (sizeof(customGlob) / sizeof(customGlob[0])); i++) { + // Each implementation gets its own user args + NSMutableData *argsData + = [NSMutableData dataWithLength:sizeof(LikeGlobUserArgs)]; + if (!argsData) return SQLITE_INTERNAL; + [userArgDataPool_ addObject:argsData]; + LikeGlobUserArgs *args = (LikeGlobUserArgs *)[argsData bytes]; + args->compareOptionPtr = &globOptions_; + args->textRep = customGlob[i].textRep; + rc = sqlite3_create_function(db_, + customGlob[i].sqlName, + 2, + customGlob[i].textRep, + args, + customGlob[i].function, + NULL, + NULL); + if (rc != SQLITE_OK) + return rc; // COV_NF_LINE because input to + // sqlite3_create_function is static + } + + hasCFAdditions_ = YES; + return SQLITE_OK; +} + +// Private method used by collation creation callback +- (void)collationArgumentRetain:(NSData *)collationArgs { + [userArgDataPool_ addObject:collationArgs]; +} + +- (sqlite3 *)sqlite3DB { + return db_; +} + +- (void)synchronousMode:(BOOL)enable { + if (enable) { + [self executeSQL:@"PRAGMA synchronous = NORMAL;"]; + [self executeSQL:@"PRAGMA fullfsync = 1;"]; + } else { + [self executeSQL:@"PRAGMA fullfsync = 0;"]; + [self executeSQL:@"PRAGMA synchronous = OFF;"]; + } +} + +- (BOOL)hasCFAdditions { + return hasCFAdditions_; +} + +- (void)setLikeComparisonOptions:(CFOptionFlags)options { + if (hasCFAdditions_) + likeOptions_ = FilteredStringCompareFlags(options); +} + +- (CFOptionFlags)likeComparisonOptions { + CFOptionFlags flags = 0; + if (hasCFAdditions_) + flags = likeOptions_; + return flags; +} + +- (void)setGlobComparisonOptions:(CFOptionFlags)options { + if (hasCFAdditions_) + globOptions_ = FilteredStringCompareFlags(options); +} + +- (CFOptionFlags)globComparisonOptions { + CFOptionFlags globOptions = 0; + if (hasCFAdditions_) + globOptions = globOptions_; + return globOptions; +} + +- (int)lastErrorCode { + return sqlite3_errcode(db_); +} + +- (NSString *)lastErrorString { + const char *errMsg = sqlite3_errmsg(db_); + if (!errMsg) return nil; + return [NSString stringWithCString:errMsg encoding:NSUTF8StringEncoding]; +} + +- (int)lastChangeCount { + return sqlite3_changes(db_); +} + +- (int)totalChangeCount { + return sqlite3_total_changes(db_); +} + +- (unsigned long long)lastInsertRowID { + return sqlite3_last_insert_rowid(db_); +} + +- (void)interrupt { + sqlite3_interrupt(db_); +} + +- (int)setBusyTimeoutMS:(int)timeoutMS { + int rc = sqlite3_busy_timeout(db_, timeoutMS); + if (rc == SQLITE_OK) { + timeoutMS_ = timeoutMS; + } + return rc; +} + +- (int)busyTimeoutMS { + return timeoutMS_; +} + +- (int)executeSQL:(NSString *)sql { + int rc; + // Sanity + if (!sql) { + rc = SQLITE_MISUSE; // Reasonable return for this case + } else { + if (hasCFAdditions_) { + rc = sqlite3_exec(db_, + [[sql precomposedStringWithCanonicalMapping] + UTF8String], + NULL, NULL, NULL); + } else { + rc = sqlite3_exec(db_, [sql UTF8String], NULL, NULL, NULL); + } + } + return rc; +} + +- (BOOL)beginDeferredTransaction { + int err; + err = [self executeSQL:@"BEGIN DEFERRED TRANSACTION;"]; + return (err == SQLITE_OK) ? YES : NO; +} + +- (BOOL)rollback { + int err = [self executeSQL:@"ROLLBACK TRANSACTION;"]; + return (err == SQLITE_OK) ? YES : NO; +} + +- (BOOL)commit { + int err = [self executeSQL:@"COMMIT TRANSACTION;"]; + return (err == SQLITE_OK) ? YES : NO; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p - %@>", + [self class], self, path_]; +} +@end + + +#pragma mark Upper/Lower + +// Private helper to handle upper/lower conversions for UTF8 +static void UpperLower8(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Args + if ((argc < 1) || (sqlite3_value_type(argv[0]) == SQLITE_NULL)) { + // COV_NF_START + sqlite3_result_error(context, "LOWER/UPPER CF implementation got bad args", + -1); + return; + // COV_NF_END + } + const char *sqlText8 = (void *)sqlite3_value_text(argv[0]); + if (!sqlText8) { + // COV_NF_START + sqlite3_result_error(context, "LOWER/UPPER CF implementation no input UTF8", + -1); + return; + // COV_NF_END + } + + // Get user data + UpperLowerUserArgs *userArgs = sqlite3_user_data(context); + if (!userArgs) { + // COV_NF_START + sqlite3_result_error(context, "LOWER/UPPER CF implementation no user args", + -1); + return; + // COV_NF_END + } + + _GTMDevAssert(userArgs->textRep == SQLITE_UTF8, + @"Received non UTF8 encoding in UpperLower8"); + + // Worker string, must be mutable for case conversion so order our calls + // to only copy once + CFMutableStringRef workerString = + CFStringCreateMutable(kCFAllocatorDefault, 0); + GTMCFAutorelease(workerString); + if (!workerString) { + // COV_NF_START + sqlite3_result_error(context, + "LOWER/UPPER CF implementation failed " \ + "to allocate CFMutableStringRef", -1); + return; + // COV_NF_END + } + CFStringAppendCString(workerString, sqlText8, kCFStringEncodingUTF8); + + // Perform the upper/lower + if (userArgs->upperCase) { + CFStringUppercase(workerString, gCurrentLocale); + } else { + CFStringLowercase(workerString, gCurrentLocale); + } + + // Convert to our canonical composition + CFStringNormalize(workerString, kCFStringNormalizationFormC); + + // Get the bytes we will return, using the more efficient accessor if we can + const char *returnString = CFStringGetCStringPtr(workerString, + kCFStringEncodingUTF8); + if (returnString) { + // COV_NF_START + // Direct buffer, but have SQLite copy it + sqlite3_result_text(context, returnString, -1, SQLITE_TRANSIENT); + // COV_NF_END + } else { + // Need to get a copy + CFIndex workerLength = CFStringGetLength(workerString); + CFIndex bufferSize = + CFStringGetMaximumSizeForEncoding(workerLength, + kCFStringEncodingUTF8); + void *returnBuffer = malloc(bufferSize); + if (!returnBuffer) { + // COV_NF_START + sqlite3_result_error(context, + "LOWER/UPPER failed to allocate return buffer", -1); + return; + // COV_NF_END + } + CFIndex convertedBytes = 0; + CFIndex convertedChars = CFStringGetBytes(workerString, + CFRangeMake(0, workerLength), + kCFStringEncodingUTF8, + 0, + false, + returnBuffer, + bufferSize, + &convertedBytes); + if (convertedChars != workerLength) { + // COV_NF_START + free(returnBuffer); + sqlite3_result_error(context, + "CFStringGetBytes() failed to " \ + "convert all characters", -1); + // COV_NF_END + } else { + // Set the result, letting SQLite take ownership and using free() as + // the destructor + // We cast the 3rd parameter to an int because sqlite3 doesn't appear + // to support 64-bit mode. + sqlite3_result_text(context, returnBuffer, (int)convertedBytes, &free); + } + } +} + +// Private helper to handle upper/lower conversions for UTF16 variants +static void UpperLower16(sqlite3_context *context, + int argc, sqlite3_value **argv) { + // Args + if ((argc < 1) || (sqlite3_value_type(argv[0]) == SQLITE_NULL)) { + // COV_NF_START + sqlite3_result_error(context, "LOWER/UPPER CF implementation got bad args", -1); + return; + // COV_NF_END + } + + // For UTF16 variants we want our working string to be in native-endian + // UTF16. This gives us the fewest number of copies (since SQLite converts + // in-place). There is no advantage to breaking out the string construction + // to use UTF16BE or UTF16LE because all that does is move the conversion + // work into the CFString constructor, so just use simple code. + int sqlText16ByteCount = sqlite3_value_bytes16(argv[0]); + const UniChar *sqlText16 = (void *)sqlite3_value_text16(argv[0]); + if (!sqlText16ByteCount || !sqlText16) { + // COV_NF_START + sqlite3_result_error(context, + "LOWER/UPPER CF implementation no input UTF16", -1); + return; + // COV_NF_END + } + + // Get user data + UpperLowerUserArgs *userArgs = sqlite3_user_data(context); + if (!userArgs) { + // COV_NF_START + sqlite3_result_error(context, "LOWER/UPPER CF implementation no user args", -1); + return; + // COV_NF_END + } + CFStringEncoding encoding = SqliteTextEncodingToCFStringEncoding(userArgs->textRep); + + // Mutable worker for upper/lower + CFMutableStringRef workerString = CFStringCreateMutable(kCFAllocatorDefault, 0); + GTMCFAutorelease(workerString); + if (!workerString) { + // COV_NF_START + sqlite3_result_error(context, + "LOWER/UPPER CF implementation failed " \ + "to allocate CFMutableStringRef", -1); + return; + // COV_NF_END + } + CFStringAppendCharacters(workerString, sqlText16, + sqlText16ByteCount / sizeof(UniChar)); + // Perform the upper/lower + if (userArgs->upperCase) { + CFStringUppercase(workerString, gCurrentLocale); + } else { + CFStringLowercase(workerString, gCurrentLocale); + } + // Convert to our canonical composition + CFStringNormalize(workerString, kCFStringNormalizationFormC); + + // Length after normalization matters + CFIndex workerLength = CFStringGetLength(workerString); + + // If we can give direct byte access use it + const UniChar *returnString = CFStringGetCharactersPtr(workerString); + if (returnString) { + // COV_NF_START details of whether cfstringgetcharactersptr returns + // a buffer or NULL are internal; not something we can depend on. + // When building for Leopard+, CFIndex is a 64-bit type, which is + // why we cast it to an int when we call the sqlite api. + _GTMDevAssert((workerLength * sizeof(UniChar) <= INT_MAX), + @"sqlite methods do not support buffers greater " + @"than 32 bit sizes"); + // Direct access to the internal buffer, hand it to sqlite for copy and + // conversion + sqlite3_result_text16(context, returnString, + (int)(workerLength * sizeof(UniChar)), + SQLITE_TRANSIENT); + // COV_NF_END + } else { + // Need to get a copy since we can't get direct access + CFIndex bufferSize = CFStringGetMaximumSizeForEncoding(workerLength, + encoding); + void *returnBuffer = malloc(bufferSize); + if (!returnBuffer) { + // COV_NF_START + sqlite3_result_error(context, + "LOWER/UPPER CF implementation failed " \ + "to allocate return buffer", -1); + return; + // COV_NF_END + } + CFIndex convertedBytes = 0; + CFIndex convertedChars = CFStringGetBytes(workerString, + CFRangeMake(0, workerLength), + encoding, + 0, + false, + returnBuffer, + bufferSize, + &convertedBytes); + if (convertedChars != workerLength) { + // COV_NF_START + free(returnBuffer); + sqlite3_result_error(context, + "LOWER/UPPER CF implementation CFStringGetBytes() " \ + "failed to convert all characters", -1); + // COV_NF_END + } else { + // When building for Leopard+, CFIndex is a 64-bit type, but + // sqlite3's functions all take ints. Assert the error for dev + // builds and cast down. + _GTMDevAssert((convertedBytes <= INT_MAX), + @"sqlite methods do not support buffers greater " + @"than 32-bit sizes"); + int convertedBytesForSQLite = (int)convertedBytes; + // Set the result, letting SQLite take ownership and using free() as + // the destructor. For output since we're copying out the bytes anyway + // we might as well use the preferred encoding of the original call. + _GTMDevAssert(userArgs->textRep == SQLITE_UTF16BE || + userArgs->textRep == SQLITE_UTF16LE, + @"Received non UTF8 encoding in UpperLower8"); + switch (userArgs->textRep) { + case SQLITE_UTF16BE: + sqlite3_result_text16be(context, returnBuffer, + convertedBytesForSQLite, &free); + break; + case SQLITE_UTF16LE: + sqlite3_result_text16le(context, returnBuffer, + convertedBytesForSQLite, &free); + break; + default: + // COV_NF_START no way to tell sqlite to not use utf8 or utf16? + sqlite3_result_error(context, + "LOWER/UPPER CF implementation " \ + "had unhandled encoding", -1); + // COV_NF_END + } + } + } +} + + +#pragma mark Collations + +static void CollateNeeded(void *userContext, sqlite3 *db, int textRep, + const char *name) { + // Cast + GTMSQLiteDatabase *gtmdb = (GTMSQLiteDatabase *)userContext; + _GTMDevAssert(gtmdb, @"Invalid database parameter from sqlite"); + + // Create space for the collation args + NSMutableData *collationArgsData = + [NSMutableData dataWithLength:sizeof(CollateUserArgs)]; + CollateUserArgs *userArgs = (CollateUserArgs *)[collationArgsData bytes]; + bzero(userArgs, sizeof(CollateUserArgs)); + userArgs->textRep = textRep; + + // Parse the name into the flags we need + NSString *collationName = + [[NSString stringWithUTF8String:name] lowercaseString]; + NSArray *collationComponents = + [collationName componentsSeparatedByString:@"_"]; + NSString *collationFlag = nil; + BOOL atLeastOneValidFlag = NO; + GTM_FOREACH_OBJECT(collationFlag, collationComponents) { + if ([collationFlag isEqualToString:@"reverse"]) { + userArgs->reverse = YES; + atLeastOneValidFlag = YES; + } else if ([collationFlag isEqualToString:@"nocase"]) { + userArgs->compareOptions |= kCFCompareCaseInsensitive; + atLeastOneValidFlag = YES; + } else if ([collationFlag isEqualToString:@"nonliteral"]) { + userArgs->compareOptions |= kCFCompareNonliteral; + atLeastOneValidFlag = YES; + } else if ([collationFlag isEqualToString:@"localized"]) { + userArgs->compareOptions |= kCFCompareLocalized; + atLeastOneValidFlag = YES; + } else if ([collationFlag isEqualToString:@"numeric"]) { + userArgs->compareOptions |= kCFCompareNumerically; + atLeastOneValidFlag = YES; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + } else if ([collationFlag isEqualToString:@"nodiacritic"]) { + userArgs->compareOptions |= kCFCompareDiacriticInsensitive; + atLeastOneValidFlag = YES; + } else if ([collationFlag isEqualToString:@"widthinsensitive"]) { + userArgs->compareOptions |= kCFCompareWidthInsensitive; + atLeastOneValidFlag = YES; +#else + } else if (([collationFlag isEqualToString:@"nodiacritic"]) || + ([collationFlag isEqualToString:@"widthinsensitive"])) { + _GTMDevLog(@"GTMSQLiteDatabase 10.5 collating not " + @"available on 10.4 or earlier"); +#endif + } + } + + // No valid tokens means nothing to do + if (!atLeastOneValidFlag) return; + + int err; + // Add the collation + switch (textRep) { + case SQLITE_UTF8: + err = sqlite3_create_collation([gtmdb sqlite3DB], name, + textRep, userArgs, &Collate8); + if (err != SQLITE_OK) return; + break; + case SQLITE_UTF16: + case SQLITE_UTF16BE: + case SQLITE_UTF16LE: + err = sqlite3_create_collation([gtmdb sqlite3DB], name, + textRep, userArgs, &Collate16); + if (err != SQLITE_OK) return; + break; + default: + return; + } + + // Have the db retain our collate function args + [gtmdb collationArgumentRetain:collationArgsData]; +} + +static int Collate8(void *userContext, int length1, const void *str1, + int length2, const void *str2) { + // User args + CollateUserArgs *userArgs = (CollateUserArgs *)userContext; + _GTMDevAssert(userArgs, @"Invalid user arguments from sqlite"); + + // Sanity and zero-lengths + if (!(str1 && str2) || (!length1 && !length2)) { + return kCFCompareEqualTo; // Best we can do and stable sort + } + if (!length1 && length2) { + if (userArgs->reverse) { + return kCFCompareGreaterThan; + } else { + return kCFCompareLessThan; + } + } else if (length1 && !length2) { + if (userArgs->reverse) { + return kCFCompareLessThan; + } else { + return kCFCompareGreaterThan; + } + } + + // We have UTF8 strings with no terminating null, we want to compare + // with as few copies as possible. Leopard introduced a no-copy string + // creation function, we'll use it when we can but we want to stay compatible + // with Tiger. + CFStringRef string1 = NULL, string2 = NULL; +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + if (gCFStringCreateWithBytesNoCopySymbol) { + string1 = gCFStringCreateWithBytesNoCopySymbol(kCFAllocatorDefault, + str1, + length1, + kCFStringEncodingUTF8, + false, + kCFAllocatorNull); + string2 = gCFStringCreateWithBytesNoCopySymbol(kCFAllocatorDefault, + str2, + length2, + kCFStringEncodingUTF8, + false, + kCFAllocatorNull); + } else { + // Have to use the copy-based variants + string1 = CFStringCreateWithBytes(kCFAllocatorDefault, + str1, + length1, + kCFStringEncodingUTF8, + false); + string2 = CFStringCreateWithBytes(kCFAllocatorDefault, + str2, + length2, + kCFStringEncodingUTF8, + false); + } +#else // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + string1 = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, + str1, + length1, + kCFStringEncodingUTF8, + false, + kCFAllocatorNull); + string2 = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, + str2, + length2, + kCFStringEncodingUTF8, + false, + kCFAllocatorNull); +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + GTMCFAutorelease(string1); + GTMCFAutorelease(string2); + // Allocation failures can't really be sanely handled from a collator + int sqliteResult; + if (!(string1 && string2)) { + // COV_NF_START + sqliteResult = (int)kCFCompareEqualTo; + // COV_NF_END + } else { + // Compare + // We have to cast to int because SQLite takes functions that + // return an int, but when compiling for Leopard+, + // CFComparisonResult is a signed long, but on Tiger it's an int + CFComparisonResult result; + result = CFStringCompare(string1, + string2, + userArgs->compareOptions); + sqliteResult = (int)result; + // Reverse + if (userArgs->reverse && sqliteResult) { + sqliteResult = -sqliteResult; + } + + } + return sqliteResult; +} + +static int Collate16(void *userContext, int length1, const void *str1, + int length2, const void *str2) { + // User args + CollateUserArgs *userArgs = (CollateUserArgs *)userContext; + _GTMDevAssert(userArgs, @"Invalid user arguments from sqlite"); + + // Sanity and zero-lengths + if (!(str1 && str2) || (!length1 && !length2)) { + return kCFCompareEqualTo; // Best we can do and stable sort + } + if (!length1 && length2) { + if (userArgs->reverse) { + return kCFCompareGreaterThan; + } else { + return kCFCompareLessThan; + } + } else if (length1 && !length2) { + if (userArgs->reverse) { + return kCFCompareLessThan; + } else { + return kCFCompareGreaterThan; + } + } + + // Target encoding + CFStringEncoding encoding = + SqliteTextEncodingToCFStringEncoding(userArgs->textRep); + + // We have UTF16 strings, we want to compare with as few copies as + // possible. Since endianness matters we want to use no-copy + // variants where possible and copy (and endian convert) only when + // we must. + CFStringRef string1 = NULL, string2 = NULL; + if ((userArgs->textRep == SQLITE_UTF16) || +#if TARGET_RT_BIG_ENDIAN + (userArgs->textRep == SQLITE_UTF16BE) +#else + (userArgs->textRep == SQLITE_UTF16LE) +#endif + ) { + string1 = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + str1, + length1 / sizeof(UniChar), + kCFAllocatorNull); + string2 = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + str2, + length2 / sizeof(UniChar), + kCFAllocatorNull); + } else { + // No point in using the "no copy" version of the call here. If the + // bytes were in the native order we'd be in the other part of this + // conditional, so we know we have to copy the string to endian convert + // it. + string1 = CFStringCreateWithBytes(kCFAllocatorDefault, + str1, + length1, + encoding, + false); + string2 = CFStringCreateWithBytes(kCFAllocatorDefault, + str2, + length2, + encoding, + false); + } + + GTMCFAutorelease(string1); + GTMCFAutorelease(string2); + int sqliteResult; + // Allocation failures can't really be sanely handled from a collator + if (!(string1 && string2)) { + // COV_NF_START + sqliteResult = (int)kCFCompareEqualTo; + // COV_NF_END + } else { + // Compare + // We cast the return value to an int because CFComparisonResult + // is a long in Leopard+ builds. I have no idea why we need + // 64-bits for a 3-value enum, but that's how it is... + CFComparisonResult result; + result = CFStringCompare(string1, + string2, + userArgs->compareOptions); + + sqliteResult = (int)result; + //Reverse + if (userArgs->reverse && sqliteResult) { + sqliteResult = -sqliteResult; + } + } + + return sqliteResult; +} + + +#pragma mark Like/Glob + +// Private helper to handle LIKE and GLOB with different encodings. This +// is essentially a reimplementation of patternCompare() in func.c of the +// SQLite sources. +static void LikeGlobCompare(sqlite3_context *context, + CFStringRef pattern, + CFStringRef targetString, + UniChar matchAll, + UniChar matchOne, + UniChar escape, + BOOL setSupport, + CFOptionFlags compareOptions) { + // Setup for pattern walk + CFIndex patternLength = CFStringGetLength(pattern); + CFStringInlineBuffer patternBuffer; + CFStringInitInlineBuffer(pattern, + &patternBuffer, + CFRangeMake(0, patternLength)); + UniChar patternChar; + CFIndex patternIndex = 0; + CFIndex targetStringLength = CFStringGetLength(targetString); + CFIndex targetStringIndex = 0; + BOOL isAnchored = YES; + + size_t dataSize = patternLength * sizeof(UniChar); + NSMutableData *tempData = [NSMutableData dataWithLength:dataSize]; + // Temp string buffer can be no larger than the whole pattern + UniChar *findBuffer = [tempData mutableBytes]; + if (!findBuffer) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE or GLOB CF implementation failed to " \ + "allocate temporary buffer", -1); + return; + // COV_NF_END + } + + // We'll use a mutable string we can just reset as we wish + CFMutableStringRef findString = + CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault, + NULL, + 0, + 0, + kCFAllocatorNull); + GTMCFAutorelease(findString); + if (!findString) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE or GLOB CF implementation failed to " \ + "allocate temporary CFString", -1); + return; + // COV_NF_END + } + // Walk the pattern + while (patternIndex < patternLength) { + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + // Match all character has no effect other than to unanchor the search + if (patternChar == matchAll) { + isAnchored = NO; + patternIndex++; + continue; + } + // Match one character pushes the string index forward by one composed + // character + if (patternChar == matchOne) { + // If this single char match would walk us off the end of the string + // we're already done, no match + if (targetStringIndex >= targetStringLength) { + sqlite3_result_int(context, 0); + return; + } + // There's still room in the string, so move the string index forward one + // composed character and go back around. + CFRange nextCharRange = + CFStringGetRangeOfComposedCharactersAtIndex(targetString, + targetStringIndex); + targetStringIndex = nextCharRange.location + nextCharRange.length; + patternIndex++; + continue; + } + // Character set matches require the parsing of the character set + if (setSupport && (patternChar == 0x5B)) { // "[" + // A character set must match one character, if there's not at least one + // character left in the string, don't bother + if (targetStringIndex >= targetStringLength) { + sqlite3_result_int(context, 0); + return; + } + // There's at least one character, try to match the remainder of the + // string using a CFCharacterSet + CFMutableCharacterSetRef charSet + = CFCharacterSetCreateMutable(kCFAllocatorDefault); + GTMCFAutorelease(charSet); + if (!charSet) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE or GLOB CF implementation failed to " \ + "allocate temporary CFMutableCharacterSet", -1); + return; + // COV_NF_END + } + + BOOL invert = NO; + // Walk one character forward + patternIndex++; + if (patternIndex >= patternLength) { + // Oops, out of room + sqlite3_result_error(context, + "LIKE or GLOB CF implementation found " \ + "unclosed character set", -1); + return; + } + // First character after pattern open is special-case + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + if (patternChar == 0x5E) { // "^" + invert = YES; + // Bump forward one character, can still be an unescaped "]" after + // negation + patternIndex++; + if (patternIndex >= patternLength) { + // Oops, out of room + sqlite3_result_error(context, + "LIKE or GLOB CF implementation found " \ + "unclosed character set after negation", -1); + return; + } + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + } + // First char in set or first char in negation can be a literal "]" not + // considered a close + if (patternChar == 0x5D) { // "]" + CFCharacterSetAddCharactersInRange(charSet, + CFRangeMake(patternChar, 1)); + patternIndex++; + if (patternIndex >= patternLength) { + // Oops, out of room + sqlite3_result_error(context, + "LIKE or GLOB CF implementation found " \ + "unclosed character set after escaped ]", -1); + return; + } + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + } + while ((patternIndex < patternLength) && + patternChar && + (patternChar != 0x5D)) { // "]" + // Check for possible character range, for this to be true we + // must have a hyphen at the next position and at least 3 + // characters of room (for hyphen, range end, and set + // close). Hyphens at the end without a trailing range are + // treated as literals + if (((patternLength - patternIndex) >= 3) && + // Second char must be "-" + (CFStringGetCharacterFromInlineBuffer(&patternBuffer, + // 0x2D is "-" + patternIndex + 1) == 0x2D) && + // And third char must be anything other than set close in + // case the hyphen is at the end of the set and needs to + // be treated as a literal + (CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex + 2) + != 0x5D)) { // "]" + // Get the range close + UniChar rangeClose = + CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex + 2); + // Add the whole range + int rangeLen = rangeClose - patternChar + 1; + CFCharacterSetAddCharactersInRange(charSet, + CFRangeMake(patternChar, + rangeLen)); + // Move past the end of the range + patternIndex += 3; + } else { + // Single Raw character + CFCharacterSetAddCharactersInRange(charSet, + CFRangeMake(patternChar, 1)); + patternIndex++; + } + // Load next char for loop + if (patternIndex < patternLength) { + patternChar = + CFStringGetCharacterFromInlineBuffer(&patternBuffer, patternIndex); + } else { + patternChar = 0; + } + } + // Check for closure + if (patternChar != 0x5D) { // "]" + sqlite3_result_error(context, + "LIKE or GLOB CF implementation found " \ + "unclosed character set", -1); + return; + } else { + // Increment past the end of the set + patternIndex++; + } + // Invert the set if needed + if (invert) CFCharacterSetInvert(charSet); + // Do the search + CFOptionFlags findOptions = 0; + if (isAnchored) findOptions |= kCFCompareAnchored; + CFRange foundRange; + unsigned long rangeLen = targetStringLength - targetStringIndex; + BOOL found = CFStringFindCharacterFromSet(targetString, + charSet, + CFRangeMake(targetStringIndex, + rangeLen), + findOptions, + &foundRange); + // If no match then the whole pattern fails + if (!found) { + sqlite3_result_int(context, 0); + return; + } + // If we did match then we need to push the string index to the + // character past the end of the match and then go back around + // the loop. + targetStringIndex = foundRange.location + foundRange.length; + // At this point patternIndex is either at the end of the + // string, or at the next special character which will be picked + // up and handled at the top of the loop. We do, however, need + // to reset the anchor status + isAnchored = YES; + // End of character sets, back around + continue; + } + // Otherwise the pattern character is a normal or escaped + // character we should consume and match with normal string + // matching + CFIndex findBufferIndex = 0; + while ((patternIndex < patternLength) && patternChar && + !((patternChar == matchAll) || (patternChar == matchOne) || + (setSupport && (patternChar == 0x5B)))) { // "[" + if (patternChar == escape) { + // No matter what the character follows the escape copy it to the + // buffer + patternIndex++; + if (patternIndex >= patternLength) { + // COV_NF_START + // Oops, escape came at end of pattern, that's an error + sqlite3_result_error(context, + "LIKE or GLOB CF implementation found " \ + "escape character at end of pattern", -1); + return; + // COV_NF_END + } + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + } + // At this point the patternChar is either the escaped character or the + // original normal character + findBuffer[findBufferIndex++] = patternChar; + // Set up for next loop + patternIndex++; + if (patternIndex < patternLength) { + patternChar = CFStringGetCharacterFromInlineBuffer(&patternBuffer, + patternIndex); + } else { + patternChar = 0; + } + } + // On loop exit we have a string ready for comparision, if that + // string is too long then it can't be a match. + if (findBufferIndex > (targetStringLength - targetStringIndex)) { + sqlite3_result_int(context, 0); + return; + } + + // We actually need to do a comparison + CFOptionFlags findOptions = compareOptions; + if (isAnchored) findOptions |= kCFCompareAnchored; + CFStringSetExternalCharactersNoCopy(findString, + findBuffer, + findBufferIndex, + findBufferIndex); + CFRange foundRange; + unsigned long rangeLen = targetStringLength - targetStringIndex; + BOOL found = CFStringFindWithOptions(targetString, + findString, + CFRangeMake(targetStringIndex, + rangeLen), + findOptions, + &foundRange); + // If no match then the whole pattern fails + if (!found) { + sqlite3_result_int(context, 0); + return; + } + // If we did match then we need to push the string index to the + // character past the end of the match and then go back around the + // loop. + targetStringIndex = foundRange.location + foundRange.length; + // At this point patternIndex is either at the end of the string, + // or at the next special character which will be picked up and + // handled at the top of the loop. We do, however, need to reset + // the anchor status + isAnchored = YES; + } + // On loop exit all pattern characters have been considered. If we're still + // alive it means that we've matched the entire pattern, except for trailing + // wildcards, we need to handle that case. + if (isAnchored) { + // If we're still anchored there was no trailing matchAll, in which case + // we have to have run to exactly the end of the string + if (targetStringIndex == targetStringLength) { + sqlite3_result_int(context, 1); + } else { + sqlite3_result_int(context, 0); + } + } else { + // If we're not anchored any remaining characters are OK + sqlite3_result_int(context, 1); + } +} + +static void Like8(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Get our LIKE options + LikeGlobUserArgs *likeArgs = sqlite3_user_data(context); + if (!likeArgs) { + // COV_NF_START + sqlite3_result_error(context, "LIKE CF implementation no user args", -1); + return; + // COV_NF_END + } + + // Read the strings + const char *pattern = (const char *)sqlite3_value_text(argv[0]); + const char *target = (const char *)sqlite3_value_text(argv[1]); + if (!pattern || !target) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation missing pattern or value", -1); + return; + // COV_NF_END + } + CFStringRef patternString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + pattern, + kCFStringEncodingUTF8, + kCFAllocatorNull); + CFStringRef targetString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + target, + kCFStringEncodingUTF8, + kCFAllocatorNull); + GTMCFAutorelease(patternString); + GTMCFAutorelease(targetString); + if (!(patternString && targetString)) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation failed " \ + "to allocate CFStrings", -1); + return; + // COV_NF_END + } + + UniChar escapeChar = 0; + // If there is a third argument it is the escape character + if (argc == 3) { + const char *escape = (const char *)sqlite3_value_text(argv[2]); + if (!escape) { + sqlite3_result_error(context, + "LIKE CF implementation missing " \ + "escape character", -1); + return; + } + CFStringRef escapeString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + escape, + kCFStringEncodingUTF8, + kCFAllocatorNull); + GTMCFAutorelease(escapeString); + if (!escapeString) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation failed to " \ + "allocate CFString for ESCAPE", -1); + return; + // COV_NF_END + } + if (CFStringGetLength(escapeString) != 1) { + sqlite3_result_error(context, + "CF implementation ESCAPE expression " \ + "must be single character", -1); + return; + } + escapeChar = CFStringGetCharacterAtIndex(escapeString, 0); + } + + // Do the compare + LikeGlobCompare(context, + patternString, + targetString, + 0x25, // % + 0x5F, // _ + escapeChar, + NO, // LIKE does not support character sets + *(likeArgs->compareOptionPtr)); +} + +static void Like16(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Get our LIKE options + LikeGlobUserArgs *likeArgs = sqlite3_user_data(context); + if (!likeArgs) { + // COV_NF_START - sql parser chokes if we feed any input + // that could trigger this + sqlite3_result_error(context, "LIKE CF implementation no user args", -1); + return; + // COV_NF_END + } + + // For UTF16 variants we want our working string to be in native-endian + // UTF16. This gives us the fewest number of copies (since SQLite converts + // in-place). There is no advantage to breaking out the string construction + // to use UTF16BE or UTF16LE because all that does is move the conversion + // work into the CFString constructor, so just use simple code. + int patternByteCount = sqlite3_value_bytes16(argv[0]); + const UniChar *patternText = (void *)sqlite3_value_text16(argv[0]); + int targetByteCount = sqlite3_value_bytes16(argv[1]); + const UniChar *targetText = (void *)sqlite3_value_text16(argv[1]); + if (!patternByteCount || !patternText || !targetByteCount || !targetText) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation missing pattern or value", -1); + return; + // COV_NF_END + } + CFStringRef patternString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + patternText, + patternByteCount / sizeof(UniChar), + kCFAllocatorNull); + CFStringRef targetString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + targetText, + targetByteCount / sizeof(UniChar), + kCFAllocatorNull); + GTMCFAutorelease(patternString); + GTMCFAutorelease(targetString); + if (!(patternString && targetString)) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation failed " \ + "to allocate CFStrings", -1); + return; + // COV_NF_END + } + + // If there is a third argument it is the escape character, force a + // UTF8 conversion for simplicity + UniChar escapeChar = 0; + if (argc == 3) { + const char *escape = (const char *)sqlite3_value_text(argv[2]); + if (!escape) { + sqlite3_result_error(context, + "LIKE CF implementation " \ + "missing escape character", -1); + return; + } + CFStringRef escapeString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + escape, + kCFStringEncodingUTF8, + kCFAllocatorNull); + GTMCFAutorelease(escapeString); + if (!escapeString) { + // COV_NF_START + sqlite3_result_error(context, + "LIKE CF implementation failed to " \ + "allocate CFString for ESCAPE", -1); + return; + // COV_NF_END + } + if (CFStringGetLength(escapeString) != 1) { + sqlite3_result_error(context, + "CF implementation ESCAPE expression " \ + "must be single character", -1); + return; + } + escapeChar = CFStringGetCharacterAtIndex(escapeString, 0); + } + + // Do the compare + LikeGlobCompare(context, + patternString, + targetString, + 0x25, // % + 0x5F, // _ + escapeChar, + NO, // LIKE does not support character sets + *(likeArgs->compareOptionPtr)); +} + +static void Glob8(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Get our GLOB options + LikeGlobUserArgs *globArgs = sqlite3_user_data(context); + if (!globArgs) { + // COV_NF_START + sqlite3_result_error(context, "GLOB CF implementation no user args", -1); + return; + // COV_NF_END + } + + // Read the strings + const char *pattern = (const char *)sqlite3_value_text(argv[0]); + const char *target = (const char *)sqlite3_value_text(argv[1]); + if (!pattern || !target) { + // COV_NF_START + sqlite3_result_error(context, + "GLOB CF implementation missing " \ + "pattern or value", -1); + return; + // COV_NF_END + } + CFStringRef patternString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + pattern, + kCFStringEncodingUTF8, + kCFAllocatorNull); + CFStringRef targetString = + CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + target, + kCFStringEncodingUTF8, + kCFAllocatorNull); + GTMCFAutorelease(patternString); + GTMCFAutorelease(targetString); + + if (!(patternString && targetString)) { + // COV_NF_START + sqlite3_result_error(context, + "GLOB CF implementation failed to " \ + "allocate CFStrings", -1); + // COV_NF_END + } else { + // Do the compare + LikeGlobCompare(context, + patternString, + targetString, + 0x2A, // * + 0x3F, // ? + 0, // GLOB does not support escape characters + YES, // GLOB supports character sets + *(globArgs->compareOptionPtr)); + } +} + +static void Glob16(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Get our GLOB options + LikeGlobUserArgs *globArgs = sqlite3_user_data(context); + if (!globArgs) { + // COV_NF_START + sqlite3_result_error(context, "GLOB CF implementation no user args", -1); + return; + // COV_NF_END + } + + // For UTF16 variants we want our working string to be in + // native-endian UTF16. This gives us the fewest number of copies + // (since SQLite converts in-place). There is no advantage to + // breaking out the string construction to use UTF16BE or UTF16LE + // because all that does is move the conversion work into the + // CFString constructor, so just use simple code. + int patternByteCount = sqlite3_value_bytes16(argv[0]); + const UniChar *patternText = (void *)sqlite3_value_text16(argv[0]); + int targetByteCount = sqlite3_value_bytes16(argv[1]); + const UniChar *targetText = (void *)sqlite3_value_text16(argv[1]); + if (!patternByteCount || !patternText || !targetByteCount || !targetText) { + // COV_NF_START + sqlite3_result_error(context, + "GLOB CF implementation missing pattern or value", -1); + return; + // COV_NF_END + } + CFStringRef patternString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + patternText, + patternByteCount / sizeof(UniChar), + kCFAllocatorNull); + CFStringRef targetString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + targetText, + targetByteCount / sizeof(UniChar), + kCFAllocatorNull); + GTMCFAutorelease(patternString); + GTMCFAutorelease(targetString); + if (!(patternString && targetString)) { + // COV_NF_START + sqlite3_result_error(context, + "GLOB CF implementation failed to "\ + "allocate CFStrings", -1); + // COV_NF_END + } else { + // Do the compare + LikeGlobCompare(context, + patternString, + targetString, + 0x2A, // * + 0x3F, // ? + 0, // GLOB does not support escape characters + YES, // GLOB supports character sets + *(globArgs->compareOptionPtr)); + } +} + +// ----------------------------------------------------------------------------- + +@implementation GTMSQLiteStatement + +#pragma mark Creation, Access and Finalization + ++ (id)statementWithSQL:(NSString *)sql + inDatabase:(GTMSQLiteDatabase *)gtmdb + errorCode:(int *)err { + return [[[GTMSQLiteStatement alloc] initWithSQL:sql + inDatabase:gtmdb + errorCode:err] + autorelease]; +} + +- (id)initWithSQL:(NSString *)sql + inDatabase:(GTMSQLiteDatabase *)gtmdb + errorCode:(int *)err { + int rc; + id obj; + if ((self = [super init])) { + // Sanity + obj = self; + if (sql && gtmdb) { + // Find out if the database is using our CF extensions + hasCFAdditions_ = [gtmdb hasCFAdditions]; + + // Prepare + if (hasCFAdditions_) { + sql = [sql precomposedStringWithCanonicalMapping]; + } + if (sql) { + rc = sqlite3_prepare([gtmdb sqlite3DB], + [sql UTF8String], + -1, + &statement_, + NULL); + if (rc != SQLITE_OK) { + [self release]; + obj = nil; + } + } else { + // COV_NF_START + rc = SQLITE_INTERNAL; + [self release]; + obj = nil; + // COV_NF_END + } + } else { + rc = SQLITE_MISUSE; + [self release]; + obj = nil; + } + } else { + // COV_NF_START + rc = SQLITE_INTERNAL; + obj = nil; + // COV_NF_END + } + if (err) *err = rc; + return obj; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + if (statement_) { + _GTMDevLog(@"-[GTMSQLiteStatement finalizeStatement] must be called when" + @" statement is no longer needed"); + } + [super finalize]; +} +#endif + +- (void)dealloc { + if (statement_) { + _GTMDevLog(@"-[GTMSQLiteStatement finalizeStatement] must be called when" + @" statement is no longer needed"); + } + [super dealloc]; +} + +- (sqlite3_stmt *)sqlite3Statement { + return statement_; +} + +- (int)finalizeStatement { + if (!statement_) return SQLITE_MISUSE; + int rc = sqlite3_finalize(statement_); + statement_ = NULL; + return rc; +} + +#pragma mark Parameters and Binding + +- (int)parameterCount { + if (!statement_) return -1; + return sqlite3_bind_parameter_count(statement_); +} + +- (int)positionOfParameterNamed:(NSString *)paramName { + if (!statement_) return -1; + if (hasCFAdditions_) { + NSString *cleanedString = + [paramName precomposedStringWithCanonicalMapping]; + if (!cleanedString) return -1; + return sqlite3_bind_parameter_index(statement_, [cleanedString UTF8String]); + } else { + return sqlite3_bind_parameter_index(statement_, [paramName UTF8String]); + } +} + +- (NSString *)nameOfParameterAtPosition:(int)position { + if ((position < 1) || !statement_) return nil; + const char *name = sqlite3_bind_parameter_name(statement_, position); + if (!name) return nil; + NSString *nameString = [NSString stringWithUTF8String:name]; + if (hasCFAdditions_) { + return [nameString precomposedStringWithCanonicalMapping]; + } else { + return nameString; + } +} + +- (int)bindSQLNullAtPosition:(int)position { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_bind_null(statement_, position); +} + +- (int)bindBlobAtPosition:(int)position bytes:(void *)bytes length:(int)length { + if (!statement_ || !bytes || !length) return SQLITE_MISUSE; + return sqlite3_bind_blob(statement_, + position, + bytes, + length, + SQLITE_TRANSIENT); +} + +- (int)bindBlobAtPosition:(int)position data:(NSData *)data { + if (!statement_ || !data || !position) return SQLITE_MISUSE; + int blobLength = (int)[data length]; + _GTMDevAssert((blobLength < INT_MAX), + @"sqlite methods do not support data lengths " + @"exceeding 32 bit sizes"); + return [self bindBlobAtPosition:position + bytes:(void *)[data bytes] + length:blobLength]; +} + +- (int)bindDoubleAtPosition:(int)position value:(double)value { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_bind_double(statement_, position, value); +} + +- (int)bindNumberAsDoubleAtPosition:(int)position number:(NSNumber *)number { + if (!number || !statement_) return SQLITE_MISUSE; + return sqlite3_bind_double(statement_, position, [number doubleValue]); +} + +- (int)bindInt32AtPosition:(int)position value:(int)value { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_bind_int(statement_, position, value); +} + +- (int)bindNumberAsInt32AtPosition:(int)position number:(NSNumber *)number { + if (!number || !statement_) return SQLITE_MISUSE; + return sqlite3_bind_int(statement_, position, [number intValue]); +} + +- (int)bindLongLongAtPosition:(int)position value:(long long)value { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_bind_int64(statement_, position, value); +} + +- (int)bindNumberAsLongLongAtPosition:(int)position number:(NSNumber *)number { + if (!number || !statement_) return SQLITE_MISUSE; + return sqlite3_bind_int64(statement_, position, [number longLongValue]); +} + +- (int)bindStringAtPosition:(int)position string:(NSString *)string { + if (!string || !statement_) return SQLITE_MISUSE; + if (hasCFAdditions_) { + string = [string precomposedStringWithCanonicalMapping]; + if (!string) return SQLITE_INTERNAL; + } + return sqlite3_bind_text(statement_, + position, + [string UTF8String], + -1, + SQLITE_TRANSIENT); +} + +#pragma mark Results + +- (int)resultColumnCount { + if (!statement_) return -1; + return sqlite3_column_count(statement_); +} + +- (NSString *)resultColumnNameAtPosition:(int)position { + if (!statement_) return nil; + const char *name = sqlite3_column_name(statement_, position); + if (!name) return nil; + NSString *nameString = [NSString stringWithUTF8String:name]; + if (hasCFAdditions_) { + return [nameString precomposedStringWithCanonicalMapping]; + } else { + return nameString; + } +} + +- (int)rowDataCount { + if (!statement_) return -1; + return sqlite3_data_count(statement_); +} + +- (int)resultColumnTypeAtPosition:(int)position { + if (!statement_) return -1; + return sqlite3_column_type(statement_, position); +} + +- (NSData *)resultBlobDataAtPosition:(int)position { + if (!statement_) return nil; + const void *bytes = sqlite3_column_blob(statement_, position); + int length = sqlite3_column_bytes(statement_, position); + if (!(bytes && length)) return nil; + return [NSData dataWithBytes:bytes length:length]; +} + +- (double)resultDoubleAtPosition:(int)position { + if (!statement_) return 0; + return sqlite3_column_double(statement_, position); +} + +- (int)resultInt32AtPosition:(int)position { + if (!statement_) return 0; + return sqlite3_column_int(statement_, position); +} + +- (long long)resultLongLongAtPosition:(int)position { + if (!statement_) return 0; + return sqlite3_column_int64(statement_, position); +} + +- (NSNumber *)resultNumberAtPosition:(int)position { + if (!statement_) return nil; + int type = [self resultColumnTypeAtPosition:position]; + if (type == SQLITE_FLOAT) { + // Special case for floats + return [NSNumber numberWithDouble:[self resultDoubleAtPosition:position]]; + } else { + // Everything else is cast to int + long long result = [self resultLongLongAtPosition:position]; + return [NSNumber numberWithLongLong:result]; + } +} + +- (NSString *)resultStringAtPosition:(int)position { + if (!statement_) return nil; + const char *text = (const char *)sqlite3_column_text(statement_, position); + if (!text) return nil; + NSString *result = [NSString stringWithUTF8String:text]; + if (hasCFAdditions_) { + return [result precomposedStringWithCanonicalMapping]; + } else { + return result; + } +} + +- (id)resultFoundationObjectAtPosition:(int)position { + if (!statement_) return nil; + int type = [self resultColumnTypeAtPosition:position]; + id result = nil; + switch (type) { + case SQLITE_INTEGER: + case SQLITE_FLOAT: + result = [self resultNumberAtPosition:position]; + break; + case SQLITE_TEXT: + result = [self resultStringAtPosition:position]; + break; + case SQLITE_BLOB: + result = [self resultBlobDataAtPosition:position]; + break; + case SQLITE_NULL: + result = [NSNull null]; + break; + } + return result; +} + +- (NSArray *)resultRowArray { + int count = [self rowDataCount]; + if (count < 1) return nil; + + NSMutableArray *finalArray = [NSMutableArray array]; + for (int i = 0; i < count; i++) { + id coldata = [self resultFoundationObjectAtPosition:i]; + if (!coldata) return nil; // Oops + [finalArray addObject:coldata]; + } + + if (![finalArray count]) return nil; + return finalArray; +} + +- (NSDictionary *)resultRowDictionary { + int count = [self rowDataCount]; + if (count < 1) return nil; + + NSMutableDictionary *finalDict = [NSMutableDictionary dictionary]; + for (int i = 0; i < count; i++) { + id coldata = [self resultFoundationObjectAtPosition:i]; + NSString *colname = [self resultColumnNameAtPosition:i]; + if (!(coldata && colname)) continue; + [finalDict setObject:coldata forKey:colname]; + } + if (![finalDict count]) return nil; + return finalDict; +} + +#pragma mark Rows + +- (int)stepRow { + int rc = SQLITE_BUSY; + while (rc == SQLITE_BUSY) { + rc = [self stepRowWithTimeout]; + } + return rc; +} + +- (int)stepRowWithTimeout { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_step(statement_); +} + +- (int)reset { + if (!statement_) return SQLITE_MISUSE; + return sqlite3_reset(statement_); +} + ++ (BOOL)isCompleteStatement:(NSString *)statement { + BOOL isComplete = NO; + if (statement) { + isComplete = (sqlite3_complete([statement UTF8String]) ? YES : NO); + } + return isComplete; +} + ++ (NSString*)quoteAndEscapeString:(NSString *)string { + char *quoted = sqlite3_mprintf("'%q'", [string UTF8String]); + if (!quoted) return nil; + NSString *quotedString = [NSString stringWithUTF8String:quoted]; + sqlite3_free(quoted); + return quotedString; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLiteTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLiteTest.m new file mode 100644 index 00000000..5d683c0f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSQLiteTest.m @@ -0,0 +1,1813 @@ +// +// GTMSQLiteTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#import "GTMSQLite.h" +#import "GTMSenTestCase.h" +#import "GTMUnitTestDevLog.h" +#import "GTMGarbageCollection.h" + +@interface GTMSQLiteTest : GTMTestCase +@end + +// This variable is used by a custom upper function that we set in a +// SQLite database to indicate that the custom function was +// successfully called. It has to be a global rather than instance +// variable because the custom upper function is not an instance function +static BOOL customUpperFunctionCalled = NO; + +@interface GTMSQLiteStatementTest : GTMTestCase +@end + +// Prototype for LIKE/GLOB test helper +static NSArray* LikeGlobTestHelper(GTMSQLiteDatabase *db, NSString *sql); + +@implementation GTMSQLiteTest + +// Test cases for change counting +- (void)testTransactionAPI { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + err = [db executeSQL:@"CREATE TABLE foo (bar TEXT COLLATE NOCASE_NONLITERAL);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to create table"); + + int changeCount = [db lastChangeCount]; + STAssertEquals(changeCount, 0, + @"Change count was not 0 after creating database/table!"); + + err = [db executeSQL:@"insert into foo (bar) values ('blah!');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + changeCount = [db lastChangeCount]; + STAssertEquals(changeCount, 1, @"Change count was not 1!"); + + // Test last row id! + unsigned long long lastRowId; + lastRowId = [db lastInsertRowID]; + STAssertEquals(lastRowId, (unsigned long long)1L, + @"First row in database was not 1?"); + + // Test setting busy and retrieving it! + int busyTimeout = 10000; + err = [db setBusyTimeoutMS:busyTimeout]; + STAssertEquals(err, SQLITE_OK, @"Error setting busy timeout"); + + int retrievedBusyTimeout; + retrievedBusyTimeout = [db busyTimeoutMS]; + STAssertEquals(retrievedBusyTimeout, busyTimeout, + @"Retrieved busy time out was not equal to what we set it" + @" to!"); + + BOOL xactOpSucceeded; + + xactOpSucceeded = [db beginDeferredTransaction]; + STAssertTrue(xactOpSucceeded, @"beginDeferredTransaction failed!"); + + err = [db executeSQL:@"insert into foo (bar) values ('blah!');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + changeCount = [db lastChangeCount]; + STAssertEquals(changeCount, 1, + @"Change count didn't stay the same" + @"when inserting during transaction"); + + xactOpSucceeded = [db rollback]; + STAssertTrue(xactOpSucceeded, @"could not rollback!"); + + changeCount = [db lastChangeCount]; + STAssertEquals(changeCount, 1, @"Change count isn't 1 after rollback :-("); + + xactOpSucceeded = [db beginDeferredTransaction]; + STAssertTrue(xactOpSucceeded, @"beginDeferredTransaction failed!"); + + for (unsigned int i = 0; i < 100; i++) { + err = [db executeSQL:@"insert into foo (bar) values ('blah!');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + } + + xactOpSucceeded = [db commit]; + STAssertTrue(xactOpSucceeded, @"could not commit!"); + + changeCount = [db totalChangeCount]; + STAssertEquals(changeCount, 102, @"Change count isn't 102 after commit :-("); +} + +- (void)testSQLiteWithoutCFAdditions { + int err; + GTMSQLiteDatabase *dbNoCFAdditions = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:NO + utf8:YES + errorCode:&err] + autorelease]; + + STAssertNotNil(dbNoCFAdditions, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + err = [dbNoCFAdditions executeSQL:nil]; + STAssertEquals(err, SQLITE_MISUSE, @"Nil SQL did not return error"); + + err = [dbNoCFAdditions executeSQL:@"SELECT UPPER('Fred');"]; + STAssertEquals(err, SQLITE_OK, @"Nil SQL did not return error"); +} + +- (void)testSynchronousAPI { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + [db synchronousMode:YES]; + [db synchronousMode:NO]; +} + +- (void)testEmptyStringsCollation { + int err; + GTMSQLiteDatabase *db8 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + STAssertNotNil(db8, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + GTMSQLiteDatabase *db16 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] + autorelease]; + + STAssertNotNil(db16, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + NSArray *databases = [NSArray arrayWithObjects:db8, db16, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + err = [db executeSQL: + @"CREATE TABLE foo (bar TEXT COLLATE NOCASE_NONLITERAL," + @" barrev text collate reverse);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for collation test"); + // Create blank rows to test matching inside collation functions + err = [db executeSQL:@"insert into foo (bar, barrev) values ('','');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + // Insert one row we want to match + err = [db executeSQL: + @"INSERT INTO foo (bar, barrev) VALUES " + @"('teststring','teststring');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + NSString *matchString = @"foobar"; + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE bar == '%@';", matchString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + [statement stepRow]; + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE barrev == '%@' order by barrev;", matchString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + [statement stepRow]; + + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE bar == '';"] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + [statement stepRow]; + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE barrev == '' order by barrev;"] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + [statement stepRow]; + [statement finalizeStatement]; + } +} + +- (void)testUTF16Database { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] + autorelease]; + + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + err = [db executeSQL:@"CREATE TABLE foo (bar TEXT COLLATE NOCASE_NONLITERAL);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to create table for collation test"); + + // Insert one row we want to match + err = [db executeSQL:[NSString stringWithFormat: + @"INSERT INTO foo (bar) VALUES ('%@');", + [NSString stringWithCString:"Frédéric" encoding:NSUTF8StringEncoding]]]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + // Create blank rows to test matching inside collation functions + err = [db executeSQL:@"insert into foo (bar) values ('');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + err = [db executeSQL:@"insert into foo (bar) values ('');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + // Loop over a few things all of which should match + NSArray *testArray = [NSArray arrayWithObjects: + [NSString stringWithCString:"Frédéric" + encoding:NSUTF8StringEncoding], + [NSString stringWithCString:"frédéric" + encoding:NSUTF8StringEncoding], + [NSString stringWithCString:"FRÉDÉRIC" + encoding:NSUTF8StringEncoding], + nil]; + NSString *testString = nil; + GTM_FOREACH_OBJECT(testString, testArray) { + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE bar == '%@';", testString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + int count = 0; + while ([statement stepRow] == SQLITE_ROW) { + count++; + } + STAssertEquals(count, 1, @"Wrong number of collated rows for \"%@\"", + testString); + [statement finalizeStatement]; + } + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:@"select * from foo;" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + + while ([statement stepRow] == SQLITE_ROW) ; + [statement finalizeStatement]; + +} + +- (void)testUpperLower { + + // Test our custom UPPER/LOWER implementation, need a database and statement + // to do it. + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + GTMSQLiteStatement *statement = nil; + + // Test simple ASCII + statement = [GTMSQLiteStatement statementWithSQL:@"SELECT LOWER('Fred');" + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + @"fred", + @"LOWER failed for ASCII string"); + [statement finalizeStatement]; + + statement = [GTMSQLiteStatement statementWithSQL:@"SELECT UPPER('Fred');" + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + @"FRED", + @"UPPER failed for ASCII string"); + + [statement finalizeStatement]; + // Test UTF-8, have to do some dancing to make the compiler take + // UTF8 literals + NSString *utfNormalString = + [NSString stringWithCString:"Frédéric" + encoding:NSUTF8StringEncoding]; + NSString *utfLowerString = + [NSString stringWithCString:"frédéric" + encoding:NSUTF8StringEncoding]; + NSString *utfUpperString = + [NSString stringWithCString:"FRÉDÉRIC" encoding:NSUTF8StringEncoding]; + + statement = + [GTMSQLiteStatement statementWithSQL: + [NSString stringWithFormat:@"SELECT LOWER('%@');", utfNormalString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + utfLowerString, + @"UPPER failed for UTF8 string"); + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL: + [NSString stringWithFormat:@"SELECT UPPER('%@');", utfNormalString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + utfUpperString, + @"UPPER failed for UTF8 string"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"Should be done"); + [statement finalizeStatement]; +} + +- (void)testUpperLower16 { + + // Test our custom UPPER/LOWER implementation, need a database and + // statement to do it. + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] + autorelease]; + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + GTMSQLiteStatement *statement = nil; + + // Test simple ASCII + statement = [GTMSQLiteStatement statementWithSQL:@"SELECT LOWER('Fred');" + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + @"fred", + @"LOWER failed for ASCII string"); + [statement finalizeStatement]; + + statement = [GTMSQLiteStatement statementWithSQL:@"SELECT UPPER('Fred');" + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertEqualObjects([statement resultStringAtPosition:0], + @"FRED", + @"UPPER failed for ASCII string"); + [statement finalizeStatement]; +} + +typedef struct { + BOOL upperCase; + int textRep; +} UpperLowerUserArgs; + +static void TestUpperLower16Impl(sqlite3_context *context, + int argc, sqlite3_value **argv); + +- (void)testUTF16DatabasesAreReallyUTF16 { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] + autorelease]; + + const struct { + const char *sqlName; + UpperLowerUserArgs userArgs; + void *function; + } customUpperLower[] = { + { "upper", { YES, SQLITE_UTF16 }, &TestUpperLower16Impl }, + { "upper", { YES, SQLITE_UTF16BE }, &TestUpperLower16Impl }, + { "upper", { YES, SQLITE_UTF16LE }, &TestUpperLower16Impl } + }; + + + sqlite3 *sqldb = [db sqlite3DB]; + int rc; + for (size_t i = 0; + i < (sizeof(customUpperLower) / sizeof(customUpperLower[0])); + i++) { + rc = sqlite3_create_function(sqldb, + customUpperLower[i].sqlName, + 1, + customUpperLower[i].userArgs.textRep, + (void *)&customUpperLower[i].userArgs, + customUpperLower[i].function, + NULL, + NULL); + STAssertEquals(rc, SQLITE_OK, + @"Failed to register upper function" + @"with SQLite db"); + } + + customUpperFunctionCalled = NO; + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:@"SELECT UPPER('Fred');" + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"Failed to step row"); + STAssertTrue(customUpperFunctionCalled, + @"Custom upper function was not called!"); + [statement finalizeStatement]; +} + +- (void)testLikeComparisonOptions { + int err; + + GTMSQLiteDatabase *db8 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + + GTMSQLiteDatabase *db16 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] autorelease]; + + NSArray *databases = [NSArray arrayWithObjects:db8, db16, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + CFOptionFlags c = 0, oldFlags; + + oldFlags = [db likeComparisonOptions]; + + // We'll do a case sensitivity test by making comparison options + // case insensitive + [db setLikeComparisonOptions:c]; + + STAssertTrue([db likeComparisonOptions] == 0, + @"LIKE Comparison options setter/getter does not work!"); + + NSString *createString = nil; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + createString = @"CREATE TABLE foo (bar NODIACRITIC_WIDTHINSENSITIVE TEXT);"; +#else + createString = @"CREATE TABLE foo (bar TEXT);"; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + err = [db executeSQL:createString]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for like comparison options test"); + + err = [db executeSQL:@"insert into foo values('test like test');"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create row for like comparison options test"); + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:@"select * from foo where bar like '%LIKE%'" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"failed to retrieve row!"); + + // Now change it back to case insensitive and rerun the same query + c |= kCFCompareCaseInsensitive; + [db setLikeComparisonOptions:c]; + err = [statement reset]; + STAssertEquals(err, SQLITE_OK, @"failed to reset select statement"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to retrieve row!"); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + // Now try adding in 10.5 only flags + c |= (kCFCompareDiacriticInsensitive | kCFCompareWidthInsensitive); + [db setLikeComparisonOptions:c]; + // Make a new statement + [statement finalizeStatement]; + statement = + [GTMSQLiteStatement statementWithSQL:@"select * from foo where bar like '%LIKE%'" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"failed to create statement"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to retrieve row!"); +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + // Now reset comparison options + [db setLikeComparisonOptions:oldFlags]; + + [statement finalizeStatement]; + } +} + +- (void)testGlobComparisonOptions { + int err; + GTMSQLiteDatabase *db = [[[GTMSQLiteDatabase alloc] + initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + + CFOptionFlags c = 0, oldFlags; + + oldFlags = [db globComparisonOptions]; + + [db setGlobComparisonOptions:c]; + + STAssertTrue([db globComparisonOptions] == 0, + @"GLOB Comparison options setter/getter does not work!"); + + err = [db executeSQL:@"CREATE TABLE foo (bar TEXT);"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for glob comparison options test"); + + err = [db executeSQL:@"insert into foo values('test like test');"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create row for glob comparison options test"); + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:@"select * from foo where bar GLOB 'TEST*'" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"failed to retrieve row!"); + + // Now change it back to case insensitive and rerun the same query + c |= kCFCompareCaseInsensitive; + [db setGlobComparisonOptions:c]; + err = [statement reset]; + STAssertEquals(err, SQLITE_OK, @"failed to reset select statement"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to retrieve row!"); + + [statement finalizeStatement]; + + // Now reset comparison options + [db setGlobComparisonOptions:oldFlags]; +} + +- (void)testCFStringReverseCollation { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + + err = [db executeSQL:@"CREATE table foo_reverse (bar TEXT COLLATE REVERSE);"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for reverse collation test"); + + err = [db executeSQL:@"insert into foo_reverse values('a2');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + err = [db executeSQL:@"insert into foo_reverse values('b1');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:@"SELECT bar from foo_reverse order by bar" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row"); + NSString *oneRow = [statement resultStringAtPosition:0]; + + STAssertEqualStrings(oneRow, @"b1", @"b did not come first!"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row!"); + + STAssertEquals(err, [db lastErrorCode], + @"lastErrorCode API did not match what last API returned!"); + // Calling lastErrorCode resets API error, so the next string will not indicate any error + STAssertEqualStrings(@"not an error", [db lastErrorString], + @"lastErrorString API did not match expected string!"); + + oneRow = [statement resultStringAtPosition:0]; + STAssertEqualStrings(oneRow, @"a2", @"a did not come second!"); + + [statement finalizeStatement]; +} + +- (void)testCFStringNumericCollation { + int err; + GTMSQLiteDatabase *db = [[[GTMSQLiteDatabase alloc] + initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + + err = [db executeSQL: + @"CREATE table numeric_test_table " + @"(numeric_sort TEXT COLLATE NUMERIC, lexographic_sort TEXT);"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for numeric collation test"); + + err = [db executeSQL:@"insert into numeric_test_table values('4','17');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + err = [db executeSQL:@"insert into numeric_test_table values('17','4');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:@"SELECT numeric_sort from numeric_test_table order by numeric_sort" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row"); + NSString *oneRow = [statement resultStringAtPosition:0]; + + STAssertEqualStrings(oneRow, @"4", @"4 did not come first!"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row!"); + + oneRow = [statement resultStringAtPosition:0]; + STAssertEqualStrings(oneRow, @"17", @"17 did not come second!"); + + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL: + @"SELECT lexographic_sort from numeric_test_table " + @"order by lexographic_sort" + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"failed to create statement for lexographic sort"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row"); + oneRow = [statement resultStringAtPosition:0]; + + STAssertEqualStrings(oneRow, @"17", @"17 did not come first!"); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, @"failed to advance row!"); + + oneRow = [statement resultStringAtPosition:0]; + STAssertEqualStrings(oneRow, @"4", @"4 did not come second!"); + + [statement finalizeStatement]; +} + +- (void)testCFStringCollation { + + // Test just one case of the collations, they all exercise largely the + // same code + int err; + GTMSQLiteDatabase *db = + [[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err]; + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + err = [db executeSQL: + @"CREATE TABLE foo (bar TEXT COLLATE NOCASE_NONLITERAL_LOCALIZED);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to create table for collation test"); + + // Insert one row we want to match + err = [db executeSQL:[NSString stringWithFormat: + @"INSERT INTO foo (bar) VALUES ('%@');", + [NSString stringWithCString:"Frédéric" encoding:NSUTF8StringEncoding]]]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute SQL"); + + // Loop over a few things all of which should match + NSArray *testArray = [NSArray arrayWithObjects: + [NSString stringWithCString:"Frédéric" + encoding:NSUTF8StringEncoding], + [NSString stringWithCString:"frédéric" + encoding:NSUTF8StringEncoding], + [NSString stringWithCString:"FRÉDÉRIC" + encoding:NSUTF8StringEncoding], + nil]; + + NSString *testString = nil; + GTM_FOREACH_OBJECT(testString, testArray) { + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL:[NSString stringWithFormat: + @"SELECT bar FROM foo WHERE bar == '%@';", testString] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + int count = 0; + while ([statement stepRow] == SQLITE_ROW) { + count++; + } + STAssertEquals(count, 1, @"Wrong number of collated rows for \"%@\"", + testString); + [statement finalizeStatement]; + } + + // Force a release to test the statement cleanup + [db release]; + +} + +- (void)testDiacriticAndWidthInsensitiveCollations { + // Diacritic & width insensitive collations are not supported + // on Tiger, so most of the test is Leopard or later +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + NSString *tableSQL = + @"CREATE TABLE FOOBAR (collated TEXT COLLATE NODIACRITIC_WIDTHINSENSITIVE, " + @" noncollated TEXT);"; + + err = [db executeSQL:tableSQL]; + STAssertEquals(err, SQLITE_OK, @"error creating table"); + + NSString *testStringValue = [NSString stringWithCString:"Frédéric" + encoding:NSUTF8StringEncoding]; + // Insert one row we want to match + err = [db executeSQL:[NSString stringWithFormat: + @"INSERT INTO FOOBAR (collated, noncollated) " + @"VALUES ('%@','%@');", + testStringValue, testStringValue]]; + + GTMSQLiteStatement *statement = + [GTMSQLiteStatement statementWithSQL: + [NSString stringWithFormat:@"SELECT noncollated FROM foobar" + @" WHERE noncollated == 'Frederic';"] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + // Make sure the comparison query didn't return a row because + // we're doing a comparison on the row without the collation + STAssertEquals([statement stepRow], SQLITE_DONE, + @"Comparison with diacritics did not succeed"); + + [statement finalizeStatement]; + + statement = + [GTMSQLiteStatement statementWithSQL: + [NSString stringWithFormat:@"SELECT collated FROM foobar" + @" WHERE collated == 'Frederic';"] + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + STAssertEquals([statement stepRow], SQLITE_ROW, + @"Comparison ignoring diacritics did not succeed"); + [statement finalizeStatement]; +#else + // On Tiger just make sure it causes the dev log. + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] autorelease]; + STAssertNotNil(db, @"Failed to create DB"); + STAssertEquals(err, SQLITE_OK, @"Failed to create DB"); + + NSString *tableSQL = + @"CREATE TABLE FOOBAR (collated TEXT" + @" COLLATE NODIACRITIC_WIDTHINSENSITIVE_NOCASE," + @" noncollated TEXT);"; + + // Expect one log for each unsupported flag + [GTMUnitTestDevLog expect:2 + casesOfString:@"GTMSQLiteDatabase 10.5 collating not available " + @"on 10.4 or earlier"]; + err = [db executeSQL:tableSQL]; + STAssertEquals(err, SQLITE_OK, @"error creating table"); + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +} + +- (void)testCFStringLikeGlob { + + // Test cases drawn from SQLite test case source + int err; + GTMSQLiteDatabase *db8 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + STAssertNotNil(db8, @"Failed to create database"); + STAssertEquals(err, SQLITE_OK, @"Failed to create database"); + + GTMSQLiteDatabase *db16 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:NO + errorCode:&err] + autorelease]; + + STAssertNotNil(db16, @"Failed to create database"); + STAssertEquals(err, SQLITE_OK, @"Failed to create database"); + + NSArray *databases = [NSArray arrayWithObjects:db8, db16, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + err = [db executeSQL:@"CREATE TABLE t1 (x TEXT);"]; + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for LIKE/GLOB test"); + + // Insert data set + err = [db executeSQL:@"INSERT INTO t1 VALUES ('a');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('ab');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('abc');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('abcd');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('acd');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('abd');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('bc');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('bcd');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('xyz');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('ABC');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('CDE');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + err = [db executeSQL:@"INSERT INTO t1 VALUES ('ABC abc xyz');"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + + // Section 1, case tests + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"ABC", @"abc", nil]), + @"Fail on LIKE test 1.1"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", nil]), + @"Fail on LIKE test 1.2"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"ABC", @"abc", nil]), + @"Fail on LIKE test 1.3"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"ABC", @"ABC abc xyz", @"abc", @"abcd", nil]), + @"Fail on LIKE test 3.1"); + [db setLikeComparisonOptions:(kCFCompareNonliteral)]; + err = [db executeSQL:@"CREATE INDEX i1 ON t1(x);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.3"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", nil]), + @"Fail on LIKE test 3.5"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abcd", @"abd", nil]), + @"Fail on LIKE test 3.7"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.9"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abcd", @"bcd", nil]), + @"Fail on LIKE test 3.11"); + [db setLikeComparisonOptions:(kCFCompareNonliteral | kCFCompareCaseInsensitive)]; + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"ABC", @"ABC abc xyz", @"abc", @"abcd", nil]), + @"Fail on LIKE test 3.13"); + [db setLikeComparisonOptions:(kCFCompareNonliteral)]; + err = [db executeSQL:@"DROP INDEX i1;"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.15"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.17"); + err = [db executeSQL:@"CREATE INDEX i1 ON t1(x);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.19"); + [db setLikeComparisonOptions:(kCFCompareNonliteral)]; + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 3.21"); + [db setLikeComparisonOptions:(kCFCompareNonliteral | + kCFCompareCaseInsensitive)]; + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abd", @"acd", nil]), + @"Fail on LIKE test 3.23"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a[^xyz]d' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abd", @"acd", nil]), + @"Fail on glob inverted character set test 3.24"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a[^' ORDER BY 1;"), + ([NSArray array]), + @"Fail on glob inverted character set test 3.25"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a['"), + ([NSArray array]), + @"Unclosed glob character set did not return empty result set 3.26"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a[^]'"), + ([NSArray array]), + @"Unclosed glob inverted character set did not return empty " + @"result set 3.27"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a[^]c]d'"), + ([NSArray arrayWithObjects:@"abd", nil]), + @"Glob character set with inverted set not matching ] did not " + @"return right rows 3.28"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x GLOB 'a[bcdefg'"), + ([NSArray array]), + @"Unclosed glob character set did not return empty result set 3.29"); + + // Section 4 + [db setLikeComparisonOptions:(kCFCompareNonliteral)]; + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 4.1"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 4.2"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 4.3"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x LIKE 'a[xyz]\%' ESCAPE ''"), + ([NSArray array]), + @"0-Character escape clause did not return empty set 4.4"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x LIKE " + @"'a[xyz]\%' ESCAPE NULL"), + ([NSArray array]), + @"Null escape did not return empty set 4.5"); + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x from t1 where x LIKE 'a[xyz]\\%' " + @"ESCAPE '\\'"), + ([NSArray array]), + @"Literal percent match using ESCAPE clause did not return empty result " + @"set 4.6"); + + + // Section 5 + [db setLikeComparisonOptions:(kCFCompareNonliteral | kCFCompareCaseInsensitive)]; + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"ABC", @"ABC abc xyz", @"abc", @"abcd", nil]), + @"Fail on LIKE test 5.1"); + + err = [db executeSQL:@"CREATE TABLE t2(x COLLATE NOCASE);"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + + err = [db executeSQL:@"INSERT INTO t2 SELECT * FROM t1;"]; + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + + err = [db executeSQL:@"CREATE INDEX i2 ON t2(x COLLATE NOCASE);"]; + + STAssertEquals(err, SQLITE_OK, @"Failed to execute sql"); + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"ABC", @"ABC abc xyz", @"abcd", nil]), + @"Fail on LIKE test 5.3"); + + [db setLikeComparisonOptions:(kCFCompareNonliteral)]; + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 5.5"); + + [db setLikeComparisonOptions:(kCFCompareNonliteral | kCFCompareCaseInsensitive)]; + + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abc", @"abcd", nil]), + @"Fail on LIKE test 5.5"); + + // Non standard tests not from the SQLite source + STAssertEqualObjects( + LikeGlobTestHelper(db, + @"SELECT x FROM t1 WHERE x GLOB 'a[b-d]d' ORDER BY 1;"), + ([NSArray arrayWithObjects:@"abd", @"acd", nil]), + @"Fail on GLOB with character range"); + } +} + +- (void)testDescription { + int err; + GTMSQLiteDatabase *db8 = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + STAssertNotNil(db8, @"Failed to create database"); + STAssertEquals(err, SQLITE_OK, @"Failed to create database"); + STAssertNotNil([db8 description], nil); +} + +// // From GTMSQLite.m +// CFStringEncoding SqliteTextEncodingToCFStringEncoding(int enc); + +// - (void)testEncodingMappingIsCorrect { +// STAssertTrue(SqliteTextEncodingToCFStringEncoding(SQLITE_UTF8) == +// kCFStringEncodingUTF8, +// @"helper method didn't return right encoding for " +// @"kCFStringEncodingUTF8"); + +// STAssertTrue(SqliteTextEncodingToCFStringEncoding(SQLITE_UTF16BE) +// == kCFStringEncodingUTF16BE, +// @"helper method didn't return right encoding for " +// @"kCFStringEncodingUTF16BE"); + +// STAssertTrue(SqliteTextEncodingToCFStringEncoding(SQLITE_UTF16LE) +// == kCFStringEncodingUTF16LE, +// @"helper method didn't return right encoding for " +// @"kCFStringEncodingUTF16LE"); + +// STAssertTrue(SqliteTextEncodingToCFStringEncoding(9999) +// == kCFStringEncodingUTF8, @"helper method didn't " +// @"return default encoding for invalid input"); +// } + +@end + + +// Helper function for LIKE/GLOB testing +static NSArray* LikeGlobTestHelper(GTMSQLiteDatabase *db, NSString *sql) { + + int err; + NSMutableArray *resultArray = [NSMutableArray array]; + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:sql + inDatabase:db + errorCode:&err]; + if (!statement || err != SQLITE_OK) return nil; + while ([statement stepRow] == SQLITE_ROW) { + id result = [statement resultFoundationObjectAtPosition:0]; + if (result) [resultArray addObject:result]; + } + if (err != SQLITE_DONE && err != SQLITE_OK) resultArray = nil; + [statement finalizeStatement]; + + return resultArray; +} + +// ============================================================================= + +@implementation GTMSQLiteStatementTest + +#pragma mark Parameters/binding tests + +- (void)testInitAPI { + int err; + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:nil + inDatabase:nil + errorCode:&err]; + STAssertNil(statement, @"Create statement succeeded with nil SQL string"); + STAssertEquals(err, SQLITE_MISUSE, @"Err was not SQLITE_MISUSE on nil " + @"SQL string"); + + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + statement = [GTMSQLiteStatement statementWithSQL:@"select * from blah" + inDatabase:db + errorCode:&err]; + + STAssertNil(statement, @"Select statement succeeded with invalid table"); + STAssertNotEquals(err, SQLITE_OK, + @"Err was not SQLITE_MISUSE on invalid table"); + + [statement finalizeStatement]; +} + +- (void)testParameterCountAPI { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + NSString *tableCreateSQL = + @"CREATE TABLE foo (tc TEXT," + @"ic integer," + @"rc real," + @"bc blob);"; + + err = [db executeSQL:tableCreateSQL]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for collation test"); + NSString *insert = + @"insert into foo (tc, ic, rc, bc) values (:tc, :ic, :rc, :bc);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + STAssertEquals([statement parameterCount], 4, + @"Bound parameter count was not 4"); + + [statement sqlite3Statement]; + [statement finalizeStatement]; +} + +- (void)testPositionOfNamedParameterAPI { + int err; + + GTMSQLiteDatabase *dbWithCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + GTMSQLiteDatabase *dbWithoutCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:NO + utf8:YES + errorCode:&err] + autorelease]; + + NSArray *databases = [NSArray arrayWithObjects:dbWithCF, dbWithoutCF, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + NSString *tableCreateSQL = + @"CREATE TABLE foo (tc TEXT," + @"ic integer," + @"rc real," + @"bc blob);"; + err = [db executeSQL:tableCreateSQL]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for collation test"); + NSString *insert = + @"insert into foo (tc, ic, rc, bc) " + @"values (:tc, :ic, :rc, :bc);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create statement"); + + NSArray *parameterNames = [NSArray arrayWithObjects:@":tc", + @":ic", + @":rc", + @":bc", nil]; + + for (unsigned int i = 1; i <= [parameterNames count]; i++) { + NSString *paramName = [parameterNames objectAtIndex:i-1]; + // Cast to signed int to avoid type errors from STAssertEquals + STAssertEquals((int)i, + [statement positionOfParameterNamed:paramName], + @"positionOfParameterNamed API did not return correct " + @"results"); + STAssertEqualStrings(paramName, + [statement nameOfParameterAtPosition:i], + @"nameOfParameterAtPosition API did not return " + @"correct name"); + } + [statement finalizeStatement]; + } +} + +- (void)testBindingBlob { + int err; + const int BLOB_COLUMN = 0; + GTMSQLiteDatabase *dbWithCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + GTMSQLiteDatabase *dbWithoutCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:NO + utf8:YES + errorCode:&err] + autorelease]; + + NSArray *databases = [NSArray arrayWithObjects:dbWithCF, dbWithoutCF, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + // Test strategy is to create a table with 3 columns + // Insert some values, and use the result collection APIs + // to make sure we get the same values back + err = [db executeSQL: + @"CREATE TABLE blobby (bc blob);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for BLOB binding test"); + NSString *insert = @"insert into blobby (bc) values (:bc);"; + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + char bytes[] = "DEADBEEF"; + NSUInteger bytesLen = strlen(bytes); + NSData *originalBytes = [NSData dataWithBytes:bytes length:bytesLen]; + + err = [statement bindBlobAtPosition:1 data:originalBytes]; + + STAssertEquals(err, SQLITE_OK, @"error binding BLOB at position 1"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"failed to insert BLOB for BLOB test"); + + [statement finalizeStatement]; + + NSString *selectSQL = @"select * from blobby;"; + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + STAssertEquals([statement resultColumnCount], 1, + @"result had more columns than the table had?"); + + STAssertEqualStrings([statement resultColumnNameAtPosition:BLOB_COLUMN], + @"bc", + @"column name dictionary was not correct"); + + STAssertEquals([statement rowDataCount], + 1, + @"More than one column returned?"); + + STAssertEquals([statement resultColumnTypeAtPosition:BLOB_COLUMN], + SQLITE_BLOB, + @"Query for column 1 of test table was not BLOB!"); + + NSData *returnedbytes = [statement resultBlobDataAtPosition:BLOB_COLUMN]; + STAssertTrue([originalBytes isEqualToData:returnedbytes], + @"Queried data was not equal :-("); + [statement finalizeStatement]; + } +} + +- (void)testBindingNull { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + err = [db executeSQL: + @"CREATE TABLE foo (tc TEXT);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for NULL binding test"); + NSString *insert = @"insert into foo (tc) values (:tc);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + err = [statement bindSQLNullAtPosition:1]; + + STAssertEquals(err, SQLITE_OK, @"error binding NULL at position 1"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"failed to insert NULL for Null Binding test"); + + [statement finalizeStatement]; + + NSString *selectSQL = @"select 1 from foo where tc is NULL;"; + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + [statement finalizeStatement]; +} + +- (void)testBindingDoubles { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + // Test strategy is to create a table with 2 real columns. + // For the first one, we'll use bindDoubleAtPosition + // For the second one, we'll use bindNumberAsDoubleAtPosition + // Then, for verification, we'll use a query that returns + // all rows where the columns are equal + double testVal = 42.42; + NSNumber *doubleValue = [NSNumber numberWithDouble:testVal]; + + err = [db executeSQL: + @"CREATE TABLE realTable (rc1 REAL, rc2 REAL);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for double binding test"); + NSString *insert = @"insert into realTable (rc1, rc2) values (:rc1, :rc2);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + err = [statement bindDoubleAtPosition:1 value:testVal]; + STAssertEquals(err, SQLITE_OK, @"error binding double at position 1"); + + err = [statement bindNumberAsDoubleAtPosition:2 number:doubleValue]; + STAssertEquals(err, SQLITE_OK, + @"error binding number as double at " + @"position 2"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, + @"failed to insert doubles for double " + @"binding test"); + + [statement finalizeStatement]; + + NSString *selectSQL = @"select rc1, rc2 from realTable where rc1 = rc2;"; + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + double retrievedValue = [statement resultDoubleAtPosition:0]; + STAssertEquals(retrievedValue, testVal, + @"Retrieved double did not equal " + @"original"); + + NSNumber *retrievedNumber = [statement resultNumberAtPosition:1]; + STAssertEqualObjects(retrievedNumber, doubleValue, + @"Retrieved NSNumber object did not equal"); + + [statement finalizeStatement]; +} + +- (void) testResultCollectionAPI { + int err; + GTMSQLiteDatabase *dbWithCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + GTMSQLiteDatabase *dbWithoutCF = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:NO + utf8:YES + errorCode:&err] + autorelease]; + + NSArray *databases = [NSArray arrayWithObjects:dbWithCF, dbWithoutCF, nil]; + GTMSQLiteDatabase *db; + GTM_FOREACH_OBJECT(db, databases) { + // Test strategy is to create a table with 3 columns + // Insert some values, and use the result collection APIs + // to make sure we get the same values back + err = [db executeSQL: + @"CREATE TABLE test (a integer, b text, c blob, d text);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for result collection test"); + + NSString *insert = + @"insert into test (a, b, c, d) " + @"values (42, 'text text', :bc, null);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + + char blobChars[] = "DEADBEEF"; + NSUInteger blobLength = strlen(blobChars); + NSData *blobData = [NSData dataWithBytes:blobChars length:blobLength]; + + err = [statement bindBlobAtPosition:1 data:blobData]; + STAssertEquals(err, SQLITE_OK, @"error binding BLOB at position 1"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, + @"failed to insert doubles for double " + @"binding test"); + + NSString *selectSQL = @"select * from test;"; + + [statement finalizeStatement]; + + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + STAssertNotNil([statement resultRowArray], + @"Failed to retrieve result array"); + STAssertNotNil([statement resultRowDictionary], + @"Failed to retrieve result dictionary"); + [statement finalizeStatement]; + } +} + +- (void) testBindingIntegers { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + // Test strategy is to create a table with 2 real columns. + // For the first one, we'll use bindIntegerAtPosition + // For the second one, we'll use bindNumberAsIntegerAtPosition + // Then, for verification, we'll use a query that returns + // all rows where the columns are equal + int testVal = 42; + NSNumber *intValue = [NSNumber numberWithInt:testVal]; + + err = [db executeSQL: + @"CREATE TABLE integerTable (ic1 integer, ic2 integer);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for integer binding test"); + NSString *insert = + @"insert into integerTable (ic1, ic2) values (:ic1, :ic2);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + err = [statement bindInt32AtPosition:1 value:testVal]; + STAssertEquals(err, SQLITE_OK, @"error binding integer at position 1"); + + err = [statement bindNumberAsInt32AtPosition:2 number:intValue]; + STAssertEquals(err, SQLITE_OK, + @"error binding number as integer at " + @"position 2"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, + @"failed to insert integers for integer " + @"binding test"); + + [statement finalizeStatement]; + + NSString *selectSQL = @"select ic1, ic2 from integerTable where ic1 = ic2;"; + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + int retrievedValue = [statement resultInt32AtPosition:0]; + STAssertEquals(retrievedValue, testVal, + @"Retrieved integer did not equal " + @"original"); + + NSNumber *retrievedNumber = [statement resultNumberAtPosition:1]; + STAssertEqualObjects(retrievedNumber, intValue, + @"Retrieved NSNumber object did not equal"); + + [statement finalizeStatement]; +} + +- (void) testBindingLongLongs { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + // Test strategy is to create a table with 2 long long columns. + // For the first one, we'll use bindLongLongAtPosition + // For the second one, we'll use bindNumberAsLongLongAtPosition + // Then, for verification, we'll use a query that returns + // all rows where the columns are equal + long long testVal = LLONG_MAX; + NSNumber *longlongValue = [NSNumber numberWithLongLong:testVal]; + + err = [db executeSQL: + @"CREATE TABLE longlongTable (llc1 integer, llc2 integer);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for long long binding test"); + NSString *insert = + @"insert into longlongTable (llc1, llc2) " + @"values (:llc1, :llc2);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + err = [statement bindLongLongAtPosition:1 value:testVal]; + STAssertEquals(err, SQLITE_OK, @"error binding long long at position 1"); + + err = [statement bindNumberAsLongLongAtPosition:2 number:longlongValue]; + STAssertEquals(err, SQLITE_OK, + @"error binding number as long long at " + @"position 2"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, + @"failed to insert long longs for long long " + @"binding test"); + + [statement finalizeStatement]; + + NSString *selectSQL = @"select llc1, llc2 from longlongTable where llc1 = llc2;"; + + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + long long retrievedValue = [statement resultLongLongAtPosition:0]; + STAssertEquals(retrievedValue, testVal, + @"Retrieved long long did not equal " + @"original"); + + NSNumber *retrievedNumber = [statement resultNumberAtPosition:1]; + STAssertEqualObjects(retrievedNumber, longlongValue, + @"Retrieved NSNumber object did not equal"); + + [statement finalizeStatement]; +} + +- (void) testBindingString { + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + // Test strategy is to create a table with 1 string column + // Then, for verification, we'll use a query that returns + // all rows where the strings are equal + err = [db executeSQL: + @"CREATE TABLE stringTable (sc1 text);"]; + + STAssertEquals(err, SQLITE_OK, + @"Failed to create table for string binding test"); + + NSString *insert = + @"insert into stringTable (sc1) " + @"values (:sc1);"; + + GTMSQLiteStatement *statement = [GTMSQLiteStatement statementWithSQL:insert + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create insert statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create insert statement"); + + NSString *testVal = @"this is a test string"; + err = [statement bindStringAtPosition:1 string:testVal]; + STAssertEquals(err, SQLITE_OK, @"error binding string at position 1"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, + @"failed to insert string for string binding test"); + + [statement finalizeStatement]; + + NSString *selectSQL = + [NSString stringWithFormat:@"select 1 from stringtable where sc1 = '%@';", + testVal]; + + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + // Check that we got at least one row back + STAssertEquals(err, SQLITE_ROW, @"did not retrieve a row from db :-("); + err = [statement stepRow]; + STAssertEquals(err, SQLITE_DONE, @"retrieved more than 1 row from db :-("); + [statement finalizeStatement]; +} + +- (void)testThatNotFinalizingStatementsThrowsAssertion { + // The run-time check is discouraged, but we're using it because the + // same test binary is used for both GC & Non-GC runs + if (!GTMIsGarbageCollectionEnabled()) { + NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; + + int err; + GTMSQLiteDatabase *db = + [[[GTMSQLiteDatabase alloc] initInMemoryWithCFAdditions:YES + utf8:YES + errorCode:&err] + autorelease]; + + STAssertNotNil(db, @"Failed to create database"); + + NSString *selectSQL = @"select 1"; + GTMSQLiteStatement *statement; + statement = [GTMSQLiteStatement statementWithSQL:selectSQL + inDatabase:db + errorCode:&err]; + + STAssertNotNil(statement, @"Failed to create select statement"); + STAssertEquals(err, SQLITE_OK, @"Failed to create select statement"); + + err = [statement stepRow]; + STAssertEquals(err, SQLITE_ROW, + @"failed to step row for finalize test"); + + NSString *expectedLog = + @"-[GTMSQLiteStatement finalizeStatement] must be called " + @"when statement is no longer needed"; + + [GTMUnitTestDevLog expectString:expectedLog]; + [GTMUnitTestDevLog expectPattern:@"Unable to close .*"]; + [localPool drain]; + } +} + +- (void)testCompleteSQLString { + NSString *str = @"CREATE TABLE longlongTable (llc1 integer, llc2 integer);"; + BOOL isComplete = [GTMSQLiteStatement isCompleteStatement:str]; + STAssertTrue(isComplete, nil); + isComplete = [GTMSQLiteStatement isCompleteStatement:@""]; + STAssertTrue(isComplete, nil); + isComplete = [GTMSQLiteStatement isCompleteStatement:@"CR"]; + STAssertFalse(isComplete, nil); +} + +- (void)testQuotingSQLString { + NSString *str = @"This is wild! It's fun!"; + NSString *str2 = [GTMSQLiteStatement quoteAndEscapeString:str]; + STAssertEqualObjects(str2, @"'This is wild! It''s fun!'", nil); + str2 = [GTMSQLiteStatement quoteAndEscapeString:@""]; + STAssertEqualObjects(str2, @"''", nil); +} + +- (void)testVersion { + STAssertGreaterThan([GTMSQLiteDatabase sqliteVersionNumber], 0, nil); + STAssertNotNil([GTMSQLiteDatabase sqliteVersionString], nil); +} + +@end + +static void TestUpperLower16Impl(sqlite3_context *context, + int argc, sqlite3_value **argv) { + + customUpperFunctionCalled = YES; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.h new file mode 100644 index 00000000..226d75b2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.h @@ -0,0 +1,134 @@ +// +// GTMScriptRunner.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +/// Encapsulates the interaction with an interpreter for running scripts. +// This class manages the interaction with some command-line interpreter (e.g., +// a shell, perl, python) and allows you to run expressions through the +// interpreter, and even full scripts that reside in files on disk. By default, +// the "/bin/sh" interpreter is used, but others may be explicitly specified. +// This can be a convenient way to run quick shell commands from Cocoa, or even +// interact with other shell tools such as "bc", or even "gdb". +// +// It's important to note that by default commands and scripts will have their +// environments erased before execution. You can control the environment they +// get with the -setEnvironment: method. +// +// The best way to show what this class does is to show some examples. +// +// Examples: +// +// GTMScriptRunner *sr = [GTMScriptRunner runner]; +// NSString *output = [sr run:@"ls -l /dev/null"]; +// /* output == "crw-rw-rw- 1 root wheel 3, 2 Mar 22 10:35 /dev/null" */ +// +// GTMScriptRunner *sr = [GTMScriptRunner runner]; +// NSString *output = [sr runScript:@"/path/to/my/script.sh"]; +// /* output == the standard output from the script*/ +// +// GTMScriptRunner *sr = [GTMScriptRunner runnerWithPerl]; +// NSString *output = [sr run:@"print 'A'x4"]; +// /* output == "AAAA" */ +// +// See the unit test file for more examples. +// +@interface GTMScriptRunner : NSObject { + @private + NSString *interpreter_; + NSArray *interpreterArgs_; + NSDictionary *environment_; + BOOL trimsWhitespace_; +} + +// Convenience methods for returning autoreleased GTMScriptRunner instances, that +// are associated with the specified interpreter. The default interpreter +// (returned from +runner is "/bin/sh"). ++ (GTMScriptRunner *)runner; ++ (GTMScriptRunner *)runnerWithBash; ++ (GTMScriptRunner *)runnerWithPerl; ++ (GTMScriptRunner *)runnerWithPython; + +// Returns an autoreleased GTMScriptRunner instance associated with the specified +// interpreter, and the given args. The specified args are the arguments that +// should be applied to the interpreter itself, not scripts run through the +// interpreter. For example, to start an interpreter using "perl -w", you could +// do: +// [GTMScriptRunner runnerWithInterpreter:@"/usr/bin/perl" +// withArgs:[NSArray arrayWithObject:@"-w"]]; +// ++ (GTMScriptRunner *)runnerWithInterpreter:(NSString *)interp; ++ (GTMScriptRunner *)runnerWithInterpreter:(NSString *)interp + withArgs:(NSArray *)args; + +// Returns a GTMScriptRunner associated with |interp| +- (id)initWithInterpreter:(NSString *)interp; + +// Returns a GTMScriptRunner associated with |interp| and |args| applied to the +// specified interpreter. This method is the designated initializer. +- (id)initWithInterpreter:(NSString *)interp withArgs:(NSArray *)args; + +// Runs the specified command string by sending it through the interpreter's +// standard input. The standard output is returned. The standard error is +// discarded. +- (NSString *)run:(NSString *)cmds; +// Same as the previous method, except the standard error is returned in |err| +// if specified. +- (NSString *)run:(NSString *)cmds standardError:(NSString **)err; + +// Runs the file at |path| using the interpreter. +- (NSString *)runScript:(NSString *)path; +// Runs the file at |path|, passing it |args| as arguments. +- (NSString *)runScript:(NSString *)path withArgs:(NSArray *)args; +// Same as above, except the standard error is returned in |err| if specified. +- (NSString *)runScript:(NSString *)path withArgs:(NSArray *)args + standardError:(NSString **)err; + +// Returns the environment dictionary to use for the inferior process that will +// run the interpreter. A return value of nil means that the interpreter's +// environment should be erased. +- (NSDictionary *)environment; + +// Sets the environment dictionary to use for the interpreter process. See +// NSTask's -setEnvironment: documentation for details about the dictionary. +// Basically, it's just a dict of key/value pairs corresponding to environment +// keys and values. Setting a value of nil means that the environment should be +// erased before running the interpreter. +// +// *** The default is nil. *** +// +// By default, all interpreters will run with a clean environment. If you want +// the interpreter process to inherit your current environment you'll need to +// do the following: +// +// GTMScriptRunner *sr = [GTMScriptRunner runner]; +// [sr setEnvironment:[[NSProcessInfo processInfo] environment]]; +// +// SECURITY NOTE: That said, in general you should NOT do this because an +// attacker can modify the environment that would then get sent to your scripts. +// And if your binary is suid, then you ABSOLUTELY should not do this. +// +- (void)setEnvironment:(NSDictionary *)newEnv; + +// Sets (and returns) whether or not whitespace is automatically trimmed from +// the ends of the returned strings. The default is YES, so trailing newlines +// will be removed. +- (BOOL)trimsWhitespace; +- (void)setTrimsWhitespace:(BOOL)trim; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.m new file mode 100644 index 00000000..fce69156 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunner.m @@ -0,0 +1,254 @@ +// +// GTMScriptRunner.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMScriptRunner.h" +#import "GTMDefines.h" + +static BOOL LaunchNSTaskCatchingExceptions(NSTask *task); + +@interface GTMScriptRunner (PrivateMethods) +- (NSTask *)interpreterTaskWithAdditionalArgs:(NSArray *)args; +@end + +@implementation GTMScriptRunner + ++ (GTMScriptRunner *)runner { + return [[[self alloc] init] autorelease]; +} + ++ (GTMScriptRunner *)runnerWithBash { + return [self runnerWithInterpreter:@"/bin/bash"]; +} + ++ (GTMScriptRunner *)runnerWithPerl { + return [self runnerWithInterpreter:@"/usr/bin/perl"]; +} + ++ (GTMScriptRunner *)runnerWithPython { + return [self runnerWithInterpreter:@"/usr/bin/python"]; +} + ++ (GTMScriptRunner *)runnerWithInterpreter:(NSString *)interp { + return [self runnerWithInterpreter:interp withArgs:nil]; +} + ++ (GTMScriptRunner *)runnerWithInterpreter:(NSString *)interp withArgs:(NSArray *)args { + return [[[self alloc] initWithInterpreter:interp withArgs:args] autorelease]; +} + +- (id)init { + return [self initWithInterpreter:nil]; +} + +- (id)initWithInterpreter:(NSString *)interp { + return [self initWithInterpreter:interp withArgs:nil]; +} + +- (id)initWithInterpreter:(NSString *)interp withArgs:(NSArray *)args { + if ((self = [super init])) { + trimsWhitespace_ = YES; + interpreter_ = [interp copy]; + interpreterArgs_ = [args retain]; + if (!interpreter_) { + interpreter_ = @"/bin/sh"; + } + } + return self; +} + +- (void)dealloc { + [environment_ release]; + [interpreter_ release]; + [interpreterArgs_ release]; + [super dealloc]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@<%p>{ interpreter = '%@', args = %@, environment = %@ }", + [self class], self, interpreter_, interpreterArgs_, environment_]; +} + +- (NSString *)run:(NSString *)cmds { + return [self run:cmds standardError:nil]; +} + +- (NSString *)run:(NSString *)cmds standardError:(NSString **)err { + if (!cmds) return nil; + + NSTask *task = [self interpreterTaskWithAdditionalArgs:nil]; + NSFileHandle *toTask = [[task standardInput] fileHandleForWriting]; + NSFileHandle *fromTask = [[task standardOutput] fileHandleForReading]; + + if (!LaunchNSTaskCatchingExceptions(task)) { + return nil; + } + + [toTask writeData:[cmds dataUsingEncoding:NSUTF8StringEncoding]]; + [toTask closeFile]; + + NSData *outData = [fromTask readDataToEndOfFile]; + NSString *output = [[[NSString alloc] initWithData:outData + encoding:NSUTF8StringEncoding] autorelease]; + + // Handle returning standard error if |err| is not nil + if (err) { + NSFileHandle *stderror = [[task standardError] fileHandleForReading]; + NSData *errData = [stderror readDataToEndOfFile]; + *err = [[[NSString alloc] initWithData:errData + encoding:NSUTF8StringEncoding] autorelease]; + if (trimsWhitespace_) { + *err = [*err stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + } + + // let folks test for nil instead of @"" + if ([*err length] < 1) { + *err = nil; + } + } + + [task terminate]; + + if (trimsWhitespace_) { + output = [output stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + } + + // let folks test for nil instead of @"" + if ([output length] < 1) { + output = nil; + } + + return output; +} + +- (NSString *)runScript:(NSString *)path { + return [self runScript:path withArgs:nil]; +} + +- (NSString *)runScript:(NSString *)path withArgs:(NSArray *)args { + return [self runScript:path withArgs:args standardError:nil]; +} + +- (NSString *)runScript:(NSString *)path withArgs:(NSArray *)args standardError:(NSString **)err { + if (!path) return nil; + + NSArray *scriptPlusArgs = [[NSArray arrayWithObject:path] arrayByAddingObjectsFromArray:args]; + NSTask *task = [self interpreterTaskWithAdditionalArgs:scriptPlusArgs]; + NSFileHandle *fromTask = [[task standardOutput] fileHandleForReading]; + + if (!LaunchNSTaskCatchingExceptions(task)) { + return nil; + } + + NSData *outData = [fromTask readDataToEndOfFile]; + NSString *output = [[[NSString alloc] initWithData:outData + encoding:NSUTF8StringEncoding] autorelease]; + + // Handle returning standard error if |err| is not nil + if (err) { + NSFileHandle *stderror = [[task standardError] fileHandleForReading]; + NSData *errData = [stderror readDataToEndOfFile]; + *err = [[[NSString alloc] initWithData:errData + encoding:NSUTF8StringEncoding] autorelease]; + if (trimsWhitespace_) { + *err = [*err stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + } + + // let folks test for nil instead of @"" + if ([*err length] < 1) { + *err = nil; + } + } + + [task terminate]; + + if (trimsWhitespace_) { + output = [output stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + } + + // let folks test for nil instead of @"" + if ([output length] < 1) { + output = nil; + } + + return output; +} + +- (NSDictionary *)environment { + return environment_; +} + +- (void)setEnvironment:(NSDictionary *)newEnv { + [environment_ autorelease]; + environment_ = [newEnv retain]; +} + +- (BOOL)trimsWhitespace { + return trimsWhitespace_; +} + +- (void)setTrimsWhitespace:(BOOL)trim { + trimsWhitespace_ = trim; +} + +@end + + +@implementation GTMScriptRunner (PrivateMethods) + +- (NSTask *)interpreterTaskWithAdditionalArgs:(NSArray *)args { + NSTask *task = [[[NSTask alloc] init] autorelease]; + [task setLaunchPath:interpreter_]; + [task setStandardInput:[NSPipe pipe]]; + [task setStandardOutput:[NSPipe pipe]]; + [task setStandardError:[NSPipe pipe]]; + + // If |environment_| is nil, then use an empty dictionary, otherwise use + // environment_ exactly. + [task setEnvironment:(environment_ + ? environment_ + : [NSDictionary dictionary])]; + + // Build args to interpreter. The format is: + // interp [args-to-interp] [script-name [args-to-script]] + NSArray *allArgs = nil; + if (interpreterArgs_) { + allArgs = interpreterArgs_; + } + if (args) { + allArgs = allArgs ? [allArgs arrayByAddingObjectsFromArray:args] : args; + } + if (allArgs){ + [task setArguments:allArgs]; + } + + return task; +} + +@end + +static BOOL LaunchNSTaskCatchingExceptions(NSTask *task) { + BOOL isOK = YES; + @try { + [task launch]; + } @catch (id ex) { + isOK = NO; + _GTMDevLog(@"Failed to launch interpreter '%@' due to: %@", + [task launchPath], ex); + } + return isOK; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunnerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunnerTest.m new file mode 100644 index 00000000..3d74b9eb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMScriptRunnerTest.m @@ -0,0 +1,423 @@ +// +// GTMScriptRunnerTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import +#import "GTMSenTestCase.h" +#import "GTMScriptRunner.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMScriptRunnerTest : GTMTestCase { + @private + NSString *shScript_; + NSString *perlScript_; + NSString *shOutputScript_; +} +@end + +@interface GTMScriptRunnerTest (PrivateMethods) +- (void)helperTestBourneShellUsingScriptRunner:(GTMScriptRunner *)sr; +@end + +@implementation GTMScriptRunnerTest + +- (void)setUp { + shScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_%d_%d_sh", geteuid(), getpid()]; + [@"#!/bin/sh\n" + @"i=1\n" + @"if [ -n \"$1\" ]; then\n" + @" i=$1\n" + @"fi\n" + @"echo $i\n" + writeToFile:shScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil]; + + perlScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_%d_%d_pl", geteuid(), getpid()]; + [@"#!/usr/bin/perl\n" + @"use strict;\n" + @"my $i = 1;\n" + @"if (defined $ARGV[0]) {\n" + @" $i = $ARGV[0];\n" + @"}\n" + @"print \"$i\n\"\n" + writeToFile:perlScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil]; + + shOutputScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_err_%d_%d_sh", geteuid(), getpid()]; + [@"#!/bin/sh\n" + @"if [ \"err\" = \"$1\" ]; then\n" + @" echo \" on err \" > /dev/stderr\n" + @"else\n" + @" echo \" on out \"\n" + @"fi\n" + writeToFile:shOutputScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil]; +} + +- (void)tearDown { + const char *path = [shScript_ fileSystemRepresentation]; + if (path) { + unlink(path); + } + path = [perlScript_ fileSystemRepresentation]; + if (path) { + unlink(path); + } + path = [shOutputScript_ fileSystemRepresentation]; + if (path) { + unlink(path); + } +} + +- (void)testShCommands { + GTMScriptRunner *sr = [GTMScriptRunner runner]; + [self helperTestBourneShellUsingScriptRunner:sr]; +} + +- (void)testBashCommands { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash]; + [self helperTestBourneShellUsingScriptRunner:sr]; +} + +- (void)testZshCommands { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithInterpreter:@"/bin/zsh"]; + [self helperTestBourneShellUsingScriptRunner:sr]; +} + +- (void)testBcCommands { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithInterpreter:@"/usr/bin/bc" + withArgs:[NSArray arrayWithObject:@"-lq"]]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple expression (NOTE that bc requires that commands end with a newline) + output = [sr run:@"1 + 2\n"]; + STAssertEqualObjects(output, @"3", @"output should equal '3'"); + + // Simple expression with variables and multiple statements + output = [sr run:@"i=1; i+2\n"]; + STAssertEqualObjects(output, @"3", @"output should equal '3'"); + + // Simple expression with base conversion + output = [sr run:@"obase=2; 2^5\n"]; + STAssertEqualObjects(output, @"100000", @"output should equal '100000'"); + + // Simple expression with sine and cosine functions + output = [sr run:@"scale=3;s(0)+c(0)\n"]; + STAssertEqualObjects(output, @"1.000", @"output should equal '1.000'"); +} + +- (void)testPerlCommands { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithPerl]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple print + output = [sr run:@"print 'hi'"]; + STAssertEqualObjects(output, @"hi", @"output should equal 'hi'"); + + // Simple print x4 + output = [sr run:@"print 'A'x4"]; + STAssertEqualObjects(output, @"AAAA", @"output should equal 'AAAA'"); + + // Simple perl-y stuff + output = [sr run:@"my $i=0; until ($i++==41){} print $i"]; + STAssertEqualObjects(output, @"42", @"output should equal '42'"); +} + +- (void)testPythonCommands { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithPython]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple print + output = [sr run:@"print 'hi'"]; + STAssertEqualObjects(output, @"hi", @"output should equal 'hi'"); + + // Simple python expression + output = [sr run:@"print '-'.join(['a', 'b', 'c'])"]; + STAssertEqualObjects(output, @"a-b-c", @"output should equal 'a-b-c'"); +} + +- (void)testBashScript { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple sh script + output = [sr runScript:shScript_]; + STAssertEqualObjects(output, @"1", @"output should equal '1'"); + + // Simple sh script with 1 command line argument + output = [sr runScript:shScript_ withArgs:[NSArray arrayWithObject:@"2"]]; + STAssertEqualObjects(output, @"2", @"output should equal '2'"); +} + +- (void)testPerlScript { + GTMScriptRunner *sr = [GTMScriptRunner runnerWithPerl]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple Perl script + output = [sr runScript:perlScript_]; + STAssertEqualObjects(output, @"1", @"output should equal '1'"); + + // Simple perl script with 1 command line argument + output = [sr runScript:perlScript_ withArgs:[NSArray arrayWithObject:@"2"]]; + STAssertEqualObjects(output, @"2", @"output should equal '2'"); +} + +- (void)testEnvironment { + GTMScriptRunner *sr = [GTMScriptRunner runner]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + NSString *error = nil; + STAssertNil([sr environment], @"should start w/ empty env"); + + output = [sr run:@"/usr/bin/env | wc -l" standardError:&error]; + int numVars = [output intValue]; + STAssertGreaterThan(numVars, 0, + @"numVars should be positive. StdErr %@", error); + // By default the environment is wiped clean, however shells often add a few + // of their own env vars after things have been wiped. For example, sh will + // add about 3 env vars (PWD, _, and SHLVL). + STAssertLessThan(numVars, 5, @"Our env should be almost empty"); + + NSDictionary *newEnv = [NSDictionary dictionaryWithObject:@"bar" + forKey:@"foo"]; + [sr setEnvironment:newEnv]; + output = [sr run:@"/usr/bin/env | wc -l" standardError:&error]; + STAssertEquals([output intValue], numVars + 1, + @"should have one more env var now. StdErr %@", error); + + [sr setEnvironment:nil]; + output = [sr run:@"/usr/bin/env | wc -l" standardError:&error]; + STAssertEquals([output intValue], numVars, + @"should be back down to %d vars. StdErr:%@", numVars, error); + + NSMutableDictionary *currVars + = [[[[NSProcessInfo processInfo] environment] mutableCopy] autorelease]; + + // When debugging a release build _ was not in the processInfo environment + // causing the assert below to fail. Not sure why, but it appeared + // to be harmless, and easy to account for. + [currVars setObject:@"/usr/bin/env" forKey:@"_"]; + [sr setEnvironment:currVars]; + + output = [sr run:@"/usr/bin/env | /usr/bin/sort" standardError:&error]; + NSArray *lineArray = [output componentsSeparatedByString:@"\n"]; + STAssertEquals([lineArray count], [currVars count], + @"StdErr:%@\nCurrentEnvironment:\n%@\nExpected environment:\n%@", + error, output, currVars); +} + +- (void)testDescription { + // make sure description doesn't choke + GTMScriptRunner *sr = [GTMScriptRunner runner]; + STAssertNotNil(sr, @"Script runner must not be nil"); + STAssertGreaterThan([[sr description] length], (NSUInteger)10, + @"expected a description of at least 10 chars"); +} + +- (void)testRunCommandOutputHandling { + // Test whitespace trimming & stdout vs. stderr w/ run command api + + GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + NSString *err = nil; + + // w/o whitespace trimming + { + [sr setTrimsWhitespace:NO]; + STAssertFalse([sr trimsWhitespace], @"setTrimsWhitespace to NO failed"); + + // test stdout + output = [sr run:@"echo \" on out \"" standardError:&err]; + STAssertEqualObjects(output, @" on out \n", @"failed to get stdout output"); + STAssertNil(err, @"stderr should have been empty"); + + // test stderr + output = [sr run:@"echo \" on err \" > /dev/stderr" standardError:&err]; + STAssertNil(output, @"stdout should have been empty"); + STAssertEqualObjects(err, @" on err \n", nil); + } + + // w/ whitespace trimming + { + [sr setTrimsWhitespace:YES]; + STAssertTrue([sr trimsWhitespace], @"setTrimsWhitespace to YES failed"); + + // test stdout + output = [sr run:@"echo \" on out \"" standardError:&err]; + STAssertEqualObjects(output, @"on out", @"failed to get stdout output"); + STAssertNil(err, @"stderr should have been empty"); + + // test stderr + output = [sr run:@"echo \" on err \" > /dev/stderr" standardError:&err]; + STAssertNil(output, @"stdout should have been empty"); + STAssertEqualObjects(err, @"on err", nil); + } +} + +- (void)testScriptOutputHandling { + // Test whitespace trimming & stdout vs. stderr w/ script api + + GTMScriptRunner *sr = [GTMScriptRunner runner]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + NSString *err = nil; + + // w/o whitespace trimming + { + [sr setTrimsWhitespace:NO]; + STAssertFalse([sr trimsWhitespace], @"setTrimsWhitespace to NO failed"); + + // test stdout + output = [sr runScript:shOutputScript_ + withArgs:[NSArray arrayWithObject:@"out"] + standardError:&err]; + STAssertEqualObjects(output, @" on out \n", nil); + STAssertNil(err, @"stderr should have been empty"); + + // test stderr + output = [sr runScript:shOutputScript_ + withArgs:[NSArray arrayWithObject:@"err"] + standardError:&err]; + STAssertNil(output, @"stdout should have been empty"); + STAssertEqualObjects(err, @" on err \n", nil); + } + + // w/ whitespace trimming + { + [sr setTrimsWhitespace:YES]; + STAssertTrue([sr trimsWhitespace], @"setTrimsWhitespace to YES failed"); + + // test stdout + output = [sr runScript:shOutputScript_ + withArgs:[NSArray arrayWithObject:@"out"] + standardError:&err]; + STAssertEqualObjects(output, @"on out", nil); + STAssertNil(err, @"stderr should have been empty"); + + // test stderr + output = [sr runScript:shOutputScript_ + withArgs:[NSArray arrayWithObject:@"err"] + standardError:&err]; + STAssertNil(output, @"stdout should have been empty"); + STAssertEqualObjects(err, @"on err", nil); + } +} + +- (void)testBadRunCommandInput { + GTMScriptRunner *sr = [GTMScriptRunner runner]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *err = nil; + + STAssertNil([sr run:nil standardError:&err], nil); + STAssertNil(err, nil); +} + +- (void)testBadScriptInput { + GTMScriptRunner *sr = [GTMScriptRunner runner]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *err = nil; + + STAssertNil([sr runScript:nil withArgs:nil standardError:&err], nil); + STAssertNil(err, nil); + STAssertNil([sr runScript:@"/path/that/does/not/exists/foo/bar/baz" + withArgs:nil standardError:&err], nil); + STAssertNotNil(err, + @"should have gotten something about the path not existing"); +} + +- (void)testBadCmdInterpreter { + GTMScriptRunner *sr = + [GTMScriptRunner runnerWithInterpreter:@"/path/that/does/not/exists/interpreter"]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *err = nil; + + STAssertNil([sr run:nil standardError:&err], nil); + STAssertNil(err, nil); + [GTMUnitTestDevLog expectString:@"Failed to launch interpreter " + "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"]; + STAssertNil([sr run:@"ls /" standardError:&err], nil); + STAssertNil(err, nil); +} + +- (void)testBadScriptInterpreter { + GTMScriptRunner *sr = + [GTMScriptRunner runnerWithInterpreter:@"/path/that/does/not/exists/interpreter"]; + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *err = nil; + + [GTMUnitTestDevLog expectString:@"Failed to launch interpreter " + "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"]; + STAssertNil([sr runScript:shScript_ withArgs:nil standardError:&err], nil); + STAssertNil(err, nil); + [GTMUnitTestDevLog expectString:@"Failed to launch interpreter " + "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"]; + STAssertNil([sr runScript:@"/path/that/does/not/exists/foo/bar/baz" + withArgs:nil standardError:&err], nil); + STAssertNil(err, nil); +} + + +@end + +@implementation GTMScriptRunnerTest (PrivateMethods) + +- (void)helperTestBourneShellUsingScriptRunner:(GTMScriptRunner *)sr { + STAssertNotNil(sr, @"Script runner must not be nil"); + NSString *output = nil; + + // Simple command + output = [sr run:@"ls /etc/passwd"]; + STAssertEqualObjects(output, @"/etc/passwd", @"output should equal '/etc/passwd'"); + + // Simple command pipe-line + output = [sr run:@"ls /etc/ | grep passwd | tail -1"]; + STAssertEqualObjects(output, @"passwd", @"output should equal 'passwd'"); + + // Simple pipe-line with quotes and awk variables + output = [sr run:@"ps jaxww | awk '{print $2}' | sort -nr | tail -2 | head -1"]; + STAssertEqualObjects(output, @"1", @"output should equal '1'"); + + // Simple shell loop with variables + output = [sr run:@"i=0; while [ $i -lt 100 ]; do i=$((i+1)); done; echo $i"]; + STAssertEqualObjects(output, @"100", @"output should equal '100'"); + + // Simple command with newlines + output = [sr run:@"i=1\necho $i"]; + STAssertEqualObjects(output, @"1", @"output should equal '1'"); + + // Simple full shell script + output = [sr run:@"#!/bin/sh\ni=1\necho $i\n"]; + STAssertEqualObjects(output, @"1", @"output should equal '1'"); + + NSString *err = nil; + + // Test getting standard error with no stdout + output = [sr run:@"ls /etc/does-not-exist" standardError:&err]; + STAssertNil(output, @"output should be nil due to expected error"); + STAssertEqualObjects(err, @"ls: /etc/does-not-exist: No such file or directory", @""); + + // Test getting standard output along with some standard error + output = [sr run:@"ls /etc/does-not-exist /etc/passwd" standardError:&err]; + STAssertEqualObjects(output, @"/etc/passwd", @""); + STAssertEqualObjects(err, @"ls: /etc/does-not-exist: No such file or directory", @""); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.h new file mode 100644 index 00000000..b1c7c2f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.h @@ -0,0 +1,73 @@ +// +// GTMSignalHandler.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// GTMSignalHandler. +// +// This is a very simple, easy-to-use class for registering handlers that get +// called when a specific signal is delivered. Also handy for ignoring +// inconvenient signals. Ignoring SIGKILL is not support for what should be +// obvious reasons. You can pass nil for target & action to ignore the signal. +// +// Example of how to catch SIGABRT and SIGTERM while ignring SIGWINCH: +// GTMSignalHandler *abrt, *term, *winch; +// abrt = [[GTMSignalHandler alloc] +// initWithSignal:SIGABRT +// target:self +// action:@selector(handleAbort:)]; +// +// term = [[GTMSignalHandler alloc] +// initWithSignal:SIGTERM +// target:self +// action:@selector(handleTerm:)]; +// +// winch = [[GTMSignalHandler alloc] initWithSignal:SIGWINCH +// initWithSignal:SIGWINCH +// target:nil +// action:NULL +// +// -(void)handleTerm:(int)signo { +// .. do stuff .. +// } +// +// Release the handler when you're no longer interested in handling that signal. +// Note that signal(SIG_IGN, signo) is performed on each signal handled by +// objects of this class, and those do not get un-done. +// +// Multiple handlers for the same signal is NOT supported. +// +// kqueue() is used to handle the signals, and the default runloop for the first +// signal handler is used for signal delivery, so keep that in mind when you're +// using this class. This class explicitly does not handle arbitrary runloops +// and threading. +// +@interface GTMSignalHandler : NSObject { + @private + int signo_; + __weak id target_; + SEL action_; +} + +// Returns a retained signal handler object that will invoke |handler| on the +// |target| whenever a signal of number |signo| is delivered to the process. +-(id)initWithSignal:(int)signo + target:(id)target + action:(SEL)action; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.m new file mode 100644 index 00000000..b6cfb706 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandler.m @@ -0,0 +1,210 @@ +// +// GTMSignalHandler.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSignalHandler.h" +#import "GTMDefines.h" + +#import // for kqueue() and kevent +#import "GTMDebugSelectorValidation.h" + +// Simplifying assumption: No more than one handler for a particular signal is +// alive at a time. When the second signal is registered, kqueue just updates +// the info about the first signal, which makes -dealloc time complicated (what +// happens when handler1(SIGUSR1) is released before handler2(SIGUSR1)?). This +// could be solved by having one kqueue per signal, or keeping a list of +// handlers interested in a particular signal, but not really worth it for apps +// that register the handlers at startup and don't change them. + + +// File descriptor for the kqueue that will hold all of our signal events. +static int gSignalKQueueFileDescriptor = 0; + +// A wrapper around the kqueue file descriptor so we can put it into a +// runloop. +static CFSocketRef gRunLoopSocket = NULL; + + +@interface GTMSignalHandler (PrivateMethods) +- (void)notify; +- (void)addFileDescriptorMonitor:(int)fd; +- (void)registerWithKQueue; +- (void)unregisterWithKQueue; +@end + + +@implementation GTMSignalHandler + +-(id)init { + // Folks shouldn't call init directly, so they get what they deserve. + _GTMDevLog(@"Don't call init, use " + @"initWithSignal:target:action:"); + return [self initWithSignal:0 target:nil action:NULL]; +} + +- (id)initWithSignal:(int)signo + target:(id)target + action:(SEL)action { + + if ((self = [super init])) { + + if (signo == 0) { + [self release]; + return nil; + } + + signo_ = signo; + target_ = target; // Don't retain since target will most likely retain us. + action_ = action; + GTMAssertSelectorNilOrImplementedWithArguments(target_, + action_, + @encode(int), + NULL); + + // We're handling this signal via kqueue, so turn off the usual signal + // handling. + signal(signo_, SIG_IGN); + + if (action != NULL) { + [self registerWithKQueue]; + } + } + return self; +} + +#if GTM_SUPPORT_GC +- (void)finalize { + [self unregisterWithKQueue]; + + [super finalize]; + +} +#endif + +- (void)dealloc { + [self unregisterWithKQueue]; + + [super dealloc]; + +} + +// Cribbed from Advanced Mac OS X Programming. +static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type, + CFDataRef address, const void *data, void *info) { + // We're using CFRunLoop calls here. Even when used on the main thread, they + // don't trigger the draining of the main application's autorelease pool that + // NSRunLoop provides. If we're used in a UI-less app, this means that + // autoreleased objects would never go away, so we provide our own pool here. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + struct kevent event; + + if (kevent(gSignalKQueueFileDescriptor, NULL, 0, &event, 1, NULL) == -1) { + _GTMDevLog(@"could not pick up kqueue event. Errno %d", errno); // COV_NF_LINE + } else { + GTMSignalHandler *handler = (GTMSignalHandler *)event.udata; + [handler notify]; + } + + [pool drain]; +} + +// Cribbed from Advanced Mac OS X Programming +- (void)addFileDescriptorMonitor:(int)fd { + CFSocketContext context = { 0, NULL, NULL, NULL, NULL }; + + gRunLoopSocket = CFSocketCreateWithNative(kCFAllocatorDefault, + fd, + kCFSocketReadCallBack, + SocketCallBack, + &context); + if (gRunLoopSocket == NULL) { + _GTMDevLog(@"could not CFSocketCreateWithNative"); // COV_NF_LINE + goto bailout; // COV_NF_LINE + } + + CFRunLoopSourceRef rls; + rls = CFSocketCreateRunLoopSource(NULL, gRunLoopSocket, 0); + if (rls == NULL) { + _GTMDevLog(@"could not create a run loop source"); // COV_NF_LINE + goto bailout; // COV_NF_LINE + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, + kCFRunLoopDefaultMode); + CFRelease(rls); + + bailout: + return; + +} + +- (void)registerWithKQueue { + + // Make sure we have our kqueue. + if (gSignalKQueueFileDescriptor == 0) { + gSignalKQueueFileDescriptor = kqueue(); + + if (gSignalKQueueFileDescriptor == -1) { + _GTMDevLog(@"could not make signal kqueue. Errno %d", errno); // COV_NF_LINE + return; // COV_NF_LINE + } + + // Add the kqueue file descriptor to the runloop. + [self addFileDescriptorMonitor:gSignalKQueueFileDescriptor]; + } + + // Add a new event for the signal. + struct kevent filter; + EV_SET(&filter, signo_, EVFILT_SIGNAL, EV_ADD | EV_ENABLE | EV_CLEAR, + 0, 0, self); + + const struct timespec noWait = { 0, 0 }; + if (kevent(gSignalKQueueFileDescriptor, &filter, 1, NULL, 0, &noWait) != 0) { + _GTMDevLog(@"could not add event for signal %d. Errno %d", signo_, errno); // COV_NF_LINE + } + +} + +- (void)unregisterWithKQueue { + // Short-circuit cases where we didn't actually register a kqueue event. + if (signo_ == 0) return; + if (action_ == nil) return; + + struct kevent filter; + EV_SET(&filter, signo_, EVFILT_SIGNAL, EV_DELETE, 0, 0, self); + + const struct timespec noWait = { 0, 0 }; + if (kevent(gSignalKQueueFileDescriptor, &filter, 1, NULL, 0, &noWait) != 0) { + _GTMDevLog(@"could not remove event for signal %d. Errno %d", signo_, errno); // COV_NF_LINE + } + +} + +- (void)notify { + // Now, fire the selector + NSMethodSignature *methodSig = [target_ methodSignatureForSelector:action_]; + _GTMDevAssert(methodSig != nil, @"failed to get the signature?"); + NSInvocation *invocation + = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setTarget:target_]; + [invocation setSelector:action_]; + [invocation setArgument:&signo_ atIndex:2]; + [invocation invoke]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandlerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandlerTest.m new file mode 100644 index 00000000..a0019f3c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSignalHandlerTest.m @@ -0,0 +1,143 @@ +// +// GTMSignalHandlerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMSignalHandler.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMSignalHandlerTest : GTMTestCase +@end + +@interface SignalCounter : NSObject { + @public + int signalCount_; + int lastSeenSignal_; +} +- (int)count; +- (int)lastSeen; +- (void)countSignal:(int)signo; ++ (id)signalCounter; +@end // SignalCounter + +@implementation SignalCounter ++ (id)signalCounter { + return [[[[self class] alloc] init] autorelease]; +} +- (int)count { + return signalCount_; +} +- (int)lastSeen { + return lastSeenSignal_; +} +// Count the number of times this signal handler has fired. +- (void)countSignal:(int)signo { + signalCount_++; + lastSeenSignal_ = signo; +} +@end + +@implementation GTMSignalHandlerTest + +// Spin the run loop so that the kqueue event notifications will get delivered. +- (void)giveSomeLove { + NSDate *endTime = [NSDate dateWithTimeIntervalSinceNow:0.5]; + [[NSRunLoop currentRunLoop] runUntilDate:endTime]; +} + +- (void)testNillage { + GTMSignalHandler *handler; + + // Just an init should return nil. + [GTMUnitTestDevLog expectString:@"Don't call init, use " + @"initWithSignal:target:action:"]; + handler = [[[GTMSignalHandler alloc] init] autorelease]; + STAssertNil(handler, nil); + + // Zero signal should return nil as well. + handler = [[[GTMSignalHandler alloc] + initWithSignal:0 + target:self + action:@selector(nomnomnom:)] autorelease]; + STAssertNil(handler, nil); + +} + +- (void)testSingleHandler { + SignalCounter *counter = [SignalCounter signalCounter]; + STAssertNotNil(counter, nil); + + GTMSignalHandler *handler = [[GTMSignalHandler alloc] + initWithSignal:SIGWINCH + target:counter + action:@selector(countSignal:)]; + STAssertNotNil(handler, nil); + raise(SIGWINCH); + [self giveSomeLove]; + + STAssertEquals([counter count], 1, nil); + STAssertEquals([counter lastSeen], SIGWINCH, nil); + + raise(SIGWINCH); + [self giveSomeLove]; + + STAssertEquals([counter count], 2, nil); + STAssertEquals([counter lastSeen], SIGWINCH, nil); + + // create a second one to make sure we're seding data where we want + SignalCounter *counter2 = [SignalCounter signalCounter]; + STAssertNotNil(counter2, nil); + [[[GTMSignalHandler alloc] initWithSignal:SIGUSR1 + target:counter2 + action:@selector(countSignal:)] autorelease]; + + raise(SIGUSR1); + [self giveSomeLove]; + + STAssertEquals([counter count], 2, nil); + STAssertEquals([counter lastSeen], SIGWINCH, nil); + STAssertEquals([counter2 count], 1, nil); + STAssertEquals([counter2 lastSeen], SIGUSR1, nil); + + [handler release]; + + // The signal is still ignored (so we shouldn't die), but the + // the handler method should not get called. + raise(SIGWINCH); + + STAssertEquals([counter count], 2, nil); + STAssertEquals([counter lastSeen], SIGWINCH, nil); + STAssertEquals([counter2 count], 1, nil); + STAssertEquals([counter2 lastSeen], SIGUSR1, nil); + +} + +- (void)testIgnore { + SignalCounter *counter = [SignalCounter signalCounter]; + STAssertNotNil(counter, nil); + + [[[GTMSignalHandler alloc] initWithSignal:SIGUSR1 + target:counter + action:NULL] autorelease]; + + raise(SIGUSR1); + [self giveSomeLove]; + STAssertEquals([counter count], 0, nil); + +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.h new file mode 100644 index 00000000..d8cc6422 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.h @@ -0,0 +1,105 @@ +// +// GTMStackTrace.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#include +#import "GTMDefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct GTMAddressDescriptor { + const void *address; // address + const char *symbol; // nearest symbol to address + const char *class_name; // if it is an obj-c method, the method's class + BOOL is_class_method; // if it is an obj-c method, type of method + const char *filename; // file that the method came from. +}; + +// Returns a string containing a nicely formatted stack trace. +// +// This function gets the stack trace for the current thread. It will +// be from the caller of GTMStackTrace upwards to the top the calling stack. +// Typically this function will be used along with some logging, +// as in the following: +// +// MyAppLogger(@"Should never get here:\n%@", GTMStackTrace()); +// +// Here is a sample stack trace returned from this function: +// +// #0 0x00002d92 D () [/Users/me/./StackLog] +// #1 0x00002e45 C () [/Users/me/./StackLog] +// #2 0x00002e53 B () [/Users/me/./StackLog] +// #3 0x00002e61 A () [/Users/me/./StackLog] +// #4 0x00002e6f main () [/Users/me/./StackLog] +// #5 0x00002692 tart () [/Users/me/./StackLog] +// #6 0x000025b9 tart () [/Users/me/./StackLog] +// + +NSString *GTMStackTrace(void); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 +// Returns a string containing a nicely formatted stack trace from the +// exception. Only available on 10.5 or later, uses +// -[NSException callStackReturnAddresses]. +// +NSString *GTMStackTraceFromException(NSException *e); +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +// Returns an array of program counters from the current thread's stack. +// *** You should probably use GTMStackTrace() instead of this function *** +// However, if you actually want all the PCs in "void *" form, then this +// funtion is more convenient. This will include PCs of GTMStaceTrace and +// its inner utility functions that you may want to strip out. +// +// You can use +[NSThread callStackReturnAddresses] in 10.5 or later. +// +// Args: +// outPcs - an array of "void *" pointers to the program counters found on the +// current thread's stack. +// count - the number of entries in the outPcs array +// +// Returns: +// The number of program counters actually added to outPcs. +// +NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count); +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +// Returns an array of GTMAddressDescriptors from the current thread's stack. +// *** You should probably use GTMStackTrace() instead of this function *** +// However, if you actually want all the PCs with symbols, this is the way +// to get them. There is no memory allocations done, so no clean up is required +// except for the caller to free outDescs if they allocated it themselves. +// This will include PCs of GTMStaceTrace and its inner utility functions that +// you may want to strip out. +// +// Args: +// outDescs - an array of "struct GTMAddressDescriptor" pointers corresponding +// to the program counters found on the current thread's stack. +// count - the number of entries in the outDescs array +// +// Returns: +// The number of program counters actually added to outPcs. +// +NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[], + NSUInteger count); + +#ifdef __cplusplus +} +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.m new file mode 100644 index 00000000..05843b50 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTrace.m @@ -0,0 +1,358 @@ +// +// GTMStackTrace.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#include +#include +#include +#include "GTMStackTrace.h" +#include "GTMObjC2Runtime.h" + +struct GTMClassDescription { + const char *class_name; + Method *class_methods; + unsigned int class_method_count; + Method *instance_methods; + unsigned int instance_method_count; +}; + +#pragma mark Private utility functions + +static struct GTMClassDescription *GTMClassDescriptions(NSUInteger *total_count) { + int class_count = objc_getClassList(nil, 0); + struct GTMClassDescription *class_descs + = calloc(class_count, sizeof(struct GTMClassDescription)); + if (class_descs) { + Class *classes = calloc(class_count, sizeof(Class)); + if (classes) { + objc_getClassList(classes, class_count); + for (int i = 0; i < class_count; ++i) { + class_descs[i].class_methods + = class_copyMethodList(object_getClass(classes[i]), + &class_descs[i].class_method_count); + class_descs[i].instance_methods + = class_copyMethodList(classes[i], + &class_descs[i].instance_method_count); + class_descs[i].class_name = class_getName(classes[i]); + } + free(classes); + } else { + // COV_NF_START - Don't know how to force this in a unittest + free(class_descs); + class_count = 0; + // COV_NF_END + } + } + if (total_count) { + *total_count = class_count; + } + return class_descs; +} + +static void GTMFreeClassDescriptions(struct GTMClassDescription *class_descs, + NSUInteger count) { + if (!class_descs) return; + for (NSUInteger i = 0; i < count; ++i) { + if (class_descs[i].instance_methods) { + free(class_descs[i].instance_methods); + } + if (class_descs[i].class_methods) { + free(class_descs[i].class_methods); + } + } + free(class_descs); +} + +static NSUInteger GTMGetStackAddressDescriptorsForAddresses(void *pcs[], + struct GTMAddressDescriptor outDescs[], + NSUInteger count) { + if (count < 1 || !pcs || !outDescs) return 0; + + NSUInteger class_desc_count; + + // Get our obj-c class descriptions. This is expensive, so we do it once + // at the top. We go through this because dladdr doesn't work with + // obj methods. + struct GTMClassDescription *class_descs + = GTMClassDescriptions(&class_desc_count); + + // Iterate through the stack. + for (NSUInteger i = 0; i < count; ++i) { + const char *class_name = NULL; + BOOL is_class_method = NO; + size_t smallest_diff = SIZE_MAX; + struct GTMAddressDescriptor *currDesc = &outDescs[i]; + currDesc->address = pcs[i]; + Method best_method = NULL; + // Iterate through all the classes we know of. + for (NSUInteger j = 0; j < class_desc_count; ++j) { + // First check the class methods. + for (NSUInteger k = 0; k < class_descs[j].class_method_count; ++k) { + IMP imp = method_getImplementation(class_descs[j].class_methods[k]); + if (imp <= (IMP)currDesc->address) { + size_t diff = (size_t)currDesc->address - (size_t)imp; + if (diff < smallest_diff) { + best_method = class_descs[j].class_methods[k]; + class_name = class_descs[j].class_name; + is_class_method = YES; + smallest_diff = diff; + } + } + } + // Then check the instance methods. + for (NSUInteger k = 0; k < class_descs[j].instance_method_count; ++k) { + IMP imp = method_getImplementation(class_descs[j].instance_methods[k]); + if (imp <= (IMP)currDesc->address) { + size_t diff = (size_t)currDesc->address - (size_t)imp; + if (diff < smallest_diff) { + best_method = class_descs[j].instance_methods[k]; + class_name = class_descs[j].class_name; + is_class_method = NO; + smallest_diff = diff; + } + } + } + } + + // If we have one, store it off. + if (best_method) { + currDesc->symbol = sel_getName(method_getName(best_method)); + currDesc->is_class_method = is_class_method; + currDesc->class_name = class_name; + } + Dl_info info = { NULL, NULL, NULL, NULL }; + + // Check to see if the one returned by dladdr is better. + dladdr(currDesc->address, &info); + if ((size_t)currDesc->address - (size_t)info.dli_saddr < smallest_diff) { + currDesc->symbol = info.dli_sname; + currDesc->is_class_method = NO; + currDesc->class_name = NULL; + } + currDesc->filename = info.dli_fname; + } + GTMFreeClassDescriptions(class_descs, class_desc_count); + return count; +} + +static NSString *GTMStackTraceFromAddressDescriptors(struct GTMAddressDescriptor descs[], + NSUInteger count) { + NSMutableString *trace = [NSMutableString string]; + + for (NSUInteger i = 0; i < count; i++) { + // Newline between all the lines + if (i) { + [trace appendString:@"\n"]; + } + if (descs[i].class_name) { + [trace appendFormat:@"#%-2u %#08lx %s[%s %s] (%s)", + i, descs[i].address, + (descs[i].is_class_method ? "+" : "-"), + descs[i].class_name, + (descs[i].symbol ? descs[i].symbol : "??"), + (descs[i].filename ? descs[i].filename : "??")]; + } else { + [trace appendFormat:@"#%-2u %#08lx %s() (%s)", + i, descs[i].address, + (descs[i].symbol ? descs[i].symbol : "??"), + (descs[i].filename ? descs[i].filename : "??")]; + } + } + return trace; +} + +#pragma mark Public functions + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +// Before 10.5, we have to do this ourselves. 10.5 adds +// +[NSThread callStackReturnAddresses]. + +// Structure representing a small portion of a stack, starting from the saved +// frame pointer, and continuing through the saved program counter. +struct GTMStackFrame { + void *saved_fp; +#if defined (__ppc__) || defined(__ppc64__) + void *padding; +#endif + void *saved_pc; +}; + +// __builtin_frame_address(0) is a gcc builtin that returns a pointer to the +// current frame pointer. We then use the frame pointer to walk the stack +// picking off program counters and other saved frame pointers. This works +// great on i386, but PPC requires a little more work because the PC (or link +// register) isn't always stored on the stack. +// +NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count) { + if (!outPcs || (count < 1)) return 0; + + struct GTMStackFrame *fp; +#if defined (__ppc__) || defined(__ppc64__) + outPcs[0] = __builtin_return_address(0); + fp = (struct GTMStackFrame *)__builtin_frame_address(1); +#elif defined (__i386__) || defined(__x86_64__) + fp = (struct GTMStackFrame *)__builtin_frame_address(0); +#else +#error architecture not supported +#endif + + NSUInteger level = 0; + while (level < count) { + if (fp == NULL) { + level--; + break; + } + outPcs[level] = fp->saved_pc; + level++; + fp = (struct GTMStackFrame *)fp->saved_fp; + } + + return level; +} +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[], + NSUInteger count) { + if (count < 1 || !outDescs) return 0; + NSUInteger result = 0; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + // Before 10.5, we collect the stack ourselves. + + void **pcs = calloc(count, sizeof(void*)); + if (!pcs) return 0; + + NSUInteger newSize = GTMGetStackProgramCounters(pcs, count); + + result = GTMGetStackAddressDescriptorsForAddresses(pcs, outDescs, newSize); + free(pcs); + +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + // Use +[NSThread callStackReturnAddresses] + + NSArray *addresses = [NSThread callStackReturnAddresses]; + NSUInteger addrCount = [addresses count]; + if (addrCount) { + void **pcs = calloc(addrCount, sizeof(void*)); + if (pcs) { + void **pcsScanner = pcs; + for (NSNumber *address in addresses) { + NSUInteger addr = [address unsignedIntegerValue]; + *pcsScanner = (void *)addr; + ++pcsScanner; + } + if (count < addrCount) { + addrCount = count; + } + // Fill in the desc structures + result = GTMGetStackAddressDescriptorsForAddresses(pcs, outDescs, addrCount); + } + if (pcs) free(pcs); + } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + return result; +} + +NSString *GTMStackTrace(void) { + // If we don't have enough frames, return an empty string + NSString *result = @""; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + // Before 10.5, we collect the stack ourselves. + + // The maximum number of stack frames that we will walk. We limit this so + // that super-duper recursive functions (or bugs) don't send us for an + // infinite loop. + struct GTMAddressDescriptor descs[100]; + size_t depth = sizeof(descs) / sizeof(struct GTMAddressDescriptor); + depth = GTMGetStackAddressDescriptors(descs, depth); + + // Start at the second item so that GTMStackTrace and it's utility calls (of + // which there is currently 1) is not included in the output. + const size_t kTracesToStrip = 2; + if (depth > kTracesToStrip) { + result = GTMStackTraceFromAddressDescriptors(&descs[kTracesToStrip], + (depth - kTracesToStrip)); + } +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + // Use +[NSThread callStackReturnAddresses] + + NSArray *addresses = [NSThread callStackReturnAddresses]; + NSUInteger count = [addresses count]; + if (count) { + void **pcs = calloc(count, sizeof(void*)); + struct GTMAddressDescriptor *descs + = calloc(count, sizeof(struct GTMAddressDescriptor)); + if (pcs && descs) { + void **pcsScanner = pcs; + for (NSNumber *address in addresses) { + NSUInteger addr = [address unsignedIntegerValue]; + *pcsScanner = (void *)addr; + ++pcsScanner; + } + // Fill in the desc structures + count = GTMGetStackAddressDescriptorsForAddresses(pcs, descs, count); + // Build the trace + // We skip 1 frame because the +[NSThread callStackReturnAddresses] will + // start w/ this frame. + const size_t kTracesToStrip = 1; + if (count > kTracesToStrip) { + result = GTMStackTraceFromAddressDescriptors(&descs[kTracesToStrip], + (count - kTracesToStrip)); + } + } + if (pcs) free(pcs); + if (descs) free(descs); + } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + return result; +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +NSString *GTMStackTraceFromException(NSException *e) { + NSString *trace = @""; + + // collect the addresses + NSArray *addresses = [e callStackReturnAddresses]; + NSUInteger count = [addresses count]; + if (count) { + void **pcs = calloc(count, sizeof(void*)); + struct GTMAddressDescriptor *descs + = calloc(count, sizeof(struct GTMAddressDescriptor)); + if (pcs && descs) { + void **pcsScanner = pcs; + for (NSNumber *address in addresses) { + NSUInteger addr = [address unsignedIntegerValue]; + *pcsScanner = (void *)addr; + ++pcsScanner; + } + // Fill in the desc structures + count = GTMGetStackAddressDescriptorsForAddresses(pcs, descs, count); + // Build the trace + trace = GTMStackTraceFromAddressDescriptors(descs, count); + } + if (pcs) free(pcs); + if (descs) free(descs); + } + + return trace; +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTraceTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTraceTest.m new file mode 100644 index 00000000..07391220 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMStackTraceTest.m @@ -0,0 +1,163 @@ +// +// GTMStackTraceTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMStackTrace.h" +#import "GTMSenTestCase.h" + +@interface GTMStackTraceTest : GTMTestCase +@end + +@implementation GTMStackTraceTest ++ (BOOL)classMethodTest { + NSString *stacktrace = GTMStackTrace(); + NSArray *stacklines = [stacktrace componentsSeparatedByString:@"\n"]; + NSString *firstFrame = [stacklines objectAtIndex:0]; + NSRange range = [firstFrame rangeOfString:@"+"]; + return range.location != NSNotFound; +} + +- (void)testStackTraceBasic { + NSString *stacktrace = GTMStackTrace(); + NSArray *stacklines = [stacktrace componentsSeparatedByString:@"\n"]; + + STAssertGreaterThan([stacklines count], (NSUInteger)3, + @"stack trace must have > 3 lines"); + STAssertLessThan([stacklines count], (NSUInteger)25, + @"stack trace must have < 25 lines"); + + NSString *firstFrame = [stacklines objectAtIndex:0]; + NSRange range = [firstFrame rangeOfString:@"testStackTraceBasic"]; + STAssertNotEquals(range.location, (NSUInteger)NSNotFound, + @"First frame should contain testStackTraceBasic," + " stack trace: %@", stacktrace); + range = [firstFrame rangeOfString:@"#0"]; + STAssertNotEquals(range.location, (NSUInteger)NSNotFound, + @"First frame should contain #0, stack trace: %@", + stacktrace); + + range = [firstFrame rangeOfString:@"-"]; + STAssertNotEquals(range.location, (NSUInteger)NSNotFound, + @"First frame should contain - since it's " + @"an instance method: %@", stacktrace); + STAssertTrue([[self class] classMethodTest], @"First frame should contain" + @"+ since it's a class method"); +} + +-(void)testGetStackAddressDescriptors { + struct GTMAddressDescriptor descs[100]; + size_t depth = sizeof(descs) / sizeof(struct GTMAddressDescriptor); + depth = GTMGetStackAddressDescriptors(descs, depth); + // Got atleast 4... + STAssertGreaterThan(depth, (size_t)4, nil); + // All that we got have symbols + for (NSUInteger lp = 0 ; lp < depth ; ++lp) { + STAssertNotNULL(descs[lp].symbol, @"didn't get a symble at depth %lu", lp); + } + + // Do it again, but don't give it enough space (to make sure it handles that) + size_t fullDepth = depth; + STAssertGreaterThan(fullDepth, (size_t)4, nil); + depth -= 2; + depth = GTMGetStackAddressDescriptors(descs, depth); + STAssertLessThan(depth, fullDepth, nil); + // All that we got have symbols + for (NSUInteger lp = 0 ; lp < depth ; ++lp) { + STAssertNotNULL(descs[lp].symbol, @"didn't get a symble at depth %lu", lp); + } + +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + +- (void)helperThatThrows { + [NSException raise:@"TestException" format:@"TestExceptionDescription"]; +} + +- (void)testStackExceptionTrace { + NSException *exception = nil; + @try { + [self helperThatThrows]; + } + @catch (NSException * e) { + exception = e; + } + STAssertNotNil(exception, nil); + NSString *stacktrace = GTMStackTraceFromException(exception); + NSArray *stacklines = [stacktrace componentsSeparatedByString:@"\n"]; + + STAssertGreaterThan([stacklines count], (NSUInteger)4, + @"stack trace must have > 4 lines"); + STAssertLessThan([stacklines count], (NSUInteger)25, + @"stack trace must have < 25 lines"); + STAssertEquals([stacklines count], + [[exception callStackReturnAddresses] count], + @"stack trace should have the same number of lines as the " + @" array of return addresses. stack trace: %@", stacktrace); + + // we can't look for it on a specific frame because NSException doesn't + // really document how deep the stack will be + NSRange range = [stacktrace rangeOfString:@"testStackExceptionTrace"]; + STAssertNotEquals(range.location, (NSUInteger)NSNotFound, + @"Stack trace should contain testStackExceptionTrace," + " stack trace: %@", stacktrace); +} + +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +- (void)testProgramCountersBasic { + void *pcs[10]; + NSUInteger depth = 10; + depth = GTMGetStackProgramCounters(pcs, depth); + + STAssertGreaterThan(depth, (NSUInteger)3, @"stack trace must have > 3 lines"); + STAssertLessThanOrEqual(depth, (NSUInteger)10, + @"stack trace must have < 10 lines"); + + // pcs is an array of program counters from the stack. pcs[0] should match + // the call into GTMGetStackProgramCounters, which is tough for us to check. + // However, we can verify that pcs[1] is equal to our current return address + // for our current function. + void *current_pc = __builtin_return_address(0); + STAssertEquals(pcs[1], current_pc, @"pcs[1] should equal the current PC"); +} + +- (void)testProgramCountersMore { + void *pcs0[0]; + NSUInteger depth0 = 0; + depth0 = GTMGetStackProgramCounters(pcs0, depth0); + STAssertEquals(depth0, (NSUInteger)0, @"stack trace must have 0 lines"); + + void *pcs1[1]; + NSUInteger depth1 = 1; + depth1 = GTMGetStackProgramCounters(pcs1, depth1); + STAssertEquals(depth1, (NSUInteger)1, @"stack trace must have 1 lines"); + + void *pcs2[2]; + NSUInteger depth2 = 2; + depth2 = GTMGetStackProgramCounters(pcs2, depth2); + STAssertEquals(depth2, (NSUInteger)2, @"stack trace must have 2 lines"); + void *current_pc = __builtin_return_address(0); + STAssertEquals(pcs2[1], current_pc, @"pcs[1] should equal the current PC"); +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.h new file mode 100644 index 00000000..07580a77 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.h @@ -0,0 +1,86 @@ +// +// GTMSystemVersion.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" + +// A class for getting information about what system we are running on +@interface GTMSystemVersion : NSObject + +// Returns the current system version major.minor.bugFix ++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix; + +// Returns the build number of the OS. Useful when looking for bug fixes +// in new OSes which all have a set system version. +// eg 10.5.5's build number is 9F33. Easy way to check the build number +// is to choose "About this Mac" from the Apple menu and click on the version +// number. ++ (NSString*)build; + ++ (BOOL)isBuildLessThan:(NSString*)build; ++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build; ++ (BOOL)isBuildGreaterThan:(NSString*)build; ++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build; ++ (BOOL)isBuildEqualTo:(NSString *)build; + +#if GTM_MACOS_SDK +// Returns YES if running on 10.3, NO otherwise. ++ (BOOL)isPanther; + +// Returns YES if running on 10.4, NO otherwise. ++ (BOOL)isTiger; + +// Returns YES if running on 10.5, NO otherwise. ++ (BOOL)isLeopard; + +// Returns YES if running on 10.6, NO otherwise. ++ (BOOL)isSnowLeopard; + +// Returns a YES/NO if the system is 10.3 or better ++ (BOOL)isPantherOrGreater; + +// Returns a YES/NO if the system is 10.4 or better ++ (BOOL)isTigerOrGreater; + +// Returns a YES/NO if the system is 10.5 or better ++ (BOOL)isLeopardOrGreater; + +// Returns a YES/NO if the system is 10.6 or better ++ (BOOL)isSnowLeopardOrGreater; +#endif // GTM_MACOS_SDK + +// Returns one of the achitecture strings below. Note that this is the +// architecture that we are currently running as, not the hardware architecture. ++ (NSString *)runtimeArchitecture; +@end + +// Architecture Strings +// TODO: Should probably break iPhone up into iPhone_ARM and iPhone_Simulator +// but haven't found a need yet. +GTM_EXTERN NSString *const kGTMArch_iPhone; +GTM_EXTERN NSString *const kGTMArch_ppc; +GTM_EXTERN NSString *const kGTMArch_ppc64; +GTM_EXTERN NSString *const kGTMArch_x86_64; +GTM_EXTERN NSString *const kGTMArch_i386; + +// System Build Number constants +GTM_EXTERN NSString *const kGTMSystemBuild10_5_5; +GTM_EXTERN NSString *const kGTMSystemBuild10_6_0_WWDC; +GTM_EXTERN NSString *const kGTMSystemBuild10_6_0_10A190; + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.m new file mode 100644 index 00000000..eb255a67 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.m @@ -0,0 +1,232 @@ +// +// GTMSystemVersion.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSystemVersion.h" +#import "GTMGarbageCollection.h" +#if GTM_MACOS_SDK +#import +#endif + +static SInt32 sGTMSystemVersionMajor = 0; +static SInt32 sGTMSystemVersionMinor = 0; +static SInt32 sGTMSystemVersionBugFix = 0; +static NSString *sBuild = nil; + +NSString *const kGTMArch_iPhone = @"iPhone"; +NSString *const kGTMArch_ppc = @"ppc"; +NSString *const kGTMArch_ppc64 = @"ppc64"; +NSString *const kGTMArch_x86_64 = @"x86_64"; +NSString *const kGTMArch_i386 = @"i386"; + +static NSString *const kSystemVersionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist"; + +NSString *const kGTMSystemBuild10_5_5 = @"9F33"; +NSString *const kGTMSystemBuild10_6_0_WWDC = @"10A96"; +NSString *const kGTMSystemBuild10_6_0_10A190 = @"10A190"; + +@implementation GTMSystemVersion ++ (void)initialize { + if (self == [GTMSystemVersion class]) { + // Gestalt is the recommended way of getting the OS version (despite a + // comment to the contrary in the 10.4 headers and docs; see + // ). + // The iPhone doesn't have Gestalt though, so use the plist there. +#if GTM_MACOS_SDK + require_noerr(Gestalt(gestaltSystemVersionMajor, &sGTMSystemVersionMajor), failedGestalt); + require_noerr(Gestalt(gestaltSystemVersionMinor, &sGTMSystemVersionMinor), failedGestalt); + require_noerr(Gestalt(gestaltSystemVersionBugFix, &sGTMSystemVersionBugFix), failedGestalt); + + return; + + failedGestalt: + ; +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3 + // gestaltSystemVersionMajor et al are only on 10.4 and above, so they + // could fail when running on 10.3. + SInt32 binaryCodedDec; + OSStatus err = err = Gestalt(gestaltSystemVersion, &binaryCodedDec); + _GTMDevAssert(!err, @"Unable to get version from Gestalt"); + + // Note that this code will return x.9.9 for any system rev parts that are + // greater than 9 (i.e., 10.10.10 will be 10.9.9). This shouldn't ever be a + // problem as the code above takes care of 10.4+. + SInt32 msb = (binaryCodedDec & 0x0000F000L) >> 12; + msb *= 10; + SInt32 lsb = (binaryCodedDec & 0x00000F00L) >> 8; + sGTMSystemVersionMajor = msb + lsb; + sGTMSystemVersionMinor = (binaryCodedDec & 0x000000F0L) >> 4; + sGTMSystemVersionBugFix = (binaryCodedDec & 0x0000000FL); +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3 + +#else // GTM_MACOS_SDK + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSDictionary *systemVersionPlist + = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath]; + NSString *version = [systemVersionPlist objectForKey:@"ProductVersion"]; + _GTMDevAssert(version, @"Unable to get version"); + NSArray *versionInfo = [version componentsSeparatedByString:@"."]; + NSUInteger length = [versionInfo count]; + _GTMDevAssert(length > 1 && length < 4, + @"Unparseable version %@", version); + sGTMSystemVersionMajor = [[versionInfo objectAtIndex:0] intValue]; + _GTMDevAssert(sGTMSystemVersionMajor != 0, + @"Unknown version for %@", version); + sGTMSystemVersionMinor = [[versionInfo objectAtIndex:1] intValue]; + if (length == 3) { + sGTMSystemVersionBugFix = [[versionInfo objectAtIndex:2] intValue]; + } + [pool release]; +#endif // GTM_MACOS_SDK + } +} + ++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix { + if (major) { + *major = sGTMSystemVersionMajor; + } + if (minor) { + *minor = sGTMSystemVersionMinor; + } + if (bugFix) { + *bugFix = sGTMSystemVersionBugFix; + } +} + ++ (NSString*)build { + @synchronized(self) { + // Not cached at initialization time because we don't expect "real" + // software to want this, and it costs a bit to get at startup. + // This will mainly be for unit test cases. + if (!sBuild) { + NSDictionary *systemVersionPlist + = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath]; + sBuild = [[systemVersionPlist objectForKey:@"ProductBuildVersion"] retain]; + GTMNSMakeUncollectable(sBuild); + _GTMDevAssert(sBuild, @"Unable to get build version"); + } + } + return sBuild; +} + ++ (BOOL)isBuildLessThan:(NSString*)build { + NSComparisonResult result + = [[self build] compare:build + options:NSNumericSearch | NSCaseInsensitiveSearch]; + return result == NSOrderedAscending; +} + ++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build { + NSComparisonResult result + = [[self build] compare:build + options:NSNumericSearch | NSCaseInsensitiveSearch]; + return result != NSOrderedDescending; +} + ++ (BOOL)isBuildGreaterThan:(NSString*)build { + NSComparisonResult result + = [[self build] compare:build + options:NSNumericSearch | NSCaseInsensitiveSearch]; + return result == NSOrderedDescending; +} + ++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build { + NSComparisonResult result + = [[self build] compare:build + options:NSNumericSearch | NSCaseInsensitiveSearch]; + return result != NSOrderedAscending; +} + ++ (BOOL)isBuildEqualTo:(NSString *)build { + NSComparisonResult result + = [[self build] compare:build + options:NSNumericSearch | NSCaseInsensitiveSearch]; + return result == NSOrderedSame; +} + +#if GTM_MACOS_SDK ++ (BOOL)isPanther { + return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 3; +} + ++ (BOOL)isTiger { + return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 4; +} + ++ (BOOL)isLeopard { + return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 5; +} + ++ (BOOL)isSnowLeopard { + return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 6; +} + ++ (BOOL)isPantherOrGreater { + return (sGTMSystemVersionMajor > 10) || + (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 3); +} + ++ (BOOL)isTigerOrGreater { + return (sGTMSystemVersionMajor > 10) || + (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 4); +} + ++ (BOOL)isLeopardOrGreater { + return (sGTMSystemVersionMajor > 10) || + (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 5); +} + ++ (BOOL)isSnowLeopardOrGreater { + return (sGTMSystemVersionMajor > 10) || + (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 6); +} + +#endif // GTM_MACOS_SDK + ++ (NSString *)runtimeArchitecture { + NSString *architecture = nil; +#if GTM_IPHONE_SDK + architecture = kGTMArch_iPhone; +#else // !GTM_IPHONE_SDK + // In reading arch(3) you'd thing this would work: + // + // const NXArchInfo *localInfo = NXGetLocalArchInfo(); + // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo"); + // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0); + // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo"); + // extensions[0] = [NSString stringWithFormat:@".%s", genericInfo->name]; + // + // but on 64bit it returns the same things as on 32bit, so... +#if __POWERPC__ +#if __LP64__ + architecture = kGTMArch_ppc64; +#else // !__LP64__ + architecture = kGTMArch_ppc; +#endif // __LP64__ +#else // !__POWERPC__ +#if __LP64__ + architecture = kGTMArch_x86_64; +#else // !__LP64__ + architecture = kGTMArch_i386; +#endif // __LP64__ +#endif // !__POWERPC__ + +#endif // GTM_IPHONE_SDK + return architecture; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersionTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersionTest.m new file mode 100644 index 00000000..24e6aa51 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMSystemVersionTest.m @@ -0,0 +1,93 @@ +// +// GTMSystemVersionTest.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMSystemVersion.h" + +@interface GTMSystemVersionTest : GTMTestCase +@end + +@implementation GTMSystemVersionTest +- (void)testBasics { + SInt32 major; + SInt32 minor; + SInt32 bugFix; + + [GTMSystemVersion getMajor:NULL minor:NULL bugFix:NULL]; + [GTMSystemVersion getMajor:&major minor:NULL bugFix:NULL]; + [GTMSystemVersion getMajor:NULL minor:&minor bugFix:NULL]; + [GTMSystemVersion getMajor:NULL minor:NULL bugFix:&bugFix]; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix]; +#if GTM_IPHONE_SDK + STAssertTrue(major >= 2 && minor >= 0 && bugFix >= 0, nil); +#else + STAssertTrue(major >= 10 && minor >= 3 && bugFix >= 0, nil); + BOOL isPanther = (major == 10) && (minor == 3); + BOOL isTiger = (major == 10) && (minor == 4); + BOOL isLeopard = (major == 10) && (minor == 5); + BOOL isSnowLeopard = (major == 10) && (minor == 6); + + BOOL isLater = (major > 10) || ((major == 10) && (minor > 6)); + STAssertEquals([GTMSystemVersion isPanther], isPanther, nil); + STAssertEquals([GTMSystemVersion isPantherOrGreater], + (BOOL)(isPanther || isTiger + || isLeopard || isSnowLeopard || isLater), nil); + STAssertEquals([GTMSystemVersion isTiger], isTiger, nil); + STAssertEquals([GTMSystemVersion isTigerOrGreater], + (BOOL)(isTiger || isLeopard || isSnowLeopard || isLater), nil); + STAssertEquals([GTMSystemVersion isLeopard], isLeopard, nil); + STAssertEquals([GTMSystemVersion isLeopardOrGreater], + (BOOL)(isLeopard || isSnowLeopard || isLater), nil); + STAssertEquals([GTMSystemVersion isSnowLeopard], isSnowLeopard, nil); + STAssertEquals([GTMSystemVersion isSnowLeopardOrGreater], + (BOOL)(isSnowLeopard || isLater), nil); +#endif +} + +- (void)testRuntimeArchitecture { + // Not sure how to test this short of recoding it and verifying. + // This at least executes the code for me. + STAssertNotNil([GTMSystemVersion runtimeArchitecture], nil); +} + +- (void)testBuild { + // Not sure how to test this short of coding up a large fragile table. + // This at least executes the code for me. + NSString *systemVersion = [GTMSystemVersion build]; + STAssertNotEquals([systemVersion length], (NSUInteger)0, nil); + + NSString *smallVersion = @"1A00"; + NSString *largeVersion = @"100Z100"; + STAssertTrue([GTMSystemVersion isBuildGreaterThan:smallVersion], nil); + STAssertFalse([GTMSystemVersion isBuildGreaterThan:systemVersion], nil); + STAssertFalse([GTMSystemVersion isBuildGreaterThan:largeVersion], nil); + STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:smallVersion], nil); + STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:systemVersion], nil); + STAssertFalse([GTMSystemVersion isBuildGreaterThanOrEqualTo:largeVersion], nil); + STAssertFalse([GTMSystemVersion isBuildEqualTo:smallVersion], nil); + STAssertTrue([GTMSystemVersion isBuildEqualTo:systemVersion], nil); + STAssertFalse([GTMSystemVersion isBuildEqualTo:largeVersion], nil); + STAssertFalse([GTMSystemVersion isBuildLessThanOrEqualTo:smallVersion], nil); + STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:systemVersion], nil); + STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:largeVersion], nil); + STAssertFalse([GTMSystemVersion isBuildLessThan:smallVersion], nil); + STAssertFalse([GTMSystemVersion isBuildLessThan:systemVersion], nil); + STAssertTrue([GTMSystemVersion isBuildLessThan:largeVersion], nil); + +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.h new file mode 100644 index 00000000..5dc0a56e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.h @@ -0,0 +1,50 @@ +// +// GTMTransientRootPortProxy.h +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMTransientRootProxy.h" + +@interface GTMTransientRootPortProxy : GTMTransientRootProxy { + @private + NSPort *receivePort_; + NSPort *sendPort_; +} + +// Returns an autoreleased instance. See below for details on args. ++ (id)rootProxyWithReceivePort:(NSPort *)receivePort + sendPort:(NSPort *)sendPort + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout; + +// This function will return a GTMTransientRootProxy that is using NSPorts +// for the connection. The |receivePort| and |sendPort| conventions +// follow the same conventions as -[NSConnection initWithReceivePort:sendPort:]. +// Note that due to Radar 6676818 "NSConnection leaks when initialized with nil +// sendPort" that you will leak a connection if you pass in "nil" for your +// sendPort if you are using NSPorts (mach or socket) to communicate between +// threads. The leak occurs on 10.5.6, and SL 10A286. This simple answer +// is just to always use two ports to communicate. Check out the test to see +// how we do cross thread communication. +- (id)initWithReceivePort:(NSPort *)receivePort + sendPort:(NSPort *)sendPort + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.m new file mode 100644 index 00000000..ee9093a1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxy.m @@ -0,0 +1,80 @@ +// +// GTMTransientRootPortProxy.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMTransientRootPortProxy.h" +#import "GTMObjC2Runtime.h" + +@interface GTMTransientRootPortProxy (ProtectedMethods) +// Returns an NSConnection for NSPorts. This method overrides the one in +// the GTMTransientRootProxy which allows us to create a connection with a +// NSPort. +// +- (NSConnection *)makeConnection; +@end + + +@implementation GTMTransientRootPortProxy + ++ (id)rootProxyWithReceivePort:(NSPort *)receivePort + sendPort:(NSPort *)sendPort + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout { + return [[[self alloc] initWithReceivePort:receivePort + sendPort:sendPort + protocol:protocol + requestTimeout:requestTimeout + replyTimeout:replyTimeout] autorelease]; +} + +- (id)initWithReceivePort:(NSPort *)receivePort + sendPort:(NSPort *)sendPort + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout { + if ((!sendPort && !receivePort) || !protocol) { + [self release]; + return nil; + } + + requestTimeout_ = requestTimeout; + replyTimeout_ = replyTimeout; + + receivePort_ = [receivePort retain]; + sendPort_ = [sendPort retain]; + + protocol_ = protocol; // Protocols can't be retained + return self; +} + +- (void)dealloc { + [receivePort_ release]; + [sendPort_ release]; + [super dealloc]; +} + +@end + +@implementation GTMTransientRootPortProxy (ProtectedMethods) + +- (NSConnection *)makeConnection { + return [NSConnection connectionWithReceivePort:receivePort_ + sendPort:sendPort_]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxyTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxyTest.m new file mode 100644 index 00000000..a85498f8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootPortProxyTest.m @@ -0,0 +1,182 @@ +// +// GTMTransientRootPortProxyTest.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMTransientRootPortProxy.h" + +#define kDefaultTimeout 5.0 + +enum { + kGTMTransientThreadConditionStarting = 777, + kGTMTransientThreadConditionStarted, + kGTMTransientThreadConditionQuitting, + kGTMTransientThreadConditionQuitted +}; + +// === Start off declaring some auxillary data structures === + +// The @protocol that we'll use for testing with. +@protocol DOPortTestProtocol +- (oneway void)doOneWayVoid; +- (bycopy NSString *)doReturnStringBycopy; +@end + +// The "server" we'll use to test the DO connection. This server will implement +// our test protocol, and it will run in a separate thread from the main +// unit testing thread, so the DO requests can be serviced. +@interface DOPortTestServer : NSObject { + @private + NSPort *clientSendPort_; + NSPort *clientReceivePort_; +} +- (void)runThread:(NSConditionLock *)lock; +- (NSPort *)clientSendPort; +- (NSPort *)clientReceivePort; +@end + +@implementation DOPortTestServer + +- (void)runThread:(NSConditionLock *)lock { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + if(![lock lockWhenCondition:kGTMTransientThreadConditionStarting + beforeDate:future]) { + _GTMDevLog(@"Unable to acquire lock in runThread! This is BAD!"); + [pool drain]; + [NSThread exit]; + } + + clientSendPort_ = [NSPort port]; + clientReceivePort_ = [NSPort port]; + + NSConnection *conn + = [[NSConnection alloc] initWithReceivePort:clientSendPort_ + sendPort:clientReceivePort_]; + [conn setRootObject:self]; + [lock unlockWithCondition:kGTMTransientThreadConditionStarted]; + while (![lock tryLockWhenCondition:kGTMTransientThreadConditionQuitting]) { + NSDate *runUntil = [NSDate dateWithTimeIntervalSinceNow:0.1]; + [[NSRunLoop currentRunLoop] runUntilDate:runUntil]; + } + [conn setRootObject:nil]; + [clientSendPort_ invalidate]; + [clientReceivePort_ invalidate]; + [conn release]; + [pool drain]; + [lock unlockWithCondition:kGTMTransientThreadConditionQuitted]; +} + +- (NSPort *)clientSendPort { + return clientSendPort_; +} + +- (NSPort *)clientReceivePort { + return clientReceivePort_; +} + +- (oneway void)doOneWayVoid { + // Do nothing +} +- (bycopy NSString *)doReturnStringBycopy { + return @"TestString"; +} + +@end + +// === Done with auxillary data structures, now for the main test class === + +@interface GTMTransientRootPortProxyTest : GTMTestCase { + DOPortTestServer *server_; + NSConditionLock *syncLock_; +} + +@end + +@implementation GTMTransientRootPortProxyTest + +- (void)testTransientRootPortProxy { + syncLock_ = [[[NSConditionLock alloc] + initWithCondition:kGTMTransientThreadConditionStarting] + autorelease]; + + // Setup our server. + server_ = [[[DOPortTestServer alloc] init] autorelease]; + [NSThread detachNewThreadSelector:@selector(runThread:) + toTarget:server_ + withObject:syncLock_]; + NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionStarted + beforeDate:future], + @"Unable to start thread"); + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionStarted]; + + NSPort *receivePort = [server_ clientReceivePort]; + NSPort *sendPort = [server_ clientSendPort]; + + GTMTransientRootPortProxy *failProxy = + [GTMTransientRootPortProxy rootProxyWithReceivePort:nil + sendPort:nil + protocol:@protocol(DOPortTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertNil(failProxy, @"should have failed w/o a port"); + failProxy = + [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort + sendPort:sendPort + protocol:nil + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertNil(failProxy, @"should have failed w/o a protocol"); + + GTMTransientRootPortProxy *proxy = + [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort + sendPort:sendPort + protocol:@protocol(DOPortTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + + STAssertEqualObjects([proxy doReturnStringBycopy], + @"TestString", @"proxy should have returned " + @"'TestString'"); + + // Redo the *exact* same test to make sure we can have multiple instances + // in the same app. + proxy = + [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort + sendPort:sendPort + protocol:@protocol(DOPortTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + + STAssertEqualObjects([proxy doReturnStringBycopy], + @"TestString", @"proxy should have returned " + @"'TestString'"); + [syncLock_ tryLockWhenCondition:kGTMTransientThreadConditionStarted]; + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitting]; + + // Wait for the server to shutdown so we clean up nicely. + // The max amount of time we will wait until we abort this test. + NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + // The server did not shutdown and we want to capture this as an error + STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionQuitted + beforeDate:timeout], + @"The server did not shutdown gracefully before the timeout."); + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitted]; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.h new file mode 100644 index 00000000..b5aa78af --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.h @@ -0,0 +1,113 @@ +// +// GTMTransientRootProxy.h +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// Handle (re-)connecting to a transient root proxy object via DO. +// +// This class is designed to handle connecting and reconnecting to a Distributed +// Objects root proxy (NSDistantObject* instance). It is a replacement for using +// the NSDistantObject returned from NSConnection, directly. When the DO +// connection is up, messages sent to this class are forwarded to the real +// object (the NSDistantObject); when the DO connection is down, messages sent +// to this class are silently swallowed. You can use the -isConnected method on +// this class to see if the DO connection is up or down. +// +// This class may be useful when you need a DO connection, but the +// server you're connected to may be going up and down. For example, the +// web browser plugins in Google Desktop may need to connect to the Google +// Desktop local webserver, but we'd want the browser plugins to be able to +// gracefully handle the local Google Desktop webserver starting and stopping. +// +// === Example Usage === +// +// Old code: +// +// NSDistantObject *o = +// [NSConnection rootProxyForConnectionWithRegisteredName:@"server" +// host:nil]; +// [o setProtocolForProxy:@protocol(MyProto)]; +// [o someMethodInMyProto]; +// // ... write a bunch of code to handle error conditions +// +// New code: +// +// GTMTransientRootProxy *o = +// [GTMTransientRootProxy rootProxyWithRegisteredName:@"server" +// host:nil +// protocol:@protocol(MyProto) +// requestTimeout:5.0 +// replyTimeout:5.0]; +// [o someMethodInMyProto]; +// +// The 'Old code' requires you to handle all the error conditions that may +// arise when using DO (such as the server crashing, or network going down), +// handle properly tearing down the broken connection, and trying to reconnect +// when the server finally comes back online. The 'New code' handles all of +// those details for you. +// +// Also, when creating a GMTransientRootProxy object, you must tell it the +// @protocol that will be used for communication - this is not optional. And +// in order to quiet compiler warnings, you'll also want to staticly type +// the pointer with the protocol as well. +// +@interface GTMTransientRootProxy : NSProxy { + @protected + __weak Protocol *protocol_; + NSDistantObject *realProxy_; + + NSString *registeredName_; + NSString *host_; + + NSTimeInterval requestTimeout_; + NSTimeInterval replyTimeout_; +} + +// Returns an autoreleased instance ++ (id)rootProxyWithRegisteredName:(NSString *)name + host:(NSString *)host + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout; + +// This function will return a GTMTransientRootProxy that is using Mach ports +// for the connection. The |name| and |host| arguments will be used to lookup +// the correct information to create the Mach port connection. +// +- (id)initWithRegisteredName:(NSString *)name + host:(NSString *)host + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout; + +// Returns YES if the DO connection is up and working, NO otherwise. +// +- (BOOL)isConnected; + +@end + +// Subclass of GTMTransientRootProxy that catches and ignores ALL exceptions. +// This class overrides GTMTransientRootProxy's -forwardInvocation: +// method, and wraps it in a try/catch block, and ignores all exceptions. +// +@interface GTMRootProxyCatchAll : GTMTransientRootProxy + +// Overridden, and ignores all thrown exceptions. +- (void)forwardInvocation:(NSInvocation *)invocation; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.m new file mode 100644 index 00000000..04591d38 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxy.m @@ -0,0 +1,229 @@ +// +// GTMTransientRootProxy.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMTransientRootProxy.h" +#import "GTMObjC2Runtime.h" + +// Private methods on NSMethodSignature that we need to call. This method has +// been available since 10.0, but Apple didn't add it to the headers until 10.5 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 +@interface NSMethodSignature (UndeclaredMethods) ++ (NSMethodSignature *)signatureWithObjCTypes:(const char *)types; +@end +#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 + +@interface GTMTransientRootProxy (PrivateMethods) +// Returns an NSConnection for NSMacPorts. This method is broken out to allow +// subclasses to override it to generate different types of NSConnections. +- (NSConnection *)makeConnection; + +// Returns the "real" proxy (stored in the realProxy_ ivar) associated with this +// instance. If realProxy_ is nil, then an attempt is made to make a connection +// to create the realProxy_. +// +- (NSDistantObject *)realProxy; + +// "Releases" the realProxy_ ivar, and removes |self| as an observer from +// the NSNotificationCenter. +// +- (void)releaseRealProxy; +@end + +@implementation GTMTransientRootProxy + ++ (id)rootProxyWithRegisteredName:(NSString *)name + host:(NSString *)host + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout { + return [[[self alloc] initWithRegisteredName:name + host:host + protocol:protocol + requestTimeout:requestTimeout + replyTimeout:replyTimeout] autorelease]; +} + +- (id)initWithRegisteredName:(NSString *)name + host:(NSString *)host + protocol:(Protocol *)protocol + requestTimeout:(NSTimeInterval)requestTimeout + replyTimeout:(NSTimeInterval)replyTimeout { + if (!name || !protocol) { + [self release]; + return nil; + } + + requestTimeout_ = requestTimeout; + replyTimeout_ = replyTimeout; + + registeredName_ = [name copy]; + host_ = [host copy]; + + protocol_ = protocol; // Protocols can't be retained + + return self; +} + +- (id)init { + return [self initWithRegisteredName:nil + host:nil + protocol:nil + requestTimeout:0.0 + replyTimeout:0.0]; +} + +- (void)dealloc { + [self releaseRealProxy]; + [registeredName_ release]; + [host_ release]; + [super dealloc]; +} + +- (BOOL)isConnected { + BOOL result = NO; + @synchronized (self) { + result = [[[self realProxy] connectionForProxy] isValid]; + } + return result; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + struct objc_method_description mdesc; + mdesc = protocol_getMethodDescription(protocol_, selector, YES, YES); + NSMethodSignature *returnValue = nil; + if (mdesc.types == NULL) { + // COV_NF_START + _GTMDevLog(@"Unable to get the protocol method description. Returning " + @"nil."); + // COV_NF_END + } else { + returnValue = [NSMethodSignature signatureWithObjCTypes:mdesc.types]; + } + return returnValue; +} + +- (void)forwardInvocation:(NSInvocation *)invocation { + @try { + NSDistantObject *target = [self realProxy]; + [invocation invokeWithTarget:target]; + + // We need to catch NSException* here rather than "id" because we need to + // treat |ex| as an NSException when using the -name method. Also, we're + // only looking to catch a few types of exception here, all of which are + // NSException types; the rest we just rethrow. + } @catch (NSException *ex) { + NSString *exName = [ex name]; + // If we catch an exception who's name matches any of the following types, + // it's because the DO connection probably went down. So, we'll just + // release our realProxy_, and attempt to reconnect on the next call. + if ([exName isEqualToString:NSPortTimeoutException] + || [exName isEqualToString:NSInvalidSendPortException] + || [exName isEqualToString:NSInvalidReceivePortException] + || [exName isEqualToString:NSFailedAuthenticationException] + || [exName isEqualToString:NSPortSendException] + || [exName isEqualToString:NSPortReceiveException]) { + [self releaseRealProxy]; // COV_NF_LINE + } else { + // If the exception was any other type (commonly + // NSInvalidArgumentException) then we'll just re-throw it to the caller. + @throw; + } + } // COV_NF_LINE +} + +@end + +@implementation GTMTransientRootProxy (PrivateMethods) + +- (NSConnection *)makeConnection { + return [NSConnection connectionWithRegisteredName:registeredName_ host:host_]; +} + +- (NSDistantObject *)realProxy { + NSDistantObject *returnProxy = nil; + + @synchronized (self) { + // No change so no notification + if (realProxy_) return realProxy_; + + NSConnection *conn = [self makeConnection]; + [conn setRequestTimeout:requestTimeout_]; + [conn setReplyTimeout:replyTimeout_]; + @try { + // Try to get the root proxy for this connection's vended object. + realProxy_ = [conn rootProxy]; + } @catch (id ex) { + // We may fail here if we can't get the root proxy in the amount of time + // specified by the timeout above. This may happen, for example, if the + // server process is stopped (via SIGSTOP). We'll just ignore this, and + // try again at the next message. + [conn invalidate]; + return nil; + } + if (!realProxy_) { + [conn invalidate]; + // Again, no change in connection status + return nil; + } + [realProxy_ retain]; + [realProxy_ setProtocolForProxy:protocol_]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(connectionDidDie:) + name:NSConnectionDidDieNotification + object:conn]; + // Retain/autorelease so it lives at least the duration of this synchronize + returnProxy = [[realProxy_ retain] autorelease]; + } // @synchronized (self) + + return returnProxy; +} + +- (void)connectionDidDie:(NSNotification *)notification { + [self releaseRealProxy]; +} + +- (void)releaseRealProxy { + BOOL connectionChanged = NO; + @synchronized (self) { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + // Only trigger if we had a proxy before + if (realProxy_) { + connectionChanged = YES; + } + [realProxy_ release]; + realProxy_ = nil; + } +} + +@end + +@implementation GTMRootProxyCatchAll + +- (void)forwardInvocation:(NSInvocation *)invocation { + @try { + [super forwardInvocation:invocation]; + } + @catch (id ex) { + // Log for developers, but basically ignore it. + _GTMDevLog(@"Proxy for invoking %@ has caught and is ignoring exception: %@", + NSStringFromSelector([invocation selector]), ex); + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxyTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxyTest.m new file mode 100644 index 00000000..70b69a1b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMTransientRootProxyTest.m @@ -0,0 +1,228 @@ +// +// GMTransientRootProxyTest.m +// +// Copyright 2006-2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMTransientRootProxy.h" +#import "GTMUnitTestDevLog.h" + +#define kDefaultTimeout 5.0 + +// === Start off declaring some auxillary data structures === +static NSString *const kTestServerName = @"gtm_test_server"; +static NSString *const kGTMTransientRootNameKey = @"GTMTransientRootNameKey"; +static NSString *const kGTMTransientRootLockKey = @"GTMTransientRootLockKey"; + +enum { + kGTMTransientThreadConditionStarting = 777, + kGTMTransientThreadConditionStarted, + kGTMTransientThreadConditionQuitting, + kGTMTransientThreadConditionQuitted +}; + +// The @protocol that we'll use for testing with. +@protocol DOTestProtocol +- (oneway void)doOneWayVoid; +- (bycopy NSString *)doReturnStringBycopy; +- (void)throwException; +@end + +// The "server" we'll use to test the DO connection. This server will implement +// our test protocol, and it will run in a separate thread from the main +// unit testing thread, so the DO requests can be serviced. +@interface DOTestServer : NSObject { +} +- (void)runThread:(NSDictionary *)args; +@end + +@implementation DOTestServer + +- (void)runThread:(NSDictionary *)args { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSConditionLock *lock = [args objectForKey:kGTMTransientRootLockKey]; + NSString *serverName = [args objectForKey:kGTMTransientRootNameKey]; + NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + if(![lock lockWhenCondition:kGTMTransientThreadConditionStarting + beforeDate:future]) { + _GTMDevLog(@"Unable to acquire lock in runThread! This is BAD!"); + [pool drain]; + [NSThread exit]; + } + + NSConnection *conn = [NSConnection defaultConnection]; + [conn setRootObject:self]; + if (![conn registerName:serverName]) { + _GTMDevLog(@"Failed to register DO root object with name '%@'", + serverName); + [pool drain]; + [NSThread exit]; + } + [lock unlockWithCondition:kGTMTransientThreadConditionStarted]; + while (![lock tryLockWhenCondition:kGTMTransientThreadConditionQuitting]) { + NSDate* runUntil = [NSDate dateWithTimeIntervalSinceNow:0.1]; + [[NSRunLoop currentRunLoop] runUntilDate:runUntil]; + } + [conn setRootObject:nil]; + [conn registerName:nil]; + [pool drain]; + [lock unlockWithCondition:kGTMTransientThreadConditionQuitted]; +} + +- (oneway void)doOneWayVoid { + // Do nothing +} +- (bycopy NSString *)doReturnStringBycopy { + return @"TestString"; +} + +- (void)throwException { + [NSException raise:@"testingException" format:@"for the unittest"]; +} + +@end + +// === Done with auxillary data structures, now for the main test class === + +@interface GTMTransientRootProxyTest : GTMTestCase { + @private + DOTestServer *server_; + NSConditionLock *syncLock_; +} +@end + +@implementation GTMTransientRootProxyTest + +- (void)testTransientRootProxy { + // Setup our server and create a unqiue server name every time we run + NSTimeInterval timeStamp = [[NSDate date] timeIntervalSinceReferenceDate]; + NSString *serverName = + [NSString stringWithFormat:@"%@_%f", kTestServerName, timeStamp]; + server_ = [[[DOTestServer alloc] init] autorelease]; + syncLock_ = [[[NSConditionLock alloc] + initWithCondition:kGTMTransientThreadConditionStarting] + autorelease]; + NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys: + syncLock_, kGTMTransientRootLockKey, + serverName, kGTMTransientRootNameKey, + nil]; + [NSThread detachNewThreadSelector:@selector(runThread:) + toTarget:server_ + withObject:args]; + NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionStarted + beforeDate:future], + @"Unable to start thread"); + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionStarted]; + + GTMTransientRootProxy *failProxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:nil + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertNil(failProxy, @"should have failed w/o a name"); + failProxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:serverName + host:nil + protocol:nil + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertNil(failProxy, @"should have failed w/o a protocol"); + failProxy = [[[GTMTransientRootProxy alloc] init] autorelease]; + STAssertNil(failProxy, @"should have failed just calling init"); + + GTMTransientRootProxy *proxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:serverName + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + + STAssertEqualObjects([proxy doReturnStringBycopy], @"TestString", + @"proxy should have returned 'TestString'"); + + // Redo the *exact* same test to make sure we can have multiple instances + // in the same app. + proxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:serverName + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertEqualObjects([proxy doReturnStringBycopy], + @"TestString", @"proxy should have returned " + @"'TestString'"); + + // Test the GTMRootProxyCatchAll within this test so we don't have to rebuild + // the server again. + + GTMRootProxyCatchAll *catchProxy = + [GTMRootProxyCatchAll rootProxyWithRegisteredName:serverName + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + + [GTMUnitTestDevLog expectString:@"Proxy for invoking throwException has " + @"caught and is ignoring exception: [NOTE: this exception originated in " + @"the server.]\nfor the unittest"]; + id e = nil; + @try { + // Has the server throw an exception + [catchProxy throwException]; + } @catch (id ex) { + e = ex; + } + STAssertNil(e, @"The GTMRootProxyCatchAll did not catch the exception: %@.", + e); + + proxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:@"FAKE_SERVER" + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:kDefaultTimeout + replyTimeout:kDefaultTimeout]; + STAssertNotNil(proxy, @"proxy shouldn't be nil, even when registered w/ a " + @"fake server"); + STAssertFalse([proxy isConnected], @"the proxy shouldn't be connected due to " + @"the fake server"); + + // Now set up a proxy, and then kill our server. We put a super short time + // out on it, because we are expecting it to fail. + proxy = + [GTMTransientRootProxy rootProxyWithRegisteredName:serverName + host:nil + protocol:@protocol(DOTestProtocol) + requestTimeout:0.01 + replyTimeout:0.01]; + [syncLock_ tryLockWhenCondition:kGTMTransientThreadConditionStarted]; + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitting]; + + // Wait for the server to shutdown so we clean up nicely. + // The max amount of time we will wait until we abort this test. + NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout]; + // The server did not shutdown and we want to capture this as an error + STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionQuitted + beforeDate:timeout], + @"The server did not shutdown gracefully before the timeout."); + [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitted]; + + // This should fail gracefully because the server is dead. + STAssertNil([proxy doReturnStringBycopy], @"proxy should have returned nil"); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.h new file mode 100644 index 00000000..e53b541b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.h @@ -0,0 +1,196 @@ +// +// GTMValidatingContainers.h +// +// Mutable containers that do verification of objects being added to them +// at runtime. Support for arrays, dictionaries and sets. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// GTMValidatingContainers are a set of mutable container classes that allow +// you to have a selector on a target that is called to verify that the objects +// being put into the container are valid. This can be controlled at compile +// time so that you don't take the performance hit in a release build using the +// GTM_CONTAINERS_VALIDATE macro. +// We have supplied validators for simple cases such as kindOfClass or +// conformsToProtocol. See GTMKindOfClassValidator et al. for details. +// +// Example of usage: +// id target = [GTMKindOfClassValidator validateAgainstClass:[NSString class]]; +// SEL selector = @selector(validateObject:forContainer:); +// GTMValidatingArray *array = [GTMValidatingArray validatingArrayWithTarget:target +// selector:selector]; +// [array addObject:@"foo"]; // Will be good +// [array addObject:[NSNumber numberWithInt:2]]; // Will fail +// +// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and +// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens +// when a validation fails. If you implement your own validators, you may want +// to control their internals using the same macros for consistency. +// +// Note that the validating collection types retain their targets. + +#import +#import "GTMDefines.h" + +// By default we only validate containers in debug. If you want to validate +// in release as well, #define GTM_CONTAINERS_VALIDATE in a prefix or build +// settings. +#ifndef GTM_CONTAINERS_VALIDATE +#if DEBUG +#define GTM_CONTAINERS_VALIDATE 1 +#else // DEBUG +#define GTM_CONTAINERS_VALIDATE 0 +#endif // DEBUG +#endif // GTM_CONTAINERS_VALIDATE + +// If GTM_CONTAINERS_VALIDATE is on, and log and assert are both turned off +// (see below), the object that failed validation will just not be added +// to the container. + +// If you don't want log to occur on validation failure define +// GTM_CONTAINERS_VALIDATION_FAILED_LOG to 0 in a prefix or build settings. +#ifndef GTM_CONTAINERS_VALIDATION_FAILED_LOG +#define GTM_CONTAINERS_VALIDATION_FAILED_LOG GTM_CONTAINERS_VALIDATE +#endif // GTM_CONTAINERS_VALIDATION_FAILED_LOG + +// If you don't want an assert to occur on validation failure define +// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT to 0 in a prefix or build settings. +#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT GTM_CONTAINERS_VALIDATE +#endif // GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + +// Sometimes you get a container back from somebody else and want to validate +// that it contains what you think it contains. _GTMValidateContainer +// allows you to do exactly that. _GTMValidateContainer... give you specialty +// functions for doing common types of validations. These all inline to nothing +// if GTM_CONTAINERS_VALIDATE is not defined. +#if GTM_CONTAINERS_VALIDATE +void _GTMValidateContainer(id container, id target, SEL selector); +void _GTMValidateContainerContainsKindOfClass(id container, Class cls); +void _GTMValidateContainerContainsMemberOfClass(id container, Class cls); +void _GTMValidateContainerConformsToProtocol(id container, Protocol *prot); +void _GTMValidateContainerItemsRespondToSelector(id container, SEL sel); +#else +GTM_INLINE void _GTMValidateContainer(id container, id target, SEL selector) { +} +GTM_INLINE void _GTMValidateContainerContainsKindOfClass(id container, + Class cls) { +} +GTM_INLINE void _GTMValidateContainerContainsMemberOfClass(id container, + Class cls) { +} +GTM_INLINE void _GTMValidateContainerConformsToProtocol(id container, + Protocol *prot) { +} +GTM_INLINE void _GTMValidateContainerItemsRespondToSelector(id container, + SEL sel) { +} +#endif + + +// See comments near top of file for class description. +@interface GTMValidatingArray : NSMutableArray { +#if GTM_CONTAINERS_VALIDATE + NSMutableArray *embeddedContainer_; + id target_; + SEL selector_; +#endif // #if GTM_CONTAINERS_VALIDATE +} ++ (id)validatingArrayWithTarget:(id)target selector:(SEL)sel; ++ (id)validatingArrayWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel; +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +@end + +// See comments near top of file for class description. +@interface GTMValidatingDictionary : NSMutableDictionary { +#if GTM_CONTAINERS_VALIDATE + NSMutableDictionary *embeddedContainer_; + id target_; + SEL selector_; +#endif // #if GTM_CONTAINERS_VALIDATE +} ++ (id)validatingDictionaryWithTarget:(id)target selector:(SEL)sel; ++ (id)validatingDictionaryWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel; +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +@end + +// See comments near top of file for class description. +@interface GTMValidatingSet : NSMutableSet { +#if GTM_CONTAINERS_VALIDATE + NSMutableSet *embeddedContainer_; + id target_; + SEL selector_; +#endif // #if GTM_CONTAINERS_VALIDATE +} ++ (id)validatingSetWithTarget:(id)target selector:(SEL)sel; ++ (id)validatingSetWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel; +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel; +@end + +#pragma mark - +#pragma mark Simple Common Validators +// See comments near top of file for examples of how these are used. +@protocol GTMContainerValidatorProtocol +- (BOOL)validateObject:(id)object forContainer:(id)container; +@end + +// Validates that a given object is a kind of class (instance of class or an +// instance of any class that inherits from that class) +@interface GTMKindOfClassValidator : NSObject { + Class cls_; +} ++ (id)validateAgainstClass:(Class)cls; +- (id)initWithClass:(Class)cls; +@end + +// Validates that a given object is a member of class (exact instance of class) +@interface GTMMemberOfClassValidator : NSObject { + Class cls_; +} ++ (id)validateAgainstClass:(Class)cls; +- (id)initWithClass:(Class)cls; +@end + +// Validates that a given object conforms to a protocol +@interface GTMConformsToProtocolValidator : NSObject { + Protocol* prot_; +} ++ (id)validateAgainstProtocol:(Protocol*)prot; +- (id)initWithProtocol:(Protocol*)prot; +@end + +// Validates that a given object responds to a given selector +@interface GTMRespondsToSelectorValidator : NSObject { + SEL sel_; +} ++ (id)validateAgainstSelector:(SEL)sel; +- (id)initWithSelector:(SEL)sel; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.m new file mode 100644 index 00000000..3b313564 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainers.m @@ -0,0 +1,490 @@ +// +// GTMValidatingContainers.m +// +// Mutable containers that do verification of objects being added to them +// at runtime. Support for arrays, dictionaries and sets. +// +// Documentation on subclassing class clusters (which we are doing) is here: +// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_9.html#//apple_ref/doc/uid/TP40002974-CH4-DontLinkElementID_105 +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMValidatingContainers.h" + +#if GTM_CONTAINERS_VALIDATE + +#import "GTMDebugSelectorValidation.h" +#if GTM_IPHONE_SDK +#import +#import +#else // GTM_IPHONE_SDK +#import +#endif // GTM_IPHONE_SDK + +GTM_INLINE BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject, + id target, + SEL selector, + id container) { + // We must take care here, since Intel leaves junk in high bytes of return + // register for predicates that return BOOL. + // For details see: + // http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html + // and + // http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187 + BOOL isGood = ((BOOL (*)(id, SEL, id, id))objc_msgSend)(target, selector, + anObject, container); + if (!isGood) { +#if GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + _GTMDevAssert(isGood, @"%@ failed container verification for %@", + anObject, [container description]); +#endif // GTM_CONTAINERS_VALIDATION_FAILED_LOG +#if GTM_CONTAINERS_VALIDATION_FAILED_LOG + _GTMDevLog(@"%@ failed container verification for %@", anObject, + [container description]); +#endif // GTM_CONTAINERS_VALIDATION_FAILED_LOG + } + return isGood; +} + +GTM_INLINE void VerifySelectorOnTarget(SEL sel, id target) { + GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target, + sel, + @encode(BOOL), + @encode(id), + @encode(id), + nil); +} + +void _GTMValidateContainerContainsKindOfClass(id container, Class cls) { + GTMKindOfClassValidator *validator; + validator = [GTMKindOfClassValidator validateAgainstClass:cls]; + _GTMValidateContainer(container, + validator, + @selector(validateObject:forContainer:)); +} + +void _GTMValidateContainerContainsMemberOfClass(id container, Class cls) { + GTMMemberOfClassValidator *validator; + validator = [GTMMemberOfClassValidator validateAgainstClass:cls]; + _GTMValidateContainer(container, + validator, + @selector(validateObject:forContainer:)); +} + +void _GTMValidateContainerConformsToProtocol(id container, Protocol* prot) { + GTMConformsToProtocolValidator *validator; + validator = [GTMConformsToProtocolValidator validateAgainstProtocol:prot]; + _GTMValidateContainer(container, + validator, + @selector(validateObject:forContainer:)); +} + +void _GTMValidateContainerItemsRespondToSelector(id container, SEL sel) { + GTMRespondsToSelectorValidator *validator; + validator = [GTMRespondsToSelectorValidator validateAgainstSelector:sel]; + _GTMValidateContainer(container, + validator, + @selector(validateObject:forContainer:)); +} + +void _GTMValidateContainer(id container, id target, SEL selector) { + if ([container respondsToSelector:@selector(objectEnumerator)]) { + NSEnumerator *enumerator = [container objectEnumerator]; + id val; + while ((val = [enumerator nextObject])) { + VerifyObjectWithTargetAndSelectorForContainer(val, + target, + selector, + container); + } + } else { +#if GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + _GTMDevAssert(0, @"container %@ does not respond to -objectEnumerator", + [container description]); +#endif // GTM_CONTAINERS_VALIDATION_FAILED_LOG +#if GTM_CONTAINERS_VALIDATION_FAILED_LOG + _GTMDevLog(@"container does not respont to -objectEnumerator: %@", + [container description]); +#endif // GTM_CONTAINERS_VALIDATION_FAILED_LOG + } +} +#endif // GTM_CONTAINERS_VALIDATE + +@implementation GTMValidatingArray + ++ (id)validatingArrayWithTarget:(id)target selector:(SEL)sel { + return [self validatingArrayWithCapacity:0 target:target selector:sel]; +} + ++ (id)validatingArrayWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + return [[[[self class] alloc] initValidatingWithCapacity:0 + target:target + selector:sel] autorelease]; +} + +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel { + return [self initValidatingWithCapacity:0 target:target selector:sel]; +} + +#if GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + embeddedContainer_ = [[NSMutableArray alloc] initWithCapacity:capacity]; + target_ = [target retain]; + selector_ = sel; + VerifySelectorOnTarget(selector_, target_); + } + return self; +} + +- (void)dealloc { + [embeddedContainer_ release]; + [target_ release]; + [super dealloc]; +} + +- (NSUInteger)count { + return [embeddedContainer_ count]; +} + +- (id)objectAtIndex:(NSUInteger)idx { + return [embeddedContainer_ objectAtIndex:idx]; +} + +- (void)addObject:(id)anObject { + if (VerifyObjectWithTargetAndSelectorForContainer(anObject, target_, + selector_, self)) { + [embeddedContainer_ addObject:anObject]; + } +} + +- (void)insertObject:(id)anObject atIndex:(NSUInteger)idx { + if (VerifyObjectWithTargetAndSelectorForContainer(anObject, target_, + selector_, self)) { + [embeddedContainer_ insertObject:anObject atIndex:idx]; + } +} + +- (void)removeLastObject { + [embeddedContainer_ removeLastObject]; +} + +- (void)removeObjectAtIndex:(NSUInteger)idx { + [embeddedContainer_ removeObjectAtIndex:idx]; +} + +- (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)anObject { + if (VerifyObjectWithTargetAndSelectorForContainer(anObject, target_, + selector_, self)) { + [embeddedContainer_ replaceObjectAtIndex:idx withObject:anObject]; + } +} + +- (NSString*)description { + return [NSString stringWithFormat:@"%@ - %@", + NSStringFromClass([self class]), + [embeddedContainer_ description]]; +} + +#else // GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + [self release]; + } + return [[NSMutableArray alloc] initWithCapacity:capacity]; +} +#endif // GTM_CONTAINERS_VALIDATE +@end + +@implementation GTMValidatingDictionary ++ (id)validatingDictionaryWithTarget:(id)target selector:(SEL)sel { + return [self validatingDictionaryWithCapacity:0 target:target selector:sel]; +} + ++ (id)validatingDictionaryWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + return [[[[self class] alloc] initValidatingWithCapacity:0 + target:target + selector:sel] autorelease]; +} + +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel { + return [self initValidatingWithCapacity:0 target:target selector:sel]; +} + +#if GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + embeddedContainer_ = [[NSMutableDictionary alloc] initWithCapacity:capacity]; + target_ = [target retain]; + selector_ = sel; + VerifySelectorOnTarget(selector_, target_); + } + return self; +} + +- (void)dealloc { + [target_ release]; + [embeddedContainer_ release]; + [super dealloc]; +} + +- (NSUInteger)count { + return [embeddedContainer_ count]; +} + +- (NSEnumerator *)keyEnumerator { + return [embeddedContainer_ keyEnumerator]; +} + +- (id)objectForKey:(id)aKey { + return [embeddedContainer_ objectForKey:aKey]; +} + +- (void)removeObjectForKey:(id)aKey { + [embeddedContainer_ removeObjectForKey:aKey]; +} + +- (void)setObject:(id)anObject forKey:(id)aKey { + if (VerifyObjectWithTargetAndSelectorForContainer(anObject, target_, + selector_, self)) { + [embeddedContainer_ setObject:anObject forKey:aKey]; + } +} + +- (NSString*)description { + return [NSString stringWithFormat:@"%@ - %@", + NSStringFromClass([self class]), + [embeddedContainer_ description]]; +} + +#else // GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + [self release]; + } + return [[NSMutableDictionary alloc] initWithCapacity:capacity]; + +} +#endif // GTM_CONTAINERS_VALIDATE +@end + +@implementation GTMValidatingSet ++ (id)validatingSetWithTarget:(id)target selector:(SEL)sel { + return [self validatingSetWithCapacity:0 target:target selector:sel]; +} + ++ (id)validatingSetWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + return [[[[self class] alloc] initValidatingWithCapacity:0 + target:target + selector:sel] autorelease]; +} +- (id)initValidatingWithTarget:(id)target selector:(SEL)sel { + return [self initValidatingWithCapacity:0 target:target selector:sel]; +} + +#if GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + embeddedContainer_ = [[NSMutableSet alloc] initWithCapacity:capacity]; + target_ = [target retain]; + selector_ = sel; + VerifySelectorOnTarget(selector_, target_); + } + return self; +} + +- (void)dealloc { + [target_ release]; + [embeddedContainer_ release]; + [super dealloc]; +} + +- (NSUInteger)count { + return [embeddedContainer_ count]; +} + +- (id)member:(id)object { + return [embeddedContainer_ member:object]; +} + +- (NSEnumerator *)objectEnumerator { + return [embeddedContainer_ objectEnumerator]; +} + +- (void)addObject:(id)object { + if (object && VerifyObjectWithTargetAndSelectorForContainer(object, + target_, + selector_, + self)) { + [embeddedContainer_ addObject:object]; + } +} + +- (void)removeObject:(id)object { + [embeddedContainer_ removeObject:object]; +} + +- (NSString*)description { + return [NSString stringWithFormat:@"%@ - %@", + NSStringFromClass([self class]), + [embeddedContainer_ description]]; +} + +#else // GTM_CONTAINERS_VALIDATE +- (id)initValidatingWithCapacity:(NSUInteger)capacity + target:(id)target + selector:(SEL)sel { + if ((self = [super init])) { + [self release]; + } + return [[NSMutableSet alloc] initWithCapacity:capacity]; +} +#endif // GTM_CONTAINERS_VALIDATE +@end + +#pragma mark - +#pragma mark Simple Common Validators +@implementation GTMKindOfClassValidator ++ (id)validateAgainstClass:(Class)cls { + return [[[[self class] alloc] initWithClass:cls] autorelease]; +} + +- (id)initWithClass:(Class)cls { +#if GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + if (!cls) { + _GTMDevLog(@"nil class"); + [self release]; + return nil; + } + cls_ = cls; + } + return self; +#else // GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + [self release]; + } + return nil; +#endif // GTM_CONTAINERS_VALIDATE +} + +- (BOOL)validateObject:(id)object forContainer:(id)container { + return [object isKindOfClass:cls_]; +} +@end + +@implementation GTMMemberOfClassValidator ++ (id)validateAgainstClass:(Class)cls { + return [[[[self class] alloc] initWithClass:cls] autorelease]; +} + +- (id)initWithClass:(Class)cls { +#if GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + if (!cls) { + _GTMDevLog(@"nil class"); + [self release]; + return nil; + } + cls_ = cls; + } + return self; +#else // GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + [self release]; + } + return nil; +#endif // GTM_CONTAINERS_VALIDATE +} + +- (BOOL)validateObject:(id)object forContainer:(id)container { + return [object isMemberOfClass:cls_]; +} +@end + +@implementation GTMConformsToProtocolValidator ++ (id)validateAgainstProtocol:(Protocol*)prot { + return [[[[self class] alloc] initWithProtocol:prot] autorelease]; +} + +- (id)initWithProtocol:(Protocol*)prot { +#if GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + if (!prot) { + _GTMDevLog(@"nil protocol"); + [self release]; + return nil; + } + prot_ = prot; + } + return self; +#else // GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + [self release]; + } + return nil; +#endif // GTM_CONTAINERS_VALIDATE +} + +- (BOOL)validateObject:(id)object forContainer:(id)container { + return [object conformsToProtocol:prot_]; +} +@end + +@implementation GTMRespondsToSelectorValidator ++ (id)validateAgainstSelector:(SEL)sel { + return [[[[self class] alloc] initWithSelector:sel] autorelease]; +} + +- (id)initWithSelector:(SEL)sel { +#if GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + if (!sel) { + _GTMDevLog(@"nil selector"); + [self release]; + return nil; + } + sel_ = sel; + } + return self; +#else // GTM_CONTAINERS_VALIDATE + if ((self = [super init])) { + [self release]; + } + return nil; +#endif // GTM_CONTAINERS_VALIDATE +} + +- (BOOL)validateObject:(id)object forContainer:(id)container { + return [object respondsToSelector:sel_]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainersTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainersTest.m new file mode 100644 index 00000000..f9cc3772 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/Foundation/GTMValidatingContainersTest.m @@ -0,0 +1,378 @@ +// +// GTMValidatingContainersTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMValidatingContainers.h" +#import "GTMSenTestCase.h" +#import "GTMUnitTestDevLog.h" + +#pragma mark Test Support Declarations +@protocol GTMVCTestProtocol +@end + +@interface GTMVCTestClass : NSObject ++ (id)instance; +@end + +@interface GTMVCTestSubClass : GTMVCTestClass +- (void)foo; +@end + +@interface GTMVCValidatingTests : GTMTestCase { + GTMVCTestClass *testClass_; + GTMVCTestSubClass *testSubClass_; +} +@end + +@interface GTMVCValidatorTests : GTMVCValidatingTests +@end + +@interface GTMVCContainerTests : GTMVCValidatingTests { + GTMConformsToProtocolValidator *validator_; + SEL selector_; +} +@end + +@interface GTMVCArrayTests : GTMVCContainerTests +@end + +@interface GTMVCDictionaryTests : GTMVCContainerTests +@end + +@interface GTMVCSetTests : GTMVCContainerTests +@end + +@interface GTMValidateContainerTests : GTMTestCase +@end + +#pragma mark - +#pragma mark Test Support Definitions + +@implementation GTMVCTestClass ++ (id)instance { + return [[[[self class] alloc] init] autorelease]; +} + +- (NSString*)description { + return NSStringFromClass([self class]); +} +@end + +@implementation GTMVCTestSubClass +- (void)foo { +} +@end + +@implementation GTMVCContainerTests +- (void)setUp { + [super setUp]; + Protocol *prot = @protocol(GTMVCTestProtocol); + validator_ = [[GTMConformsToProtocolValidator alloc] initWithProtocol:prot]; + selector_ = @selector(validateObject:forContainer:); +} + +- (void)tearDown { + [validator_ release]; + [super tearDown]; +} +@end + +@implementation GTMVCValidatingTests + +- (void)setUp { + [super setUp]; + testClass_ = [[GTMVCTestClass alloc] init]; + testSubClass_ = [[GTMVCTestSubClass alloc] init]; +} + +- (void)tearDown { + [testClass_ release]; + [testSubClass_ release]; + [super tearDown]; +} + +@end + +@implementation GTMVCValidatorTests + +- (void)testKindOfClassValidator { +#if GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + [GTMUnitTestDevLog expectString:@"nil class"]; + GTMKindOfClassValidator *validator; + validator = [GTMKindOfClassValidator validateAgainstClass:nil]; + STAssertNil(validator, @"should be nil"); + + Class cls = [GTMVCTestClass class]; + validator = [GTMKindOfClassValidator validateAgainstClass:cls]; + STAssertNotNil(validator, @"should be valid"); + + BOOL isGood = [validator validateObject:testClass_ forContainer:nil]; + STAssertTrue(isGood, @"should be validated"); + + isGood = [validator validateObject:testSubClass_ forContainer:nil]; + STAssertTrue(isGood, @"should be validated"); + + isGood = [validator validateObject:[NSNumber numberWithInt:0] + forContainer:nil]; + STAssertFalse(isGood, @"should fail"); +#else // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + GTMKindOfClassValidator *validator; + validator = [GTMKindOfClassValidator validateAgainstClass:nil]; + STAssertNil(validator, @"should be nil"); + + Class cls = [GTMVCTestClass class]; + validator = [GTMKindOfClassValidator validateAgainstClass:cls]; + STAssertNil(validator, @"should be nil"); +#endif // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +} + +- (void)testMemberOfClassValidator { +#if GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + [GTMUnitTestDevLog expectString:@"nil class"]; + GTMMemberOfClassValidator *validator; + validator = [GTMMemberOfClassValidator validateAgainstClass:nil]; + STAssertNil(validator, @"should be nil"); + + Class cls = [GTMVCTestClass class]; + validator = [GTMMemberOfClassValidator validateAgainstClass:cls]; + STAssertNotNil(validator, @"should be valid"); + + BOOL isGood = [validator validateObject:testClass_ forContainer:nil]; + STAssertTrue(isGood, @"should be validated"); + + isGood = [validator validateObject:testSubClass_ forContainer:nil]; + STAssertFalse(isGood, @"should fail"); + + isGood = [validator validateObject:nil forContainer:nil]; + STAssertFalse(isGood, @"should fail"); + + isGood = [validator validateObject:[NSNumber numberWithInt:0] + forContainer:nil]; + STAssertFalse(isGood, @"should fail"); +#else // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + GTMMemberOfClassValidator *validator; + validator = [GTMMemberOfClassValidator validateAgainstClass:nil]; + STAssertNil(validator, @"should be nil"); + + Class cls = [GTMVCTestClass class]; + validator = [GTMMemberOfClassValidator validateAgainstClass:cls]; + STAssertNil(validator, @"should be nil"); +#endif // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +} + +- (void)testConformsToProtocolValidator { +#if GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + [GTMUnitTestDevLog expectString:@"nil protocol"]; + GTMConformsToProtocolValidator *validator; + validator = [GTMConformsToProtocolValidator validateAgainstProtocol:nil]; + STAssertNil(validator, @"should be nil"); + + Protocol *prot = @protocol(GTMVCTestProtocol); + validator = [GTMConformsToProtocolValidator validateAgainstProtocol:prot]; + STAssertNotNil(validator, @"should be valid"); + + BOOL isGood = [validator validateObject:testClass_ forContainer:nil]; + STAssertFalse(isGood, @"should fail"); + + isGood = [validator validateObject:testSubClass_ forContainer:nil]; + STAssertTrue(isGood, @"should succeed"); + + isGood = [validator validateObject:nil forContainer:nil]; + STAssertFalse(isGood, @"should fail"); +#else // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + GTMConformsToProtocolValidator *validator; + validator = [GTMConformsToProtocolValidator validateAgainstProtocol:nil]; + STAssertNil(validator, @"should be nil"); + + Protocol *prot = @protocol(GTMVCTestProtocol); + validator = [GTMConformsToProtocolValidator validateAgainstProtocol:prot]; + STAssertNil(validator, @"should be nil"); +#endif // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +} + +- (void)testRespondsToSelectorValidator { +#if GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + [GTMUnitTestDevLog expectString:@"nil selector"]; + GTMRespondsToSelectorValidator *validator; + validator = [GTMRespondsToSelectorValidator validateAgainstSelector:nil]; + STAssertNil(validator, @"should be nil"); + + SEL sel = @selector(foo); + validator = [GTMRespondsToSelectorValidator validateAgainstSelector:sel]; + STAssertNotNil(validator, @"should be valid"); + + BOOL isGood = [validator validateObject:testClass_ forContainer:nil]; + STAssertFalse(isGood, @"should fail"); + + isGood = [validator validateObject:testSubClass_ forContainer:nil]; + STAssertTrue(isGood, @"should succeed"); + + isGood = [validator validateObject:nil forContainer:nil]; + STAssertFalse(isGood, @"should fail"); +#else // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + GTMRespondsToSelectorValidator *validator; + validator = [GTMRespondsToSelectorValidator validateAgainstSelector:nil]; + STAssertNil(validator, @"should be nil"); + + SEL sel = @selector(foo); + validator = [GTMRespondsToSelectorValidator validateAgainstSelector:sel]; + STAssertNil(validator, @"should be nil"); +#endif // GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +} + + +@end + +@implementation GTMVCArrayTests +- (void)testContainer { + GTMValidatingArray *array; + array = [GTMValidatingArray validatingArrayWithTarget:validator_ + selector:selector_]; + STAssertNotNil(array, @"should be valid"); + + array = [[[GTMValidatingArray alloc] initValidatingWithTarget:validator_ + selector:selector_] autorelease]; + STAssertNotNil(array, @"should be valid"); + + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for GTMValidatingArray .*"]; + [array addObject:testSubClass_]; + [array addObject:testClass_]; + STAssertEquals([array objectAtIndex:0], testSubClass_, @""); + + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for GTMValidatingArray .*"]; + [array insertObject:testClass_ atIndex:0]; + [array insertObject:testSubClass_ atIndex:0]; + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for GTMValidatingArray .*"]; + [array replaceObjectAtIndex:0 withObject:testClass_]; + [array replaceObjectAtIndex:0 withObject:testSubClass_]; + [array removeLastObject]; + [array removeObjectAtIndex:0]; + NSUInteger expectedCount = 0U; +#if !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + // If we're not validating, we don't expect any logs + [GTMUnitTestDevLog resetExpectedLogs]; + expectedCount = 2U; +#endif // !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + STAssertEquals([array count], expectedCount, @"should have no objects left"); + +} +@end + +@implementation GTMVCDictionaryTests +- (void)testContainer { + GTMValidatingDictionary *dictionary; + dictionary = [GTMValidatingDictionary validatingDictionaryWithTarget:validator_ + selector:selector_]; + STAssertNotNil(dictionary, @"should be valid"); + + dictionary = [[[GTMValidatingDictionary alloc] initValidatingWithTarget:validator_ + selector:selector_] autorelease]; + STAssertNotNil(dictionary, @"should be valid"); + + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for GTMValidatingDictionary .*"]; + [dictionary setObject:testClass_ forKey:@"Key1"]; + [dictionary setObject:testSubClass_ forKey:@"Key2"]; + STAssertEquals([dictionary objectForKey:@"Key2"], testSubClass_, @""); + STAssertNotNil([dictionary keyEnumerator], @""); + + [dictionary removeObjectForKey:@"Key2"]; + [dictionary removeObjectForKey:@"Key1"]; + STAssertEquals([dictionary count], (NSUInteger)0, @"should have no objects left"); + + // So we get full code coverage + [testSubClass_ foo]; +#if !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + // If we're not validating, we don't expect any logs + [GTMUnitTestDevLog resetExpectedLogs]; +#endif // !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) +} +@end + +@implementation GTMVCSetTests +- (void)testContainer { + GTMValidatingSet *set; + set = [GTMValidatingSet validatingSetWithTarget:validator_ + selector:selector_]; + STAssertNotNil(set, @"should be valid"); + + set = [[[GTMValidatingSet alloc] initValidatingWithTarget:validator_ + selector:selector_] autorelease]; + STAssertNotNil(set, @"should be valid"); + + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for GTMValidatingSet .*"]; + [set addObject:testClass_]; + [set addObject:testSubClass_]; + STAssertEqualObjects([set member:testSubClass_], testSubClass_, @""); + STAssertNotNil([set objectEnumerator], @""); + + [set removeObject:testClass_]; + [set removeObject:testSubClass_]; +#if !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + // If we're not validating, we don't expect any logs + [GTMUnitTestDevLog resetExpectedLogs]; +#endif // !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + STAssertEquals([set count], (NSUInteger)0, @"should have no objects left"); +} +@end + +@implementation GTMValidateContainerTests +- (void)testValidatingContainers { + NSDictionary *homogenousDict = [NSDictionary dictionaryWithObjectsAndKeys: + [GTMVCTestSubClass instance], @"key1", + [GTMVCTestSubClass instance], @"key2", + nil]; + NSDictionary *heterogenousDict = [NSDictionary dictionaryWithObjectsAndKeys: + [GTMVCTestClass instance], @"key1", + [GTMVCTestSubClass instance], @"key2", + nil]; + + // Test bad container + [GTMUnitTestDevLog expectPattern:@"container does not respont to -objectEnumerator: .*"]; + _GTMValidateContainerContainsKindOfClass([NSString string], + [GTMVCTestSubClass class]); + + _GTMValidateContainerContainsKindOfClass(homogenousDict, + [GTMVCTestSubClass class]); + _GTMValidateContainerContainsKindOfClass(heterogenousDict, + [GTMVCTestClass class]); + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for .*"]; + _GTMValidateContainerContainsKindOfClass(heterogenousDict, + [GTMVCTestSubClass class]); + + _GTMValidateContainerContainsMemberOfClass(homogenousDict, + [GTMVCTestSubClass class]); + [GTMUnitTestDevLog expectPattern:@"GTMVCTestSubClass failed container verification for .*"]; + _GTMValidateContainerContainsMemberOfClass(heterogenousDict, + [GTMVCTestClass class]); + + _GTMValidateContainerConformsToProtocol(homogenousDict, + @protocol(GTMVCTestProtocol)); + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for .*"]; + _GTMValidateContainerConformsToProtocol(heterogenousDict, + @protocol(GTMVCTestProtocol)); + + _GTMValidateContainerItemsRespondToSelector(homogenousDict, + @selector(foo)); + [GTMUnitTestDevLog expectPattern:@"GTMVCTestClass failed container verification for .*"]; + _GTMValidateContainerItemsRespondToSelector(heterogenousDict, + @selector(foo)); +#if !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) + // If we're not validating, we don't expect any logs + [GTMUnitTestDevLog resetExpectedLogs]; +#endif // !(GTM_CONTAINERS_VALIDATE && GTM_CONTAINERS_VALIDATION_FAILED_LOG && !GTM_CONTAINERS_VALIDATION_FAILED_ASSERT) +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM-Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM-Info.plist new file mode 100644 index 00000000..41b915de --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.GTM + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMDefines.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMDefines.h new file mode 100644 index 00000000..b88193cd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMDefines.h @@ -0,0 +1,241 @@ +// +// GTMDefines.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// ============================================================================ + +#include +#include + +// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs +#ifndef MAC_OS_X_VERSION_10_5 + #define MAC_OS_X_VERSION_10_5 1050 +#endif +#ifndef MAC_OS_X_VERSION_10_6 + #define MAC_OS_X_VERSION_10_6 1060 +#endif + +// ---------------------------------------------------------------------------- +// CPP symbols that can be overridden in a prefix to control how the toolbox +// is compiled. +// ---------------------------------------------------------------------------- + + +// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and +// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens +// when a validation fails. If you implement your own validators, you may want +// to control their internals using the same macros for consistency. +#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT + #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 +#endif + +// Give ourselves a consistent way to do inlines. Apple's macros even use +// a few different actual definitions, so we're based off of the foundation +// one. +#if !defined(GTM_INLINE) + #if defined (__GNUC__) && (__GNUC__ == 4) + #define GTM_INLINE static __inline__ __attribute__((always_inline)) + #else + #define GTM_INLINE static __inline__ + #endif +#endif + +// Give ourselves a consistent way of doing externs that links up nicely +// when mixing objc and objc++ +#if !defined (GTM_EXTERN) + #if defined __cplusplus + #define GTM_EXTERN extern "C" + #else + #define GTM_EXTERN extern + #endif +#endif + +// Give ourselves a consistent way of exporting things if we have visibility +// set to hidden. +#if !defined (GTM_EXPORT) + #define GTM_EXPORT __attribute__((visibility("default"))) +#endif + +// _GTMDevLog & _GTMDevAssert +// +// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for +// developer level errors. This implementation simply macros to NSLog/NSAssert. +// It is not intended to be a general logging/reporting system. +// +// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert +// for a little more background on the usage of these macros. +// +// _GTMDevLog log some error/problem in debug builds +// _GTMDevAssert assert if conditon isn't met w/in a method/function +// in all builds. +// +// To replace this system, just provide different macro definitions in your +// prefix header. Remember, any implementation you provide *must* be thread +// safe since this could be called by anything in what ever situtation it has +// been placed in. +// + +// We only define the simple macros if nothing else has defined this. +#ifndef _GTMDevLog + +#ifdef DEBUG + #define _GTMDevLog(...) NSLog(__VA_ARGS__) +#else + #define _GTMDevLog(...) do { } while (0) +#endif + +#endif // _GTMDevLog + +// Declared here so that it can easily be used for logging tracking if +// necessary. See GTMUnitTestDevLog.h for details. +@class NSString; +GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...); + +#ifndef _GTMDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#if !defined(NS_BLOCK_ASSERTIONS) + #define _GTMDevAssert(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while(0) +#else // !defined(NS_BLOCK_ASSERTIONS) + #define _GTMDevAssert(condition, ...) do { } while (0) +#endif // !defined(NS_BLOCK_ASSERTIONS) + +#endif // _GTMDevAssert + +// _GTMCompileAssert +// _GTMCompileAssert is an assert that is meant to fire at compile time if you +// want to check things at compile instead of runtime. For example if you +// want to check that a wchar is 4 bytes instead of 2 you would use +// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) +// Note that the second "arg" is not in quotes, and must be a valid processor +// symbol in it's own right (no spaces, punctuation etc). + +// Wrapping this in an #ifndef allows external groups to define their own +// compile time assert scheme. +#ifndef _GTMCompileAssert + // We got this technique from here: + // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html + + #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg + #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) + #define _GTMCompileAssert(test, msg) \ + typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] +#endif // _GTMCompileAssert + +// Macro to allow fast enumeration when building for 10.5 or later, and +// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration +// does keys, so pick the right thing, nothing is done on the FastEnumeration +// side to be sure you're getting what you wanted. +#ifndef GTM_FOREACH_OBJECT + #if TARGET_OS_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) + #define GTM_FOREACH_OBJECT(element, collection) \ + for (element in collection) + #define GTM_FOREACH_KEY(element, collection) \ + for (element in collection) + #else + #define GTM_FOREACH_OBJECT(element, collection) \ + for (NSEnumerator * _ ## element ## _enum = [collection objectEnumerator]; \ + (element = [_ ## element ## _enum nextObject]) != nil; ) + #define GTM_FOREACH_KEY(element, collection) \ + for (NSEnumerator * _ ## element ## _enum = [collection keyEnumerator]; \ + (element = [_ ## element ## _enum nextObject]) != nil; ) + #endif +#endif + +// ============================================================================ + +// ---------------------------------------------------------------------------- +// CPP symbols defined based on the project settings so the GTM code has +// simple things to test against w/o scattering the knowledge of project +// setting through all the code. +// ---------------------------------------------------------------------------- + +// Provide a single constant CPP symbol that all of GTM uses for ifdefing +// iPhone code. +#if TARGET_OS_IPHONE // iPhone SDK + // For iPhone specific stuff + #define GTM_IPHONE_SDK 1 + #if TARGET_IPHONE_SIMULATOR + #define GTM_IPHONE_SIMULATOR 1 + #else + #define GTM_IPHONE_DEVICE 1 + #endif // TARGET_IPHONE_SIMULATOR +#else + // For MacOS specific stuff + #define GTM_MACOS_SDK 1 +#endif + +// Provide a symbol to include/exclude extra code for GC support. (This mainly +// just controls the inclusion of finalize methods). +#ifndef GTM_SUPPORT_GC + #if GTM_IPHONE_SDK + // iPhone never needs GC + #define GTM_SUPPORT_GC 0 + #else + // We can't find a symbol to tell if GC is supported/required, so best we + // do on Mac targets is include it if we're on 10.5 or later. + #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 + #define GTM_SUPPORT_GC 0 + #else + #define GTM_SUPPORT_GC 1 + #endif + #endif +#endif + +// To simplify support for 64bit (and Leopard in general), we provide the type +// defines for non Leopard SDKs +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 + // NSInteger/NSUInteger and Max/Mins + #ifndef NSINTEGER_DEFINED + #if __LP64__ || NS_BUILD_32_LIKE_64 + typedef long NSInteger; + typedef unsigned long NSUInteger; + #else + typedef int NSInteger; + typedef unsigned int NSUInteger; + #endif + #define NSIntegerMax LONG_MAX + #define NSIntegerMin LONG_MIN + #define NSUIntegerMax ULONG_MAX + #define NSINTEGER_DEFINED 1 + #endif // NSINTEGER_DEFINED + // CGFloat + #ifndef CGFLOAT_DEFINED + #if defined(__LP64__) && __LP64__ + // This really is an untested path (64bit on Tiger?) + typedef double CGFloat; + #define CGFLOAT_MIN DBL_MIN + #define CGFLOAT_MAX DBL_MAX + #define CGFLOAT_IS_DOUBLE 1 + #else /* !defined(__LP64__) || !__LP64__ */ + typedef float CGFloat; + #define CGFLOAT_MIN FLT_MIN + #define CGFLOAT_MAX FLT_MAX + #define CGFLOAT_IS_DOUBLE 0 + #endif /* !defined(__LP64__) || !__LP64__ */ + #define CGFLOAT_DEFINED 1 + #endif // CGFLOAT_DEFINED +#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM_Prefix.pch b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM_Prefix.pch new file mode 100644 index 00000000..a7c0011a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTM_Prefix.pch @@ -0,0 +1,37 @@ +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// We don't require a prefix to use any GTM code, so this prefix is just to +// speed up the basic compiles of *all* of the GTM projects/targets. + +// We don't want to drag GTMDefines into the prefix so we make sure each file +// that directly needs it includes it, so we just use the iphone test directly +// instead of our GTM_IPHONE_SDK symbol. +#ifdef __OBJC__ + #include + #if TARGET_OS_IPHONE // iPhone SDK + #import + #import + #else + #import + #endif + // This turns on unit test logging so that we can track unittests if we are + // doing them. See GTMUnitTestDevLog.h for details. + // (_GTMUnitTestDevLog comes from GTMDevLogUnitTestingBridge.m) + #define _GTMDevLog _GTMUnitTestDevLog +#endif + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMiPhone-Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMiPhone-Info.plist new file mode 100644 index 00000000..68982241 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/GTMiPhone-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.GTMiPhone + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/ReleaseNotes.txt b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/ReleaseNotes.txt new file mode 100644 index 00000000..7e76a234 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/ReleaseNotes.txt @@ -0,0 +1,399 @@ +Google Toolbox for Mac Release Notes + +Project site: http://code.google.com/p/google-toolbox-for-mac/ +Discussion group: http://groups.google.com/group/google-toolbox-for-mac + + +Release ?.?.? +Changes since 1.5.1 + +- Added GTMNSArray+Merge for merging one array into another with or without + a custom merging function, returning a new array with the merged contents. + +- Added GTMSignalHandler for simple signal handling (via kqueue/runloop). This + has gotten an api tweak, so some code that started using it will need + updating. Initial landing had a bug where it could leak memory due to + how CFRunLoops work, now fixed. + +- Fixed up GTMIPhoneUnitTestDelegate to be pickier about which tests it runs + +- Added GTMNSString+URLArguments to GTMiPhone + +- Added GTMHTTPFetcher and GTMHTTPServer to GTMiPhone + +- Made sure that build would work with iPhone device attached, and that all + tests run directly on the phone. + +- Added GTMValidatingContainers which are a set of mutable container classes + that allow you to have a selector on a target that is called to verify that + the objects being put into the container are valid. This can be controlled + at compile time so that you don't take the performance hit in a release build. + +- Added GTMPath, which represents an existing absolute path on the file system. + It also makes it very easy to contruct new paths in the file system as well + as whole directory hierarchies. + +- Added GTMNSString+Replace for a common replacement need. + +- Added NSString+FindFolder for two commen helpers for building paths to common + locations. + +- Added GTMLargeTypeWindow for doing display windows similar to Address Book + Large Type display for phone numbers. + +- Removed GTMNSWorkspace+ScreenSaver as it has always been a little dodgy due + to it's dependencies on undocumented frameworks, and the ScreenSaver + framework doesn't play nicely in GC mode. + +- Added property methods to GTMHTTPFetcher. These are convenient alternatives + to storing an NSDictionary in the userData. + +- Renamed GTMDevLog.m to GTMDevLogUnitTestingBridge.m and added some more + comments where it comes into play to hopefully make it more clear that it + isn't needed in most cases. + +- Fixed a potential GTMHTTPFetcher crash on failed authentication. + +- Added a obj-c logging package, GTMLogger, for applications that want an + application level logging system. See GTMLogger.h, GTMLogger+ASL.h, and + GTMLoggerRingBufferWriter.h for what the basic system and two optional + additions can do. + +- Added GTMNSMakeUncollectable for forcing objects to survive in a GC world. + +- Added GTMCFAutorelease to make the [GTMNSMakeCollectable(cfFoo) autorelease] + simpler and clearer, it's now just GTMCFAutorelease(cfFoo), and works in + both GC and non-GC world. + +- Added GTMIsGarbageCollectionEnabled to GTMGarbageCollection.h. See the note + there for it's usage. + +- Disabled the unittests for things on top of NSAppleScript in a GC world since + Apple has bugs and it can crash. See the unittest for a note about it. + +- GTMStackTrace now can figure out ObjC symbols. Downside it is now ObjC only. + +- GTMFourCharCode can now be used with NSAppleEventDescriptors easily. + typeType, typeKeyword, typeApplSignature, and typeEnumerated all get + turned into GTMFourCharCodes. + +- Fixed up crash in GTMLoggerRingBufferWriter when used with GC on. + +- Significant updates to GTMNSAppleScript+Handler allowing you to + list all handlers and properties (including inherited) and cleans up + several errors in how scripting was being handled. + +- Added GTMGetURLHandler class that gives you a very easy way of supporting + Get URL events just by adding a key to your plists, and adding a single + method to your class. See GTMGetURLHandler.m for more details. + +- Added XcodeProject, AppleScript, and InterfaceBuilder Spotlight Plugins. + Allows you to index .xcodeproj, .scpt, .scptd, .xib, .nib, and + .aib files. See Readmes beside individual projects in SpotlightPlugins. + +- Added GTMExceptionalInlines for dealing with cases where you get + warning: variable 'r' might be clobbered by 'longjmp' or 'vfork' + when using certain Apple inlined functions in @synchronized/@try blocks. + +- Updated to Xcode 3.1 so the GTM and iPhone project have the same baseline. + The code should work in other version of xcode, but the projects and + xcconfig files now use 3.1 features. + +- Added GTMABAddressBook which is a cocoa wrapper for the 'C' AddressBook + APIs on the iPhone. + +- Added several set environment variable statements to RunIPhoneUnitTest.sh + to encourage bugs to come out of the woodwork. + +- Added GTMTestTimer.h for doing high fidelity timings. + +- Added ability to control using zombies to iPhone unit test script. It can be + controlled by the GTM_DISABLE_ZOMBIES environment variable + +- Added ability to control termination to iPhone unit test script. It can be + controlled by the GTM_DISABLE_TERMINATION environment variable + +- Fixed several leaks found with leak checking enabled. + +- Updated the iPhone xcconfigs to support the different OS versions. + +- GTM_INLINE will make sure a function gets inlined, and provides a consistent + way for all GTM code to do it. + +- Added GTMDebugThreadValidation to allow you to enforce the fact that your + code must run in the main thread in DEBUG builds. + +- Updated some internals of the iPhone unittesting so it doesn't double print + the test descriptions, file names, or lines numbers of a test failure line. + Also includes the test names in the error output. + +- Changed the xcconfigs so that know it's easier to set different settings at + the different levels and not accidentally overwrite settings set at lower + levels in the "settings collapse". Also tightened up warnings significantly. + +- Changed how gtm_unitTestExposedBindingsTestValues works. If you have an + implementation of gtm_unitTestExposedBindingsTestValues in your own code + you will need to update to the new way of calling. See implementations in + GTMNSObject+BindingUnitTesting.m for details. + +- Added support for grabbing the build number for a particular OS in + GTMSystemVersion and easily comparing it to known build numbers, and switched + some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work + better. + +- Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and + all radar checks were updated accordingly. Build All script was also updated + to build on SnowLeopard if you have the SDK available. + +- Turned off building ppc64 GTM because the SnowLeopard SDK currently + doesn't have ppc64 support, so SenTestCase isn't defined. This makes it + impossible to build the ppc64 10.5 config on SnowLeopard. We have left the + setting in the xcconfig for those of you who need it, but have disabled + it in the GTM project settings. + +- Turned on stack smashing protection on the debug builds for all Leopard + and above. + +- Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS + environment variable. It isn't on by default because several of Apple's + frameworks leak. You can work around these false positives by using the + GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks + make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable, + otherwise every memory allocation you do will look like a leak. + +- Added has ability to check if a script has an open handler to + GTMNSAppleScript+Handler. + +- GTMStackTrace support for building a trace from the call stack in an + NSException (for 10.5+ and iPhone). + +- GTMStackTrace works on 10.5+ (and iPhone) using NSThread to build the call + stack. + +- GTMLightweightProxy for breaking retain cycles. + +- Added GTM_EXTERN that makes it easier to mix and match objc and objc++ code. + +- Added GTMHotKeysTextField for display and editing of hot key settings. + +- Added GTMCarbonEvent for dealing with Carbon Events and HotKeys in a ObjC + like way. + +- Backported the Atomic Barrier Swap functions for Objective C back to Tiger. + +- Added a variety of new functions to GTMUnitTestingUtilities for checking + if the screensaver is in the way, waiting on user events, and generating + keystrokes. + +- If you are using any Carbon routines that log (DebugStr, AssertMacros.h) and + use GTMUnitTestDevLog, the log routines now go through _GTMDevLog so that + they can be caught in GTMUnitTestDevLog and verified like any _GTMDevLog calls + you may make. For an example of this in action see GTMCarbonEventTest.m. + Since we have turned this on, we have turned off using _debug frameworks + from the RunUnitTests.sh because it was reporting a pile of uninteresting + issues that were interfering with unittests. + +- Added GTMFileSystemKQueue. It provides a simple wrapper for kqueuing + something in the file system and tracking changes to it. Initial landing + had a bug where it could leak memory due to how CFRunLoops work, now fixed. + +- RunIPhoneUnitTest.sh now cleans up the user home directory and creates + a documents directory within it, used when requesting a NSDocumentDirectory. + +- Added GTMNSFileManager+Carbon which contains routines for path <-> Alias + conversion and path <-> FSRef conversion. + +- Added GTM_EXPORT as a standard way of exporting symbols. + +- Added GTMUnitTestDevLogDebug which extends GTMUnitTestDevLog to only look + for the messages in debug builds, to make it easier to validate messages + that are only present in debug builds. + +- Added GTM_SUPPORT_GC for controlling the inclusion of GC related code. + +- If you are using GTMUnitTestDevLog, it also tries to capture logs from + NSAssert. + +- Added GTM_FOREACH_OBJECT/GTM_FOREACH_KEY that uses NSEnumerator and + objectEnumerator/keyEnumerator on 10.4, but on 10.5+/iPhone uses + FastEnumeration. + +- GTMNSWorkspace+Running gives a variety of ways of determining the attributes + of running processes. + +- If the iPhone unittesting support is exiting when done, it now properly sets + the exit code based on test success/failure. + +- Added GTMNSObject+KeyValueObserving to make it easier on folks to do KVO + "correctly". Based on some excellent code by Michael Ash. + http://www.mikeash.com/?page=pyblog/key-value-observing-done-right.html + This has been added for iPhone and OS X. + +- Fixed up GTMSenTestCase on iPhone so that it has a description that matches + that of OCUnit. + +- Added GTMAbstractDOListener, GTMTransientRootProxy, and + GTMTransientRootPortProxy. These classes can be used to simplify the + use of distributed objects. GTMAbstractDOListener can be used to handle + connections from any type of port. GTMTransientRootProxy is designed for + using named connections while GTMTransientRootPortProxy is for connections + with supplied NSPorts. + +- Finally dropped GTMHTTPFetcher and GTMProgressMonitorInputStream, GData + versions now pretty much line up w/ these, so rather then both projects + maintaing them, we've dropped them and point folks at the gdata versions + which can be used independent of the rest of GData. + +- Changed gtm_createCGPath to gtm_cgPath in GTMNSBezier+CGPath. The path + returned is now autoreleased so you don't need to worry about releasing it. + +- Made some changes to the GTMNSObject+UnitTesting APIs. Specifically renamed + gtm_createUnitTestImage to gtm_unitTestImage. The value it returns is now + autoreleased, so no need to release it. Also change + gtm_createUnitTestBitmapOfSize:withData: to a C function. + +- Cleaned up GTM so that it passes the Clang checker without any warnings. + +- Added GTMLuminance for working with colors in HSL space easily. + +- Added GTMTheme for doing product wide theme modifications. + +- The Run*UnitTest.sh script now support an env var to have them delete the + current target/configs *.gcda files to avoid coverage data warning when you + edit source. + + +Release 1.5.1 +Changes since 1.5.0 +16-June-2008 + +- Fixed building tiger gcov w/ a directory path that contains a space. + + +Release 1.5.0 +Changes since 1.0.0 +13-June-2008 + +- Updated the project to Xcode 3. This is the only supported Xcode version + for the project. The code can build against the Tiger or Leopard SDKs, and + developers can pull individual files into a Xcode 2.x project and things + should work just fine. + +- Fixed up the prefix header of the project and prefix handing in the Unittest + Xcode Config. (thanks schafdog) + +- Fixed error in handling default compression for NSData+zlib + +- Changed name on API in NSString+XML and added another api to make this a + litte more clear. (thanks Kent) + +- GTMRegex + - Found and fixed a bug in the enumerators that was causing them to + incorrectly walk a string when using '^' in an expression. + - Added helpers for substring tests and unittests for the new apis. + - Added initializer that takes an outError to allow the collection of any + pattern parsing error message (in case the pattern came from a user and + complete error information is needed to message the user). + +- Added GTMScriptRunner for spawning scripts. + +- Added GTMNSFileManager+Path for two small helpers. + +- Added GTMNSWorkspace+ScreenSaver + +- Added GTMNSString+Data + +- added a common header (GTMDefines) for any common defines so the conditionals + are all in one place + +- Support for things compiling against the iPhone SDK + - Everything in the GTMiPhone project works in the iPhone + - Added iPhone xcconfig files + - Added iPhone unittests (See below) + +- More work on the UI unittests + - support pretty much any part of a UI + - support for CALayers + - full support for the iPhone + - the iPhone uses the same macro set at OCUnit, but has its own runtime + for running tests. + - extended capabilities of UIUnitTesting to be more flexible and give better + error reporting for states. + +- Renamed the actual framework to "GoogleToolboxForMac.framework" (it should + have matched the project on code.google.com from the start) + +- added a Debug-gcov target that will product debug bits w/ code coverage + support to check unittests, etc. + +- GTMDebugSelectorValidation to provide something to include in class impls + to get validation of object/selector pair(s) being implemented so you don't + have to wait for a runtime invocation failures. (especially useful for + things that take a success and failure selector so one doesn't always get + called) + +- added _GTMDevLog (really in GTMDefines) that are a set of macros that can be + used for logging. This allows any project to redefine them to direct logging + into its runtime needs. + +- Moved GTMGeometryUtils into Foundation from AppKit + +- Removed several HI* calls from GTMGeometryUtils as Carbon UI in general is + deprecated. + +- Xcode configs + - changed the layout to make it a little easier to tell how to use them. + - added Leopard or later configs + +- Unittest coverage greatly increased + +- Added RunMacOSUnitTests shell script. We run this script for starting up our + unittests because it turns on a variety of "enhancements" (such as zombies, + scribbling etc) to encourage our unittests to fail for us. + + https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19915 + +- Remove NSColor+Theme and NSWorkspace+Theme as they are no longer needed for + testing things for unittests, instead GTMUnitTestingUtilities.m(Lines 64-79) + force the user settable things to ensure tests are consistent. + +- Added GTMBase64. + +- Added GTMHTTPFetcher and GTMProgressMonitorInputStream. + +- Moved the data files for unittests into subdirectories call TestData to + help make it a little easier to find files w/in the main directories. + +- GTMDelegatingTableColumn get an overhaul to match the 10.5 sdk so it's closer + to a dropin for previous sdks. + +- Added a lot of functionality to NSAppleEventDescriptor and NSAppleScript + allowing you to easily call labeled and positional handlers in an AppleScript, + get/set properties and get NSAppleEventDescriptors for most basic datatypes. + +- Added GTMFourCharCode for wrapping FourCharCodes in an ObjC object. Mainly for + use by the NSAppleEventDescriptor code, and also useful for storing them + in ObjC collection classes. + +- Added GTMStackTrace. + +- Added NSString+URLArguments and NSDictionary+URLArguments + +- Added GTMHTTPServer as a simple server but mainly for use in unittesting. + +- Added _GTMCompileAssert for doing compile time assertions to GTMDefines.h + +- Added GTMUnitTestDevLog and GTMTestCase for logging and tracking logs while + running unittests to verify what is being logged is what you expect. All + unittests should now inherit from GTMTestCase instead of SenTestCase to take + advantage of the new log tracking. See GTMUnitTestDevLog.h for details. + +- Extracted GTMIPhoneUnitTestDelegate from GTMIPhoneUnitTestMain.m to its own + file. Tests can now be run from another application. + + +Release 1.0.0 +14-January-2008 + +- Initial public release. Includes some simple utils, xcode configs, and + some support for doing unit tests of graphical things. diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/English.lproj/InfoPlist.strings b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/English.lproj/InfoPlist.strings new file mode 100644 index 00000000..41ade49e Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/English.lproj/InfoPlist.strings differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/GetMetadataForFile.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/GetMetadataForFile.m new file mode 100644 index 00000000..d635f405 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/GetMetadataForFile.m @@ -0,0 +1,121 @@ +// +// GetMetadataForFile.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import + +static BOOL ImportScriptBundle(NSMutableDictionary *attributes, + NSString *path) { + NSBundle *scriptBundle = [NSBundle bundleWithPath:path]; + NSString *descriptionPath = [scriptBundle pathForResource:@"description" + ofType:@"rtfd"]; + NSAttributedString *attrString = nil; + if (descriptionPath) { + attrString = [[[NSAttributedString alloc] initWithPath:descriptionPath + documentAttributes:NULL] autorelease]; + } + BOOL wasGood = NO; + if (attrString) { + NSString *description = [attrString string]; + [attributes setObject:description forKey:(NSString*)kMDItemDescription]; + wasGood = YES; + } + + NSArray *scripts = [scriptBundle pathsForResourcesOfType:@"scpt" + inDirectory:@"Scripts"]; + NSEnumerator *scriptEnum = [scripts objectEnumerator]; + NSString *scriptPath; + NSMutableArray *scriptSources = [NSMutableArray array]; + while ((scriptPath = [scriptEnum nextObject])) { + NSURL *scriptURL = [NSURL fileURLWithPath:scriptPath]; + NSDictionary *error; + NSAppleScript *script + = [[[NSAppleScript alloc] initWithContentsOfURL:scriptURL + error:&error] + autorelease]; + NSString *scriptSource = [script source]; + if (scriptSource) { + [scriptSources addObject:scriptSource]; + } + } + if ([scriptSources count]) { + NSString *source = [scriptSources componentsJoinedByString:@"\n"]; + [attributes setObject:source forKey:(NSString*)kMDItemTextContent]; + wasGood = YES; + } + return wasGood; +} + +static BOOL ImportScript(NSMutableDictionary *attributes, + NSString *path) { + NSURL *fileURL = [NSURL fileURLWithPath:path]; + FSRef ref; + BOOL wasGood = NO; + if (CFURLGetFSRef((CFURLRef)fileURL, &ref)) { + ResFileRefNum resFile = FSOpenResFile(&ref, fsRdPerm); + if (resFile) { + const ResID kScriptDescriptionResID = 1128; + ResFileRefNum curResFile = CurResFile(); + UseResFile(resFile); + Handle res = Get1Resource('TEXT', kScriptDescriptionResID); + if (res) { + NSString *descString + = [[[NSString alloc]initWithBytes:(char*)(*res) + length:GetHandleSize(res) + encoding:NSMacOSRomanStringEncoding] autorelease]; + ReleaseResource(res); + if (descString) { + [attributes setObject:descString forKey:(NSString*)kMDItemDescription]; + wasGood = YES; + } + } + UseResFile(curResFile); + CloseResFile(resFile); + } + + NSDictionary *error; + NSAppleScript *script = [[[NSAppleScript alloc] initWithContentsOfURL:fileURL + error:&error] + autorelease]; + NSString *scriptSource = [script source]; + if (scriptSource) { + [attributes setObject:scriptSource forKey:(NSString*)kMDItemTextContent]; + wasGood = YES; + } + } + return wasGood; +} + +// Currently grabs the script description and puts it into kMDItemDescription. +// Grabs the script code and puts it into kMDItemTextContent. +Boolean GetMetadataForFile(void* interface, + CFMutableDictionaryRef cfAttributes, + CFStringRef cfContentTypeUTI, + CFStringRef cfPathToFile) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSMutableDictionary *attributes = (NSMutableDictionary*)cfAttributes; + NSString *pathToFile = (NSString*)cfPathToFile; + BOOL wasGood = NO; + if (UTTypeConformsTo(cfContentTypeUTI, CFSTR("com.apple.applescript.scriptbundle"))) { + wasGood = ImportScriptBundle(attributes, pathToFile); + } else if (UTTypeConformsTo(cfContentTypeUTI, CFSTR("com.apple.applescript.script"))) { + wasGood = ImportScript(attributes, pathToFile); + } + [pool release]; + return wasGood ? TRUE : FALSE; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/Info.plist new file mode 100644 index 00000000..be3c6225 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/Info.plist @@ -0,0 +1,74 @@ + + + + + UTImportedTypeDeclarations + + + UTTypeIdentifier + com.apple.applescript.scriptbundle + UTTypeReferenceURL + http://www.apple.com/applescript/ + UTTypeDescription + Script Bundle + UTTypeConformsTo + + com.apple.package + public.composite-content + public.data + + UTTypeTagSpecification + + public.filename-extension + + scptd + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeRole + MDImporter + LSItemContentTypes + + com.apple.applescript.script + com.apple.applescript.scriptbundle + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.spotlightimporter.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleVersion + 1.0 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + CFPlugInFactories + + B498BAB3-7887-4E93-862A-19E74809248D0 + MetadataImporterPluginFactory + + CFPlugInTypes + + 8B08C4BF-415B-11D8-B3F9-0003936726FC + + B498BAB3-7887-4E93-862A-19E74809248D0 + + + CFPlugInUnloadFunction + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/PluginID.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/PluginID.h new file mode 100644 index 00000000..955a476f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/PluginID.h @@ -0,0 +1,19 @@ +// +// PluginID.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#define PLUGIN_ID "B498BAB3-7887-4E93-862A-19E74809248D0" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/ReadMe.rtf b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/ReadMe.rtf new file mode 100644 index 00000000..ee2fa250 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/ReadMe.rtf @@ -0,0 +1,38 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\vieww10980\viewh11300\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 AppleScript Spotlight Plugin\ +\ +Copyright 2008 Google Inc.\ +\ +Licensed under the Apache License, Version 2.0 (the "License"); you may not\ +use this file except in compliance with the License. You may obtain a copy\ +of the License at\ +\ +http://www.apache.org/licenses/LICENSE-2.0\ + \ +Unless required by applicable law or agreed to in writing, software\ +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\ +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\ +License for the specific language governing permissions and limitations under\ +the License.\ +\ +-----------------------\ +\ +This is a spotlight importer for AppleScripts.\ +It imports the description and the code of an AppleScript to make them easily searchable.\ +\ +To install the spotlight plugin, please copy it into /Applications/AppleScript/Script Editor/Contents/Library/Spotlight.\ +\ +If you are wondering why we just don't copy this one into /Library/Spotlight or ~/Library/Spotlight it is due to the fact that on 10.5 the UTIs declared by Spotlight importers don't seem to be recognized unless they are in an application's /Library/Spotlight directory. There isn't a UTI for AppleScript bundle files (.scptd) so we declare one in the importer. If the importer isn't located in an application's /Library/Spotlight directory, you won't be able to import .scptd files.\ +\ +Radars logged:\ +6160646 UTIs declared in Spotlight Importers in Library/Spotlight not recognized\ +6160685 Need UTI for AppleScript script bundle\ +6160707 UTCoreTypes.h needs to be updated\ +\ +It is part of the Google Toolbox For Mac project\ +http://code.google.com/p/google-toolbox-for-mac/} \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/schema.xml b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/schema.xml new file mode 100644 index 00000000..d057fd74 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/AppleScript/schema.xml @@ -0,0 +1,38 @@ + + + + + + + + kMDItemDescription + + + + + + + kMDItemDescription + + + + + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Common/main.c b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Common/main.c new file mode 100644 index 00000000..16eecacf --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Common/main.c @@ -0,0 +1,204 @@ +// +// main.c +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#include +#include +#include +#include "PluginID.h" + +// ----------------------------------------------------------------------------- +// constants +// ----------------------------------------------------------------------------- + + + +// +// Below is the generic glue code for all plug-ins. +// +// You should not have to modify this code aside from changing +// names if you decide to change the names defined in the Info.plist +// + +// ----------------------------------------------------------------------------- +// typedefs +// ----------------------------------------------------------------------------- + +// The import function to be implemented in GetMetadataForFile.c +Boolean GetMetadataForFile(void *thisInterface, + CFMutableDictionaryRef attributes, + CFStringRef contentTypeUTI, + CFStringRef pathToFile); + +// The layout for an instance of MetaDataImporterPlugIn +typedef struct __MetadataImporterPluginType { + MDImporterInterfaceStruct *conduitInterface; + CFUUIDRef factoryID; + UInt32 refCount; +} MetadataImporterPluginType; + +// ----------------------------------------------------------------------------- +// prototypes +// ----------------------------------------------------------------------------- +// Forward declaration for the IUnknown implementation. +// + +MetadataImporterPluginType* AllocMetadataImporterPluginType(CFUUIDRef inFactoryID); +void DeallocMetadataImporterPluginType(MetadataImporterPluginType *instance); +void* MetadataImporterPluginFactory(CFAllocatorRef allocator, CFUUIDRef typeID); +static ULONG MetadataImporterPluginAddRef(void *instance); +static ULONG MetadataImporterPluginRelease(void *instance); +static HRESULT MetadataImporterQueryInterface(void *instance, REFIID iid, LPVOID *ppv); +// ----------------------------------------------------------------------------- +// testInterfaceFtbl definition +// ----------------------------------------------------------------------------- +// The TestInterface function table. +// + +static MDImporterInterfaceStruct testInterfaceFtbl = { + NULL, + MetadataImporterQueryInterface, + MetadataImporterPluginAddRef, + MetadataImporterPluginRelease, + GetMetadataForFile +}; + + +// ----------------------------------------------------------------------------- +// AllocMetadataImporterPluginType +// ----------------------------------------------------------------------------- +// Utility function that allocates a new instance. +// You can do some initial setup for the importer here if you wish +// like allocating globals etc... +// +MetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID) { + MetadataImporterPluginType *theNewInstance + = (MetadataImporterPluginType *)malloc(sizeof(MetadataImporterPluginType)); + memset(theNewInstance, 0, sizeof(MetadataImporterPluginType)); + + // Point to the function table + theNewInstance->conduitInterface = &testInterfaceFtbl; + + // Retain and keep an open instance refcount for each factory. + theNewInstance->factoryID = CFRetain(inFactoryID); + CFPlugInAddInstanceForFactory(inFactoryID); + + // This function returns the IUnknown interface so set the refCount to one. + theNewInstance->refCount = 1; + return theNewInstance; +} + +// ----------------------------------------------------------------------------- +// DeallocXcodeProjectSpotlightPluginMDImporterPluginType +// ----------------------------------------------------------------------------- +// Utility function that deallocates the instance when +// the refCount goes to zero. +// In the current implementation importer interfaces are never deallocated +// but implement this as this might change in the future +// +void DeallocMetadataImporterPluginType(MetadataImporterPluginType *instance) { + CFUUIDRef theFactoryID = instance->factoryID; + free(instance); + if (theFactoryID) { + CFPlugInRemoveInstanceForFactory(theFactoryID); + CFRelease(theFactoryID); + } +} + +// ----------------------------------------------------------------------------- +// MetadataImporterQueryInterface +// ----------------------------------------------------------------------------- +// Implementation of the IUnknown QueryInterface function. +// +HRESULT MetadataImporterQueryInterface(void *instance, REFIID iid, LPVOID *ppv) { + CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid); + MetadataImporterPluginType *plugin = ((MetadataImporterPluginType*)instance); + HRESULT result = E_INVALIDARG; + if (interfaceID) { + if (CFEqual(interfaceID, kMDImporterInterfaceID)) { + // If the Right interface was requested, bump the ref count, + // set the ppv parameter equal to the instance, and + // return good status. + plugin->conduitInterface->AddRef(instance); + *ppv = instance; + result = S_OK; + } else { + if (CFEqual(interfaceID, IUnknownUUID)) { + // If the IUnknown interface was requested, same as above. + plugin->conduitInterface->AddRef(instance); + *ppv = instance; + result = S_OK; + } else { + // Requested interface unknown, bail with error. + *ppv = NULL; + result = E_NOINTERFACE; + } + } + CFRelease(interfaceID); + } + return result; +} + +// ----------------------------------------------------------------------------- +// MetadataImporterPluginAddRef +// ----------------------------------------------------------------------------- +// Implementation of reference counting for this type. Whenever an interface +// is requested, bump the refCount for the instance. NOTE: returning the +// refcount is a convention but is not required so don't rely on it. +// +ULONG MetadataImporterPluginAddRef(void *instance) { + MetadataImporterPluginType *plugin = ((MetadataImporterPluginType*)instance); + plugin->refCount += 1; + return plugin->refCount; +} + +// ----------------------------------------------------------------------------- +// SampleCMPluginRelease +// ----------------------------------------------------------------------------- +// When an interface is released, decrement the refCount. +// If the refCount goes to zero, deallocate the instance. +// +ULONG MetadataImporterPluginRelease(void *instance) { + ULONG refCount = 0; + MetadataImporterPluginType *plugin = ((MetadataImporterPluginType*)instance); + plugin->refCount -= 1; + if (plugin->refCount == 0) { + DeallocMetadataImporterPluginType(plugin); + refCount = 0; + } else { + refCount = (plugin)->refCount; + } + return refCount; +} + +// ----------------------------------------------------------------------------- +// XcodeProjectSpotlightPluginMDImporterPluginFactory +// ----------------------------------------------------------------------------- +// Implementation of the factory function for this type. +// +void *MetadataImporterPluginFactory(CFAllocatorRef allocator, CFUUIDRef typeID) { + // If correct type is being requested, allocate an + //instance of TestType and return the IUnknown interface. + MetadataImporterPluginType *result = NULL; + if (CFEqual(typeID, kMDImporterTypeID)){ + CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, CFSTR(PLUGIN_ID)); + result = AllocMetadataImporterPluginType(uuid); + CFRelease(uuid); + } + // If the requested type is incorrect, return NULL. + return result; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPost.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPost.sh new file mode 100644 index 00000000..f58c5b03 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPost.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +su ${USER} -c "/usr/bin/mdimport -r '/Applications/AppleScript/Script Editor.app/Contents/Library/Spotlight/AppleScript.mdimporter'" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPreflight.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPreflight.sh new file mode 100644 index 00000000..65ff80d7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/ApplescriptInstallerPreflight.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +# Set up the spotlight importer directory for Script Editor. + +mkdir -m 775 -p "/Applications/AppleScript/Script Editor.app/Contents/Library/Spotlight" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/InterfaceBuilderInstallerPost.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/InterfaceBuilderInstallerPost.sh new file mode 100644 index 00000000..2850a6c4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/InterfaceBuilderInstallerPost.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +su ${USER} -c "/usr/bin/mdimport -r '/Library/Spotlight/InterfaceBuilder.mdimporter'" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/License.rtf b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/License.rtf new file mode 100644 index 00000000..33fbacf0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/License.rtf @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf350 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 Copyright 2008 {\field{\*\fldinst{HYPERLINK "http://www.google.com"}}{\fldrslt Google Inc.}}\ +\ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\ +\ +{\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt http://www.apache.org/licenses/LICENSE-2.0}}\ + \ +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.} \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/Welcome.rtf b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/Welcome.rtf new file mode 100644 index 00000000..74f8854d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/Welcome.rtf @@ -0,0 +1,11 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf350 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 Finding source can be difficult. These are importers to help you index your various source files. Included in the package are importers for Xcode projects, AppleScript files, and Interface Builder files.\ +\ +These importers are part of the Google Toolbox For Mac project. Check it out at:\ +\ +{\field{\*\fldinst{HYPERLINK "http://code.google.com/p/google-toolbox-for-mac/"}}{\fldrslt http://code.google.com/p/google-toolbox-for-mac/}}} \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/XcodeProjectInstallerPost.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/XcodeProjectInstallerPost.sh new file mode 100644 index 00000000..db9bfdb2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/Installer/XcodeProjectInstallerPost.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +su ${USER} -c "/usr/bin/mdimport -r '/Library/Spotlight/XcodeProject.mdimporter'" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/English.lproj/InfoPlist.strings b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/English.lproj/InfoPlist.strings new file mode 100644 index 00000000..b1508941 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/English.lproj/InfoPlist.strings differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/GetMetadataForFile.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/GetMetadataForFile.m new file mode 100644 index 00000000..32c37c59 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/GetMetadataForFile.m @@ -0,0 +1,208 @@ +// +// GetMetadataForFile.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMGarbageCollection.h" + +static BOOL AddStringsToTextContent(NSSet *stringSet, + NSMutableDictionary *attributes) { + BOOL wasGood = NO; + if ([stringSet count]) { + NSString *allStrings = [[stringSet allObjects] componentsJoinedByString:@"\n"]; + NSString *oldContent = [attributes objectForKey:(NSString*)kMDItemTextContent]; + if (oldContent) { + allStrings = [NSString stringWithFormat:@"%@\n%@", allStrings, oldContent]; + } + [attributes setObject:allStrings forKey:(NSString*)kMDItemTextContent]; + wasGood = YES; + } + return wasGood; +} + +static BOOL ExtractClasses(NSDictionary *ibToolData, + NSMutableDictionary *attributes) { + NSString *classesKey = @"com.apple.ibtool.document.classes"; + NSDictionary *classes = [ibToolData objectForKey:classesKey]; + NSMutableSet *classSet = [NSMutableSet set]; + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + NSArray *classPrefixesToIgnore + = [ud objectForKey:@"classPrefixesToIgnore"]; + if (!classPrefixesToIgnore) { + classPrefixesToIgnore = [NSArray arrayWithObjects: + @"IB", + @"FirstResponder", + @"NS", + @"Web", + nil]; + [ud setObject:classPrefixesToIgnore forKey:@"classPrefixesToIgnore"]; + [ud synchronize]; + } + NSDictionary *entry; + NSEnumerator *entryEnum = [classes objectEnumerator]; + while ((entry = [entryEnum nextObject])) { + NSString *classStr = [entry objectForKey:@"class"]; + if (classStr) { + NSString *prefix; + NSEnumerator *classPrefixesToIgnoreEnum + = [classPrefixesToIgnore objectEnumerator]; + while (classStr && (prefix = [classPrefixesToIgnoreEnum nextObject])) { + if ([classStr hasPrefix:prefix]) { + classStr = nil; + } + } + if (classStr) { + [classSet addObject:classStr]; + } + } + } + return AddStringsToTextContent(classSet, attributes); +} + +static BOOL ExtractLocalizableStrings(NSDictionary *ibToolData, + NSMutableDictionary *attributes) { + NSString *localStrKey = @"com.apple.ibtool.document.localizable-strings"; + NSDictionary *strings = [ibToolData objectForKey:localStrKey]; + NSMutableSet *stringSet = [NSMutableSet set]; + NSDictionary *entry; + NSEnumerator *entryEnum = [strings objectEnumerator]; + while ((entry = [entryEnum nextObject])) { + NSEnumerator *stringEnum = [entry objectEnumerator]; + NSString *string; + while ((string = [stringEnum nextObject])) { + [stringSet addObject:string]; + } + } + return AddStringsToTextContent(stringSet, attributes); +} + +static BOOL ExtractConnections(NSDictionary *ibToolData, + NSMutableDictionary *attributes) { + NSString *connectionsKey = @"com.apple.ibtool.document.connections"; + NSDictionary *connections = [ibToolData objectForKey:connectionsKey]; + NSMutableSet *connectionsSet = [NSMutableSet set]; + NSDictionary *entry; + NSEnumerator *entryEnum = [connections objectEnumerator]; + while ((entry = [entryEnum nextObject])) { + NSString *typeStr = [entry objectForKey:@"type"]; + NSString *value = nil; + if (typeStr) { + if ([typeStr isEqualToString:@"IBBindingConnection"]) { + value = [entry objectForKey:@"keypath"]; + } else if ([typeStr isEqualToString:@"IBCocoaOutletConnection"] || + [typeStr isEqualToString:@"IBCocoaActionConnection"]) { + value = [entry objectForKey:@"label"]; + } + if (value) { + [connectionsSet addObject:value]; + } + } + } + return AddStringsToTextContent(connectionsSet, attributes); +} + +static NSString *FindIBTool(void) { + NSString *result = nil; + + NSString *possiblePaths[] = { + @"/usr/bin/ibtool", + @"/Developer/usr/bin/ibtool", + }; + + NSFileManager *fm = [NSFileManager defaultManager]; + BOOL isDir; + for (size_t i = 0; i < (sizeof(possiblePaths) / sizeof(NSString*)); ++i) { + if ([fm fileExistsAtPath:possiblePaths[i] isDirectory:&isDir] && + !isDir) { + result = possiblePaths[i]; + break; + } + } + + return result; +} + +static NSData *CommandOutput(NSString *cmd) { + NSMutableData *result = [NSMutableData data]; + + // NOTE: we use popen/pclose in here instead of NSTask because NSTask uses + // a delayed selector to clean up the process it spawns, so since we have + // no runloop it gets ungly trying to clean up the zombie process. + + FILE *fp; + char buffer[2048]; + size_t len; + if((fp = popen([cmd UTF8String], "r"))) { + // spool it all in + while ((len = fread(buffer, 1, sizeof(buffer), fp)) > 0) { + [result appendBytes:buffer length:len]; + } + // make sure we get a clean exit status + if (pclose(fp) != 0) { + result = nil; + } + } + return result; +} + +static BOOL ImportIBFile(NSMutableDictionary *attributes, + NSString *pathToFile) { + BOOL wasGood = NO; + NSString *ibtoolPath = FindIBTool(); + if (ibtoolPath) { + NSString *cmdString + = @"%@ --classes --localizable-strings --connections \"%@\""; + NSString *cmd = [NSString stringWithFormat:cmdString, ibtoolPath, pathToFile]; + NSData *data = CommandOutput(cmd); + if (data) { + NSDictionary *results + = GTMCFAutorelease(CFPropertyListCreateFromXMLData(NULL, + (CFDataRef)data , + kCFPropertyListImmutable, + NULL)); + if (results && [results isKindOfClass:[NSDictionary class]]) { + wasGood = ExtractClasses(results, attributes); + wasGood |= ExtractLocalizableStrings(results, attributes); + wasGood |= ExtractConnections(results, attributes); + } + } + } + + return wasGood; +} + +// Grabs all of the classes, localizable strings, bindings, outlets +// and actions and sticks them into kMDItemTextContent. +Boolean GetMetadataForFile(void* interface, + CFMutableDictionaryRef cfAttributes, + CFStringRef contentTypeUTI, + CFStringRef cfPathToFile) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSMutableDictionary *attributes = (NSMutableDictionary*)cfAttributes; + NSString *pathToFile = (NSString*)cfPathToFile; + BOOL wasGood = NO; + if (UTTypeConformsTo(contentTypeUTI, + CFSTR("com.apple.interfacebuilder.document")) + || UTTypeConformsTo(contentTypeUTI, + CFSTR("com.apple.interfacebuilder.document.cocoa")) + || UTTypeConformsTo(contentTypeUTI, + CFSTR("com.apple.interfacebuilder.document.carbon"))) { + wasGood = ImportIBFile(attributes, pathToFile); + } + [pool release]; + return wasGood == NO ? FALSE : TRUE; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/Info.plist new file mode 100644 index 00000000..8412ec04 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeRole + MDImporter + LSItemContentTypes + + com.apple.interfacebuilder.document.cocoa + com.apple.interfacebuilder.document.carbon + com.apple.interfacebuilder.document + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.spotlightimporter.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleVersion + 1.0 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + CFPlugInFactories + + 556C7CA3-979B-44B2-BF4A-EADD88AFE0D9 + MetadataImporterPluginFactory + + CFPlugInTypes + + 8B08C4BF-415B-11D8-B3F9-0003936726FC + + 556C7CA3-979B-44B2-BF4A-EADD88AFE0D9 + + + CFPlugInUnloadFunction + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/PluginID.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/PluginID.h new file mode 100644 index 00000000..c89c0913 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/PluginID.h @@ -0,0 +1,19 @@ +// +// PluginID.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#define PLUGIN_ID "556C7CA3-979B-44B2-BF4A-EADD88AFE0D9" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/ReadMe.rtf b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/ReadMe.rtf new file mode 100644 index 00000000..16cd43d2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/ReadMe.rtf @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 InterfaceBuilder Spotlight Plugin\ +\ +Copyright 2008 Google Inc.\ +\ +Licensed under the Apache License, Version 2.0 (the "License"); you may not\ +use this file except in compliance with the License. You may obtain a copy\ +of the License at\ +\ +http://www.apache.org/licenses/LICENSE-2.0\ + \ +Unless required by applicable law or agreed to in writing, software\ +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\ +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\ +License for the specific language governing permissions and limitations under\ +the License.\ +\ +-----------------------\ +\ +This is a spotlight importer for nibs and xibs.\ +Makes it easy for you to search nibs and xibs for classes they use.\ +Class names, bindings, outlets, actions and localizable strings are added \ +to the text content attribute.\ +\ +To install the spotlight plugin, please copy it into /Library/Spotlight or ~/Library/Spotlight.\ +\ +This spotlight plugin requires Xcode 3 or better (specifically ibtool).\ +\ +It is part of the Google Toolbox For Mac project\ +http://code.google.com/p/google-toolbox-for-mac/} \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCarbonTest.xib b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCarbonTest.xib new file mode 100644 index 00000000..aea96ba6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCarbonTest.xib @@ -0,0 +1,3106 @@ + + + + 1050 + 9E17 + 672 + 949.33 + 352.00 + + YES + + + + + YES + com.apple.InterfaceBuilder.CarbonPlugin + + + YES + + Menu + + YES + + + TestLocalizedString + + 1048576 + 2147483647 + + NSMenuCheckmark + 1623195648 + + + NSMenuMixedState + 1623195648 + + submenuAction: + + TestLocalizedString + + YES + + + About NewApplication + + 2147483647 + + + About NewApplication + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + UHJlZmVyZW5jZXPigKY + , + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + Services + + + + + + + + + Services + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Hide NewApplication + h + 1048576 + 2147483647 + + + Hide NewApplication + h + + + + + + + + + + + + + + + + + + + + + + Hide Others + h + 1572864 + 2147483647 + + + Hide Others + h + + + + + + + + + + + + + + + + + + + + + + Show All + + 1048576 + 2147483647 + + + Show All + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Quit NewApplication + q + 1048576 + 2147483647 + + + Quit NewApplication + q + + + + + + + + + + + + + + + + + + + + + + _NSAppleMenu + + TestLocalizedString + + + + + + + + + TestLocalizedString + + + + + + + + + + + + + + + + + + + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + New + n + + + + + + + + + + + + + + + + + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + T3BlbuKApg + o + + + + + + + + + + + + + + + + + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + Clear Menu + + + + + + + + + + + + + + + + + + + + + + Open Recent + + + + + + + + + Open Recent + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Close + w + 1048576 + 2147483647 + + + Close + w + + + + + + + + + + + + + + + + + + + + + + Save + s + 1048576 + 2147483647 + + + Save + s + + + + + + + + + + + + + + + + + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + U2F2ZSBBc+KApg + S + + + + + + + + + + + + + + + + + + + + + + Revert to Saved + + 2147483647 + + + Revert to Saved + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + UGFnZSBTZXR1cOKApg + P + 1179648 + 2147483647 + + + UGFnZSBTZXR1cOKApg + P + + + + + + + + + + + + + + + + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + UHJpbnTigKY + p + + + + + + + + + + + + + + + + + + + + + File + + + + + + + + + File + + + + + + + + + + + + + + + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + Undo + z + + + + + + + + + + + + + + + + + + + + + + Redo + Z + 1179648 + 2147483647 + + + Redo + Z + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Cut + x + 1048576 + 2147483647 + + + Cut + x + + + + + + + + + + + + + + + + + + + + + + Copy + c + 1048576 + 2147483647 + + + Copy + c + + + + + + + + + + + + + + + + + + + + + + Paste + v + 1048576 + 2147483647 + + + Paste + v + + + + + + + + + + + + + + + + + + + + + + Delete + + 1048576 + 2147483647 + + + Delete + + + + + + + + + + + + + + + + + + + + + + + Select All + a + 1048576 + 2147483647 + + + Select All + a + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + RmluZOKApg + f + + + + + + + + + + + + + + + + + + + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + Find Next + g + + + + + + + + + + + + + + + + + + + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + Find Previous + G + + + + + + + + + + + + + + + + + + + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + Use Selection for Find + e + + + + + + + + + + + + + + + + + + + + + + Jump to Selection + j + 1048576 + 2147483647 + + + Jump to Selection + j + + + + + + + + + + + + + + + + + + + + + Find + + + + + + + + + Find + + + + + + + + + + + + + + + + + + + + + + + Spelling + + 1048576 + 2147483647 + + + submenuAction: + + Spelling + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + U2hvdyBTcGVsbGluZ+KApg + : + + + + + + + + + + + + + + + + + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + Check Spelling + ; + + + + + + + + + + + + + + + + + + + + + + Check Spelling as You Type + + 1048576 + 2147483647 + + + Check Spelling as You Type + + + + + + + + + + + + + + + + + + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + Check Grammar With Spelling + + + + + + + + + + + + + + + + + + + + + + Spelling + + + + + + + + + Spelling + + + + + + + + + + + + + + + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy Paste + + 1048576 + 2147483647 + + + Smart Copy Paste + + + + + + + + + + + + + + + + + + + + + + + Smart Quotes + + 1048576 + 2147483647 + + + Smart Quotes + + + + + + + + + + + + + + + + + + + + + + + Smart Links + + 1048576 + 2147483647 + + + Smart Links + + + + + + + + + + + + + + + + + + + + + + Substitutions + + + + + + + + + Substitutions + + + + + + + + + + + + + + + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + Start Speaking + + + + + + + + + + + + + + + + + + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + Stop Speaking + + + + + + + + + + + + + + + + + + + + + + Speech + + + + + + + + + Speech + + + + + + + + + + + + + + + + + + + + + + Edit + + + + + + + + + Edit + + + + + + + + + + + + + + + + + + + + + + + Format + + 1048576 + 2147483647 + + + submenuAction: + + Format + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + Show Fonts + t + + + + + + + + + + + + + + + + + + + + + + Show Colors + C + 1179648 + 2147483647 + + + Show Colors + C + + + + + + + + + + + + + + + + + + + + + + Format + + + + + + + + + Format + + + + + + + + + + + + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + Show Toolbar + t + + + + + + + + + + + + + + + + + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 1048576 + 2147483647 + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + + + + + + + + + + + + + + + + + + + + + View + + + + + + + + + View + + + + + + + + + + + + + + + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + Minimize + m + + + + + + + + + + + + + + + + + + + + + + Zoom + + 1048576 + 2147483647 + + + Zoom + + + + + + + + + + + + + + + + + + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + + + + + + + + + + + + + + + + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + Bring All to Front + + + + + + + + + + + + + + + + + + + + + + + _NSWindowsMenu + + Window + + + + + + + + + Window + + + + + + + + + + + + + + + + + + + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + NewApplication Help + ? + + + + + + + + + + + + + + + + + + + + + + _NSWindowsMenu + + Help + + + + + + + + + Help + + + + + + + + + + + + + + + + + + + + + + + _NSMainMenu + + Menu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Window + + + 256 + {480, 360} + + + + + + + + + + + + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + YES + + + + + {{300, 300}, {480, 360}} + {{0, 48}, {1920, 1129}} + + + YES + + + + + + YES + + + + YES + + 0 + + YES + + + + + + 316 + + + YES + + + + Window + + + 317 + + + + + 399 + + + YES + + + + + + + + + + MainMenu + + + 400 + + + YES + + + + + + 401 + + + YES + + + + + + 402 + + + YES + + + + + + 403 + + + YES + + + + + + 404 + + + YES + + + + + + 405 + + + YES + + + + + + 406 + + + YES + + + + + + 407 + + + YES + + + + + + + + + + + + + + + + 408 + + + YES + + + + + + 409 + + + + + 410 + + + + + 411 + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + YES + + + + + + 420 + + + + + 421 + + + YES + + + + + + + + + + + + + + + + + + 422 + + + YES + + + + + + 423 + + + YES + + + + + + 424 + + + YES + + + + + + 425 + + + + + 426 + + + + + 427 + + + YES + + + + + + 428 + + + + + 429 + + + + + 430 + + + + + 431 + + + + + 432 + + + + + 433 + + + + + 434 + + + + + 435 + + + YES + + + + + + + + + 436 + + + + + 437 + + + + + 438 + + + + + 439 + + + + + 440 + + + YES + + + + + + + + + + 441 + + + + + 442 + + + + + 443 + + + + + 444 + + + + + 445 + + + + + 446 + + + YES + + + + + + + 447 + + + + + 448 + + + + + 449 + + + YES + + + + + + + + 450 + + + + + 451 + + + + + 452 + + + + + 453 + + + YES + + + + + + + + + 454 + + + + + 455 + + + + + 456 + + + + + 457 + + + + + 458 + + + YES + + + + + + + + + + + + + + + + 459 + + + + + 460 + + + + + 461 + + + + + 462 + + + + + 463 + + + YES + + + + + + 464 + + + + + 465 + + + + + 466 + + + + + 467 + + + + + 468 + + + + + 469 + + + + + 470 + + + + + 471 + + + YES + + + + + + 472 + + + + + 473 + + + YES + + + + + + + 474 + + + + + 475 + + + + + 476 + + + YES + + + + + + + 477 + + + + + 478 + + + + + + + YES + + YES + 316.IBEditorWindowLastContentRect + 316.IBPluginDependency + 316.IBWindowTemplateEditedContentRect + 316.editorWindowContentRectSynchronizationRect + 317.IBPluginDependency + 399.IBEditorWindowLastContentRect + 399.IBPluginDependency + 399.editorWindowContentRectSynchronizationRect + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 407.editorWindowContentRectSynchronizationRect + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 419.editorWindowContentRectSynchronizationRect + 420.IBPluginDependency + 421.IBPluginDependency + 421.editorWindowContentRectSynchronizationRect + 422.IBPluginDependency + 423.IBPluginDependency + 424.IBPluginDependency + 425.IBPluginDependency + 426.IBPluginDependency + 427.IBPluginDependency + 428.IBPluginDependency + 429.IBPluginDependency + 430.IBPluginDependency + 431.IBPluginDependency + 432.IBPluginDependency + 433.IBPluginDependency + 434.IBPluginDependency + 435.IBPluginDependency + 435.editorWindowContentRectSynchronizationRect + 436.IBPluginDependency + 437.IBPluginDependency + 438.IBPluginDependency + 439.IBPluginDependency + 440.IBPluginDependency + 440.editorWindowContentRectSynchronizationRect + 441.IBPluginDependency + 442.IBPluginDependency + 443.IBPluginDependency + 444.IBPluginDependency + 445.IBPluginDependency + 446.IBPluginDependency + 446.editorWindowContentRectSynchronizationRect + 447.IBPluginDependency + 448.IBPluginDependency + 449.IBPluginDependency + 449.editorWindowContentRectSynchronizationRect + 450.IBPluginDependency + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 453.editorWindowContentRectSynchronizationRect + 454.IBPluginDependency + 455.IBPluginDependency + 456.IBPluginDependency + 457.IBPluginDependency + 458.IBEditorWindowLastContentRect + 458.IBPluginDependency + 458.editorWindowContentRectSynchronizationRect + 459.IBPluginDependency + 460.IBPluginDependency + 461.IBPluginDependency + 462.IBPluginDependency + 463.IBPluginDependency + 464.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 467.IBPluginDependency + 468.IBPluginDependency + 469.IBPluginDependency + 470.IBPluginDependency + 470.editorWindowContentRectSynchronizationRect + 471.IBPluginDependency + 471.editorWindowContentRectSynchronizationRect + 472.IBPluginDependency + 473.IBPluginDependency + 473.editorWindowContentRectSynchronizationRect + 474.IBPluginDependency + 475.IBPluginDependency + 476.IBPluginDependency + 476.editorWindowContentRectSynchronizationRect + 477.IBPluginDependency + 478.IBPluginDependency + + + YES + {{247, 233}, {480, 360}} + com.apple.InterfaceBuilder.CarbonPlugin + {{247, 233}, {480, 360}} + {{325, 394}, {480, 360}} + com.apple.InterfaceBuilder.CarbonPlugin + {{21, 803}, {507, 20}} + com.apple.InterfaceBuilder.CarbonPlugin + {{325, 836}, {478, 20}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{159, 779}, {199, 203}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{358, 919}, {146, 23}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{511, 593}, {181, 243}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{692, 573}, {275, 83}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{382, 719}, {241, 103}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{382, 719}, {167, 43}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{382, 719}, {188, 63}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{361, 909}, {197, 73}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{33, 620}, {245, 183}} + com.apple.InterfaceBuilder.CarbonPlugin + {{27, 799}, {245, 183}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{272, 916}, {64, 6}} + com.apple.InterfaceBuilder.CarbonPlugin + {{432, 959}, {216, 23}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{311, 939}, {234, 43}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + {{555, 793}, {176, 43}} + com.apple.InterfaceBuilder.CarbonPlugin + com.apple.InterfaceBuilder.CarbonPlugin + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 478 + + + 0 + + 3 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCocoaTest.xib b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCocoaTest.xib new file mode 100644 index 00000000..e2119bc8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/InterfaceBuilder/TestData/XibCocoaTest.xib @@ -0,0 +1,3075 @@ + + + + 1050 + 9E17 + 672 + 949.33 + 352.00 + + YES + + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + NSFontManager + + + AMainMenu + + YES + + + TestLocalizedString + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + TestLocalizedString + + YES + + + About NewApplication + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide NewApplication + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit NewApplication + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + T3BlbuKApg + o + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + U2F2ZSBBc+KApg + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + UHJpbnTigKY + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + YES + + + RmluZOKApg + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + U2hvdyBTcGVsbGluZ+KApg + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + + 2147483647 + + + 1 + + + + Smart Quotes + + 2147483647 + + + 2 + + + + Smart Links + + 2147483647 + + + 3 + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Q3VzdG9taXplIFRvb2xiYXLigKY + + 2147483647 + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + 15 + 2 + {{196, 240}, {480, 270}} + 603979776 + Window + TestCustomClass + + {3.40282e+38, 3.40282e+38} + + + 256 + + YES + + + 268 + {{66, 214}, {96, 32}} + + YES + + 67239424 + 134217728 + Button + + LucidaGrande + 1.300000e+01 + 1044 + + + -2038284033 + 129 + + + 200 + 25 + + + + {480, 270} + + + {{0, 0}, {1920, 1178}} + {3.40282e+38, 3.40282e+38} + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + unhideAllApplications: + + + + 372 + + + + addFontTrait: + + + + 420 + + + + addFontTrait: + + + + 421 + + + + modifyFont: + + + + 422 + + + + orderFrontFontPanel: + + + + 423 + + + + modifyFont: + + + + 424 + + + + raiseBaseline: + + + + 425 + + + + lowerBaseline: + + + + 426 + + + + copyFont: + + + + 427 + + + + subscript: + + + + 428 + + + + superscript: + + + + 429 + + + + tightenKerning: + + + + 430 + + + + underline: + + + + 431 + + + + orderFrontColorPanel: + + + + 432 + + + + useAllLigatures: + + + + 433 + + + + loosenKerning: + + + + 434 + + + + pasteFont: + + + + 435 + + + + unscript: + + + + 436 + + + + useStandardKerning: + + + + 437 + + + + useStandardLigatures: + + + + 438 + + + + turnOffLigatures: + + + + 439 + + + + turnOffKerning: + + + + 440 + + + + alignLeft: + + + + 441 + + + + alignJustified: + + + + 442 + + + + copyRuler: + + + + 443 + + + + alignCenter: + + + + 444 + + + + toggleRuler: + + + + 445 + + + + alignRight: + + + + 446 + + + + pasteRuler: + + + + 447 + + + + terminate: + + + + 448 + + + + visible: testBinding + + + + + + visible: testBinding + visible + testBinding + 2 + + + 459 + + + + testAction: + + + + 462 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + Main Menu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 367 + + + YES + + + + + + 368 + + + YES + + + + + + 373 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 378 + + + YES + + + + + + 379 + + + YES + + + + + + + + + + + + + 380 + + + + + 381 + + + + + 382 + + + + + 383 + + + + + 384 + + + + + 385 + + + + + 386 + + + + + 387 + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 460 + + + YES + + + + + + 461 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBEditorWindowLastContentRect + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBEditorWindowLastContentRect + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 367.IBEditorWindowLastContentRect + 367.IBPluginDependency + 367.IBWindowTemplateEditedContentRect + 367.NSWindowTemplate.visibleAtLaunch + 367.editorWindowContentRectSynchronizationRect + 368.IBPluginDependency + 375.IBPluginDependency + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 385.IBPluginDependency + 386.IBPluginDependency + 387.IBPluginDependency + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 460.IBPluginDependency + 461.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{518, 723}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{617, 609}, {132, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{531, 606}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{530, 483}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{287, 503}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{197, 734}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{530, 483}, {153, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{530, 483}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{447, 673}, {197, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{101, 746}, {507, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 977}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{397, 703}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{530, 483}, {177, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{440, 714}, {177, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{490, 307}, {480, 270}} + com.apple.InterfaceBuilder.CocoaPlugin + {{490, 307}, {480, 270}} + + {{11, 666}, {480, 270}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{113, 563}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{418, 469}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{323, 672}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 462 + + + + YES + + FirstResponder + NSObject + + testAction: + id + + + IBUserSource + + + + + + 0 + + 3 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/English.lproj/InfoPlist.strings b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/English.lproj/InfoPlist.strings new file mode 100644 index 00000000..7f81cad9 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/English.lproj/InfoPlist.strings differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/GetMetadataForFile.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/GetMetadataForFile.m new file mode 100644 index 00000000..5bdab363 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/GetMetadataForFile.m @@ -0,0 +1,85 @@ +// +// GetMetadataForFile.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +static BOOL ImportProjectFile(NSMutableDictionary *attributes, + NSString *pathToFile) { + pathToFile = [pathToFile stringByAppendingPathComponent:@"project.pbxproj"]; + NSMutableSet *filenames = [[[NSMutableSet alloc] init] autorelease]; + NSMutableSet *comments = [[[NSMutableSet alloc] init] autorelease]; + BOOL wasGood = NO; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:pathToFile]; + if (dict) { + NSDictionary *objects = [dict objectForKey:@"objects"]; + if (objects) { + NSEnumerator *objEnumerator = [objects objectEnumerator]; + NSDictionary *object; + while ((object = [objEnumerator nextObject])) { + NSString *isaType = [object objectForKey:@"isa"]; + if ([isaType caseInsensitiveCompare:@"PBXFileReference"] == NSOrderedSame) { + NSString *path = [object objectForKey:@"path"]; + if (path) { + [filenames addObject:[path lastPathComponent]]; + } + } else if ([isaType caseInsensitiveCompare:@"PBXNativeTarget"] == NSOrderedSame) { + NSString *name = [object objectForKey:@"name"]; + if (name) { + [filenames addObject:name]; + } + name = [object objectForKey:@"productName"]; + if (name) { + [filenames addObject:name]; + } + } + NSString *comment = [object objectForKey:@"comments"]; + if (comment) { + [comments addObject:comment]; + } + } + } + } + if ([filenames count]) { + NSString *description = [[filenames allObjects] componentsJoinedByString:@"\n"]; + [attributes setObject:description forKey:(NSString*)kMDItemDescription]; + wasGood = YES; + } + if ([comments count]) { + NSString *comment = [[comments allObjects] componentsJoinedByString:@"\n"]; + [attributes setObject:comment forKey:(NSString*)kMDItemComment]; + wasGood = YES; + } + return wasGood; +} + +// Currently grabs all the filenames, target names, and product names +// and sticks them into kMDItemDescription. +// It also grabs all of the comments and sticks them into kMDItemComment. +Boolean GetMetadataForFile(void* interface, + CFMutableDictionaryRef cfAttributes, + CFStringRef contentTypeUTI, + CFStringRef cfPathToFile) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSMutableDictionary *attributes = (NSMutableDictionary*)cfAttributes; + NSString *pathToFile = (NSString*)cfPathToFile; + BOOL wasGood = NO; + if (UTTypeConformsTo(contentTypeUTI, CFSTR("com.apple.xcode.project"))) { + wasGood = ImportProjectFile(attributes, pathToFile); + } + [pool release]; + return wasGood == NO ? FALSE : TRUE; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/Info.plist new file mode 100644 index 00000000..def1f7f7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeRole + MDImporter + LSItemContentTypes + + com.apple.xcode.project + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.spotlightimporter.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleVersion + 1.0 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + CFPlugInFactories + + 1CDB2B3C-CD6F-407D-9217-230E6DED8B00 + MetadataImporterPluginFactory + + CFPlugInTypes + + 8B08C4BF-415B-11D8-B3F9-0003936726FC + + 1CDB2B3C-CD6F-407D-9217-230E6DED8B00 + + + CFPlugInUnloadFunction + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/PluginID.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/PluginID.h new file mode 100644 index 00000000..69c7a279 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/PluginID.h @@ -0,0 +1,19 @@ +// +// PluginID.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#define PLUGIN_ID "1CDB2B3C-CD6F-407D-9217-230E6DED8B00" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/ReadMe.rtf b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/ReadMe.rtf new file mode 100644 index 00000000..bd2eb697 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/ReadMe.rtf @@ -0,0 +1,31 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 XcodeProject Spotlight Plugin\ +\ +Copyright 2008 Google Inc.\ +\ +Licensed under the Apache License, Version 2.0 (the "License"); you may not\ +use this file except in compliance with the License. You may obtain a copy\ +of the License at\ +\ +http://www.apache.org/licenses/LICENSE-2.0\ + \ +Unless required by applicable law or agreed to in writing, software\ +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\ +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\ +License for the specific language governing permissions and limitations under\ +the License.\ +\ +-----------------------\ +\ +This is a spotlight importer for Xcode Projects. \ +Makes it easy for you to search xcode project for specific files they include\ +or text in the project comments.\ +\ +To install the spotlight plugin, please copy it into /Library/Spotlight or ~/Library/Spotlight.\ +\ +It is part of the Google Toolbox For Mac project\ +http://code.google.com/p/google-toolbox-for-mac/} \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/schema.xml b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/schema.xml new file mode 100644 index 00000000..cd3f3f7c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/SpotlightPlugins/XcodeProject/schema.xml @@ -0,0 +1,31 @@ + + + + + + + + kMDItemComment kMDItemDescription + + + + + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/TigerGcov/libgcov_readme.html b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/TigerGcov/libgcov_readme.html new file mode 100644 index 00000000..fc381a70 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/TigerGcov/libgcov_readme.html @@ -0,0 +1,11 @@ + + + + libgcov_readme.html + + + + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTest-Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTest-Info.plist new file mode 100644 index 00000000..71daf7db --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTest-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.h new file mode 100644 index 00000000..016da7e6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.h @@ -0,0 +1,144 @@ +// +// GTMAppKit+UnitTesting.m +// +// Categories for making unit testing of graphics/UI easier. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMNSObject+UnitTesting.h" + +// Categories for making unit testing of graphics/UI easier. +// Allows you to take a state/images of instances of AppKit classes. +// See GTMNSObject+UnitTesting.h for details. + +@interface NSApplication (GTMUnitTestingAdditions) +@end + +@interface NSWindow (GTMUnitTestingAdditions) +@end + +@interface NSControl (GTMUnitTestingAdditions) +@end + +@interface NSTextField (GTMUnitTestingAdditions) +@end + +@interface NSCell (GTMUnitTestingAdditions) +@end + +@interface NSImage (GTMUnitTestingAdditions) +@end + +@interface NSMenu (GTMUnitTestingAdditions) +@end + +@interface NSMenuItem (GTMUnitTestingAdditions) +@end + +@protocol GTMUnitTestViewDrawer; + +// Fails when the |a1|'s drawing in an area |a2| does not equal the image file named |a3|. +// See the description of the -gtm_pathForImageNamed method +// to understand how |a3| is found and written out. +// See the description of the GTMUnitTestView for a better idea +// how the view works. +// Implemented as a macro to match the rest of the SenTest macros. +// +// Args: +// a1: The object that implements the GTMUnitTestViewDrawer protocol +// that is doing the drawing. +// a2: The size of the drawing +// a3: The name of the image file to check against. +// Do not include the extension +// a4: contextInfo to pass to drawer +// description: A format string as in the printf() function. +// Can be nil or an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +// + +#define GTMAssertDrawingEqualToImageNamed(a1, a2, a3, a4, description, ...) \ + do { \ + id a1Drawer = (a1); \ + NSSize a2Size = (a2); \ + NSString* a3String = (a3); \ + void *a4ContextInfo = (a4); \ + NSRect frame = NSMakeRect(0, 0, a2Size.width, a2Size.height); \ + GTMUnitTestView *view = [[[GTMUnitTestView alloc] initWithFrame:frame drawer:a1Drawer contextInfo:a4ContextInfo] autorelease]; \ + GTMAssertObjectImageEqualToImageNamed(view, a3String, STComposeString(description, ##__VA_ARGS__)); \ + } while(0) + +// Category for making unit testing of graphics/UI easier. + +// Allows you to take a state of a view. Supports both image and state. +// See NSObject+UnitTesting.h for details. +@interface NSView (GTMUnitTestingAdditions) +// Returns whether unitTestEncodeState should recurse into subviews +// +// If you have "Full keyboard access" in the +// Keyboard & Mouse > Keyboard Shortcuts preferences pane set to "Text boxes +// and Lists only" that Apple adds a set of subviews to NSTextFields. So in the +// case of NSTextFields we don't want to recurse into their subviews. There may +// be other cases like this, so instead of specializing unitTestEncodeState: to +// look for NSTextFields, NSTextFields will just not allow us to recurse into +// their subviews. +// +// Returns: +// should unitTestEncodeState pick up subview state. +- (BOOL)gtm_shouldEncodeStateForSubviews; + +@end + +// A view that allows you to delegate out drawing using the formal +// GTMUnitTestViewDelegate protocol +// This is useful when writing up unit tests for visual elements. +// Your test will often end up looking like this: +// - (void)testFoo { +// GTMAssertDrawingEqualToFile(self, NSMakeSize(200, 200), @"Foo", nil, nil); +// } +// and your testSuite will also implement the unitTestViewDrawRect method to do +// it's actual drawing. The above creates a view of size 200x200 that draws +// it's content using |self|'s unitTestViewDrawRect method and compares it to +// the contents of the file Foo.tif to make sure it's valid +@interface GTMUnitTestView : NSView { + @private + id drawer_; // delegate for doing drawing (STRONG) + void* contextInfo_; // info passed in by user for them to use when drawing +} + +// Create a GTMUnitTestView. +// +// Args: +// rect: the area to draw. +// drawer: the object that will do the drawing via the GTMUnitTestViewDrawer +// protocol +// contextInfo: +- (id)initWithFrame:(NSRect)frame drawer:(id)drawer contextInfo:(void*)contextInfo; +@end + +/// \cond Protocols + +// Formal protocol for doing unit testing of views. See description of +// GTMUnitTestView for details. +@protocol GTMUnitTestViewDrawer + +// Draw the view. Equivalent to drawRect on a standard NSView. +// +// Args: +// rect: the area to draw. +- (void)gtm_unitTestViewDrawRect:(NSRect)rect contextInfo:(void*)contextInfo; +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.m new file mode 100644 index 00000000..c35d07d8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMAppKit+UnitTesting.m @@ -0,0 +1,341 @@ +// +// GTMAppKit+UnitTesting.m +// +// Categories for making unit testing of graphics/UI easier. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import "GTMAppKit+UnitTesting.h" +#import "GTMGeometryUtils.h" +#import "GTMMethodCheck.h" +#import "GTMGarbageCollection.h" + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 + #define ENCODE_NSINTEGER(coder, i, key) [(coder) encodeInt:(i) forKey:(key)] +#else + #define ENCODE_NSINTEGER(coder, i, key) [(coder) encodeInteger:(i) forKey:(key)] +#endif + +@implementation NSApplication (GMUnitTestingAdditions) +GTM_METHOD_CHECK(NSObject, gtm_unitTestEncodeState:); + +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + ENCODE_NSINTEGER(inCoder, [[self mainWindow] windowNumber], @"ApplicationMainWindow"); + + // Descend down into the windows allowing them to store their state + NSWindow *window = nil; + int i = 0; + GTM_FOREACH_OBJECT(window, [self windows]) { + if ([window isVisible]) { + // Only record visible windows because invisible windows may be closing on us + // This appears to happen differently in 64 bit vs 32 bit, and items + // in the window may hold an extra retain count for a while until the + // event loop is spun. To avoid all this, we just don't record non + // visible windows. + // See rdar://5851458 for details. + [inCoder encodeObject:window forKey:[NSString stringWithFormat:@"Window %d", i]]; + i = i + 1; + } + } + + // and encode the menu bar + NSMenu *mainMenu = [self mainMenu]; + if (mainMenu) { + [inCoder encodeObject:mainMenu forKey:@"MenuBar"]; + } +} +@end + +@implementation NSWindow (GMUnitTestingAdditions) + +- (CGImageRef)gtm_unitTestImage { + return [[[self contentView] superview] gtm_unitTestImage]; +} + +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeObject:[self title] forKey:@"WindowTitle"]; + [inCoder encodeBool:[self isVisible] forKey:@"WindowIsVisible"]; + // Do not record if window is key, because users running unit tests + // and clicking around to other apps, could change this mid test causing + // issues. + // [inCoder encodeBool:[self isKeyWindow] forKey:@"WindowIsKey"]; + [inCoder encodeBool:[self isMainWindow] forKey:@"WindowIsMain"]; + [inCoder encodeObject:[self contentView] forKey:@"WindowContent"]; +} + +@end + +@implementation NSControl (GTMUnitTestingAdditions) + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeObject:[self class] forKey:@"ControlType"]; + [inCoder encodeObject:[self objectValue] forKey:@"ControlValue"]; + [inCoder encodeObject:[self selectedCell] forKey:@"ControlSelectedCell"]; + ENCODE_NSINTEGER(inCoder, [self tag], @"ControlTag"); + [inCoder encodeBool:[self isEnabled] forKey:@"ControlIsEnabled"]; +} + +@end + +@implementation NSTextField (GTMUnitTestingAdditions) + +- (BOOL)gtm_shouldEncodeStateForSubviews { + return NO; +} + +@end + +@implementation NSCell (GTMUnitTestingAdditions) + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + BOOL isImageCell = NO; + if ([self hasValidObjectValue]) { + id val = [self objectValue]; + [inCoder encodeObject:val forKey:@"CellValue"]; + isImageCell = [val isKindOfClass:[NSImage class]]; + } + if (!isImageCell) { + // Image cells have a title that includes addresses that aren't going + // to be constant, so we don't encode them. All the info we need + // is going to be in the CellValue encoding. + [inCoder encodeObject:[self title] forKey:@"CellTitle"]; + } + ENCODE_NSINTEGER(inCoder, [self state], @"CellState"); + ENCODE_NSINTEGER(inCoder, [self tag], @"CellTag"); +} + +@end + +@implementation NSImage (GTMUnitTestingAdditions) + +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeObject:NSStringFromSize([self size]) forKey:@"ImageSize"]; + [inCoder encodeObject:[self name] forKey:@"ImageName"]; +} + +- (CGImageRef)gtm_unitTestImage { + // Create up a context + NSSize size = [self size]; + NSRect rect = GTMNSRectOfSize(size); + CGSize cgSize = GTMNSSizeToCGSize(size); + CGContextRef contextRef = GTMCreateUnitTestBitmapContextOfSizeWithData(cgSize, + NULL); + NSGraphicsContext *bitmapContext + = [NSGraphicsContext graphicsContextWithGraphicsPort:contextRef flipped:NO]; + _GTMDevAssert(bitmapContext, @"Couldn't create ns bitmap context"); + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:bitmapContext]; + [self drawInRect:rect fromRect:rect operation:NSCompositeCopy fraction:1.0]; + + CGImageRef image = CGBitmapContextCreateImage(contextRef); + CFRelease(contextRef); + [NSGraphicsContext restoreGraphicsState]; + return (CGImageRef)GTMCFAutorelease(image); +} + +@end + +@implementation NSMenu (GTMUnitTestingAdditions) + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + // Hack here to work around + // rdar://5881796 Application menu item title wrong when accessed programatically + // which causes us to have different results on x86_64 vs x386. + // Hack is braced intentionally. We don't record the title of the + // "application" menu or it's menu title because they are wrong on 32 bit. + // They appear to work right on 64bit. + { + NSMenu *mainMenu = [NSApp mainMenu]; + NSMenu *appleMenu = [[mainMenu itemAtIndex:0] submenu]; + if (![self isEqual:appleMenu]) { + [inCoder encodeObject:[self title] forKey:@"MenuTitle"]; + } + } + // Descend down into the menuitems allowing them to store their state + NSMenuItem *menuItem = nil; + int i = 0; + GTM_FOREACH_OBJECT(menuItem, [self itemArray]) { + [inCoder encodeObject:menuItem + forKey:[NSString stringWithFormat:@"MenuItem %d", i]]; + ++i; + } +} + +@end + +@implementation NSMenuItem (GTMUnitTestingAdditions) + +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + // Hack here to work around + // rdar://5881796 Application menu item title wrong when accessed programatically + // which causes us to have different results on x86_64 vs x386. + // See comment above. + { + NSMenu *mainMenu = [NSApp mainMenu]; + NSMenuItem *appleMenuItem = [mainMenu itemAtIndex:0]; + if (![self isEqual:appleMenuItem]) { + [inCoder encodeObject:[self title] forKey:@"MenuItemTitle"]; + } + } + [inCoder encodeObject:[self keyEquivalent] forKey:@"MenuItemKeyEquivalent"]; + [inCoder encodeBool:[self isSeparatorItem] forKey:@"MenuItemIsSeparator"]; + ENCODE_NSINTEGER(inCoder, [self state], @"MenuItemState"); + [inCoder encodeBool:[self isEnabled] forKey:@"MenuItemIsEnabled"]; + [inCoder encodeBool:[self isAlternate] forKey:@"MenuItemIsAlternate"]; + [inCoder encodeObject:[self toolTip] forKey:@"MenuItemTooltip"]; + ENCODE_NSINTEGER(inCoder, [self tag], @"MenuItemTag"); + ENCODE_NSINTEGER(inCoder, [self indentationLevel], @"MenuItemIndentationLevel"); + + // Do our submenu if neccessary + if ([self hasSubmenu]) { + [inCoder encodeObject:[self submenu] forKey:@"MenuItemSubmenu"]; + } +} + +@end + +// A view that allows you to delegate out drawing using the formal +// GTMUnitTestViewDelegate protocol above. This is useful when writing up unit +// tests for visual elements. +// Your test will often end up looking like this: +// - (void)testFoo { +// GTMAssertDrawingEqualToFile(self, NSMakeSize(200, 200), @"Foo", nil, nil); +// } +// and your testSuite will also implement the unitTestViewDrawRect method to do +// it's actual drawing. The above creates a view of size 200x200 that draws +// it's content using |self|'s unitTestViewDrawRect method and compares it to +// the contents of the file Foo.tif to make sure it's valid +@implementation GTMUnitTestView + +- (id)initWithFrame:(NSRect)frame + drawer:(id)drawer + contextInfo:(void*)contextInfo { + self = [super initWithFrame:frame]; + if (self != nil) { + drawer_ = [drawer retain]; + contextInfo_ = contextInfo; + } + return self; +} + +- (void)dealloc { + [drawer_ release]; + [super dealloc]; +} + + +- (void)drawRect:(NSRect)rect { + [drawer_ gtm_unitTestViewDrawRect:rect contextInfo:contextInfo_]; +} + + +@end + +@implementation NSView (GTMUnitTestingAdditions) + +// Returns an image containing a representation of the object +// suitable for use in comparing against a master image. +// Does all of it's drawing with smoothfonts and antialiasing off +// to avoid issues with font smoothing settings and antialias differences +// between ppc and x86. +// +// Returns: +// an image of the object +- (CGImageRef)gtm_unitTestImage { + // Create up a context + NSRect bounds = [self bounds]; + CGSize cgSize = GTMNSSizeToCGSize(bounds.size); + CGContextRef contextRef = GTMCreateUnitTestBitmapContextOfSizeWithData(cgSize, + NULL); + NSGraphicsContext *bitmapContext + = [NSGraphicsContext graphicsContextWithGraphicsPort:contextRef flipped:NO]; + _GTMDevAssert(bitmapContext, @"Couldn't create ns bitmap context"); + + // Save our state and turn off font smoothing and antialias. + CGContextSaveGState(contextRef); + CGContextSetShouldSmoothFonts(contextRef, false); + CGContextSetShouldAntialias(contextRef, false); + [self displayRectIgnoringOpacity:bounds inContext:bitmapContext]; + + CGImageRef image = CGBitmapContextCreateImage(contextRef); + CFRelease(contextRef); + return (CGImageRef)GTMCFAutorelease(image); +} + +// Returns whether gtm_unitTestEncodeState should recurse into subviews +// of a particular view. +// If you have "Full keyboard access" in the +// Keyboard & Mouse > Keyboard Shortcuts preferences pane set to "Text boxes +// and Lists only" that Apple adds a set of subviews to NSTextFields. So in the +// case of NSTextFields we don't want to recurse into their subviews. There may +// be other cases like this, so instead of specializing gtm_unitTestEncodeState: to +// look for NSTextFields, NSTextFields will just not allow us to recurse into +// their subviews. +// +// Returns: +// should gtm_unitTestEncodeState pick up subview state. +- (BOOL)gtm_shouldEncodeStateForSubviews { + return YES; +} + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeBool:[self isHidden] forKey:@"ViewIsHidden"]; + if ([self gtm_shouldEncodeStateForSubviews]) { + NSView *subview = nil; + int i = 0; + GTM_FOREACH_OBJECT(subview, [self subviews]) { + [inCoder encodeObject:subview forKey:[NSString stringWithFormat:@"ViewSubView %d", i]]; + i = i + 1; + } + } +} + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.h new file mode 100644 index 00000000..b757ba91 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.h @@ -0,0 +1,46 @@ +// +// GTMCALayer+UnitTesting.h +// +// Code for making unit testing of graphics/UI easier. Generally you +// will only want to look at the macros: +// GTMAssertDrawingEqualToFile +// GTMAssertViewRepEqualToFile +// and the protocol GTMUnitTestCALayerDrawer. When using these routines +// make sure you are using device colors and not calibrated/generic colors +// or else your test graphics WILL NOT match across devices/graphics cards. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMNSObject+UnitTesting.h" + +// Category for making unit testing of graphics/UI easier. + +// Allows you to take a state of a view. Supports both image and state. +// See GTMNSObject+UnitTesting.h for details. +@interface CALayer (GTMUnitTestingAdditions) +// Returns whether gtm_unitTestEncodeState should recurse into sublayers +// +// Returns: +// should gtm_unitTestEncodeState pick up sublayer state. +- (BOOL)gtm_shouldEncodeStateForSublayers; +@end + +@interface NSObject (GTMCALayerUnitTestingDelegateMethods) +// Delegate method that allows a delegate for a layer to +// decide whether we should recurse +- (BOOL)gtm_shouldEncodeStateForSublayersOfLayer:(CALayer*)layer; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.m new file mode 100644 index 00000000..3ffa209e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMCALayer+UnitTesting.m @@ -0,0 +1,90 @@ +// +// GTMCALayer+UnitTesting.m +// +// Category for making unit testing of graphics/UI easier. +// Allows you to save a view out to a image file, and compare a view +// with a previously stored representation to make sure it hasn't changed. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMCALayer+UnitTesting.h" +#import "GTMGarbageCollection.h" + +@implementation CALayer (GTMUnitTestingAdditions) + +// Returns an image containing a representation of the object +// suitable for use in comparing against a master image. +// NB this means that all colors should be from "NSDevice" color space +// Does all of it's drawing with smoothfonts and antialiasing off +// to avoid issues with font smoothing settings and antialias differences +// between ppc and x86. +// +// Returns: +// an image of the object +- (CGImageRef)gtm_unitTestImage { + CGRect bounds = [self bounds]; + CGSize size = CGSizeMake(CGRectGetWidth(bounds), CGRectGetHeight(bounds)); + CGContextRef context = GTMCreateUnitTestBitmapContextOfSizeWithData(size, + NULL); + _GTMDevAssert(context, @"Couldn't create context"); + + // iPhone renders are flipped + CGAffineTransform transform = CGAffineTransformMakeTranslation(0, size.height); + transform = CGAffineTransformScale(transform, 1.0, -1.0); + CGContextConcatCTM(context, transform); + + [self renderInContext:context]; + CGImageRef image = CGBitmapContextCreateImage(context); + CFRelease(context); + return (CGImageRef)GTMCFAutorelease(image); +} + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeBool:[self isHidden] forKey:@"LayerIsHidden"]; + [inCoder encodeBool:[self isDoubleSided] forKey:@"LayerIsDoublesided"]; + [inCoder encodeBool:[self isOpaque] forKey:@"LayerIsOpaque"]; + [inCoder encodeFloat:[self opacity] forKey:@"LayerOpacity"]; + // TODO: There is a ton more we can add here. What are we interested in? + if ([self gtm_shouldEncodeStateForSublayers]) { + int i = 0; + for (CALayer *subLayer in [self sublayers]) { + [inCoder encodeObject:subLayer + forKey:[NSString stringWithFormat:@"CALayerSubLayer %d", i]]; + i = i + 1; + } + } +} + +// Returns whether gtm_unitTestEncodeState should recurse into sublayers +// +// Returns: +// should gtm_unitTestEncodeState pick up sublayer state. +- (BOOL)gtm_shouldEncodeStateForSublayers { + BOOL value = YES; + if([self.delegate respondsToSelector:@selector(gtm_shouldEncodeStateForSublayersOfLayer:)]) { + value = [self.delegate gtm_shouldEncodeStateForSublayersOfLayer:self]; + } + return value; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMDevLogUnitTestingBridge.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMDevLogUnitTestingBridge.m new file mode 100644 index 00000000..3d2b84d0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMDevLogUnitTestingBridge.m @@ -0,0 +1,44 @@ +// +// GTMDevLogUnitTestingBridge.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#include "GTMUnitTestDevLog.h" + +// +// NOTE: Odds are this file should not be included in your project. It is +// only needed for some enhanced unit testing. +// +// By adding: +// #define _GTMDevLog _GTMUnitTestDevLog +// to your prefix header (like the GTM Framework does), this function then +// works to forward logging messages to the GTMUnitTestDevLog class to +// allow logging validation during unittest, otherwise the messages go to +// NSLog like normal. +// +// See GTMUnitTestDevLog.h for more information on checking logs in unittests. +// +void _GTMUnitTestDevLog(NSString *format, ...) { + Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog"); + va_list argList; + va_start(argList, format); + if (devLogClass) { + [devLogClass log:format args:argList]; + } else { + NSLogv(format, argList); // COV_NF_LINE the class is in all our unittest setups + } + va_end(argList); +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.h new file mode 100644 index 00000000..4583b5d8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.h @@ -0,0 +1,38 @@ +// +// GTMIPhoneUnitTestDelegate.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// Application delegate that runs all test methods in registered classes +// extending SenTestCase. The application is terminated afterwards. +// You can also run the tests directly from your application by invoking +// runTests and clean up, restore data, etc. before the application +// terminates. +@interface GTMIPhoneUnitTestDelegate : NSObject { + @private + NSUInteger totalFailures_; + NSUInteger totalSuccesses_; +} +// Runs through all the registered classes and runs test methods on any +// that are subclasses of SenTestCase. Prints results and run time to +// the default output. +- (void)runTests; +// Fetch the number of successes or failures from the last runTests. +- (NSUInteger)totalSuccesses; +- (NSUInteger)totalFailures; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.m new file mode 100644 index 00000000..39de1f56 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestDelegate.m @@ -0,0 +1,206 @@ +// +// GTMIPhoneUnitTestDelegate.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMIPhoneUnitTestDelegate.h" + +#import "GTMDefines.h" +#if !GTM_IPHONE_SDK +#error GTMIPhoneUnitTestDelegate for iPhone only +#endif +#import +#import +#import +#import "GTMSenTestCase.h" + +// Used for sorting methods below +static int MethodSort(const void *a, const void *b) { + const char *nameA = sel_getName(method_getName(*(Method*)a)); + const char *nameB = sel_getName(method_getName(*(Method*)b)); + return strcmp(nameA, nameB); +} + +// Return YES if class is subclass (1 or more generations) of SenTestCase +static BOOL IsTestFixture(Class aClass) { + BOOL iscase = NO; + Class testCaseClass = [SenTestCase class]; + Class superclass; + for (superclass = aClass; + !iscase && superclass; + superclass = class_getSuperclass(superclass)) { + iscase = superclass == testCaseClass ? YES : NO; + } + return iscase; +} + +@implementation GTMIPhoneUnitTestDelegate + +// Run through all the registered classes and run test methods on any +// that are subclasses of SenTestCase. Terminate the application upon +// test completion. +- (void)applicationDidFinishLaunching:(UIApplication *)application { + [self runTests]; + + if (!getenv("GTM_DISABLE_TERMINATION")) { + // To help using xcodebuild, make the exit status 0/1 to signal the tests + // success/failure. + int exitStatus = (([self totalFailures] == 0U) ? 0 : 1); + exit(exitStatus); + } +} + +// Run through all the registered classes and run test methods on any +// that are subclasses of SenTestCase. Print results and run time to +// the default output. +- (void)runTests { + int count = objc_getClassList(NULL, 0); + NSMutableData *classData + = [NSMutableData dataWithLength:sizeof(Class) * count]; + Class *classes = (Class*)[classData mutableBytes]; + _GTMDevAssert(classes, @"Couldn't allocate class list"); + objc_getClassList(classes, count); + totalFailures_ = 0; + totalSuccesses_ = 0; + NSString *suiteName = [[NSBundle mainBundle] bundlePath]; + NSDate *suiteStartDate = [NSDate date]; + NSString *suiteStartString + = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n", + suiteName, suiteStartDate]; + fputs([suiteStartString UTF8String], stderr); + fflush(stderr); + for (int i = 0; i < count; ++i) { + Class currClass = classes[i]; + if (IsTestFixture(currClass)) { + NSDate *fixtureStartDate = [NSDate date]; + NSString *fixtureName = NSStringFromClass(currClass); + NSString *fixtureStartString + = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n", + fixtureName, fixtureStartDate]; + int fixtureSuccesses = 0; + int fixtureFailures = 0; + fputs([fixtureStartString UTF8String], stderr); + fflush(stderr); + id testcase = [[currClass alloc] init]; + _GTMDevAssert(testcase, @"Unable to instantiate Test Suite: '%@'\n", + fixtureName); + unsigned int methodCount; + Method *methods = class_copyMethodList(currClass, &methodCount); + if (!methods) { + // If the class contains no methods, head on to the next class + NSString *output = [NSString stringWithFormat:@"Test Suite '%@' " + @"finished at %@.\nExecuted 0 tests, with 0 " + @"failures (0 unexpected) in 0 (0) seconds\n", + fixtureName, fixtureStartDate]; + + fputs([output UTF8String], stderr); + continue; + } + // This handles disposing of methods for us even if an + // exception should fly. + [NSData dataWithBytesNoCopy:methods + length:sizeof(Method) * methodCount]; + // Sort our methods so they are called in Alphabetical order just + // because we can. + qsort(methods, methodCount, sizeof(Method), MethodSort); + for (size_t j = 0; j < methodCount; ++j) { + Method currMethod = methods[j]; + SEL sel = method_getName(currMethod); + char *returnType = NULL; + const char *name = sel_getName(sel); + // If it starts with test, takes 2 args (target and sel) and returns + // void run it. + if (strstr(name, "test") == name) { + returnType = method_copyReturnType(currMethod); + if (returnType) { + // This handles disposing of returnType for us even if an + // exception should fly. Length +1 for the terminator, not that + // the length really matters here, as we never reference inside + // the data block. + [NSData dataWithBytesNoCopy:returnType + length:strlen(returnType) + 1]; + } + } + if (returnType // True if name starts with "test" + && strcmp(returnType, @encode(void)) == 0 + && method_getNumberOfArguments(currMethod) == 2) { + BOOL failed = NO; + NSDate *caseStartDate = [NSDate date]; + @try { + [testcase performTest:sel]; + } @catch (NSException *exception) { + failed = YES; + } + if (failed) { + fixtureFailures += 1; + } else { + fixtureSuccesses += 1; + } + NSTimeInterval caseEndTime + = [[NSDate date] timeIntervalSinceDate:caseStartDate]; + NSString *caseEndString + = [NSString stringWithFormat:@"Test Case '-[%@ %s]' %@ (%0.3f " + @"seconds).\n", + fixtureName, name, + failed ? @"failed" : @"passed", + caseEndTime]; + fputs([caseEndString UTF8String], stderr); + fflush(stderr); + } + } + [testcase release]; + NSDate *fixtureEndDate = [NSDate date]; + NSTimeInterval fixtureEndTime + = [fixtureEndDate timeIntervalSinceDate:fixtureStartDate]; + NSString *fixtureEndString + = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n" + @"Executed %d tests, with %d failures (%d " + @"unexpected) in %0.3f (%0.3f) seconds\n\n", + fixtureName, fixtureEndDate, + fixtureSuccesses + fixtureFailures, + fixtureFailures, fixtureFailures, + fixtureEndTime, fixtureEndTime]; + + fputs([fixtureEndString UTF8String], stderr); + fflush(stderr); + totalSuccesses_ += fixtureSuccesses; + totalFailures_ += fixtureFailures; + } + } + NSDate *suiteEndDate = [NSDate date]; + NSTimeInterval suiteEndTime + = [suiteEndDate timeIntervalSinceDate:suiteStartDate]; + NSString *suiteEndString + = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n" + @"Executed %d tests, with %d failures (%d " + @"unexpected) in %0.3f (%0.3f) seconds\n\n", + suiteName, suiteEndDate, + totalSuccesses_ + totalFailures_, + totalFailures_, totalFailures_, + suiteEndTime, suiteEndTime]; + fputs([suiteEndString UTF8String], stderr); + fflush(stderr); +} + +- (NSUInteger)totalSuccesses { + return totalSuccesses_; +} + +- (NSUInteger)totalFailures { + return totalFailures_; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestMain.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestMain.m new file mode 100644 index 00000000..2a0a70d2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMIPhoneUnitTestMain.m @@ -0,0 +1,33 @@ +// +// GTMIPhoneUnitTestMain.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#if !GTM_IPHONE_SDK + #error GTMIPhoneUnitTestMain for iPhone only +#endif +#import + +// Creates an application that runs all tests from classes extending +// SenTestCase, outputs results and test run time, and terminates right +// afterwards. +int main(int argc, char *argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, @"GTMIPhoneUnitTestDelegate"); + [pool release]; + return retVal; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.h new file mode 100644 index 00000000..55c3dfe9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.h @@ -0,0 +1,120 @@ +// +// GTMNSObject+BindingUnitTesting.h +// +// Utilities for doing advanced unittesting with object bindings. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#include + +// Utility functions for GTMTestExposedBindings Macro. Don't use it directly +// but use the macro below instead +BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object, + NSArray **errors); + +// Tests the setters and getters for exposed bindings +// For objects that expose bindings, this tests them for you, saving you from +// having to write a whole pile of set/get test code if you add binding support. +// You will need to implement valueClassForBinding: for your bindings, +// and you may possibly want to implement unitTestExposedBindingsToIgnore +// and unitTestExposedBindingsTestValues. See descriptions of those +// methods below for details. +// Implemented as a macro to match the rest of the SenTest macros. +// +// Args: +// a1: The object to be checked. +// description: A format string as in the printf() function. +// Can be nil or an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +// +#define GTMTestExposedBindings(a1, description, ...) \ +do { \ + NSObject *a1Object = (a1); \ + NSArray *errors = nil; \ + BOOL isGood = GTMDoExposedBindingsFunctionCorrectly(a1Object, &errors); \ + if (!isGood) { \ + NSString *failString; \ + GTM_FOREACH_OBJECT(failString, errors) { \ + if (description) { \ + STFail(@"%@: %@", failString, STComposeString(description, ##__VA_ARGS__)); \ + } else { \ + STFail(@"%@", failString); \ + } \ + } \ + } \ +} while(0) + +// Utility class for setting up Binding Tests. Basically a pair of a value to +// set a binding to, followed by the expected return value. +// See description of gtm_unitTestExposedBindingsTestValues: below +// for example of usage. +@interface GTMBindingUnitTestData : NSObject { + @private + id valueToSet_; + id expectedValue_; +} + ++ (id)testWithIdentityValue:(id)value; ++ (id)testWithValue:(id)value expecting:(id)expecting; +- (id)initWithValue:(id)value expecting:(id)expecting; +- (id)valueToSet; +- (id)expectedValue; +@end + +@interface NSObject (GTMBindingUnitTestingAdditions) +// Allows you to ignore certain bindings when running GTMTestExposedBindings +// If you have bindings you want to ignore, add them to the array returned +// by this method. The standard way to implement this would be: +// - (NSMutableArray*)unitTestExposedBindingsToIgnore { +// NSMutableArray *array = [super unitTestExposedBindingsToIgnore]; +// [array addObject:@"bindingToIgnore1"]; +// ... +// return array; +// } +// The NSObject implementation by default will ignore NSFontBoldBinding, +// NSFontFamilyNameBinding, NSFontItalicBinding, NSFontNameBinding and +// NSFontSizeBinding if your exposed bindings contains NSFontBinding because +// the NSFont*Bindings are NOT KVC/KVO compliant. +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore; + +// Allows you to set up test values for your different bindings. +// if you have certain values you want to test against your bindings, add +// them to the array returned by this method. The array is an array of +// GTMBindingUnitTestData. +// The standard way to implement this would be: +// - (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding { +// NSMutableArray *dict = [super unitTestExposedBindingsTestValues:binding]; +// if ([binding isEqualToString:@"myBinding"]) { +// MySpecialBindingValueSet *value +// = [[[MySpecialBindingValueSet alloc] init] autorelease]; +// [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; +// ... +// else if ([binding isEqualToString:@"myBinding2"]) { +// ... +// } +// return array; +// } +// The NSObject implementation handles many of the default bindings, and +// gives you a reasonable set of test values to start. +// See the implementation for the current list of bindings, and values that we +// set for those bindings. +- (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding; + +// A special version of isEqualTo to test whether two binding values are equal +// by default it calls directly to isEqualTo: but can be overridden for special +// cases (like NSImages) where the standard isEqualTo: isn't sufficient. +- (BOOL)gtm_unitTestIsEqualTo:(id)value; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.m new file mode 100644 index 00000000..d064a479 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.m @@ -0,0 +1,568 @@ +// +// GTMNSObject+BindingUnitTesting.m +// +// An informal protocol for doing advanced binding unittesting with objects. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import "GTMNSObject+BindingUnitTesting.h" +#import "GTMSystemVersion.h" + +BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object, + NSArray **errors) { + NSMutableArray *errorArray = [NSMutableArray array]; + if (errors) { + *errors = nil; + } + NSArray *bindings = [object exposedBindings]; + if ([bindings count]) { + NSArray *bindingsToIgnore = [object gtm_unitTestExposedBindingsToIgnore]; + NSString *bindingKey; + GTM_FOREACH_OBJECT(bindingKey, bindings) { + if (![bindingsToIgnore containsObject:bindingKey]) { + Class theClass = [object valueClassForBinding:bindingKey]; + if (!theClass) { + NSString *error + = [NSString stringWithFormat:@"%@ should have valueClassForBinding '%@'", + object, bindingKey]; + [errorArray addObject:error]; + continue; + } + @try { + @try { + [object valueForKey:bindingKey]; + } + @catch (NSException *e) { + _GTMDevLog(@"%@ is not key value coding compliant for key %@", + object, bindingKey); + continue; + } // COV_NF_LINE - compiler bug + NSArray *testValues + = [object gtm_unitTestExposedBindingsTestValues:bindingKey]; + GTMBindingUnitTestData *testData; + GTM_FOREACH_OBJECT(testData, testValues) { + id valueToSet = [testData valueToSet]; + [object setValue:valueToSet forKey:bindingKey]; + id valueReceived = [object valueForKey:bindingKey]; + id desiredValue = [testData expectedValue]; + if (![desiredValue gtm_unitTestIsEqualTo:valueReceived]) { + NSString *error + = [NSString stringWithFormat:@"%@ unequal to expected %@ for binding '%@'", + valueReceived, desiredValue, bindingKey]; + [errorArray addObject:error]; + continue; + } + } + } + @catch(NSException *e) { + NSString *error + = [NSString stringWithFormat:@"%@:%@-> Binding %@", + [e name], [e reason], bindingKey]; + [errorArray addObject:error]; + } // COV_NF_LINE - compiler bug + } + } + } else { + NSString *error = + [NSString stringWithFormat:@"%@ does not have any exposed bindings", + object]; + [errorArray addObject:error]; + } + if (errors) { + *errors = errorArray; + } + return [errorArray count] == 0; +} + +@implementation GTMBindingUnitTestData ++ (id)testWithIdentityValue:(id)value { + return [self testWithValue:value expecting:value]; +} + ++ (id)testWithValue:(id)value expecting:(id)expecting { + return [[[self alloc] initWithValue:value expecting:expecting] autorelease]; +} + +- (id)initWithValue:(id)value expecting:(id)expecting { + if ((self = [super init])) { + valueToSet_ = [value retain]; + expectedValue_ = [expecting retain]; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isEqual = [object isMemberOfClass:[self class]]; + if (isEqual) { + id objValue = [object valueToSet]; + id objExpect = [object expectedValue]; + isEqual = (((valueToSet_ == objValue) || ([valueToSet_ isEqual:objValue])) + && ((expectedValue_ == objExpect) || ([expectedValue_ isEqual:objExpect]))); + } + return isEqual; +} + +- (NSUInteger)hash { + return [valueToSet_ hash] + [expectedValue_ hash]; +} + +- (void)dealloc { + [valueToSet_ release]; + [expectedValue_ release]; + [super dealloc]; +} + +- (id)valueToSet { + return valueToSet_; +} + +- (id)expectedValue { + return expectedValue_; +} +@end + +@implementation NSObject (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [NSMutableArray arrayWithObject:NSValueBinding]; + if ([[self exposedBindings] containsObject:NSFontBinding]) { + NSString *fontBindings[] = { NSFontBoldBinding, NSFontFamilyNameBinding, + NSFontItalicBinding, NSFontNameBinding, NSFontSizeBinding }; + for (size_t i = 0; i < sizeof(fontBindings) / sizeof(NSString*); ++i) { + [array addObject:fontBindings[i]]; + } + } + return array; +} + +- (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding { + + NSMutableArray *array = [NSMutableArray array]; + id value = [self valueForKey:binding]; + + // Always test identity if possible + if (value) { + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } + + // Now some default test values for a variety of bindings to make + // sure that we cover all the bases and save other people writing lots of + // duplicate test code. + + // If anybody can think of more to add, please go nuts. + if ([binding isEqualToString:NSAlignmentBinding]) { + value = [NSNumber numberWithInt:NSLeftTextAlignment]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:NSRightTextAlignment]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:NSCenterTextAlignment]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:NSJustifiedTextAlignment]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:NSNaturalTextAlignment]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + NSNumber *valueToSet = [NSNumber numberWithInt:500]; + [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet + expecting:value]]; + valueToSet = [NSNumber numberWithInt:-1]; + [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet + expecting:value]]; + } else if ([binding isEqualToString:NSAlternateImageBinding] || + [binding isEqualToString:NSImageBinding] || + [binding isEqualToString:NSMixedStateImageBinding] || + [binding isEqualToString:NSOffStateImageBinding] || + [binding isEqualToString:NSOnStateImageBinding]) { + // This handles all image bindings + value = [NSImage imageNamed:@"NSApplicationIcon"]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSAnimateBinding] || + [binding isEqualToString:NSDocumentEditedBinding] || + [binding isEqualToString:NSEditableBinding] || + [binding isEqualToString:NSEnabledBinding] || + [binding isEqualToString:NSHiddenBinding] || + [binding isEqualToString:NSVisibleBinding] || + [binding isEqualToString:NSIsIndeterminateBinding] || + // NSTranparentBinding 10.5 only + [binding isEqualToString:@"transparent"]) { + // This handles all bool value bindings + value = [NSNumber numberWithBool:YES]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithBool:NO]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSAlternateTitleBinding] || + [binding isEqualToString:NSHeaderTitleBinding] || + [binding isEqualToString:NSLabelBinding] || + [binding isEqualToString:NSTitleBinding] || + [binding isEqualToString:NSToolTipBinding]) { + // This handles all string value bindings + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"happy"]]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@""]]; + + // Test some non-ascii roman text + char a_not_alpha[] = { 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 }; + value = [NSString stringWithUTF8String:a_not_alpha]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some korean + char hangugo[] = { 0xED, 0x95, 0x9C, 0xEA, 0xB5, + 0xAD, 0xEC, 0x96, 0xB4, 0x00 }; + value = [NSString stringWithUTF8String:hangugo]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some japanese + char nihongo[] = { 0xE6, 0x97, 0xA5, 0xE6, 0x9C, + 0xAC, 0xE8, 0xAA, 0x9E, 0x00 }; + value = [NSString stringWithUTF8String:nihongo]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some arabic + char arabic[] = { 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 }; + value = [NSString stringWithUTF8String:arabic]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSRepresentedFilenameBinding]) { + // This handles all path bindings + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/happy"]]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/"]]; + + // Test some non-ascii roman text + char a_not_alpha[] = { '/', 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 }; + value = [NSString stringWithUTF8String:a_not_alpha]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some korean + char hangugo[] = { '/', 0xED, 0x95, 0x9C, 0xEA, 0xB5, + 0xAD, 0xEC, 0x96, 0xB4, 0x00 }; + value = [NSString stringWithUTF8String:hangugo]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some japanese + char nihongo[] = { '/', 0xE6, 0x97, 0xA5, 0xE6, 0x9C, + 0xAC, 0xE8, 0xAA, 0x9E, 0x00 }; + value = [NSString stringWithUTF8String:nihongo]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + // Test some arabic + char arabic[] = { '/', 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 }; + value = [NSString stringWithUTF8String:arabic]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSMaximumRecentsBinding]) { + value = [NSNumber numberWithInt:0]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:-1]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:INT16_MAX]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithInt:INT16_MIN]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSRowHeightBinding]) { + NSNumber *valueOne = [NSNumber numberWithInt:1]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:valueOne]]; + value = [NSNumber numberWithInt:0]; + id value2 = [NSNumber numberWithInt:INT16_MIN]; + // Row height no longer accepts <= 0 values on SnowLeopard + // which is a good thing. + if ([GTMSystemVersion isSnowLeopardOrGreater]) { + [array addObject:[GTMBindingUnitTestData testWithValue:value + expecting:valueOne]]; + + [array addObject:[GTMBindingUnitTestData testWithValue:value2 + expecting:valueOne]]; + } else { + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value2]]; + } + value = [NSNumber numberWithInt:INT16_MAX]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSMaxValueBinding] || + [binding isEqualToString:NSMaxWidthBinding] || + [binding isEqualToString:NSMinValueBinding] || + [binding isEqualToString:NSMinWidthBinding] || + [binding isEqualToString:NSContentWidthBinding] || + [binding isEqualToString:NSContentHeightBinding] || + [binding isEqualToString:NSWidthBinding] || + [binding isEqualToString:NSAnimationDelayBinding]) { + // NSAnimationDelay is deprecated on SnowLeopard. We continue to test it + // to make sure it doesn't get broken. + + // This handles all float value bindings + value = [NSNumber numberWithFloat:0]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:FLT_MAX]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:-FLT_MAX]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:FLT_MIN]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:-FLT_MIN]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:FLT_EPSILON]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSNumber numberWithFloat:-FLT_EPSILON]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSTextColorBinding]) { + // This handles all color value bindings + value = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.0]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.5]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSColor colorWithCalibratedRed:0.5 green:0.5 blue:0.5 alpha:0.5]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSColor colorWithDeviceCyan:0.25 magenta:0.25 yellow:0.25 + black:0.25 alpha:0.25]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSFontBinding]) { + // This handles all font value bindings + value = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSFont toolTipsFontOfSize:[NSFont smallSystemFontSize]]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + value = [NSFont labelFontOfSize:144.0]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSRecentSearchesBinding] || + [binding isEqualToString:NSSortDescriptorsBinding]) { + // This handles all array value bindings + value = [NSArray array]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else if ([binding isEqualToString:NSTargetBinding]) { + value = [NSNull null]; + [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]]; + } else { + _GTMDevLog(@"Skipped Binding: %@ for %@", binding, self); // COV_NF_LINE + } + return array; +} + +- (BOOL)gtm_unitTestIsEqualTo:(id)value { + return [self isEqualTo:value]; +} + +@end + +#pragma mark - +#pragma mark All the special AppKit Bindings issues below + +@interface NSImage (GTMBindingUnitTestingAdditions) +@end + +@implementation NSImage (GTMBindingUnitTestingAdditions) +- (BOOL)gtm_unitTestIsEqualTo:(id)value { + // NSImage just does pointer equality in the default isEqualTo implementation + // we need something a little more heavy duty that actually compares the + // images internally. + return [[self TIFFRepresentation] isEqualTo:[value TIFFRepresentation]]; +} +@end + +@interface NSScroller (GTMBindingUnitTestingAdditions) +@end + +@implementation NSScroller (GTMBindingUnitTestingAdditions) +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + SInt32 major, minor, bugFix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix]; + if (major <= 10 && minor <= 5 && bugFix <= 5) { + // rdar://5849154 - NSScroller exposes binding with no value + // class for NSValueBinding + [array addObject:NSValueBinding]; + } + if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // Broken on SnowLeopard WWDC and below + // rdar://5849236 - NSScroller exposes binding for NSFontBinding + [array addObject:NSFontBinding]; + } + return array; +} +@end + +@interface NSTextField (GTMBindingUnitTestingAdditions) +@end + +@implementation NSTextField (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + // Not KVC Compliant + for (int i = 0; i < 10; i++) { + [array addObject:[NSString stringWithFormat:@"displayPatternValue%d", i]]; + } + return array; +} + +- (NSMutableArray *)gtm_unitTestExposedBindingsTestValues:(NSString*)binding { + NSMutableArray *array = [super gtm_unitTestExposedBindingsTestValues:binding]; + if ([binding isEqualToString:NSAlignmentBinding]) { + if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // rdar://5851487 - If NSAlignmentBinding for a NSTextField is set to -1 + // and then got it returns 7 + NSNumber *textAlignment = [NSNumber numberWithInt:NSNaturalTextAlignment]; + GTMBindingUnitTestData *dataToRemove = + [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1] + expecting:textAlignment]; + [array removeObject:dataToRemove]; + GTMBindingUnitTestData *dataToAdd = + [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1] + expecting:[NSNumber numberWithInt:7]]; + [array addObject:dataToAdd]; + } + } + return array; +} +@end + +@interface NSSearchField (GTMBindingUnitTestingAdditions) +@end + +@implementation NSSearchField (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + SInt32 major, minor, bugFix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix]; + if (major <= 10 && minor <= 5 && bugFix <= 6) { + // rdar://5851491 - Setting NSAlignmentBinding of search field to + // NSCenterTextAlignment broken + // Broken on 10.5.6 and below. + [array addObject:NSAlignmentBinding]; + } + // Not KVC Compliant + [array addObject:NSPredicateBinding]; + return array; +} + +@end + +@interface NSWindow (GTMBindingUnitTestingAdditions) +@end + +@implementation NSWindow (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + // Not KVC Compliant + [array addObject:NSContentWidthBinding]; + [array addObject:NSContentHeightBinding]; + for (int i = 0; i < 10; i++) { + [array addObject:[NSString stringWithFormat:@"displayPatternTitle%d", i]]; + } + return array; +} + +@end + +@interface NSBox (GTMBindingUnitTestingAdditions) +@end + +@implementation NSBox (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + // Not KVC Compliant + for (int i = 0; i < 10; i++) { + [array addObject:[NSString stringWithFormat:@"displayPatternTitle%d", i]]; + } + return array; +} + +@end + +@interface NSTableView (GTMBindingUnitTestingAdditions) +@end + +@implementation NSTableView (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // rdar://6288332 - NSTableView does not respond to NSFontBinding + // Broken on 10.5, and SnowLeopard WWDC + [array addObject:NSFontBinding]; + } + // Not KVC Compliant + [array addObject:NSContentBinding]; + [array addObject:NSDoubleClickTargetBinding]; + [array addObject:NSDoubleClickArgumentBinding]; + [array addObject:NSSelectionIndexesBinding]; + return array; +} + +@end + +@interface NSTextView (GTMBindingUnitTestingAdditions) +@end + +@implementation NSTextView (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + //rdar://5849335 - NSTextView only partially KVC compliant for key + // NSAttributedStringBinding + [array addObject:NSAttributedStringBinding]; + } + // Not KVC Compliant + [array addObject:NSDataBinding]; + [array addObject:NSValueURLBinding]; + [array addObject:NSValuePathBinding]; + return array; +} + +@end + +@interface NSTabView (GTMBindingUnitTestingAdditions) +@end + +@implementation NSTabView (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) { + // rdar://5849248 - NSTabView exposes binding with no value class + // for NSSelectedIdentifierBinding + [array addObject:NSSelectedIdentifierBinding]; + } + // Not KVC Compliant + [array addObject:NSSelectedIndexBinding]; + [array addObject:NSSelectedLabelBinding]; + return array; +} + +@end + +@interface NSButton (GTMBindingUnitTestingAdditions) +@end + +@implementation NSButton (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + // Not KVC Compliant + [array addObject:NSArgumentBinding]; + return array; +} + +@end + +@interface NSProgressIndicator (GTMBindingUnitTestingAdditions) +@end + +@implementation NSProgressIndicator (GTMBindingUnitTestingAdditions) + +- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore { + NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore]; + // Not KVC Compliant + [array addObject:NSAnimateBinding]; + return array; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.h new file mode 100644 index 00000000..37eae5bf --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.h @@ -0,0 +1,417 @@ +// +// GTMNSObject+UnitTesting.h +// +// Utilities for doing advanced unittesting with objects. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import + +#if GTM_MACOS_SDK +#import +#elif GTM_IPHONE_SDK +#import +#endif + +#import "GTMSenTestCase.h" + +// Utility functions for GTMAssert* Macros. Don't use them directly +// but use the macros below instead +BOOL GTMIsObjectImageEqualToImageNamed(id object, + NSString *filename, + NSString **error); +BOOL GTMIsObjectStateEqualToStateNamed(id object, + NSString *filename, + NSString **error); + +// Fails when image of |a1| does not equal image in image file named |a2| +// +// Generates a failure when the unittest image of |a1| is not equal to the +// image stored in the image file named |a2|, or |a2| does not exist in the +// executable code's bundle. +// If |a2| does not exist in the executable code's bundle, we save a image +// representation of |a1| in the save directory with name |a2|. This can then +// be included in the bundle as the master to test against. +// If |a2| != |a1|, we save a image representation of |a1| in the save +// directory named |a2|_Failed and a file named |a2|_Failed_Diff showing the +// diff in red so that we can see what has changed. +// See pathForImageNamed to see how name is searched for. +// The save directory is specified by +gtm_setUnitTestSaveToDirectory, and is +// the desktop by default. +// Implemented as a macro to match the rest of the SenTest macros. +// +// Args: +// a1: The object to be checked. Must implement the -createUnitTestImage method. +// a2: The name of the image file to check against. +// Do not include the extension +// description: A format string as in the printf() function. +// Can be nil or an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +// +#define GTMAssertObjectImageEqualToImageNamed(a1, a2, description, ...) \ +do { \ + id a1Object = (a1); \ + NSString* a2String = (a2); \ + NSString *failString = nil; \ + BOOL isGood = GTMIsObjectImageEqualToImageNamed(a1Object, a2String, &failString); \ + if (!isGood) { \ + if (description) { \ + STFail(@"%@: %@", failString, STComposeString(description, ##__VA_ARGS__)); \ + } else { \ + STFail(@"%@", failString); \ + } \ + } \ +} while(0) + +// Fails when state of |a1| does not equal state in file |a2| +// +// Generates a failure when the unittest state of |a1| is not equal to the +// state stored in the state file named |a2|, or |a2| does not exist in the +// executable code's bundle. +// If |a2| does not exist in the executable code's bundle, we save a state +// representation of |a1| in the save directiry with name |a2|. This can then +// be included in the bundle as the master to test against. +// If |a2| != |a1|, we save a state representation of |a1| in the save +// directory with name |a2|_Failed so that we can compare the two files to see +// what has changed. +// The save directory is specified by +gtm_setUnitTestSaveToDirectory, and is +// the desktop by default. +// Implemented as a macro to match the rest of the SenTest macros. +// +// Args: +// a1: The object to be checked. Must implement the -createUnitTestImage method. +// a2: The name of the state file to check against. +// Do not include the extension +// description: A format string as in the printf() function. +// Can be nil or an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +// +#define GTMAssertObjectStateEqualToStateNamed(a1, a2, description, ...) \ +do { \ + id a1Object = (a1); \ + NSString* a2String = (a2); \ + NSString *failString = nil; \ + BOOL isGood = GTMIsObjectStateEqualToStateNamed(a1Object, a2String, &failString); \ + if (!isGood) { \ + if (description) { \ + STFail(@"%@: %@", failString, STComposeString(description, ##__VA_ARGS__)); \ + } else { \ + STFail(@"%@", failString); \ + } \ + } \ +} while(0); + +// test both GTMAssertObjectImageEqualToImageNamed and GTMAssertObjectStateEqualToStateNamed +// +// Combines the above two macros into a single ubermacro for comparing +// both state and image. When only the best will do... +#define GTMAssertObjectEqualToStateAndImageNamed(a1, a2, description, ...) \ +do { \ + GTMAssertObjectImageEqualToImageNamed(a1, a2, description, ##__VA_ARGS__); \ + GTMAssertObjectStateEqualToStateNamed(a1, a2, description, ##__VA_ARGS__); \ +} while (0) + +// Create a CGBitmapContextRef appropriate for using in creating a unit test +// image. If data is non-NULL, returns the buffer that the bitmap is +// using for it's underlying storage. You must free this buffer using +// free. If data is NULL, uses it's own internal storage. +// Defined as a C function instead of an obj-c method because you have to +// release the CGContextRef that is returned. +// +// Returns: +// an CGContextRef of the object. Caller must release + +CGContextRef GTMCreateUnitTestBitmapContextOfSizeWithData(CGSize size, + unsigned char **data); + +// GTMUnitTestingImaging protocol is for objects which need to save their +// image for using with the unit testing categories +@protocol GTMUnitTestingImaging +// Create a CGImageRef containing a representation suitable for use in +// comparing against a master image. +// +// Returns: +// an CGImageRef of the object. +- (CGImageRef)gtm_unitTestImage; +@end + +// GTMUnitTestingEncoding protocol is for objects which need to save their +// "state" for using with the unit testing categories +@protocol GTMUnitTestingEncoding +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. Encode data in the coder in the same +// manner that you would encode data in any other Keyed NSCoder subclass. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder; +@end + +// Category for saving and comparing object state and image for unit tests +// +// The GTMUnitTestAdditions category gives object the ability to store their +// state for use in unittesting in two different manners. +// 1) Objects can elect to save their "image" that we can compare at +// runtime to an image file to make sure that the representation hasn't +// changed. All views and Windows can save their image. In the case of Windows, +// they are "bluescreened" so that any transparent areas can be compared between +// machines. +// 2) Objects can elect to save their "state". State is the attributes that we +// want to verify when running unit tests. Applications, Windows, Views, +// Controls and Cells currently return a variety of state information. If you +// want to customize the state information that a particular object returns, you +// can do it via the GTMUnitTestingEncodedObjectNotification. Items that have +// delegates (Applications/Windows) can also have their delegates return state +// information if appropriate via the unitTestEncoderDidEncode:inCoder: delegate +// method. +// To compare state/image in your unit tests, you can use the three macros above +// GTMAssertObjectStateEqualToStateNamed, GTMAssertObjectImageEqualToImageNamed and +// GTMAssertObjectEqualToStateAndImageNamed. +@interface NSObject (GTMUnitTestingAdditions) +// Allows you to control where the unit test utilities save any files +// (image or state) that they create on your behalf. By default they +// will save to the desktop. ++ (void)gtm_setUnitTestSaveToDirectory:(NSString*)path; ++ (NSString *)gtm_getUnitTestSaveToDirectory; + +// Checks to see that system settings are valid for doing an image comparison. +// Most of these are set by our unit test app. See the unit test app main.m +// for details. +// +// Returns: +// YES if we can do image comparisons for this object type. +- (BOOL)gtm_areSystemSettingsValidForDoingImage; + +// Return the type of image to work with. Only valid types on the iPhone +// are kUTTypeJPEG and kUTTypePNG. MacOS supports several more. +- (CFStringRef)gtm_imageUTI; + +// Return the extension to be used for saving unittest images +// +// Returns +// An extension (e.g. "png") +- (NSString*)gtm_imageExtension; + +// Return image data in the format expected for gtm_imageExtension +// So for a "png" extension I would expect "png" data +// +// Returns +// NSData for image +- (NSData*)gtm_imageDataForImage:(CGImageRef)image; + +// Save the unitTestImage to a image file with name +// |name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension +// in the save folder (desktop by default) +// +// Args: +// name: The name for the image file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToImageNamed:(NSString*)name; + +// Save unitTestImage of |self| to an image file at path |path|. +// All non-drawn areas will be transparent. +// +// Args: +// name: The name for the image file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToImageAt:(NSString*)path; + +// Compares unitTestImage of |self| to the image located at |path| +// +// Args: +// path: the path to the image file you want to compare against. +// If diff is non-nil, it will contain an auto-released diff of the images. +// +// Returns: +// YES if they are equal, NO is they are not +// If diff is non-nil, it will contain a diff of the images. Must +// be released by caller. +// +- (BOOL)gtm_compareWithImageAt:(NSString*)path diffImage:(CGImageRef*)diff; + +// Find the path for a image by name in your bundle. +// Searches for the following: +// "name.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersionBugfix.arch.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.extension" +// "name.OSVersionMajor.OSVersionMinor.arch.extension" +// "name.arch.OSVersionMajor.extension" +// "name.OSVersionMajor.arch.extension" +// "name.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension" +// "name.OSVersionMajor.OSVersionMinorextension" +// "name.OSVersionMajor.extension" +// "name.extension" +// Do not include the extension on your name. +// +// Args: +// name: The name for the image file you would like to find. +// +// Returns: +// the path if the image exists in your bundle +// or nil if no image to be found +// +- (NSString *)gtm_pathForImageNamed:(NSString*)name; + +// Generates a CGImageRef from the image at |path| +// Args: +// path: The path to the image. +// +// Returns: +// An autoreleased CGImageRef own, or nil if no image at path +- (CGImageRef)gtm_imageWithContentsOfFile:(NSString*)path; + +// Generates a path for a image in the save directory, which is desktop +// by default. +// Path will be: +// SaveDir/|name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension +// +// Args: +// name: The name for the image file you would like to generate a path for. +// +// Returns: +// the path +// +- (NSString *)gtm_saveToPathForImageNamed:(NSString*)name; + +// Gives us a representation of unitTestImage of |self|. +// +// Returns: +// a representation if successful +// nil if failed +// +- (NSData *)gtm_imageRepresentation; + +// Return the extension to be used for saving unittest states +// +// Returns +// An extension (e.g. "gtmUTState") +- (NSString*)gtm_stateExtension; + +// Save the encoded unit test state to a state file with name +// |name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension +// in the save folder (desktop by default) +// +// Args: +// name: The name for the state file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToStateNamed:(NSString*)name; + +// Save encoded unit test state of |self| to a state file at path |path|. +// +// Args: +// name: The name for the state file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToStateAt:(NSString*)path; + +// Compares encoded unit test state of |self| to the state file located at |path| +// +// Args: +// path: the path to the state file you want to compare against. +// +// Returns: +// YES if they are equal, NO is they are not +// +- (BOOL)gtm_compareWithStateAt:(NSString*)path; + + +// Find the path for a state by name in your bundle. +// Searches for: +// "name.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersionBugfix.arch.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.extension" +// "name.OSVersionMajor.OSVersionMinor.arch.extension" +// "name.arch.OSVersionMajor.extension" +// "name.OSVersionMajor.arch.extension" +// "name.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension" +// "name.OSVersionMajor.OSVersionMinor.extension" +// "name.OSVersionMajor.extension" +// "name.extension" +// Do not include the extension on your name. +// +// Args: +// name: The name for the state file you would like to find. +// +// Returns: +// the path if the state exists in your bundle +// or nil if no state to be found +// +- (NSString *)gtm_pathForStateNamed:(NSString*)name; + +// Generates a path for a state in the save directory, which is desktop +// by default. +// Path will be: +// SaveDir/|name|.arch.OSVersionMajor.OSVersionMinor.OSVersionBugfix.extension +// +// Args: +// name: The name for the state file you would like to generate a path for. +// +// Returns: +// the path +// +- (NSString *)gtm_saveToPathForStateNamed:(NSString*)name; + +// Gives us the encoded unit test state for |self| +// +// Returns: +// the encoded state if successful +// nil if failed +// +- (NSDictionary *)gtm_stateRepresentation; + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. Encode data in the coder in the same +// manner that you would encode data in any other Keyed NSCoder subclass. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder; +@end + +// Informal protocol for delegates that wanst to be able to add state info +// when state info is collected for their "owned" objects +@interface NSObject (GTMUnitTestingEncodingAdditions) +// Delegate function for unit test objects that have delegates. Delegates have +// the option of encoding more data into the coder to store their state for +// unittest usage. +- (void)gtm_unitTestEncoderWillEncode:(id)sender inCoder:(NSCoder*)inCoder; +@end + +// Whenever an object is encoded by the unit test encoder, it send out a +// notification so that objects who want to add data to the encoded objects unit +// test state can do so. The Coder will be in the userInfo dictionary for the +// notification under the GTMUnitTestingEncoderKey key. +GTM_EXTERN NSString *const GTMUnitTestingEncodedObjectNotification; + +// Key for finding the encoder in the userInfo dictionary for +// GTMUnitTestingEncodedObjectNotification notifications. +GTM_EXTERN NSString *const GTMUnitTestingEncoderKey; diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.m new file mode 100644 index 00000000..cc6a7ea4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+UnitTesting.m @@ -0,0 +1,982 @@ +// +// GTMNSObject+UnitTesting.m +// +// An informal protocol for doing advanced unittesting with objects. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSObject+UnitTesting.h" +#import "GTMSystemVersion.h" +#import "GTMGarbageCollection.h" + +#if GTM_IPHONE_SDK +#import +#else +#import +#endif + +NSString *const GTMUnitTestingEncodedObjectNotification + = @"GTMUnitTestingEncodedObjectNotification"; +NSString *const GTMUnitTestingEncoderKey = @"GTMUnitTestingEncoderKey"; + +#if GTM_IPHONE_SDK +// No UTIs on iPhone. Only two we need. +const CFStringRef kUTTypePNG = CFSTR("public.png"); +const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg"); +#endif + +// This class exists so that we can locate our bundle using [NSBundle +// bundleForClass:]. We don't use [NSBundle mainBundle] because when we are +// being run as a unit test, we aren't the mainBundle +@interface GTMUnitTestingAdditionsBundleFinder : NSObject { + // Nothing here +} +// or here +@end + +@implementation GTMUnitTestingAdditionsBundleFinder +// Nothing here. We're just interested in the name for finding our bundle. +@end + +BOOL GTMIsObjectImageEqualToImageNamed(id object, + NSString* filename, + NSString **error) { + NSString *failString = nil; + if (error) { + *error = nil; + } + BOOL isGood = [object respondsToSelector:@selector(gtm_unitTestImage)]; + if (isGood) { + if ([object gtm_areSystemSettingsValidForDoingImage]) { + NSString *aPath = [object gtm_pathForImageNamed:filename]; + CGImageRef diff = nil; + isGood = aPath != nil; + if (isGood) { + isGood = [object gtm_compareWithImageAt:aPath diffImage:&diff]; + } + if (!isGood) { + if (aPath) { + filename = [filename stringByAppendingString:@"_Failed"]; + } + BOOL aSaved = [object gtm_saveToImageNamed:filename]; + NSString *fileNameWithExtension + = [NSString stringWithFormat:@"%@.%@", + filename, [object gtm_imageExtension]]; + NSString *fullSavePath = [object gtm_saveToPathForImageNamed:filename]; + if (NO == aSaved) { + if (!aPath) { + failString = [NSString stringWithFormat:@"File %@ did not exist in " + @"bundle. Tried to save as %@ and failed.", + fileNameWithExtension, fullSavePath]; + } else { + failString = [NSString stringWithFormat:@"Object image different " + @"than file %@. Tried to save as %@ and failed.", + aPath, fullSavePath]; + } + } else { + if (!aPath) { + failString = [NSString stringWithFormat:@"File %@ did not exist in " + @" bundle. Saved to %@", fileNameWithExtension, + fullSavePath]; + } else { + NSString *diffPath = [filename stringByAppendingString:@"_Diff"]; + diffPath = [object gtm_saveToPathForImageNamed:diffPath]; + NSData *data = nil; + if (diff) { + data = [object gtm_imageDataForImage:diff]; + } + if ([data writeToFile:diffPath atomically:YES]) { + failString = [NSString stringWithFormat:@"Object image different " + @"than file %@. Saved image to %@. " + @"Saved diff to %@", + aPath, fullSavePath, diffPath]; + } else { + failString = [NSString stringWithFormat:@"Object image different " + @"than file %@. Saved image to %@. Unable to save " + @"diff. Most likely the image and diff are " + @"different sizes.", + aPath, fullSavePath]; + } + } + } + } + CGImageRelease(diff); + } else { + failString = @"systemSettings not valid for taking image"; // COV_NF_LINE + } + } else { + failString = @"Object does not conform to GTMUnitTestingImaging protocol"; + } + if (error) { + *error = failString; + } + return isGood; +} + +BOOL GTMIsObjectStateEqualToStateNamed(id object, + NSString* filename, + NSString **error) { + NSString *failString = nil; + if (error) { + *error = nil; + } + BOOL isGood = [object conformsToProtocol:@protocol(GTMUnitTestingEncoding)]; + if (isGood) { + NSString *aPath = [object gtm_pathForStateNamed:filename]; + isGood = aPath != nil; + if (isGood) { + isGood = [object gtm_compareWithStateAt:aPath]; + } + if (!isGood) { + if (aPath) { + filename = [filename stringByAppendingString:@"_Failed"]; + } + BOOL aSaved = [object gtm_saveToStateNamed:filename]; + NSString *fileNameWithExtension = [NSString stringWithFormat:@"%@.%@", + filename, [object gtm_stateExtension]]; + NSString *fullSavePath = [object gtm_saveToPathForStateNamed:filename]; + if (NO == aSaved) { + if (!aPath) { + failString = [NSString stringWithFormat:@"File %@ did not exist in " + @"bundle. Tried to save as %@ and failed.", + fileNameWithExtension, fullSavePath]; + } else { + failString = [NSString stringWithFormat:@"Object state different " + @"than file %@. Tried to save as %@ and failed.", + aPath, fullSavePath]; + } + } else { + if (!aPath) { + failString = [NSString stringWithFormat:@"File %@ did not exist in " + @ "bundle. Saved to %@", fileNameWithExtension, + fullSavePath]; + } else { + failString = [NSString stringWithFormat:@"Object state different " + @"than file %@. Saved to %@", aPath, fullSavePath]; + } + } + } + } else { + failString = @"Object does not conform to GTMUnitTestingEncoding protocol"; + } + if (error) { + *error = failString; + } + return isGood; +} + +CGContextRef GTMCreateUnitTestBitmapContextOfSizeWithData(CGSize size, + unsigned char **data) { + CGContextRef context = NULL; + size_t height = size.height; + size_t width = size.width; + size_t bytesPerRow = width * 4; + size_t bitsPerComponent = 8; + CGColorSpaceRef cs = NULL; +#if GTM_IPHONE_SDK + cs = CGColorSpaceCreateDeviceRGB(); +#else + cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); +#endif + _GTMDevAssert(cs, @"Couldn't create colorspace"); + CGBitmapInfo info + = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault; + if (data) { + *data = (unsigned char*)calloc(bytesPerRow, height); + _GTMDevAssert(*data, @"Couldn't create bitmap"); + } + context = CGBitmapContextCreate(data ? *data : NULL, width, height, + bitsPerComponent, bytesPerRow, cs, info); + _GTMDevAssert(context, @"Couldn't create an context"); + if (!data) { + CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height)); + } + CGContextSetRenderingIntent(context, kCGRenderingIntentRelativeColorimetric); + CGContextSetInterpolationQuality(context, kCGInterpolationNone); + CGContextSetShouldAntialias(context, NO); + CGContextSetAllowsAntialiasing(context, NO); + CGContextSetShouldSmoothFonts(context, NO); + CGColorSpaceRelease(cs); + return context; +} + +@interface NSObject (GTMUnitTestingAdditionsPrivate) +/// Find the path for a file named name.extension in your bundle. +// Searches for the following: +// "name.extension", +// "name.arch.extension", +// "name.arch.OSVersionMajor.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.extension" +// "name.arch.OSVersionMajor.extension" +// "name.OSVersionMajor.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.arch.extension" +// "name.OSVersionMajor.extension" +// "name.OSVersionMajor.OSVersionMinor.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.extension" +// Do not include the ".extension" extension on your name. +// +// Args: +// name: The name for the file you would like to find. +// extension: the extension for the file you would like to find +// +// Returns: +// the path if the file exists in your bundle +// or nil if no file is found +// +- (NSString *)gtm_pathForFileNamed:(NSString*)name + extension:(NSString*)extension; +- (NSString *)gtm_saveToPathForFileNamed:(NSString*)name + extension:(NSString*)extension; +- (CGImageRef)gtm_unitTestImage; +// Returns nil if there is no override +- (NSString *)gtm_getOverrideDefaultUnitTestSaveToDirectory; +@end + +// This is a keyed coder for storing unit test state data. It is used only by +// the GTMUnitTestingAdditions category. Most of the work is done in +// encodeObject:forKey:. +@interface GTMUnitTestingKeyedCoder : NSCoder { + NSMutableDictionary *dictionary_; // storage for data (STRONG) +} + +// get the data stored in coder. +// +// Returns: +// NSDictionary with currently stored data. +- (NSDictionary*)dictionary; +@end + +// Small utility function for checking to see if a is b +/- 1. +GTM_INLINE BOOL almostEqual(unsigned char a, unsigned char b) { + unsigned char diff = a > b ? a - b : b - a; + BOOL notEqual = diff < 2; + return notEqual; +} + +@implementation GTMUnitTestingKeyedCoder + +// Set up storage for coder. Stores type and version. +// Version 1 +// +// Returns: +// self +- (id)init { + self = [super init]; + if (self != nil) { + dictionary_ = [[NSMutableDictionary alloc] initWithCapacity:2]; + [dictionary_ setObject:@"GTMUnitTestingArchive" forKey:@"$GTMArchive"]; + + // Version number can be changed here. + [dictionary_ setObject:[NSNumber numberWithInt:1] forKey:@"$GTMVersion"]; + } + return self; +} + +// Standard dealloc +- (void)dealloc { + [dictionary_ release]; + [super dealloc]; +} + +// Utility function for checking for a key value. We don't want duplicate keys +// in any of our dictionaries as we may be writing over data stored by previous +// objects. +// +// Arguments: +// key - key to check for in dictionary +- (void)checkForKey:(NSString*)key { + _GTMDevAssert(![dictionary_ objectForKey:key], + @"Key already exists for %@", key); +} + +// Key routine for the encoder. We store objects in our dictionary based on +// their key. As we encode objects we send out notifications to let other +// classes doing tests add their specific data to the base types. If we can't +// encode the object (it doesn't support gtm_unitTestEncodeState) and we don't +// get any info back from the notifier, we attempt to store it's description. +// +// Arguments: +// objv - object to be encoded +// key - key to encode it with +// +- (void)encodeObject:(id)objv forKey:(NSString *)key { + // Sanity checks + if (!objv) return; + [self checkForKey:key]; + + // Set up a new dictionary for the current object + NSMutableDictionary *curDictionary = dictionary_; + dictionary_ = [[NSMutableDictionary alloc] initWithCapacity:0]; + + // If objv responds to gtm_unitTestEncodeState get it to record + // its data. + if ([objv respondsToSelector:@selector(gtm_unitTestEncodeState:)]) { + [objv gtm_unitTestEncodeState:self]; + } + + // We then send out a notification to let other folks + // add data for this object + NSDictionary *notificationDict + = [NSDictionary dictionaryWithObject:self forKey:GTMUnitTestingEncoderKey]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:GTMUnitTestingEncodedObjectNotification + object:objv + userInfo:notificationDict]; + + // If we got anything from the object, or from the notification, store it in + // our dictionary. Otherwise store the description. + if ([dictionary_ count] > 0) { + [curDictionary setObject:dictionary_ forKey:key]; + } else { + NSString *description = [objv description]; + // If description has a pointer value in it, we don't want to store it + // as the pointer value can change from run to run + if (description && [description rangeOfString:@"0x"].length == 0) { + [curDictionary setObject:description forKey:key]; + } else { + _GTMDevAssert(NO, @"Unable to encode forKey: %@", key); // COV_NF_LINE + } + } + [dictionary_ release]; + dictionary_ = curDictionary; +} + +// Basic encoding methods for POD types. +// +// Arguments: +// *v - value to encode +// key - key to encode it in + +- (void)encodeBool:(BOOL)boolv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithBool:boolv] forKey:key]; +} + +- (void)encodeInt:(int)intv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithInt:intv] forKey:key]; +} + +- (void)encodeInt32:(int32_t)intv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithLong:intv] forKey:key]; +} + +- (void)encodeInt64:(int64_t)intv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithLongLong:intv] forKey:key]; +} + +- (void)encodeFloat:(float)realv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithFloat:realv] forKey:key]; +} + +- (void)encodeDouble:(double)realv forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSNumber numberWithDouble:realv] forKey:key]; +} + +- (void)encodeBytes:(const uint8_t *)bytesp + length:(unsigned)lenv + forKey:(NSString *)key { + [self checkForKey:key]; + [dictionary_ setObject:[NSData dataWithBytes:bytesp + length:lenv] + forKey:key]; +} + +// Get our storage back as an NSDictionary +// +// Returns: +// NSDictionary containing our encoded info +-(NSDictionary*)dictionary { + return [[dictionary_ retain] autorelease]; +} + +@end + +static NSString *gGTMUnitTestSaveToDirectory = nil; + +@implementation NSObject (GTMUnitTestingAdditions) + ++ (void)gtm_setUnitTestSaveToDirectory:(NSString*)path { + @synchronized([self class]) { + [gGTMUnitTestSaveToDirectory autorelease]; + gGTMUnitTestSaveToDirectory = [path copy]; + } +} + ++ (NSString *)gtm_getUnitTestSaveToDirectory { + NSString *result = nil; + @synchronized([self class]) { + if (!gGTMUnitTestSaveToDirectory) { +#if GTM_IPHONE_SDK + // Developer build, use their home directory Desktop. + gGTMUnitTestSaveToDirectory + = [[[[[NSHomeDirectory() stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent] + stringByAppendingPathComponent:@"Desktop"]; +#else + NSArray *desktopDirs + = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, + NSUserDomainMask, + YES); + gGTMUnitTestSaveToDirectory = [desktopDirs objectAtIndex:0]; +#endif + // Did we get overridden? + NSString *override = [self gtm_getOverrideDefaultUnitTestSaveToDirectory]; + if (override) { + gGTMUnitTestSaveToDirectory = override; + } + [gGTMUnitTestSaveToDirectory retain]; + } + result = gGTMUnitTestSaveToDirectory; + } + + return result; +} + +// Return nil if there is no override +- (NSString *)gtm_getOverrideDefaultUnitTestSaveToDirectory { + NSString *result = nil; + + // If we have an environment variable that ends in "BUILD_NUMBER" odds are + // we're on an automated build system, so use the build products dir as an + // override instead of writing on the desktop. + NSDictionary *env = [[NSProcessInfo processInfo] environment]; + NSString *key; + GTM_FOREACH_KEY(key, env) { + if ([key hasSuffix:@"BUILD_NUMBER"]) { + break; + } + } + if (key) { + result = [env objectForKey:@"BUILT_PRODUCTS_DIR"]; + } + + if (result && [result length] == 0) { + result = nil; + } + return result; +} + +/// Find the path for a file named name.extension in your bundle. +// Searches for the following: +// "name.extension", +// "name.arch.extension", +// "name.arch.OSVersionMajor.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.extension" +// "name.arch.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.extension" +// "name.arch.OSVersionMajor.extension" +// "name.OSVersionMajor.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.arch.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.arch.extension" +// "name.OSVersionMajor.extension" +// "name.OSVersionMajor.OSVersionMinor.extension" +// "name.OSVersionMajor.OSVersionMinor.OSVersion.bugfix.extension" +// Do not include the ".extension" extension on your name. +// +// Args: +// name: The name for the file you would like to find. +// extension: the extension for the file you would like to find +// +// Returns: +// the path if the file exists in your bundle +// or nil if no file is found +// +- (NSString *)gtm_pathForFileNamed:(NSString*)name + extension:(NSString*)extension { + NSString *thePath = nil; + Class bundleClass = [GTMUnitTestingAdditionsBundleFinder class]; + NSBundle *myBundle = [NSBundle bundleForClass:bundleClass]; + _GTMDevAssert(myBundle, + @"Couldn't find bundle for class: %@ searching for file:%@.%@", + NSStringFromClass(bundleClass), name, extension); + // System Version + SInt32 major, minor, bugFix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix]; + NSString *systemVersions[4]; + systemVersions[0] = [NSString stringWithFormat:@".%d.%d.%d", + major, minor, bugFix]; + systemVersions[1] = [NSString stringWithFormat:@".%d.%d", major, minor]; + systemVersions[2] = [NSString stringWithFormat:@".%d", major]; + systemVersions[3] = @""; + NSString *extensions[2]; + extensions[0] + = [NSString stringWithFormat:@".%@", + [GTMSystemVersion runtimeArchitecture]]; + extensions[1] = @""; + + size_t i, j; + // Note that we are searching for the most exact match first. + for (i = 0; + !thePath && i < sizeof(extensions) / sizeof(*extensions); + ++i) { + for (j = 0; + !thePath && j < sizeof(systemVersions) / sizeof(*systemVersions); + j++) { + NSString *fullName = [NSString stringWithFormat:@"%@%@%@", + name, extensions[i], systemVersions[j]]; + thePath = [myBundle pathForResource:fullName ofType:extension]; + if (thePath) break; + fullName = [NSString stringWithFormat:@"%@%@%@", + name, systemVersions[j], extensions[i]]; + thePath = [myBundle pathForResource:fullName ofType:extension]; + } + } + + return thePath; +} + +- (NSString *)gtm_saveToPathForFileNamed:(NSString*)name + extension:(NSString*)extension { + NSString *systemArchitecture = [GTMSystemVersion runtimeArchitecture]; + + SInt32 major, minor, bugFix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix]; + + NSString *fullName = [NSString stringWithFormat:@"%@.%@.%d.%d.%d", + name, systemArchitecture, major, minor, bugFix]; + + NSString *basePath = [[self class] gtm_getUnitTestSaveToDirectory]; + return [[basePath stringByAppendingPathComponent:fullName] + stringByAppendingPathExtension:extension]; +} + +#pragma mark UnitTestImage + +// Checks to see that system settings are valid for doing an image comparison. +// To be overridden by subclasses. +// Returns: +// YES if we can do image comparisons for this object type. +- (BOOL)gtm_areSystemSettingsValidForDoingImage { + return YES; +} + +- (CFStringRef)gtm_imageUTI { +#if GTM_IPHONE_SDK + return kUTTypePNG; +#else + // Currently can't use PNG on Leopard. (10.5.2) + // Radar:5844618 PNG importer/exporter in ImageIO is lossy + return kUTTypeTIFF; +#endif +} + +// Return the extension to be used for saving unittest images +// +// Returns +// An extension (e.g. "png") +- (NSString*)gtm_imageExtension { + CFStringRef uti = [self gtm_imageUTI]; +#if GTM_IPHONE_SDK + if (CFEqual(uti, kUTTypePNG)) { + return @"png"; + } else if (CFEqual(uti, kUTTypeJPEG)) { + return @"jpg"; + } else { + _GTMDevAssert(NO, @"Illegal UTI for iPhone"); + } + return nil; +#else + CFStringRef extension + = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension); + _GTMDevAssert(extension, @"No extension for uti: %@", uti); + + return GTMCFAutorelease(extension); +#endif +} + +// Return image data in the format expected for gtm_imageExtension +// So for a "png" extension I would expect "png" data +// +// Returns +// NSData for image +- (NSData*)gtm_imageDataForImage:(CGImageRef)image { + NSData *data = nil; +#if GTM_IPHONE_SDK + // iPhone support + UIImage *uiImage = [UIImage imageWithCGImage:image]; + CFStringRef uti = [self gtm_imageUTI]; + if (CFEqual(uti, kUTTypePNG)) { + data = UIImagePNGRepresentation(uiImage); + } else if (CFEqual(uti, kUTTypeJPEG)) { + data = UIImageJPEGRepresentation(uiImage, 1.0f); + } else { + _GTMDevAssert(NO, @"Illegal UTI for iPhone"); + } +#else + data = [NSMutableData data]; + CGImageDestinationRef dest + = CGImageDestinationCreateWithData((CFMutableDataRef)data, + [self gtm_imageUTI], + 1, + NULL); + // LZW Compression for TIFF + NSDictionary *tiffDict + = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:NSTIFFCompressionLZW], + (const NSString*)kCGImagePropertyTIFFCompression, + nil]; + NSDictionary *destProps + = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithFloat:1.0f], + (const NSString*)kCGImageDestinationLossyCompressionQuality, + tiffDict, + (const NSString*)kCGImagePropertyTIFFDictionary, + nil]; + CGImageDestinationAddImage(dest, image, (CFDictionaryRef)destProps); + CGImageDestinationFinalize(dest); + CFRelease(dest); +#endif + return data; + +} + +// Save the unitTestImage to an image file with name |name| at +// ~/Desktop/|name|.extension. +// +// Note: When running under Pulse automation output is redirected to the +// Pulse base directory. +// +// Args: +// name: The name for the image file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToImageNamed:(NSString*)name { + NSString *newPath = [self gtm_saveToPathForImageNamed:name]; + return [self gtm_saveToImageAt:newPath]; +} + +// Save unitTestImage of |self| to an image file at path |path|. +// +// Args: +// name: The name for the image file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToImageAt:(NSString*)path { + if (!path) return NO; + NSData *data = [self gtm_imageRepresentation]; + return [data writeToFile:path atomically:YES]; +} + +// Generates a CGImageRef from the image at |path| +// Args: +// path: The path to the image. +// +// Returns: +// A CGImageRef that you own, or nil if no image at path +- (CGImageRef)gtm_imageWithContentsOfFile:(NSString*)path { + CGImageRef imageRef = nil; +#if GTM_IPHONE_SDK + UIImage *image = [UIImage imageWithContentsOfFile:path]; + if (image) { + imageRef = CGImageRetain(image.CGImage); + } +#else + CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, + kCFURLPOSIXPathStyle, NO); + if (url) { + CGImageSourceRef imageSource = CGImageSourceCreateWithURL(url, NULL); + CFRelease(url); + if (imageSource) { + imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); + CFRelease(imageSource); + } + } +#endif + return (CGImageRef)GTMCFAutorelease(imageRef); +} + +/// Compares unitTestImage of |self| to the image located at |path| +// +// Args: +// path: the path to the image file you want to compare against. +// If diff is non-nil, it will contain an auto-released diff of the images. +// +// Returns: +// YES if they are equal, NO is they are not +// If diff is non-nil, it will contain an auto-released diff of the images. +// +- (BOOL)gtm_compareWithImageAt:(NSString*)path diffImage:(CGImageRef*)diff { + BOOL answer = NO; + if (diff) { + *diff = nil; + } + CGImageRef fileRep = [self gtm_imageWithContentsOfFile:path]; + _GTMDevAssert(fileRep, @"Unable to create imagerep from %@", path); + + CGImageRef imageRep = [self gtm_unitTestImage]; + _GTMDevAssert(imageRep, @"Unable to create imagerep for %@", self); + + size_t fileHeight = CGImageGetHeight(fileRep); + size_t fileWidth = CGImageGetWidth(fileRep); + size_t imageHeight = CGImageGetHeight(imageRep); + size_t imageWidth = CGImageGetWidth(imageRep); + if (fileHeight == imageHeight && fileWidth == imageWidth) { + // if all the sizes are equal, run through the bytes and compare + // them for equality. + // Do an initial fast check, if this fails and the caller wants a + // diff, we'll do the slow path and create the diff. The diff path + // could be optimized, but probably not necessary at this point. + answer = YES; + + CGSize imageSize = CGSizeMake(fileWidth, fileHeight); + CGRect imageRect = CGRectMake(0, 0, fileWidth, fileHeight); + unsigned char *fileData; + unsigned char *imageData; + CGContextRef fileContext + = GTMCreateUnitTestBitmapContextOfSizeWithData(imageSize, &fileData); + _GTMDevAssert(fileContext, @"Unable to create filecontext"); + CGContextDrawImage(fileContext, imageRect, fileRep); + CGContextRef imageContext + = GTMCreateUnitTestBitmapContextOfSizeWithData(imageSize, &imageData); + _GTMDevAssert(imageContext, @"Unable to create imageContext"); + CGContextDrawImage(imageContext, imageRect, imageRep); + + size_t fileBytesPerRow = CGBitmapContextGetBytesPerRow(fileContext); + size_t imageBytesPerRow = CGBitmapContextGetBytesPerRow(imageContext); + size_t row, col; + + _GTMDevAssert(imageWidth * 4 <= imageBytesPerRow, + @"We expect image data to be 32bit RGBA"); + + for (row = 0; row < fileHeight && answer; row++) { + answer = memcmp(fileData + fileBytesPerRow * row, + imageData + imageBytesPerRow * row, + imageWidth * 4) == 0; + } + if (!answer && diff) { + answer = YES; + unsigned char *diffData; + CGContextRef diffContext + = GTMCreateUnitTestBitmapContextOfSizeWithData(imageSize, &diffData); + _GTMDevAssert(diffContext, @"Can't make diff context"); + size_t diffRowBytes = CGBitmapContextGetBytesPerRow(diffContext); + for (row = 0; row < imageHeight; row++) { + uint32_t *imageRow = (uint32_t*)(imageData + imageBytesPerRow * row); + uint32_t *fileRow = (uint32_t*)(fileData + fileBytesPerRow * row); + uint32_t* diffRow = (uint32_t*)(diffData + diffRowBytes * row); + for (col = 0; col < imageWidth; col++) { + uint32_t imageColor = imageRow[col]; + uint32_t fileColor = fileRow[col]; + + unsigned char imageAlpha = imageColor & 0xF; + unsigned char imageBlue = imageColor >> 8 & 0xF; + unsigned char imageGreen = imageColor >> 16 & 0xF; + unsigned char imageRed = imageColor >> 24 & 0xF; + unsigned char fileAlpha = fileColor & 0xF; + unsigned char fileBlue = fileColor >> 8 & 0xF; + unsigned char fileGreen = fileColor >> 16 & 0xF; + unsigned char fileRed = fileColor >> 24 & 0xF; + + // Check to see if color is almost right. + // No matter how hard I've tried, I've still gotten occasionally + // screwed over by colorspaces not mapping correctly, and small + // sampling errors coming in. This appears to work for most cases. + // Almost equal is defined to check within 1% on all components. + BOOL equal = almostEqual(imageRed, fileRed) && + almostEqual(imageGreen, fileGreen) && + almostEqual(imageBlue, fileBlue) && + almostEqual(imageAlpha, fileAlpha); + answer &= equal; + if (diff) { + uint32_t newColor; + if (equal) { + newColor = (((uint32_t)imageRed) << 24) + + (((uint32_t)imageGreen) << 16) + + (((uint32_t)imageBlue) << 8) + + (((uint32_t)imageAlpha) / 2); + } else { + newColor = 0xFF0000FF; + } + diffRow[col] = newColor; + } + } + } + *diff = CGBitmapContextCreateImage(diffContext); + free(diffData); + CFRelease(diffContext); + } + free(fileData); + CFRelease(fileContext); + free(imageData); + CFRelease(imageContext); + } + return answer; +} + +// Find the path for an image by name in your bundle. +// Do not include the extension on your name. +// +// Args: +// name: The name for the image file you would like to find. +// +// Returns: +// the path if the image exists in your bundle +// or nil if no image to be found +// +- (NSString *)gtm_pathForImageNamed:(NSString*)name { + return [self gtm_pathForFileNamed:name + extension:[self gtm_imageExtension]]; +} + +- (NSString *)gtm_saveToPathForImageNamed:(NSString*)name { + return [self gtm_saveToPathForFileNamed:name + extension:[self gtm_imageExtension]]; +} + +// Gives us a representation of unitTestImage of |self|. +// +// Returns: +// a representation of image if successful +// nil if failed +// +- (NSData *)gtm_imageRepresentation { + CGImageRef imageRep = [self gtm_unitTestImage]; + NSData *data = [self gtm_imageDataForImage:imageRep]; + _GTMDevAssert(data, @"unable to create %@ from %@", + [self gtm_imageExtension], self); + return data; +} + +#pragma mark UnitTestState + +// Return the extension to be used for saving unittest states +// +// Returns +// An extension (e.g. "gtmUTState") +- (NSString*)gtm_stateExtension { + return @"gtmUTState"; +} + +// Save the encoded unit test state to a state file with name |name| at +// ~/Desktop/|name|.extension. +// +// Note: When running under Pulse automation output is redirected to the +// Pulse base directory. +// +// Args: +// name: The name for the state file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToStateNamed:(NSString*)name { + NSString *newPath = [self gtm_saveToPathForStateNamed:name]; + return [self gtm_saveToStateAt:newPath]; +} + +// Save encoded unit test state of |self| to a state file at path |path|. +// +// Args: +// name: The name for the state file you would like saved. +// +// Returns: +// YES if the file was successfully saved. +// +- (BOOL)gtm_saveToStateAt:(NSString*)path { + if (!path) return NO; + NSDictionary *dictionary = [self gtm_stateRepresentation]; + return [dictionary writeToFile:path atomically:YES]; +} + +// Compares encoded unit test state of |self| to the state file located at +// |path| +// +// Args: +// path: the path to the state file you want to compare against. +// +// Returns: +// YES if they are equal, NO is they are not +// +- (BOOL)gtm_compareWithStateAt:(NSString*)path { + NSDictionary *masterDict = [NSDictionary dictionaryWithContentsOfFile:path]; + _GTMDevAssert(masterDict, @"Unable to create dictionary from %@", path); + NSDictionary *selfDict = [self gtm_stateRepresentation]; + return [selfDict isEqual: masterDict]; +} + +// Find the path for a state by name in your bundle. +// Do not include the extension. +// +// Args: +// name: The name for the state file you would like to find. +// +// Returns: +// the path if the state exists in your bundle +// or nil if no state to be found +// +- (NSString *)gtm_pathForStateNamed:(NSString*)name { + return [self gtm_pathForFileNamed:name extension:[self gtm_stateExtension]]; +} + +- (NSString *)gtm_saveToPathForStateNamed:(NSString*)name { + return [self gtm_saveToPathForFileNamed:name + extension:[self gtm_stateExtension]]; +} + +// Gives us the encoded unit test state |self| +// +// Returns: +// the encoded state if successful +// nil if failed +// +- (NSDictionary *)gtm_stateRepresentation { + NSDictionary *dictionary = nil; + if ([self conformsToProtocol:@protocol(GTMUnitTestingEncoding)]) { + id encoder = (id)self; + GTMUnitTestingKeyedCoder *archiver; + archiver = [[[GTMUnitTestingKeyedCoder alloc] init] autorelease]; + [encoder gtm_unitTestEncodeState:archiver]; + dictionary = [archiver dictionary]; + } + return dictionary; +} + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. Encode data in the coder in the same +// manner that you would encode data in any other Keyed NSCoder subclass. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + // All impls of gtm_unitTestEncodeState + // should be calling [super gtm_unitTestEncodeState] as their first action. + _GTMDevAssert([inCoder isKindOfClass:[GTMUnitTestingKeyedCoder class]], + @"Coder must be of kind GTMUnitTestingKeyedCoder"); + + // If the object has a delegate, give it a chance to respond + if ([self respondsToSelector:@selector(delegate)]) { + id delegate = [self performSelector:@selector(delegate)]; + if (delegate && + [delegate respondsToSelector:@selector(gtm_unitTestEncoderWillEncode:inCoder:)]) { + [delegate gtm_unitTestEncoderWillEncode:self inCoder:inCoder]; + } + } +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.h new file mode 100644 index 00000000..1d355911 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.h @@ -0,0 +1,1004 @@ +// +// GTMSenTestCase.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Portions of this file fall under the following license, marked with +// SENTE_BEGIN - SENTE_END +// +// Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. +// +// Use of this source code is governed by the following license: +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Note: this license is equivalent to the FreeBSD license. +// +// This notice may not be removed from this file. + +// Some extra test case macros that would have been convenient for SenTestingKit +// to provide. I didn't stick GTM in front of the Macro names, so that they would +// be easy to remember. + +#import "GTMDefines.h" + +#if (!GTM_IPHONE_SDK) +#import +#else +#import +NSString *STComposeString(NSString *, ...); +#endif + +// Generates a failure when a1 != noErr +// Args: +// a1: should be either an OSErr or an OSStatus +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNoErr(a1, description, ...) \ +do { \ + @try {\ + OSStatus a1value = (a1); \ + if (a1value != noErr) { \ + NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", a1value, #a1]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 != a2 +// Args: +// a1: received value. Should be either an OSErr or an OSStatus +// a2: expected value. Should be either an OSErr or an OSStatus +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertErr(a1, a2, description, ...) \ +do { \ + @try {\ + OSStatus a1value = (a1); \ + OSStatus a2value = (a2); \ + if (a1value != a2value) { \ + NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, a2value, a1value, #a1]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + + +// Generates a failure when a1 is NULL +// Args: +// a1: should be a pointer (use STAssertNotNil for an object) +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNotNULL(a1, description, ...) \ +do { \ + @try {\ + const void* a1value = (a1); \ + if (a1value == NULL) { \ + NSString *_expression = [NSString stringWithFormat:@"(%s) != NULL", #a1]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 is not NULL +// Args: +// a1: should be a pointer (use STAssertNil for an object) +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNULL(a1, description, ...) \ +do { \ + @try {\ + const void* a1value = (a1); \ + if (a1value != NULL) { \ + NSString *_expression = [NSString stringWithFormat:@"(%s) == NULL", #a1]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 is equal to a2. This test is for C scalars, +// structs and unions. +// Args: +// a1: argument 1 +// a2: argument 2 +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNotEquals(a1, a2, description, ...) \ +do { \ + @try {\ + if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ + } else { \ + __typeof__(a1) a1value = (a1); \ + __typeof__(a2) a2value = (a2); \ + NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ + NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ + if ([a1encoded isEqualToValue:a2encoded]) { \ + NSString *_expression = [NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 is equal to a2. This test is for objects. +// Args: +// a1: argument 1. object. +// a2: argument 2. object. +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNotEqualObjects(a1, a2, desc, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + id a2value = (a2); \ + if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ + (@encode(__typeof__(a2value)) == @encode(id)) && \ + ![(id)a1value isEqual:(id)a2value] ) continue; \ + NSString *_expression = [NSString stringWithFormat:@"%s('%@') != %s('%@')", #a1, [a1 description], #a2, [a2 description]]; \ + if (desc) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(desc, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(desc, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 is not 'op' to a2. This test is for C scalars. +// Args: +// a1: argument 1 +// a2: argument 2 +// op: operation +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertOperation(a1, a2, op, description, ...) \ +do { \ + @try {\ + if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ + } else { \ + __typeof__(a1) a1value = (a1); \ + __typeof__(a2) a2value = (a2); \ + if (!(a1value op a2value)) { \ + double a1DoubleValue = a1value; \ + double a2DoubleValue = a2value; \ + NSString *_expression = [NSString stringWithFormat:@"%s (%lg) %s %s (%lg)", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ + if (description) { \ + _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ + } \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:_expression]]; \ + } \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException \ + failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when a1 is not > a2. This test is for C scalars. +// Args: +// a1: argument 1 +// a2: argument 2 +// op: operation +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertGreaterThan(a1, a2, description, ...) \ + STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) + +// Generates a failure when a1 is not >= a2. This test is for C scalars. +// Args: +// a1: argument 1 +// a2: argument 2 +// op: operation +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ + STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) + +// Generates a failure when a1 is not < a2. This test is for C scalars. +// Args: +// a1: argument 1 +// a2: argument 2 +// op: operation +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertLessThan(a1, a2, description, ...) \ + STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) + +// Generates a failure when a1 is not <= a2. This test is for C scalars. +// Args: +// a1: argument 1 +// a2: argument 2 +// op: operation +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertLessThanOrEqual(a1, a2, description, ...) \ + STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) + +// Generates a failure when string a1 is not equal to string a2. This call +// differs from STAssertEqualObjects in that strings that are different in +// composition (precomposed vs decomposed) will compare equal if their final +// representation is equal. +// ex O + umlaut decomposed is the same as O + umlaut composed. +// Args: +// a1: string 1 +// a2: string 2 +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertEqualStrings(a1, a2, description, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + id a2value = (a2); \ + if (a1value == a2value) continue; \ + if ([a1value isKindOfClass:[NSString class]] && \ + [a2value isKindOfClass:[NSString class]] && \ + [a1value compare:a2value options:0] == NSOrderedSame) continue; \ + [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ + andObject: a2value \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when string a1 is equal to string a2. This call +// differs from STAssertEqualObjects in that strings that are different in +// composition (precomposed vs decomposed) will compare equal if their final +// representation is equal. +// ex O + umlaut decomposed is the same as O + umlaut composed. +// Args: +// a1: string 1 +// a2: string 2 +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNotEqualStrings(a1, a2, description, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + id a2value = (a2); \ + if ([a1value isKindOfClass:[NSString class]] && \ + [a2value isKindOfClass:[NSString class]] && \ + [a1value compare:a2value options:0] != NSOrderedSame) continue; \ + [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ + andObject: a2value \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when c-string a1 is not equal to c-string a2. +// Args: +// a1: string 1 +// a2: string 2 +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertEqualCStrings(a1, a2, description, ...) \ +do { \ + @try {\ + const char* a1value = (a1); \ + const char* a2value = (a2); \ + if (a1value == a2value) continue; \ + if (strcmp(a1value, a2value) == 0) continue; \ + [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ + andObject: [NSString stringWithUTF8String:a2value] \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +// Generates a failure when c-string a1 is equal to c-string a2. +// Args: +// a1: string 1 +// a2: string 2 +// description: A format string as in the printf() function. Can be nil or +// an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +#define STAssertNotEqualCStrings(a1, a2, description, ...) \ +do { \ + @try {\ + const char* a1value = (a1); \ + const char* a2value = (a2); \ + if (strcmp(a1value, a2value) != 0) continue; \ + [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ + andObject: [NSString stringWithUTF8String:a2value] \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +#if GTM_IPHONE_SDK + +// SENTE_BEGIN +/*" Generates a failure when !{ [a1 isEqualTo:a2] } is false + (or one is nil and the other is not). + _{a1 The object on the left.} + _{a2 The object on the right.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertEqualObjects(a1, a2, description, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + id a2value = (a2); \ + if (a1value == a2value) continue; \ + if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ + (@encode(__typeof__(a2value)) == @encode(id)) && \ + [(id)a1value isEqual: (id)a2value] ) continue; \ + [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ + andObject: a2value \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + + +/*" Generates a failure when a1 is not equal to a2. This test is for + C scalars, structs and unions. + _{a1 The argument on the left.} + _{a2 The argument on the right.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertEquals(a1, a2, description, ...) \ +do { \ + @try {\ + if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ + } else { \ + __typeof__(a1) a1value = (a1); \ + __typeof__(a2) a2value = (a2); \ + NSValue *a1encoded = [NSValue value:&a1value withObjCType: @encode(__typeof__(a1))]; \ + NSValue *a2encoded = [NSValue value:&a2value withObjCType: @encode(__typeof__(a2))]; \ + if (![a1encoded isEqualToValue:a2encoded]) { \ + [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ + andValue: a2encoded \ + withAccuracy: nil \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + +#define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) + + +/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. + This test is for scalars such as floats and doubles where small differences + could make these items not exactly equal, but also works for all scalars. + _{a1 The scalar on the left.} + _{a2 The scalar on the right.} + _{accuracy The maximum difference between a1 and a2 for these values to be + considered equal.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ + +#define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ +do { \ + @try {\ + if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ + [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ + } else { \ + __typeof__(a1) a1value = (a1); \ + __typeof__(a2) a2value = (a2); \ + __typeof__(accuracy) accuracyvalue = (accuracy); \ + if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ + NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ + NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ + NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ + [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ + andValue: a2encoded \ + withAccuracy: accuracyencoded \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + + + +/*" Generates a failure unconditionally. + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STFail(description, ...) \ +[self failWithException:[NSException failureInFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]] + + + +/*" Generates a failure when a1 is not nil. + _{a1 An object.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertNil(a1, description, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + if (a1value != nil) { \ + NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ + NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: NO \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == nil fails", #a1] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + + +/*" Generates a failure when a1 is nil. + _{a1 An object.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertNotNil(a1, description, ...) \ +do { \ + @try {\ + id a1value = (a1); \ + if (a1value == nil) { \ + NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ + NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: NO \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + }\ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != nil fails", #a1] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while(0) + + +/*" Generates a failure when expression evaluates to false. + _{expr The expression that is tested.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertTrue(expr, description, ...) \ +do { \ + BOOL _evaluatedExpression = (expr);\ + if (!_evaluatedExpression) {\ + NSString *_expression = [NSString stringWithUTF8String: #expr];\ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: NO \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ +} while (0) + + +/*" Generates a failure when expression evaluates to false and in addition will + generate error messages if an exception is encountered. + _{expr The expression that is tested.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertTrueNoThrow(expr, description, ...) \ +do { \ + @try {\ + BOOL _evaluatedExpression = (expr);\ + if (!_evaluatedExpression) {\ + NSString *_expression = [NSString stringWithUTF8String: #expr];\ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: NO \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) ", #expr] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while (0) + + +/*" Generates a failure when the expression evaluates to true. + _{expr The expression that is tested.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertFalse(expr, description, ...) \ +do { \ + BOOL _evaluatedExpression = (expr);\ + if (_evaluatedExpression) {\ + NSString *_expression = [NSString stringWithUTF8String: #expr];\ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: YES \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ +} while (0) + + +/*" Generates a failure when the expression evaluates to true and in addition + will generate error messages if an exception is encountered. + _{expr The expression that is tested.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertFalseNoThrow(expr, description, ...) \ +do { \ + @try {\ + BOOL _evaluatedExpression = (expr);\ + if (_evaluatedExpression) {\ + NSString *_expression = [NSString stringWithUTF8String: #expr];\ + [self failWithException:[NSException failureInCondition: _expression \ + isTrue: YES \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + } \ + } \ + @catch (id anException) {\ + [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"!(%s) ", #expr] \ + exception:anException \ + inFile:[NSString stringWithUTF8String:__FILE__] \ + atLine:__LINE__ \ + withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while (0) + + +/*" Generates a failure when expression does not throw an exception. + _{expression The expression that is evaluated.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent. +"*/ +#define STAssertThrows(expr, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (id anException) { \ + continue; \ + }\ + [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: nil \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ +} while (0) + + +/*" Generates a failure when expression does not throw an exception of a + specific class. + _{expression The expression that is evaluated.} + _{specificException The specified class of the exception.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertThrowsSpecific(expr, specificException, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (specificException *anException) { \ + continue; \ + }\ + @catch (id anException) {\ + NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ + [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ + continue; \ + }\ + NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ + [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: nil \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ +} while (0) + + +/*" Generates a failure when expression does not throw an exception of a + specific class with a specific name. Useful for those frameworks like + AppKit or Foundation that throw generic NSException w/specific names + (NSInvalidArgumentException, etc). + _{expression The expression that is evaluated.} + _{specificException The specified class of the exception.} + _{aName The name of the specified exception.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} + +"*/ +#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (specificException *anException) { \ + if ([aName isEqualToString: [anException name]]) continue; \ + NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ + [self failWithException: \ + [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ + continue; \ + }\ + @catch (id anException) {\ + NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ + [self failWithException: \ + [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ + continue; \ + }\ + NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ + [self failWithException: \ + [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: nil \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ +} while (0) + + +/*" Generates a failure when expression does throw an exception. + _{expression The expression that is evaluated.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertNoThrow(expr, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (id anException) { \ + [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ +} while (0) + + +/*" Generates a failure when expression does throw an exception of the specitied + class. Any other exception is okay (i.e. does not generate a failure). + _{expression The expression that is evaluated.} + _{specificException The specified class of the exception.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} +"*/ +#define STAssertNoThrowSpecific(expr, specificException, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (specificException *anException) { \ + [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ + }\ + @catch (id anythingElse) {\ + ; \ + }\ +} while (0) + + +/*" Generates a failure when expression does throw an exception of a + specific class with a specific name. Useful for those frameworks like + AppKit or Foundation that throw generic NSException w/specific names + (NSInvalidArgumentException, etc). + _{expression The expression that is evaluated.} + _{specificException The specified class of the exception.} + _{aName The name of the specified exception.} + _{description A format string as in the printf() function. Can be nil or + an empty string but must be present.} + _{... A variable number of arguments to the format string. Can be absent.} + +"*/ +#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ +do { \ + @try { \ + (expr);\ + } \ + @catch (specificException *anException) { \ + if ([aName isEqualToString: [anException name]]) { \ + NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ + [self failWithException: \ + [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ + exception: anException \ + inFile: [NSString stringWithUTF8String:__FILE__] \ + atLine: __LINE__ \ + withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ + } \ + continue; \ + }\ + @catch (id anythingElse) {\ + ; \ + }\ +} while (0) + + + +@interface NSException (GTMSenTestAdditions) ++ (NSException *)failureInFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ...; ++ (NSException *)failureInCondition:(NSString *)condition + isTrue:(BOOL)isTrue + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ...; ++ (NSException *)failureInEqualityBetweenObject:(id)left + andObject:(id)right + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ...; ++ (NSException *)failureInEqualityBetweenValue:(NSValue *)left + andValue:(NSValue *)right + withAccuracy:(NSValue *)accuracy + inFile:(NSString *)filename + atLine:(int) ineNumber + withDescription:(NSString *)formatString, ...; ++ (NSException *)failureInRaise:(NSString *)expression + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ...; ++ (NSException *)failureInRaise:(NSString *)expression + exception:(NSException *)exception + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ...; +@end + +// SENTE_END + +@interface SenTestCase : NSObject { + SEL currentSelector_; +} + +- (void)setUp; +- (void)invokeTest; +- (void)tearDown; +- (void)performTest:(SEL)sel; +- (void)failWithException:(NSException*)exception; +@end + +GTM_EXTERN NSString *const SenTestFailureException; + +GTM_EXTERN NSString *const SenTestFilenameKey; +GTM_EXTERN NSString *const SenTestLineNumberKey; + +#endif // GTM_IPHONE_SDK + +// All unittest cases in GTM should inherit from GTMTestCase. It makes sure +// to set up our logging system correctly to verify logging calls. +// See GTMUnitTestDevLog.h for details +@interface GTMTestCase : SenTestCase +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.m new file mode 100644 index 00000000..8482c5a6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMSenTestCase.m @@ -0,0 +1,362 @@ +// +// GTMSenTestCase.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import + +#if !GTM_IPHONE_SDK +#import "GTMGarbageCollection.h" +#endif // !GTM_IPHONE_SDK + +#if GTM_IPHONE_SDK +#import + +@interface NSException (GTMSenTestPrivateAdditions) ++ (NSException *)failureInFile:(NSString *)filename + atLine:(int)lineNumber + reason:(NSString *)reason; +@end + +@implementation NSException (GTMSenTestPrivateAdditions) ++ (NSException *)failureInFile:(NSString *)filename + atLine:(int)lineNumber + reason:(NSString *)reason { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey, + filename, SenTestFilenameKey, + nil]; + + return [self exceptionWithName:SenTestFailureException + reason:reason + userInfo:userInfo]; +} +@end + +@implementation NSException (GTMSenTestAdditions) + ++ (NSException *)failureInFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason = testDescription; + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + ++ (NSException *)failureInCondition:(NSString *)condition + isTrue:(BOOL)isTrue + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@", + condition, isTrue ? "TRUE" : "FALSE", testDescription]; + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + ++ (NSException *)failureInEqualityBetweenObject:(id)left + andObject:(id)right + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason = + [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", + [left description], [right description], testDescription]; + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + ++ (NSException *)failureInEqualityBetweenValue:(NSValue *)left + andValue:(NSValue *)right + withAccuracy:(NSValue *)accuracy + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason; + if (accuracy) { + reason = + [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", + left, right, testDescription]; + } else { + reason = + [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@", + left, right, accuracy, testDescription]; + } + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + ++ (NSException *)failureInRaise:(NSString *)expression + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@", + expression, testDescription]; + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + ++ (NSException *)failureInRaise:(NSString *)expression + exception:(NSException *)exception + inFile:(NSString *)filename + atLine:(int)lineNumber + withDescription:(NSString *)formatString, ... { + + NSString *testDescription = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + testDescription = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + + NSString *reason; + if ([[exception name] isEqualToString:SenTestFailureException]) { + // it's our exception, assume it has the right description on it. + reason = [exception reason]; + } else { + // not one of our exception, use the exceptions reason and our description + reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@", + expression, [exception reason], testDescription]; + } + + return [self failureInFile:filename atLine:lineNumber reason:reason]; +} + +@end + +NSString *STComposeString(NSString *formatString, ...) { + NSString *reason = @""; + if (formatString) { + va_list vl; + va_start(vl, formatString); + reason = + [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; + va_end(vl); + } + return reason; +} + +NSString *const SenTestFailureException = @"SenTestFailureException"; +NSString *const SenTestFilenameKey = @"SenTestFilenameKey"; +NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey"; + +@interface SenTestCase (SenTestCasePrivate) +// our method of logging errors ++ (void)printException:(NSException *)exception fromTestName:(NSString *)name; +@end + +@implementation SenTestCase +- (void)failWithException:(NSException*)exception { + [exception raise]; +} + +- (void)setUp { +} + +- (void)performTest:(SEL)sel { + currentSelector_ = sel; + @try { + [self invokeTest]; + } @catch (NSException *exception) { + [[self class] printException:exception + fromTestName:NSStringFromSelector(sel)]; + [exception raise]; + } +} + ++ (void)printException:(NSException *)exception fromTestName:(NSString *)name { + NSDictionary *userInfo = [exception userInfo]; + NSString *filename = [userInfo objectForKey:SenTestFilenameKey]; + NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey]; + NSString *className = NSStringFromClass([self class]); + if ([filename length] == 0) { + filename = @"Unknown.m"; + } + fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n", + [filename UTF8String], + (long)[lineNumber integerValue], + [className UTF8String], + [name UTF8String], + [[exception reason] UTF8String]); + fflush(stderr); +} + +- (void)invokeTest { + NSException *e = nil; + @try { + // Wrap things in autorelease pools because they may + // have an STMacro in their dealloc which may get called + // when the pool is cleaned up + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + // We don't log exceptions here, instead we let the person that called + // this log the exception. This ensures they are only logged once but the + // outer layers get the exceptions to report counts, etc. + @try { + [self setUp]; + @try { + [self performSelector:currentSelector_]; + } @catch (NSException *exception) { + e = [exception retain]; + } + [self tearDown]; + } @catch (NSException *exception) { + e = [exception retain]; + } + [pool release]; + } @catch (NSException *exception) { + e = [exception retain]; + } + if (e) { + [e autorelease]; + [e raise]; + } +} + +- (void)tearDown { +} + +- (NSString *)description { + // This matches the description OCUnit would return to you + return [NSString stringWithFormat:@"-[%@ %@]", [self class], + NSStringFromSelector(currentSelector_)]; +} +@end + +#endif // GTM_IPHONE_SDK + +@implementation GTMTestCase : SenTestCase +- (void)invokeTest { + Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog"); + if (devLogClass) { + [devLogClass performSelector:@selector(enableTracking)]; + [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; + + } + [super invokeTest]; + if (devLogClass) { + [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; + [devLogClass performSelector:@selector(disableTracking)]; + } +} +@end + +// Leak detection +#if !GTM_IPHONE_DEVICE +// Don't want to get leaks on the iPhone Device as the device doesn't +// have 'leaks'. The simulator does though. + +static void _GTMRunLeaks(void) { + // This is an atexit handler. It runs leaks for us to check if we are + // leaking anything in our tests. + const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE"); + NSMutableString *exclusions = [NSMutableString string]; + if (cExclusionsEnv) { + NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv]; + NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","]; + NSString *exclusion; + NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet]; + GTM_FOREACH_OBJECT(exclusion, exclusionsArray) { + exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet]; + [exclusions appendFormat:@"-exclude \"%@\" ", exclusion]; + } + } + NSString *string + = [NSString stringWithFormat:@"/usr/bin/leaks %@%d" + @"| /usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'", + exclusions, getpid()]; + int ret = system([string UTF8String]); + if (ret) { + fprintf(stderr, "%s:%d: Error: Unable to run leaks. 'system' returned: %d", + __FILE__, __LINE__, ret); + fflush(stderr); + } +} + +static __attribute__((constructor)) void _GTMInstallLeaks(void) { + BOOL checkLeaks = YES; +#if !GTM_IPHONE_SDK + checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES; +#endif // !GTM_IPHONE_SDK + if (checkLeaks) { + checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO; + if (checkLeaks) { + if (checkLeaks) { + fprintf(stderr, "Leak Checking Enabled\n"); + fflush(stderr); + int ret = atexit(&_GTMRunLeaks); + _GTMDevAssert(ret == 0, + @"Unable to install _GTMRunLeaks as an atexit handler (%d)", + errno); + } + } + } +} + +#endif // !GTM_IPHONE_DEVICE diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.h new file mode 100644 index 00000000..0128718b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.h @@ -0,0 +1,39 @@ +// +// GTMTestHTTPServer.h +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +@class GTMHTTPServer; + +// This is a HTTP Server that can respond to certain requests that look like +// Google service logins. It takes extra url arguments to tell it what to +// return for testing the code using it. See GTMHTTPFetcherTest for an example +// of its usage. +@interface GTMTestHTTPServer : NSObject { + NSString *docRoot_; + GTMHTTPServer *server_; +} + +// Any url that isn't a specific server request (login, etc.), will be fetched +// off |docRoot| (to allow canned repsonses). +- (id)initWithDocRoot:(NSString *)docRoot; + +// fetch the port the server is running on +- (uint16_t)port; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.m new file mode 100644 index 00000000..7744b5e9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestHTTPServer.m @@ -0,0 +1,166 @@ +// +// GTMTestHTTPServer.m +// +// Copyright 2007-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMTestHTTPServer.h" +#import "GTMHTTPServer.h" +#import "GTMRegex.h" + +static NSArray *GetSubPatternsOfFirstStringMatchedByPattern(NSString *stringToSearch, + NSString *pattern) { + GTMRegex *regex = [GTMRegex regexWithPattern:pattern]; + NSString *firstMatch = [regex firstSubStringMatchedInString:stringToSearch]; + NSArray *subPatterns = [regex subPatternsOfString:firstMatch]; + return subPatterns; +} + +@implementation GTMTestHTTPServer + +- (id)initWithDocRoot:(NSString *)docRoot { + self = [super init]; + if (self) { + docRoot_ = [docRoot copy]; + server_ = [[GTMHTTPServer alloc] initWithDelegate:self]; + NSError *error = nil; + if ((docRoot == nil) || (![server_ start:&error])) { + _GTMDevLog(@"Failed to start up the webserver (docRoot='%@', error=%@)", + docRoot_, error); + [self release]; + return nil; + } + } + return self; +} + +- (void)dealloc { + [docRoot_ release]; + [server_ release]; + [super dealloc]; +} + +- (uint16_t)port { + return [server_ port]; +} + +- (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server + handleRequest:(GTMHTTPRequestMessage *)request { + _GTMDevAssert(server == server_, @"how'd we get a different server?!"); + UInt32 resultStatus = 0; + NSData *data = nil; + // clients should treat dates as opaque, generally + NSString *modifiedDate = @"thursday"; + + NSString *postString = @""; + NSData *postData = [request body]; + if ([postData length] > 0) { + postString = [[[NSString alloc] initWithData:postData + encoding:NSUTF8StringEncoding] autorelease]; + } + + NSDictionary *allHeaders = [request allHeaderFieldValues]; + NSString *ifModifiedSince = [allHeaders objectForKey:@"If-Modified-Since"]; + NSString *authorization = [allHeaders objectForKey:@"Authorization"]; + NSString *path = [[request URL] absoluteString]; + + if ([path hasSuffix:@".auth"]) { + if (![authorization isEqualToString:@"GoogleLogin auth=GoodAuthToken"]) { + GTMHTTPResponseMessage *response = + [GTMHTTPResponseMessage emptyResponseWithCode:401]; + return response; + } else { + path = [path substringToIndex:[path length] - 5]; + } + } + + NSString *overrideHeader = [allHeaders objectForKey:@"X-HTTP-Method-Override"]; + NSString *httpCommand = [request method]; + if ([httpCommand isEqualToString:@"POST"] && + [overrideHeader length] > 1) { + httpCommand = overrideHeader; + } + NSArray *searchResult = nil; + if ([path hasSuffix:@"/accounts/ClientLogin"]) { + // it's a sign-in attempt; it's good unless the password is "bad" or + // "captcha" + + // use regular expression to find the password + NSString *password = @""; + searchResult = GetSubPatternsOfFirstStringMatchedByPattern(path, @"Passwd=([^&\n]*)"); + if ([searchResult count] == 2) { + password = [searchResult objectAtIndex:1]; + } + + if ([password isEqualToString:@"bad"]) { + resultStatus = 403; + } else if ([password isEqualToString:@"captcha"]) { + NSString *loginToken = @""; + NSString *loginCaptcha = @""; + + searchResult = GetSubPatternsOfFirstStringMatchedByPattern(postString, @"logintoken=([^&\n]*)"); + if ([searchResult count] == 2) { + loginToken = [searchResult objectAtIndex:1]; + } + + searchResult = GetSubPatternsOfFirstStringMatchedByPattern(postString, @"logincaptcha=([^&\n]*)"); + if ([searchResult count] == 2) { + loginCaptcha = [searchResult objectAtIndex:1]; + } + + if ([loginToken isEqualToString:@"CapToken"] && + [loginCaptcha isEqualToString:@"good"]) { + resultStatus = 200; + } else { + // incorrect captcha token or answer provided + resultStatus = 403; + } + } else { + // valid username/password + resultStatus = 200; + } + } else if ([httpCommand isEqualToString:@"DELETE"]) { + // it's an object delete; read and return empty data + resultStatus = 200; + } else { + // queries that have something like "?status=456" should fail with the + // status code + searchResult = GetSubPatternsOfFirstStringMatchedByPattern(path, @"status=([0-9]+)"); + if ([searchResult count] == 2) { + resultStatus = [[searchResult objectAtIndex:1] intValue]; + } else if ([ifModifiedSince isEqualToString:modifiedDate]) { + resultStatus = 304; + } else { + NSString *docPath = [docRoot_ stringByAppendingPathComponent:path]; + data = [NSData dataWithContentsOfFile:docPath]; + if (data) { + resultStatus = 200; + } else { + resultStatus = 404; + } + } + } + + GTMHTTPResponseMessage *response = + [GTMHTTPResponseMessage responseWithBody:data + contentType:@"text/plain" + statusCode:resultStatus]; + [response setValue:modifiedDate forHeaderField:@"Last-Modified"]; + [response setValue:[NSString stringWithFormat:@"TestCookie=%@", [path lastPathComponent]] + forHeaderField:@"Set-Cookie"]; + return response; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimer.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimer.h new file mode 100644 index 00000000..6c5fc55c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimer.h @@ -0,0 +1,125 @@ +// +// GTMTestTimer.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMDefines.h" +#import + +// GTMTestTimer is done in straight inline C to avoid obj-c calling overhead. +// It is for doing test timings at very high precision. +// Test Timers have standard CoreFoundation Retain/Release rules. +// Test Timers are not thread safe. Test Timers do NOT check their arguments +// for NULL. You will crash if you pass a NULL argument in. + +typedef struct { + mach_timebase_info_data_t time_base_info_; + bool running_; + uint64_t start_; + uint64_t split_; + uint64_t elapsed_; + NSUInteger iterations_; + NSUInteger retainCount_; +} GTMTestTimer; + +// Create a test timer +GTM_INLINE GTMTestTimer *GTMTestTimerCreate(void) { + GTMTestTimer *t = calloc(sizeof(GTMTestTimer), 1); + if (t) { + if (mach_timebase_info(&t->time_base_info_) == KERN_SUCCESS) { + t->retainCount_ = 1; + } else { + // COV_NF_START + free(t); + t = NULL; + // COV_NF_END + } + } + return t; +} + +// Retain a timer +GTM_INLINE void GTMTestTimerRetain(GTMTestTimer *t) { + t->retainCount_ += 1; +} + +// Release a timer. When release count hits zero, we free it. +GTM_INLINE void GTMTestTimerRelease(GTMTestTimer *t) { + t->retainCount_ -= 1; + if (t->retainCount_ == 0) { + free(t); + } +} + +// Starts a timer timing. Specifically starts a new split. If the timer is +// currently running, it resets the start time of the current split. +GTM_INLINE void GTMTestTimerStart(GTMTestTimer *t) { + t->start_ = mach_absolute_time(); + t->running_ = true; +} + +// Stops a timer and returns split time (time from last start) in nanoseconds. +GTM_INLINE uint64_t GTMTestTimerStop(GTMTestTimer *t) { + uint64_t now = mach_absolute_time(); + t->running_ = false; + ++t->iterations_; + t->split_ = now - t->start_; + t->elapsed_ += t->split_; + t->start_ = 0; + return t->split_; +} + +// returns the current timer elapsed time (combined value of all splits, plus +// current split if the timer is running) in nanoseconds. +GTM_INLINE double GTMTestTimerGetNanoseconds(GTMTestTimer *t) { + uint64_t total = t->elapsed_; + if (t->running_) { + total += mach_absolute_time() - t->start_; + } + return (double)(total * t->time_base_info_.numer + / t->time_base_info_.denom); +} + +// Returns the current timer elapsed time (combined value of all splits, plus +// current split if the timer is running) in seconds. +GTM_INLINE double GTMTestTimerGetSeconds(GTMTestTimer *t) { + return GTMTestTimerGetNanoseconds(t) * 0.000000001; +} + +// Returns the current timer elapsed time (combined value of all splits, plus +// current split if the timer is running) in milliseconds. +GTM_INLINE double GTMTestTimerGetMilliseconds(GTMTestTimer *t) { + return GTMTestTimerGetNanoseconds(t) * 0.000001; +} + +// Returns the current timer elapsed time (combined value of all splits, plus +// current split if the timer is running) in microseconds. +GTM_INLINE double GTMTestTimerGetMicroseconds(GTMTestTimer *t) { + return GTMTestTimerGetNanoseconds(t) * 0.001; +} + +// Returns the number of splits (start-stop) cycles recorded. +// GTMTestTimerGetSeconds()/GTMTestTimerGetIterations() gives you an average +// of all your splits. +GTM_INLINE NSUInteger GTMTestTimerGetIterations(GTMTestTimer *t) { + return t->iterations_; +} + +// Returns true if the timer is running. +GTM_INLINE bool GTMTestTimerIsRunning(GTMTestTimer *t) { + return t->running_; +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimerTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimerTest.m new file mode 100644 index 00000000..86f9d221 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMTestTimerTest.m @@ -0,0 +1,56 @@ +// +// GTMTestTimerTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMTestTimer.h" + +@interface GTMTestTimerTest : GTMTestCase +@end + +@implementation GTMTestTimerTest +- (void)testTimer { + GTMTestTimer *timer = GTMTestTimerCreate(); + STAssertNotNULL(timer, nil); + GTMTestTimerRetain(timer); + GTMTestTimerRelease(timer); + STAssertEqualsWithAccuracy(GTMTestTimerGetSeconds(timer), 0.0, 0.0, nil); + GTMTestTimerStart(timer); + STAssertTrue(GTMTestTimerIsRunning(timer), nil); + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + GTMTestTimerStop(timer); + + // We use greater than (and an almost absurd less than) because + // these tests are very dependant on machine load, and we don't want + // automated tests reporting false negatives. + STAssertGreaterThan(GTMTestTimerGetSeconds(timer), 0.1, nil); + STAssertGreaterThan(GTMTestTimerGetMilliseconds(timer), 100.0,nil); + STAssertGreaterThan(GTMTestTimerGetMicroseconds(timer), 100000.0, nil); + + // Check to make sure we're not WAY off the mark (by a factor of 10) + STAssertLessThan(GTMTestTimerGetMicroseconds(timer), 1000000.0, nil); + + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + GTMTestTimerStart(timer); + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + STAssertGreaterThan(GTMTestTimerGetSeconds(timer), 0.2, nil); + GTMTestTimerStop(timer); + STAssertEquals(GTMTestTimerGetIterations(timer), (NSUInteger)2, nil); + GTMTestTimerRelease(timer); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.h new file mode 100644 index 00000000..ee420e94 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.h @@ -0,0 +1,128 @@ +// +// GTMUIKit+UnitTesting.h +// +// Code for making unit testing of graphics/UI easier. Generally you +// will only want to look at the macros: +// GTMAssertDrawingEqualToFile +// GTMAssertViewRepEqualToFile +// and the protocol GTMUnitTestViewDrawer. When using these routines +// make sure you are using device colors and not calibrated/generic colors +// or else your test graphics WILL NOT match across devices/graphics cards. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMNSObject+UnitTesting.h" + +@protocol GTMUnitTestViewDrawer; + +// Fails when the |a1|'s drawing in an area |a2| does not equal the image file named |a3|. +// See the description of the GTMAssertViewRepEqualToFile macro +// to understand how |a3| is found and written out. +// See the description of the GTMUnitTestView for a better idea +// how the view works. +// Implemented as a macro to match the rest of the SenTest macros. +// +// Args: +// a1: The object that implements the GTMUnitTestViewDrawer protocol +// that is doing the drawing. +// a2: The size of the drawing +// a3: The name of the image file to check against. +// Do not include the extension +// a4: contextInfo to pass to drawer +// description: A format string as in the printf() function. +// Can be nil or an empty string but must be present. +// ...: A variable number of arguments to the format string. Can be absent. +// + +#define GTMAssertDrawingEqualToFile(a1, a2, a3, a4, description, ...) \ + do { \ + id a1Drawer = (a1); \ + CGSize a2Size = (a2); \ + NSString* a3String = (a3); \ + void *a4ContextInfo = (a4); \ + CGRect frame = CGRectMake(0, 0, a2Size.width, a2Size.height); \ + GTMUnitTestView *view = [[[GTMUnitTestView alloc] initWithFrame:frame drawer:a1Drawer contextInfo:a4ContextInfo] autorelease]; \ + GTMAssertObjectImageEqualToImageNamed(view, a3String, STComposeString(description, ##__VA_ARGS__)); \ + } while(0) + +// Category for making unit testing of graphics/UI easier. + +// Allows you to take a state of a view. Supports both image and state. +// See GTMNSObject+UnitTesting.h for details. +@interface UIView (GTMUnitTestingAdditions) + +// Encodes the state of an object in a manner suitable for comparing against a master state file +// This enables us to determine whether the object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder; + +// Returns whether gtm_unitTestEncodeState should recurse into subviews +// +// Returns: +// should gtm_unitTestEncodeState pick up subview state. +- (BOOL)gtm_shouldEncodeStateForSubviews; +@end + +// Category to help UIImage testing. UIImage can be tested using +// GTMAssertObjectImageEqualToImageNamed macro, which automatically creates +// result images and diff images in case test fails. +@interface UIImage (GTMUnitTestingAdditions) +@end + +// A view that allows you to delegate out drawing using the formal +// GTMUnitTestViewDelegate protocol +// This is useful when writing up unit tests for visual elements. +// Your test will often end up looking like this: +// - (void)testFoo { +// GTMAssertDrawingEqualToFile(self, CGSizeMake(200, 200), @"Foo", nil, nil); +// } +// and your testSuite will also implement the unitTestViewDrawRect method to do +// it's actual drawing. The above creates a view of size 200x200 that draws +// it's content using |self|'s unitTestViewDrawRect method and compares it to +// the contents of the file Foo.tif to make sure it's valid +@interface GTMUnitTestView : UIView { + @private + id drawer_; // delegate for doing drawing (STRONG) + void* contextInfo_; // info passed in by user for them to use when drawing +} + +// Create a GTMUnitTestView. +// +// Args: +// rect: the area to draw. +// drawer: the object that will do the drawing via the GTMUnitTestViewDrawer +// protocol +// contextInfo: +- (id)initWithFrame:(CGRect)frame drawer:(id)drawer contextInfo:(void*)contextInfo; + +@end + +/// \cond Protocols + +// Formal protocol for doing unit testing of views. See description of +// GTMUnitTestView for details. +@protocol GTMUnitTestViewDrawer + +// Draw the view. Equivalent to drawRect on a standard UIView. +// +// Args: +// rect: the area to draw. +- (void)gtm_unitTestViewDrawRect:(CGRect)rect contextInfo:(void*)contextInfo; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.m new file mode 100644 index 00000000..7d3f200e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTesting.m @@ -0,0 +1,122 @@ +// +// GTMUIKit+UnitTesting.m +// +// Category for making unit testing of graphics/UI easier. +// Allows you to save a view out to a image file, and compare a view +// with a previously stored representation to make sure it hasn't changed. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMUIKit+UnitTesting.h" +#import "GTMCALayer+UnitTesting.h" +#import "GTMDefines.h" + +#if !GTM_IPHONE_SDK +#error This file is for iPhone use only +#endif // GTM_IPHONE_SDK + +// A view that allows you to delegate out drawing using the formal +// GTMUnitTestViewDelegate protocol above. This is useful when writing up unit +// tests for visual elements. +// Your test will often end up looking like this: +// - (void)testFoo { +// GTMAssertDrawingEqualToFile(self, CGSizeMake(200, 200), @"Foo", nil, nil); +// } +// and your testSuite will also implement the unitTestViewDrawRect method to do +// it's actual drawing. The above creates a view of size 200x200 that draws +// it's content using |self|'s unitTestViewDrawRect method and compares it to +// the contents of the file Foo.tif to make sure it's valid +@implementation GTMUnitTestView + +- (id)initWithFrame:(CGRect)frame + drawer:(id)drawer + contextInfo:(void*)contextInfo{ + self = [super initWithFrame:frame]; + if (self != nil) { + drawer_ = [drawer retain]; + contextInfo_ = contextInfo; + } + return self; +} + +- (void)dealloc { + [drawer_ release]; + [super dealloc]; +} + +- (void)drawRect:(CGRect)rect { + [drawer_ gtm_unitTestViewDrawRect:rect contextInfo:contextInfo_]; +} + +@end + +@implementation UIView (GTMUnitTestingAdditions) + +// Returns an image containing a representation of the object +// suitable for use in comparing against a master image. +// NB this means that all colors should be from "NSDevice" color space +// Does all of it's drawing with smoothfonts and antialiasing off +// to avoid issues with font smoothing settings and antialias differences +// between ppc and x86. +// +// Returns: +// an image of the object +- (CGImageRef)gtm_unitTestImage { + CALayer* layer = [self layer]; + return [layer gtm_unitTestImage]; +} + +// Encodes the state of an object in a manner suitable for comparing +// against a master state file so we can determine whether the +// object is in a suitable state. +// +// Arguments: +// inCoder - the coder to encode our state into +- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder { + [super gtm_unitTestEncodeState:inCoder]; + [inCoder encodeBool:[self isHidden] forKey:@"ViewIsHidden"]; + CALayer* layer = [self layer]; + if (layer) { + [layer gtm_unitTestEncodeState:inCoder]; + } + if ([self gtm_shouldEncodeStateForSubviews]) { + int i = 0; + for (UIView *subview in [self subviews]) { + [inCoder encodeObject:subview + forKey:[NSString stringWithFormat:@"ViewSubView %d", i]]; + i++; + } + } +} + +// Returns whether gtm_unitTestEncodeState should recurse into subviews +// +// Returns: +// should gtm_unitTestEncodeState pick up subview state. +- (BOOL)gtm_shouldEncodeStateForSubviews { + return YES; +} + +- (BOOL)gtm_shouldEncodeStateForSublayersOfLayer:(CALayer*)layer { + return NO; +} +@end + +@implementation UIImage (GTMUnitTestingAdditions) +- (CGImageRef)gtm_unitTestImage { + return [self CGImage]; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTestingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTestingTest.m new file mode 100644 index 00000000..8b3effae --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIKit+UnitTestingTest.m @@ -0,0 +1,65 @@ +// +// GTMUIKit+UnitTestingTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMUIKit+UnitTesting.h" +#import "GTMSenTestCase.h" + +@interface GTMUIView_UnitTestingTest : SenTestCase +@end + +@implementation GTMUIView_UnitTestingTest + +- (void)testDrawing { + GTMAssertDrawingEqualToFile(self, + CGSizeMake(200,200), + @"GTMUIViewUnitTestingTest", + [UIApplication sharedApplication], + nil); +} + +- (void)testState { + UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)] autorelease]; + UIView *subview = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)] autorelease]; + [view addSubview:subview]; + GTMAssertObjectStateEqualToStateNamed(view, @"GTMUIViewUnitTestingTest", nil); +} + +- (void)testUIImage { + NSString* name = @"GTMUIViewUnitTestingTest"; + UIImage* image = + [UIImage imageNamed:[name stringByAppendingPathExtension:@"png"]]; + GTMAssertObjectImageEqualToImageNamed(image, name, nil); +} + +- (void)gtm_unitTestViewDrawRect:(CGRect)rect contextInfo:(void*)contextInfo { + UIApplication *app = [UIApplication sharedApplication]; + STAssertEqualObjects(app, + contextInfo, + @"Should be a UIApplication"); + CGPoint center = CGPointMake(CGRectGetMidX(rect), + CGRectGetMidY(rect)); + rect = CGRectMake(center.x - 50, center.y - 50, 100, 100); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextAddEllipseInRect(context, rect); + CGContextSetLineWidth(context, 5); + [[UIColor redColor] set]; + CGContextStrokePath(context); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/Info.plist b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/Info.plist new file mode 100644 index 00000000..11355f71 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/Info.plist @@ -0,0 +1,71 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.GTMUIUnitTestingHarness + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + + CFBundleURLTypes + + + CFBundleURLName + GTMUIUnitTestingHarnessURL + CFBundleURLSchemes + + gtmgeturlhandlertest + + GTMBundleURLClass + GTMGetURLHandlerTest + + + CFBundleURLName + GTMGetURLHandlerBadClassURL + CFBundleURLSchemes + + gtmgeturlhandlerbadclasstest + + GTMBundleURLClass + GTMGetURLHandlerBadClassWarning + + + CFBundleURLName + GTMGetURLHandlerMissingClassURL + CFBundleURLSchemes + + gtmgeturlhandlermissingclasstest + + GTMBundleURLClass + GTMGetURLHandlerMissingClassWarning + + + CFBundleURLName + GTMGetURLHandlerMissingHandlerURL + CFBundleURLSchemes + + gtmgeturlhandlermissinghandlerurl + + + + NSPrincipalClass + NSApplication + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/main.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/main.m new file mode 100644 index 00000000..8fb364d7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIUnitTestingHarness/main.m @@ -0,0 +1,27 @@ +// +// main.m +// GTMUnitTestingTest +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +#import +#import "GTMUnitTestingUtilities.h" + +int main(int argc, char *argv[]) { + [GTMUnitTestingUtilities setUpForUIUnitTestsIfBeingTested]; + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIViewUnitTestingTest.png b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIViewUnitTestingTest.png new file mode 100644 index 00000000..03fd9f02 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUIViewUnitTestingTest.png differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.h new file mode 100644 index 00000000..30c70776 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.h @@ -0,0 +1,76 @@ +// +// GTMUnitTestDevLog.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMDefines.h" +#import + +// GTMUnitTestDevLog tracks what messages are logged to verify that you only +// log what you expect to log during the running of unittests. This allows you +// to log with impunity from your actual core implementations and still be able +// to find unexpected logs in your output when running unittests. +// In your unittests you tell GTMUnitTestDevLog what messages you expect your +// test to spit out, and it will cause any that don't match to appear as errors +// in your unittest run output. You can match on exact strings or standard +// regexps. +// Set GTM_SHOW_UNITTEST_DEVLOGS in the environment to show the logs that that +// are expected and encountered. Otherwise they aren't display to keep the +// unit test results easier to read. + +@interface GTMUnitTestDevLog : NSObject +// Log a message ++ (void)log:(NSString*)format, ...; ++ (void)log:(NSString*)format args:(va_list)args; + +// Turn tracking on/off ++ (void)enableTracking; ++ (void)disableTracking; ++ (BOOL)isTrackingEnabled; + +// Note that you are expecting a string that has an exact match. No need to +// escape any pattern characters. ++ (void)expectString:(NSString *)format, ...; + +// Note that you are expecting a pattern. Pattern characters that you want +// exact matches on must be escaped. See [GTMRegex escapedPatternForString]. +// Patterns match across newlines (kGTMRegexOptionSupressNewlineSupport) making +// it easier to match output from the descriptions of NS collection types such +// as NSArray and NSDictionary. ++ (void)expectPattern:(NSString *)format, ...; + +// Note that you are expecting exactly 'n' strings ++ (void)expect:(NSUInteger)n casesOfString:(NSString *)format, ...; + +// Note that you are expecting exactly 'n' patterns ++ (void)expect:(NSUInteger)n casesOfPattern:(NSString*)format, ...; ++ (void)expect:(NSUInteger)n casesOfPattern:(NSString*)format args:(va_list)args; + +// Call when you want to verify that you have matched all the logs you expect +// to match. If your unittests inherit from GTMTestcase (like they should) you +// will get this called for free. ++ (void)verifyNoMoreLogsExpected; + +// Resets the expected logs so that you don't have anything expected. +// In general should not be needed, unless you have a variable logging case +// of some sort. ++ (void)resetExpectedLogs; +@end + +// Does the same as GTMUnitTestDevLog, but the logs are only expected in debug. +// ie-the expect requests don't count in release builds. +@interface GTMUnitTestDevLogDebug : GTMUnitTestDevLog +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.m new file mode 100644 index 00000000..f2f9418f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestDevLog.m @@ -0,0 +1,279 @@ +// +// GTMUnitTestDevLog.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMUnitTestDevLog.h" + + +#import "GTMRegex.h" +#import "GTMSenTestCase.h" + +#if !GTM_IPHONE_SDK +// Add support for grabbing messages from Carbon. +#import +static void GTMDevLogDebugAssert(OSType componentSignature, + UInt32 options, + const char *assertionString, + const char *exceptionLabelString, + const char *errorString, + const char *fileName, + long lineNumber, + void *value, + ConstStr255Param outputMsg) { + NSString *outLog = [[[NSString alloc] initWithBytes:&(outputMsg[1]) + length:StrLength(outputMsg) + encoding:NSMacOSRomanStringEncoding] + autorelease]; + _GTMDevLog(@"%@", outLog); // Don't want any percents in outLog honored +} +static inline void GTMInstallDebugAssertOutputHandler(void) { + InstallDebugAssertOutputHandler(GTMDevLogDebugAssert); +} +static inline void GTMUninstallDebugAssertOutputHandler(void) { + InstallDebugAssertOutputHandler(NULL); +} +#else // GTM_IPHONE_SDK +static inline void GTMInstallDebugAssertOutputHandler(void) {}; +static inline void GTMUninstallDebugAssertOutputHandler(void) {}; +#endif // GTM_IPHONE_SDK + +@interface GTMUnttestDevLogAssertionHandler : NSAssertionHandler +@end + +@implementation GTMUnttestDevLogAssertionHandler +- (void)handleFailureInMethod:(SEL)selector + object:(id)object + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format, ... { + va_list argList; + va_start(argList, format); + NSString *descStr + = [[[NSString alloc] initWithFormat:format arguments:argList] autorelease]; + va_end(argList); + + // You need a format that will be useful in logs, but won't trip up Xcode or + // any other build systems parsing of the output. + NSString *outLog + = [NSString stringWithFormat:@"RecordedNSAssert in %@ - %@ (%@:%ld)", + NSStringFromSelector(selector), + descStr, + fileName, (long)line]; + _GTMDevLog(@"%@", outLog); // Don't want any percents in outLog honored + [NSException raise:NSInternalInconsistencyException + format:@"NSAssert raised"]; +} + +- (void)handleFailureInFunction:(NSString *)functionName + file:(NSString *)fileName + lineNumber:(NSInteger)line + description:(NSString *)format, ... { + va_list argList; + va_start(argList, format); + NSString *descStr + = [[[NSString alloc] initWithFormat:format arguments:argList] autorelease]; + va_end(argList); + + // You need a format that will be useful in logs, but won't trip up Xcode or + // any other build systems parsing of the output. + NSString *outLog + = [NSString stringWithFormat:@"RecordedNSAssert in %@ - %@ (%@:%ld)", + functionName, + descStr, + fileName, (long)line]; + _GTMDevLog(@"%@", outLog); // Don't want any percents in outLog honored + [NSException raise:NSInternalInconsistencyException + format:@"NSAssert raised"]; +} + +@end + +@implementation GTMUnitTestDevLog +// If unittests are ever being run on separate threads, this may need to be +// made a thread local variable. +static BOOL gTrackingEnabled = NO; + ++ (NSMutableArray *)patterns { + static NSMutableArray *patterns = nil; + if (!patterns) { + patterns = [[NSMutableArray array] retain]; + } + return patterns; +} + ++ (BOOL)isTrackingEnabled { + return gTrackingEnabled; +} + ++ (void)enableTracking { + GTMInstallDebugAssertOutputHandler(); + + NSMutableDictionary *threadDictionary + = [[NSThread currentThread] threadDictionary]; + if ([threadDictionary objectForKey:@"NSAssertionHandler"] != nil) { + NSLog(@"Warning: replacing NSAssertionHandler to capture assertions"); + } + + // Install an assertion handler to capture those. + GTMUnttestDevLogAssertionHandler *handler = + [[[GTMUnttestDevLogAssertionHandler alloc] init] autorelease]; + [threadDictionary setObject:handler forKey:@"NSAssertionHandler"]; + + gTrackingEnabled = YES; +} + ++ (void)disableTracking { + GTMUninstallDebugAssertOutputHandler(); + + // Clear our assertion handler back out. + NSMutableDictionary *threadDictionary + = [[NSThread currentThread] threadDictionary]; + [threadDictionary removeObjectForKey:@"NSAssertionHandler"]; + + gTrackingEnabled = NO; +} + ++ (void)log:(NSString*)format, ... { + va_list argList; + va_start(argList, format); + [self log:format args:argList]; + va_end(argList); +} + ++ (void)log:(NSString*)format args:(va_list)args { + if ([self isTrackingEnabled]) { + NSString *logString = [[[NSString alloc] initWithFormat:format + arguments:args] autorelease]; + @synchronized(self) { + NSMutableArray *patterns = [self patterns]; + BOOL logError = [patterns count] == 0 ? YES : NO; + GTMRegex *regex = nil; + if (!logError) { + regex = [[[patterns objectAtIndex:0] retain] autorelease]; + logError = [regex matchesString:logString] ? NO : YES; + [patterns removeObjectAtIndex:0]; + } + if (logError) { + if (regex) { + [NSException raise:SenTestFailureException + format:@"Unexpected log: %@\nExpected: %@", + logString, regex]; + } else { + [NSException raise:SenTestFailureException + format:@"Unexpected log: %@", logString]; + } + } else { + static BOOL envChecked = NO; + static BOOL showExpectedLogs = YES; + if (!envChecked) { + showExpectedLogs = getenv("GTM_SHOW_UNITTEST_DEVLOGS") ? YES : NO; + } + if (showExpectedLogs) { + NSLog(@"Expected Log: %@", logString); + } + } + } + } else { + NSLogv(format, args); + } +} + ++ (void)expectString:(NSString *)format, ... { + va_list argList; + va_start(argList, format); + NSString *string = [[[NSString alloc] initWithFormat:format + arguments:argList] autorelease]; + va_end(argList); + NSString *pattern = [GTMRegex escapedPatternForString:string]; + [self expect:1 casesOfPattern:pattern]; + +} + ++ (void)expectPattern:(NSString *)format, ... { + va_list argList; + va_start(argList, format); + [self expect:1 casesOfPattern:format args:argList]; + va_end(argList); +} + ++ (void)expect:(NSUInteger)n casesOfString:(NSString *)format, ... { + va_list argList; + va_start(argList, format); + NSString *string = [[[NSString alloc] initWithFormat:format + arguments:argList] autorelease]; + va_end(argList); + NSString *pattern = [GTMRegex escapedPatternForString:string]; + [self expect:n casesOfPattern:pattern]; +} + ++ (void)expect:(NSUInteger)n casesOfPattern:(NSString*)format, ... { + va_list argList; + va_start(argList, format); + [self expect:n casesOfPattern:format args:argList]; + va_end(argList); +} + ++ (void)expect:(NSUInteger)n +casesOfPattern:(NSString*)format + args:(va_list)args { + NSString *pattern = [[[NSString alloc] initWithFormat:format + arguments:args] autorelease]; + GTMRegex *regex = [GTMRegex regexWithPattern:pattern + options:kGTMRegexOptionSupressNewlineSupport]; + @synchronized(self) { + NSMutableArray *patterns = [self patterns]; + for (NSUInteger i = 0; i < n; ++i) { + [patterns addObject:regex]; + } + } +} + ++ (void)verifyNoMoreLogsExpected { + @synchronized(self) { + NSMutableArray *patterns = [self patterns]; + if ([patterns count] > 0) { + NSMutableArray *patternsCopy = [[patterns copy] autorelease]; + [self resetExpectedLogs]; + [NSException raise:SenTestFailureException + format:@"Logs still expected %@", patternsCopy]; + } + } +} + ++ (void)resetExpectedLogs { + @synchronized(self) { + NSMutableArray *patterns = [self patterns]; + [patterns removeAllObjects]; + } +} +@end + + +@implementation GTMUnitTestDevLogDebug + ++ (void)expect:(NSUInteger)n +casesOfPattern:(NSString*)format + args:(va_list)args { +#if DEBUG + // In debug, let the base work happen + [super expect:n casesOfPattern:format args:args]; +#else + // nothing when not in debug +#endif +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingBindingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingBindingTest.m new file mode 100644 index 00000000..19ab5b06 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingBindingTest.m @@ -0,0 +1,116 @@ +// +// GTMUnitTestingBindingTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMUnitTestingTest.h" +#import "GTMNSObject+BindingUnitTesting.h" + +@interface GTMUnitTestingBindingTest : GTMTestCase { + int expectedFailureCount_; +} +@end + +@interface GTMUnitTestingBindingBadClass : NSObject +@end + +@implementation GTMUnitTestingBindingTest + +// Iterates through all of our subviews testing the exposed bindings +- (void)doSubviewBindingTest:(NSView*)view { + NSArray *subviews = [view subviews]; + NSView *subview; + GTM_FOREACH_OBJECT(subview, subviews) { + GTMTestExposedBindings(subview, @"testing %@", subview); + [self doSubviewBindingTest:subview]; + } +} + +- (void)testBindings { + // Get our window to work with and test it's bindings + GTMUnitTestingTestController *testWindowController + = [[GTMUnitTestingTestController alloc] initWithWindowNibName:@"GTMUnitTestingTest"]; + NSWindow *window = [testWindowController window]; + GTMTestExposedBindings(window, @"Window failed binding test"); + [self doSubviewBindingTest:[window contentView]]; + [window close]; + [testWindowController release]; + + // Run a test against something with no bindings. + // We're expecting a failure here. + expectedFailureCount_ = 1; + GTMTestExposedBindings(@"foo", @"testing no bindings"); + STAssertEquals(expectedFailureCount_, 0, @"Didn't get expected failures testing bindings"); + + // Run test against some with bad bindings. + // We're expecting failures here. + expectedFailureCount_ = 4; + GTMUnitTestingBindingBadClass *bad = [[[GTMUnitTestingBindingBadClass alloc] init] autorelease]; + GTMTestExposedBindings(bad, @"testing bad bindings"); + STAssertEquals(expectedFailureCount_, 0, @"Didn't get expected failures testing bad bindings"); +} + +- (void)failWithException:(NSException *)anException { + if (expectedFailureCount_ > 0) { + expectedFailureCount_ -= 1; + } else { + [super failWithException:anException]; // COV_NF_LINE - not expecting exception + } +} + +@end + +// Forces several error cases in our binding tests to test them +@implementation GTMUnitTestingBindingBadClass + +NSString *const kGTMKeyWithNoClass = @"keyWithNoClass"; +NSString *const kGTMKeyWithNoValue = @"keyWithNoValue"; +NSString *const kGTMKeyWeCantSet = @"keyWeCantSet"; +NSString *const kGTMKeyThatIsntEqual = @"keyThatIsntEqual"; + +- (NSArray *)exposedBindings { + return [NSArray arrayWithObjects:kGTMKeyWithNoClass, + kGTMKeyWithNoValue, + kGTMKeyWeCantSet, + kGTMKeyThatIsntEqual, + nil]; +} + +- (NSArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding { + GTMBindingUnitTestData *data + = [GTMBindingUnitTestData testWithIdentityValue:kGTMKeyThatIsntEqual]; + return [NSArray arrayWithObject:data]; +} + +- (Class)valueClassForBinding:(NSString*)binding { + return [binding isEqualTo:kGTMKeyWithNoClass] ? nil : [NSString class]; +} + +- (id)valueForKey:(NSString*)binding { + if ([binding isEqualTo:kGTMKeyWithNoValue]) { + [NSException raise:NSUndefinedKeyException format:nil]; + } + return @"foo"; +} + +- (void)setValue:(id)value forKey:(NSString*)binding { + if ([binding isEqualTo:kGTMKeyWeCantSet]) { + [NSException raise:NSUndefinedKeyException format:nil]; + } +} +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.h new file mode 100644 index 00000000..ea9521b9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.h @@ -0,0 +1,29 @@ +// +// GTMUnitTestingTest.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import + +// GTMUnitTestingTestController controller so that initWithWindowNibName can +// find the appropriate bundle to load our nib from. See [GTMUnitTestingTest +// -testUnitTestingFramework] for more info +@interface GTMUnitTestingTestController : NSWindowController { + IBOutlet NSTextField *field_; +} + +- (NSTextField *)textField; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.m new file mode 100644 index 00000000..72e68804 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingTest.m @@ -0,0 +1,252 @@ +// +// GTMUnitTestingTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "GTMUnitTestingTest.h" +#import "GTMAppKit+UnitTesting.h" + +NSString *const kGTMWindowNibName = @"GTMUnitTestingTest"; +NSString *const kGTMWindowSaveFileName = @"GTMUnitTestingWindow"; + +@interface GTMUnitTestingTest : GTMTestCase { + int expectedFailureCount_; +} +@end + +// GTMUnitTestingTest support classes +@interface GTMUnitTestingView : NSObject { + BOOL goodContext_; +} +- (BOOL)hadGoodContext; +@end + +@interface GTMUnitTestingDelegate : NSObject { + BOOL didEncode_; +} +- (BOOL)didEncode; +@end + +@interface GTMUnitTestingProxyTest : NSProxy +@end + +@implementation GTMUnitTestingTest + +// Brings up the window defined in the nib and takes a snapshot of it. +// We use the "empty" GTMUnitTestingTestController controller so that +// initWithWindowNibName can find the appropriate bundle to load our nib from. +// For some reason when running unit tests, with all the injecting going on +// the nib loader can get confused as to where it should load a nib from. +// Having a NSWindowController subclass in the same bundle as the nib seems +// to help the nib loader find the nib, and any custom classes that are attached +// to it. +- (void)testUnitTestingFramework { + // set up our delegates so we can test delegate handling + GTMUnitTestingDelegate *appDelegate = [[GTMUnitTestingDelegate alloc] init]; + [NSApp setDelegate:appDelegate]; + + // Get our window + GTMUnitTestingTestController *testWindowController + = [[GTMUnitTestingTestController alloc] initWithWindowNibName:kGTMWindowNibName]; + NSWindow *window = [testWindowController window]; + // Test the app state. This will cover windows and menus + GTMAssertObjectStateEqualToStateNamed(NSApp, + @"GTMUnitTestingTestApp", + @"Testing the app state"); + + // Test the window image and state + GTMAssertObjectEqualToStateAndImageNamed(window, + kGTMWindowSaveFileName, + @"Testing the window image and state"); + + // Verify that all of our delegate encoders got called + STAssertTrue([appDelegate didEncode], @"app delegate didn't get called?"); + + // Clean up + [NSApp setDelegate:nil]; + [appDelegate release]; + [testWindowController release]; +} + +- (void)testViewUnitTesting { + GTMUnitTestingView *unitTestingView = [[GTMUnitTestingView alloc] init]; + GTMAssertDrawingEqualToImageNamed(unitTestingView, + NSMakeSize(200,200), + @"GTMUnitTestingView", + NSApp, + @"Testing view drawing"); + STAssertTrue([unitTestingView hadGoodContext], @"bad context?"); + [unitTestingView release]; +} + +- (void)testImageUnitTesting { + NSImage *image = [NSImage imageNamed:@"NSApplicationIcon"]; + GTMUnitTestingDelegate *imgDelegate = [[GTMUnitTestingDelegate alloc] init]; + [image setDelegate:imgDelegate]; + GTMAssertObjectEqualToStateAndImageNamed(image, + @"GTMUnitTestingImage", + @"Testing NSImage image and state"); + STAssertTrue([imgDelegate didEncode], @"imgDelegate didn't get called?"); + [image setDelegate:nil]; + [imgDelegate release]; +} + +- (void)testFailures { + NSString *const bogusTestName = @"GTMUnitTestTestingFailTest"; + NSString *tempDir = NSTemporaryDirectory(); + STAssertNotNil(tempDir, @"No Temp Dir?"); + NSString *originalPath = [NSObject gtm_getUnitTestSaveToDirectory]; + STAssertNotNil(originalPath, @"No save dir?"); + [NSObject gtm_setUnitTestSaveToDirectory:tempDir]; + STAssertEqualObjects(tempDir, [NSObject gtm_getUnitTestSaveToDirectory], + @"Save to dir not set?"); + NSString *statePath = [self gtm_saveToPathForStateNamed:bogusTestName]; + STAssertNotNil(statePath, @"no state path?"); + NSString *imagePath = [self gtm_saveToPathForImageNamed:bogusTestName]; + STAssertNotNil(imagePath, @"no image path?"); + GTMUnitTestingTestController *testWindowController + = [[GTMUnitTestingTestController alloc] initWithWindowNibName:kGTMWindowNibName]; + NSWindow *window = [testWindowController window]; + + // Test against a golden master filename that doesn't exist + expectedFailureCount_ = 2; + GTMAssertObjectEqualToStateAndImageNamed(window, + bogusTestName, + @"Creating image and state files"); + STAssertEquals(expectedFailureCount_, 0, + @"Didn't get expected failures creating files"); + + // Change our image and state and verify failures + [[testWindowController textField] setStringValue:@"Foo"]; + expectedFailureCount_ = 2; + GTMAssertObjectEqualToStateAndImageNamed(window, + kGTMWindowSaveFileName, + @"Testing the window image and state"); + STAssertEquals(expectedFailureCount_, 0, + @"Didn't get expected failures testing files"); + + // Now change the size of our image and verify failures + NSRect oldFrame = [window frame]; + NSRect newFrame = oldFrame; + newFrame.size.width += 1; + [window setFrame:newFrame display:YES]; + expectedFailureCount_ = 1; + GTMAssertObjectImageEqualToImageNamed(window, + kGTMWindowSaveFileName, + @"Testing the changed window size"); + [window setFrame:oldFrame display:YES]; + + // Set our unit test save dir to a bogus directory and + // run the tests again. + [NSObject gtm_setUnitTestSaveToDirectory:@"/zim/blatz/foo/bob/bar"]; + expectedFailureCount_ = 2; + GTMAssertObjectEqualToStateAndImageNamed(window, + kGTMWindowSaveFileName, + @"Testing the window image and state"); + STAssertEquals(expectedFailureCount_, 0, + @"Didn't get expected failures testing files"); + expectedFailureCount_ = 2; + GTMAssertObjectEqualToStateAndImageNamed(window, + @"GTMUnitTestingWindowDoesntExist", + @"Testing the window image and state"); + STAssertEquals(expectedFailureCount_, 0, + @"Didn't get expected failures testing files"); + + // Reset our unit test save dir + [NSObject gtm_setUnitTestSaveToDirectory:nil]; + + // Test against something that doesn't have an image + expectedFailureCount_ = 1; + GTMAssertObjectImageEqualToImageNamed(@"a string", + @"GTMStringsDontHaveImages", + @"Testing that strings should fail"); + STAssertEquals(expectedFailureCount_, 0, @"Didn't get expected failures testing files"); + + // Test against something that doesn't implement our support + expectedFailureCount_ = 1; + GTMUnitTestingProxyTest *proxy = [[GTMUnitTestingProxyTest alloc] init]; + GTMAssertObjectStateEqualToStateNamed(proxy, + @"NSProxiesDontDoState", + @"Testing that NSProxy should fail"); + STAssertEquals(expectedFailureCount_, 0, @"Didn't get expected failures testing proxy"); + [proxy release]; + + [window close]; +} + +- (void)failWithException:(NSException *)anException { + if (expectedFailureCount_ > 0) { + expectedFailureCount_ -= 1; + } else { + [super failWithException:anException]; // COV_NF_LINE - not expecting exception + } +} + + +@end + +@implementation GTMUnitTestingTestController +- (NSTextField *)textField { + return field_; +} + +@end + +@implementation GTMUnitTestingDelegate + +- (void)gtm_unitTestEncoderWillEncode:(id)sender inCoder:(NSCoder*)inCoder { + // Test various encodings + [inCoder encodeBool:YES forKey:@"BoolTest"]; + [inCoder encodeInt:1 forKey:@"IntTest"]; + [inCoder encodeInt32:1 forKey:@"Int32Test"]; + [inCoder encodeInt64:1 forKey:@"Int64Test"]; + [inCoder encodeFloat:1.0f forKey:@"FloatTest"]; + [inCoder encodeDouble:1.0 forKey:@"DoubleTest"]; + [inCoder encodeBytes:(const uint8_t*)"BytesTest" length:9 forKey:@"BytesTest"]; + didEncode_ = YES; +} + +- (BOOL)didEncode { + return didEncode_; +} +@end + +@implementation GTMUnitTestingView + +- (void)gtm_unitTestViewDrawRect:(NSRect)rect contextInfo:(void*)contextInfo { + [[NSColor redColor] set]; + NSRectFill(rect); + goodContext_ = [(id)contextInfo isEqualTo:NSApp]; +} + +- (BOOL)hadGoodContext { + return goodContext_; +} +@end + +// GTMUnitTestingProxyTest is for testing the case where we don't conform to +// the GTMUnitTestingEncoding protocol. +@implementation GTMUnitTestingProxyTest +- (id)init { + return self; +} + +- (BOOL)conformsToProtocol:(Protocol *)protocol { + return NO; +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.h new file mode 100644 index 00000000..128a4c4f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.h @@ -0,0 +1,91 @@ +// +// GTMUnitTestingUtilities.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import + +// Collection of utilities for unit testing +@interface GTMUnitTestingUtilities : NSObject + +// Returns YES if we are currently being unittested. ++ (BOOL)areWeBeingUnitTested; + +// Sets up the user interface so that we can run consistent UI unittests on +// it. This includes setting scroll bar types, setting selection colors +// setting color spaces etc so that everything is consistent across machines. +// This should be called in main, before NSApplicationMain is called. ++ (void)setUpForUIUnitTests; + +// Syntactic sugar combining the above, and wrapping them in an +// NSAutoreleasePool so that your main can look like this: +// int main(int argc, const char *argv[]) { +// [UnitTestingUtilities setUpForUIUnitTestsIfBeingTested]; +// return NSApplicationMain(argc, argv); +// } ++ (void)setUpForUIUnitTestsIfBeingTested; + +// Check if the screen saver is running. Some unit tests don't work when +// the screen saver is active. ++ (BOOL)isScreenSaverActive; + +// Allows for posting either a keydown or a keyup with all the modifiers being +// applied. Passing a 'g' with NSKeyDown and NSShiftKeyMask +// generates two events (a shift key key down and a 'g' key keydown). Make sure +// to balance this with a keyup, or things could get confused. Events get posted +// using the CGRemoteOperation events which means that it gets posted in the +// system event queue. Thus you can affect other applications if your app isn't +// the active app (or in some cases, such as hotkeys, even if it is). +// Arguments: +// type - Event type. Currently accepts NSKeyDown and NSKeyUp +// keyChar - character on the keyboard to type. Make sure it is lower case. +// If you need upper case, pass in the NSShiftKeyMask in the +// modifiers. i.e. to generate "G" pass in 'g' and NSShiftKeyMask. +// to generate "+" pass in '=' and NSShiftKeyMask. +// cocoaModifiers - an int made up of bit masks. Handles NSAlphaShiftKeyMask, +// NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, and +// NSCommandKeyMask ++ (void)postKeyEvent:(NSEventType)type + character:(CGCharCode)keyChar + modifiers:(UInt32)cocoaModifiers; + +// Syntactic sugar for posting a keydown immediately followed by a key up event +// which is often what you really want. +// Arguments: +// keyChar - character on the keyboard to type. Make sure it is lower case. +// If you need upper case, pass in the NSShiftKeyMask in the +// modifiers. i.e. to generate "G" pass in 'g' and NSShiftKeyMask. +// to generate "+" pass in '=' and NSShiftKeyMask. +// cocoaModifiers - an int made up of bit masks. Handles NSAlphaShiftKeyMask, +// NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, and +// NSCommandKeyMask ++ (void)postTypeCharacterEvent:(CGCharCode)keyChar + modifiers:(UInt32)cocoaModifiers; + +// Runs the event loop in NSDefaultRunLoopMode until date. Can be useful for +// testing user interface responses in a controlled timed event loop. For most +// uses using: +// [[NSRunLoop currentRunLoop] runUntilDate:date] +// will do. The only reason you would want to use this is if you were +// using the postKeyEvent:character:modifiers to send events and wanted to +// receive user input. +// Arguments: +// date - end of execution time ++ (void)runUntilDate:(NSDate*)date; + +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.m new file mode 100644 index 00000000..e72a921a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/GTMUnitTestingUtilities.m @@ -0,0 +1,310 @@ +// +// GTMUnitTestingUtilities.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMUnitTestingUtilities.h" +#import +#import "GTMDefines.h" +#import "GTMGarbageCollection.h" + +// The Users profile before we change it on them +static CMProfileRef gGTMCurrentColorProfile = NULL; + +// Compares two color profiles +static BOOL GTMAreCMProfilesEqual(CMProfileRef a, CMProfileRef b); +// Stores the user's color profile away, and changes over to generic. +static void GTMSetColorProfileToGenericRGB(); +// Restores the users profile. +static void GTMRestoreColorProfile(void); + +static CGKeyCode GTMKeyCodeForCharCode(CGCharCode charCode); + +@implementation GTMUnitTestingUtilities + +// Returns YES if we are currently being unittested. ++ (BOOL)areWeBeingUnitTested { + BOOL answer = NO; + + // Check to see if the SenTestProbe class is linked in before we call it. + Class SenTestProbeClass = NSClassFromString(@"SenTestProbe"); + if (SenTestProbeClass != Nil) { + // Doing this little dance so we don't actually have to link + // SenTestingKit in + SEL selector = NSSelectorFromString(@"isTesting"); + NSMethodSignature *sig = [SenTestProbeClass methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:selector]; + [invocation invokeWithTarget:SenTestProbeClass]; + [invocation getReturnValue:&answer]; + } + return answer; +} + +// Sets up the user interface so that we can run consistent UI unittests on it. ++ (void)setUpForUIUnitTests { + // Give some names to undocumented defaults values + const NSInteger MediumFontSmoothing = 2; + const NSInteger BlueTintedAppearance = 1; + + // This sets up some basic values that we want as our defaults for doing pixel + // based user interface tests. These defaults only apply to the unit test app, + // except or the color profile which will be set system wide, and then + // restored when the tests complete. + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + // Scroll arrows together bottom + [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; + // Smallest font size to CG should perform antialiasing on + [defaults setInteger:4 forKey:@"AppleAntiAliasingThreshold"]; + // Type of smoothing + [defaults setInteger:MediumFontSmoothing forKey:@"AppleFontSmoothing"]; + // Blue aqua + [defaults setInteger:BlueTintedAppearance forKey:@"AppleAquaColorVariant"]; + // Standard highlight colors + [defaults setObject:@"0.709800 0.835300 1.000000" + forKey:@"AppleHighlightColor"]; + [defaults setObject:@"0.500000 0.500000 0.500000" + forKey:@"AppleOtherHighlightColor"]; + // Use english plz + [defaults setObject:[NSArray arrayWithObject:@"en"] forKey:@"AppleLanguages"]; + // How fast should we draw sheets. This speeds up the sheet tests considerably + [defaults setFloat:.001f forKey:@"NSWindowResizeTime"]; + // Switch over the screen profile to "generic rgb". This installs an + // atexit handler to return our profile back when we are done. + GTMSetColorProfileToGenericRGB(); +} + ++ (void)setUpForUIUnitTestsIfBeingTested { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + if ([self areWeBeingUnitTested]) { + [self setUpForUIUnitTests]; + } + [pool release]; +} + ++ (BOOL)isScreenSaverActive { + BOOL answer = NO; + ProcessSerialNumber psn; + if (GetFrontProcess(&psn) == noErr) { + CFDictionaryRef cfProcessInfo + = ProcessInformationCopyDictionary(&psn, + kProcessDictionaryIncludeAllInformationMask); + NSDictionary *processInfo = GTMCFAutorelease(cfProcessInfo); + + NSString *bundlePath = [processInfo objectForKey:@"BundlePath"]; + // ScreenSaverEngine is the frontmost app if the screen saver is actually + // running Security Agent is the frontmost app if the "enter password" + // dialog is showing + NSString *bundleName = [bundlePath lastPathComponent]; + answer = ([bundleName isEqualToString:@"ScreenSaverEngine.app"] + || [bundleName isEqualToString:@"SecurityAgent.app"]); + } + return answer; +} + +// Allows for posting either a keydown or a keyup with all the modifiers being +// applied. Passing a 'g' with NSKeyDown and NSShiftKeyMask +// generates two events (a shift key key down and a 'g' key keydown). Make sure +// to balance this with a keyup, or things could get confused. Events get posted +// using the CGRemoteOperation events which means that it gets posted in the +// system event queue. Thus you can affect other applications if your app isn't +// the active app (or in some cases, such as hotkeys, even if it is). +// Arguments: +// type - Event type. Currently accepts NSKeyDown and NSKeyUp +// keyChar - character on the keyboard to type. Make sure it is lower case. +// If you need upper case, pass in the NSShiftKeyMask in the +// modifiers. i.e. to generate "G" pass in 'g' and NSShiftKeyMask. +// to generate "+" pass in '=' and NSShiftKeyMask. +// cocoaModifiers - an int made up of bit masks. Handles NSAlphaShiftKeyMask, +// NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, and +// NSCommandKeyMask ++ (void)postKeyEvent:(NSEventType)type + character:(CGCharCode)keyChar + modifiers:(UInt32)cocoaModifiers { + require(![self isScreenSaverActive], CantWorkWithScreenSaver); + require(type == NSKeyDown || type == NSKeyUp, CantDoEvent); + CGKeyCode code = GTMKeyCodeForCharCode(keyChar); + verify(code != 256); + CGEventRef event = CGEventCreateKeyboardEvent(NULL, code, type == NSKeyDown); + require(event, CantCreateEvent); + CGEventSetFlags(event, cocoaModifiers); + CGEventPost(kCGSessionEventTap, event); + CFRelease(event); +CantCreateEvent: +CantDoEvent: +CantWorkWithScreenSaver: + return; +} + +// Syntactic sugar for posting a keydown immediately followed by a key up event +// which is often what you really want. +// Arguments: +// keyChar - character on the keyboard to type. Make sure it is lower case. +// If you need upper case, pass in the NSShiftKeyMask in the +// modifiers. i.e. to generate "G" pass in 'g' and NSShiftKeyMask. +// to generate "+" pass in '=' and NSShiftKeyMask. +// cocoaModifiers - an int made up of bit masks. Handles NSAlphaShiftKeyMask, +// NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, and +// NSCommandKeyMask ++ (void)postTypeCharacterEvent:(CGCharCode)keyChar modifiers:(UInt32)cocoaModifiers { + [self postKeyEvent:NSKeyDown character:keyChar modifiers:cocoaModifiers]; + [self postKeyEvent:NSKeyUp character:keyChar modifiers:cocoaModifiers]; +} + +// Runs the event loop in NSDefaultRunLoopMode until date. Can be useful for +// testing user interface responses in a controlled timed event loop. For most +// uses using: +// [[NSRunLoop currentRunLoop] runUntilDate:date] +// will do. The only reason you would want to use this is if you were +// using the postKeyEvent:character:modifiers to send events and wanted to +// receive user input. +// Arguments: +// date - end of execution time ++ (void)runUntilDate:(NSDate*)date { + NSEvent *event; + while ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:date + inMode:NSDefaultRunLoopMode + dequeue:YES])) { + [NSApp sendEvent:event]; + } +} + +@end + +BOOL GTMAreCMProfilesEqual(CMProfileRef a, CMProfileRef b) { + BOOL equal = YES; + if (a != b) { + CMProfileMD5 aMD5; + CMProfileMD5 bMD5; + CMError aMD5Err = CMGetProfileMD5(a, aMD5); + CMError bMD5Err = CMGetProfileMD5(b, bMD5); + equal = (!aMD5Err && + !bMD5Err && + !memcmp(aMD5, bMD5, sizeof(CMProfileMD5))) ? YES : NO; + } + return equal; +} + +void GTMRestoreColorProfile(void) { + if (gGTMCurrentColorProfile) { + CGDirectDisplayID displayID = CGMainDisplayID(); + CMError error = CMSetProfileByAVID((UInt32)displayID, + gGTMCurrentColorProfile); + CMCloseProfile(gGTMCurrentColorProfile); + if (error) { + // COV_NF_START + // No way to force this case in a unittest. + _GTMDevLog(@"Failed to restore previous color profile! " + "You may need to open System Preferences : Displays : Color " + "and manually restore your color settings. (Error: %i)", error); + // COV_NF_END + } else { + _GTMDevLog(@"Color profile restored"); + } + gGTMCurrentColorProfile = NULL; + } +} + +void GTMSetColorProfileToGenericRGB(void) { + NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace]; + CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile]; + CMProfileRef previousProfile; + CGDirectDisplayID displayID = CGMainDisplayID(); + CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile); + if (error) { + // COV_NF_START + // No way to force this case in a unittest. + _GTMDevLog(@"Failed to get current color profile. " + "I will not be able to restore your current profile, thus I'm " + "not changing it. Many unit tests may fail as a result. (Error: %i)", + error); + return; + // COV_NF_END + } + if (GTMAreCMProfilesEqual(genericProfile, previousProfile)) { + CMCloseProfile(previousProfile); + return; + } + CFStringRef previousProfileName; + CFStringRef genericProfileName; + CMCopyProfileDescriptionString(previousProfile, &previousProfileName); + CMCopyProfileDescriptionString(genericProfile, &genericProfileName); + + _GTMDevLog(@"Temporarily changing your system color profile from \"%@\" to \"%@\".", + previousProfileName, genericProfileName); + _GTMDevLog(@"This allows the pixel-based unit-tests to have consistent color " + "values across all machines."); + _GTMDevLog(@"The colors on your screen will change for the duration of the testing."); + + + if ((error = CMSetProfileByAVID((UInt32)displayID, genericProfile))) { + // COV_NF_START + // No way to force this case in a unittest. + _GTMDevLog(@"Failed to set color profile to \"%@\"! Many unit tests will fail as " + "a result. (Error: %i)", genericProfileName, error); + // COV_NF_END + } else { + gGTMCurrentColorProfile = previousProfile; + atexit(GTMRestoreColorProfile); + } + CFRelease(previousProfileName); + CFRelease(genericProfileName); +} + +// Returns a virtual key code for a given charCode. Handles all of the +// NS*FunctionKeys as well. +static CGKeyCode GTMKeyCodeForCharCode(CGCharCode charCode) { + // character map taken from http://classicteck.com/rbarticles/mackeyboard.php + int characters[] = { + 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x', 'c', 'v', 256, 'b', 'q', 'w', + 'e', 'r', 'y', 't', '1', '2', '3', '4', '6', '5', '=', '9', '7', '-', + '8', '0', ']', 'o', 'u', '[', 'i', 'p', '\n', 'l', 'j', '\'', 'k', ';', + '\\', ',', '/', 'n', 'm', '.', '\t', ' ', '`', '\b', 256, '\e' + }; + + // function key map taken from + // file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSEvent.html + int functionKeys[] = { + // NSUpArrowFunctionKey - NSF12FunctionKey + 126, 125, 123, 124, 122, 120, 99, 118, 96, 97, 98, 100, 101, 109, 103, 111, + // NSF13FunctionKey - NSF28FunctionKey + 105, 107, 113, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + // NSF29FunctionKey - NSScrollLockFunctionKey + 256, 256, 256, 256, 256, 256, 256, 256, 117, 115, 256, 119, 116, 121, 256, 256, + // NSPauseFunctionKey - NSPrevFunctionKey + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + // NSNextFunctionKey - NSModeSwitchFunctionKey + 256, 256, 256, 256, 256, 256, 114, 1 + }; + + CGKeyCode outCode = 0; + + // Look in the function keys + if (charCode >= NSUpArrowFunctionKey && charCode <= NSModeSwitchFunctionKey) { + outCode = functionKeys[charCode - NSUpArrowFunctionKey]; + } else { + // Look in our character map + for (size_t i = 0; i < (sizeof(characters) / sizeof (int)); i++) { + if (characters[i] == charCode) { + outCode = i; + break; + } + } + } + return outCode; +} + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunIPhoneUnitTest.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunIPhoneUnitTest.sh new file mode 100644 index 00000000..ccf1456c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunIPhoneUnitTest.sh @@ -0,0 +1,108 @@ +#!/bin/sh +# RunIPhoneUnitTest.sh +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# Runs all unittests through the iPhone simulator. We don't handle running them +# on the device. To run on the device just choose "run". +# Controlling environment variables: +# +# GTM_DISABLE_ZOMBIES - +# Set to a non-zero value to turn on zombie checks. You will probably +# want to turn this off if you enable leaks. +# +# GTM_ENABLE_LEAKS - +# Set to a non-zero value to turn on the leaks check. You will probably want +# to disable zombies, otherwise you will get a lot of false positives. +# +# GTM_DISABLE_TERMINATION +# Set to a non-zero value so that the app doesn't terminate when it's finished +# running tests. This is useful when using it with external tools such +# as Instruments. +# +# GTM_LEAKS_SYMBOLS_TO_IGNORE +# List of comma separated symbols that leaks should ignore. Mainly to control +# leaks in frameworks you don't have control over. +# Search this file for GTM_LEAKS_SYMBOLS_TO_IGNORE to see examples. +# Please feel free to add other symbols as you find them but make sure to +# reference Radars or other bug systems so we can track them. +# +# GTM_REMOVE_GCOV_DATA +# Before starting the test, remove any *.gcda files for the current run so +# you won't get errors when the source file has changed and the data can't +# be merged. +# + +ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")) +ScriptName=$(basename "$0") +ThisScript="${ScriptDir}/${ScriptName}" + +GTMXcodeNote() { + echo ${ThisScript}:${1}: note: GTM ${2} +} + +if [ "$PLATFORM_NAME" == "iphonesimulator" ]; then + # We kill the iPhone simulator because otherwise we run into issues where + # the unittests fail becuase the simulator is currently running, and + # at this time the iPhone SDK won't allow two simulators running at the same + # time. + /usr/bin/killall "iPhone Simulator" + + if [ $GTM_REMOVE_GCOV_DATA ]; then + if [ "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" != "-" ]; then + if [ -d "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" ]; then + GTMXcodeNote ${LINENO} "Removing any .gcda files" + (cd "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" && \ + find . -type f -name "*.gcda" -print0 | xargs -0 rm -f ) + fi + fi + fi + + export DYLD_ROOT_PATH="$SDKROOT" + export DYLD_FRAMEWORK_PATH="$CONFIGURATION_BUILD_DIR" + export IPHONE_SIMULATOR_ROOT="$SDKROOT" + export CFFIXED_USER_HOME="$TEMP_FILES_DIR/iPhone Simulator User Dir" + + # See http://developer.apple.com/technotes/tn2004/tn2124.html for an + # explanation of these environment variables. + + export MallocScribble=YES + export MallocPreScribble=YES + export MallocGuardEdges=YES + export MallocStackLogging=YES + export NSAutoreleaseFreedObjectCheckEnabled=YES + export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES + + if [ ! $GTM_DISABLE_ZOMBIES ]; then + GTMXcodeNote ${LINENO} "Enabling zombies" + export CFZombieLevel=3 + export NSZombieEnabled=YES + fi + + # Cleanup user home and documents directory + if [ -d "$CFFIXED_USER_HOME" ]; then + rm -rf "$CFFIXED_USER_HOME" + fi + mkdir "$CFFIXED_USER_HOME" + mkdir "$CFFIXED_USER_HOME/Documents" + + # 6251475 iPhone simulator leaks @ CFHTTPCookieStore shutdown if + # CFFIXED_USER_HOME empty + GTM_LEAKS_SYMBOLS_TO_IGNORE="CFHTTPCookieStore" + + "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents +else + GTMXcodeNote ${LINENO} "Skipping running of unittests for device build." +fi +exit 0 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunMacOSUnitTests.sh b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunMacOSUnitTests.sh new file mode 100644 index 00000000..87f678f3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/RunMacOSUnitTests.sh @@ -0,0 +1,213 @@ +# +# RunMacOSUnitTests.sh +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# Run the unit tests in this test bundle. +# Set up some env variables to make things as likely to crash as possible. +# See http://developer.apple.com/technotes/tn2004/tn2124.html for details. +# + +# Controlling environment variables: +# +# GTM_DISABLE_ZOMBIES - +# Set to a non-zero value to turn on zombie checks. You will probably +# want to turn this off if you enable leaks. +# +# GTM_ENABLE_LEAKS - +# Set to a non-zero value to turn on the leaks check. You will probably want +# to disable zombies, otherwise you will get a lot of false positives. +# +# GTM_NO_DEBUG_FRAMEWORKS - +# Set to zero to prevent the use of the debug versions of system +# libraries/frameworks if you have them installed on your system. The +# frameworks can be found at +# http://connect.apple.com > Downloads > Developer Tools +# (https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19915) +# +# GTM_LEAKS_SYMBOLS_TO_IGNORE +# List of comma separated symbols that leaks should ignore. Mainly to control +# leaks in frameworks you don't have control over. +# Search this file for GTM_LEAKS_SYMBOLS_TO_IGNORE to see examples. +# Please feel free to add other symbols as you find them but make sure to +# reference Radars or other bug systems so we can track them. +# +# GTM_REMOVE_GCOV_DATA +# Before starting the test, remove any *.gcda files for the current run so +# you won't get errors when the source file has changed and the data can't +# be merged. +# + +ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")) +ScriptName=$(basename "$0") +ThisScript="${ScriptDir}/${ScriptName}" + +GTMXcodeNote() { + echo ${ThisScript}:${1}: note: GTM ${2} +} + +# The workaround below is due to +# Radar 6248062 otest won't run with MallocHistory enabled under rosetta +# Basically we go through and check what architecture we are running on +# and which architectures we can support +AppendToSymbolsLeaksShouldIgnore() { + if [ "${GTM_LEAKS_SYMBOLS_TO_IGNORE}" = "" ]; then + GTM_LEAKS_SYMBOLS_TO_IGNORE="${1}" + else + GTM_LEAKS_SYMBOLS_TO_IGNORE="${GTM_LEAKS_SYMBOLS_TO_IGNORE}, ${1}" + fi +} + +AppendToLeakTestArchs() { + if [ "${LEAK_TEST_ARCHS}" = "" ]; then + LEAK_TEST_ARCHS="${1}" + else + LEAK_TEST_ARCHS="${LEAK_TEST_ARCHS} ${1}" + fi +} + +AppendToNoLeakTestArchs() { + if [ "${NO_LEAK_TEST_ARCHS}" = "" ]; then + NO_LEAK_TEST_ARCHS="${1}" + else + NO_LEAK_TEST_ARCHS="${NO_LEAK_TEST_ARCHS} ${1}" + fi +} + +UpdateArchitecturesToTest() { + case "${NATIVE_ARCH_ACTUAL}" in + ppc) + if [ "${1}" = "ppc" ]; then + AppendToLeakTestArchs "${1}" + fi + ;; + + ppc64) + if [ "${1}" = "ppc" -o "${1}" = "ppc64" ]; then + AppendToLeakTestArchs "${1}" + fi + ;; + + i386) + if [ "${1}" = "i386" ]; then + AppendToLeakTestArchs "${1}" + elif [ "${1}" = "ppc" ]; then + AppendToNoLeakTestArchs "${1}" + fi + ;; + + x86_64) + if [ "${1}" = "i386" -o "${1}" = "x86_64" ]; then + AppendToLeakTestArchs "${1}" + elif [ "${1}" = "ppc" -o "${1}" = "ppc64" ]; then + AppendToNoLeakTestArchs "${1}" + fi + ;; + + *) + echo "RunMacOSUnitTests.sh Unknown native architecture: ${NATIVE_ARCH_ACTUAL}" + exit 1 + ;; + esac +} + +RunTests() { + if [ "${CURRENT_ARCH}" = "" ]; then + CURRENT_ARCH=`arch` + fi + + if [ "${ONLY_ACTIVE_ARCH}" = "YES" ]; then + ARCHS="${CURRENT_ARCH}" + fi + + if [ "${ARCHS}" = "" ]; then + ARCHS=`arch` + fi + + if [ "${VALID_ARCHS}" = "" ]; then + VALID_ARCHS=`arch` + fi + + if [ "${NATIVE_ARCH_ACTUAL}" = "" ]; then + NATIVE_ARCH_ACTUAL=`arch` + fi + + LEAK_TEST_ARCHS="" + NO_LEAK_TEST_ARCHS="" + + for TEST_ARCH in ${ARCHS}; do + for TEST_VALID_ARCH in ${VALID_ARCHS}; do + if [ "${TEST_VALID_ARCH}" = "${TEST_ARCH}" ]; then + UpdateArchitecturesToTest "${TEST_ARCH}" + fi + done + done + + # These are symbols that leak on OS 10.5.5 + # radar 6247293 NSCollatorElement leaks in +initialize. + AppendToSymbolsLeaksShouldIgnore "+[NSCollatorElement initialize]" + # radar 6247911 The first call to udat_open leaks only on x86_64 + AppendToSymbolsLeaksShouldIgnore "icu::TimeZone::initDefault()" + # radar 6263983 +[IMService allServices] leaks + AppendToSymbolsLeaksShouldIgnore "-[IMServiceAgentImpl allServices]" + # radar 6264034 +[IKSFEffectDescription initialize] Leaks + AppendToSymbolsLeaksShouldIgnore "+[IKSFEffectDescription initialize]" + + # Running leaks on architectures that support leaks. + export MallocStackLogging=YES + export GTM_LEAKS_SYMBOLS_TO_IGNORE="${GTM_LEAKS_SYMBOLS_TO_IGNORE}" + ARCHS="${LEAK_TEST_ARCHS}" + VALID_ARCHS="${LEAK_TEST_ARCHS}" + "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests" + + # Running leaks on architectures that don't support leaks. + unset MallocStackLogging + unset GTM_ENABLE_LEAKS + ARCHS="${NO_LEAK_TEST_ARCHS}" + VALID_ARCHS="${NO_LEAK_TEST_ARCHS}" + "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests" +} + +# Jack up some memory stress so we can catch more bugs. +export MallocScribble=YES +export MallocPreScribble=YES +export MallocGuardEdges=YES +export NSAutoreleaseFreedObjectCheckEnabled=YES +export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES + +if [ ! $GTM_DISABLE_ZOMBIES ]; then + GTMXcodeNote ${LINENO} "Enabling zombies" + # CFZombieLevel disabled because it doesn't play well with the + # security framework + # export CFZombieLevel=3 + export NSZombieEnabled=YES +fi + +if [ $GTM_REMOVE_GCOV_DATA ]; then + if [ "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" != "-" ]; then + if [ -d "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" ]; then + GTMXcodeNote ${LINENO} "Removing any .gcda files" + (cd "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" && \ + find . -type f -name "*.gcda" -print0 | xargs -0 rm -f ) + fi + fi +fi + +# If leaks testing is enabled, we have to go through our convoluted path +# to handle architectures that don't allow us to do leak testing. +if [ $GTM_ENABLE_LEAKS ]; then + RunTests +else + "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests" +fi diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.gtmUTState b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.gtmUTState new file mode 100644 index 00000000..87ae9e57 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.gtmUTState @@ -0,0 +1,33 @@ + + + + + $GTMArchive + GTMUnitTestingArchive + $GTMVersion + 1 + LayerIsDoublesided + + LayerIsHidden + + LayerIsOpaque + + LayerOpacity + 1 + ViewIsHidden + + ViewSubView 0 + + LayerIsDoublesided + + LayerIsHidden + + LayerIsOpaque + + LayerOpacity + 1 + ViewIsHidden + + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.png b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.png new file mode 100644 index 00000000..03fd9f02 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUIViewUnitTestingTest.png differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff new file mode 100644 index 00000000..2bbdb9c3 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.gtmUTState b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.gtmUTState new file mode 100644 index 00000000..969ddf6b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.gtmUTState @@ -0,0 +1,30 @@ + + + + + $GTMArchive + GTMUnitTestingArchive + $GTMVersion + 1 + BoolTest + + BytesTest + + Qnl0ZXNUZXN0 + + DoubleTest + 1 + FloatTest + 1 + ImageName + NSApplicationIcon + ImageSize + {128, 128} + Int32Test + 1 + Int64Test + 1 + IntTest + 1 + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.tiff new file mode 100644 index 00000000..4d082972 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingImage.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingTestApp.gtmUTState b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingTestApp.gtmUTState new file mode 100644 index 00000000..03e611c9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingTestApp.gtmUTState @@ -0,0 +1,1591 @@ + + + + + $GTMArchive + GTMUnitTestingArchive + $GTMVersion + 1 + ApplicationMainWindow + 0 + BoolTest + + BytesTest + + Qnl0ZXNUZXN0 + + DoubleTest + 1 + FloatTest + 1 + Int32Test + 1 + Int64Test + 1 + IntTest + 1 + MenuBar + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + About NewApplication + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 10 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + q + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Quit NewApplication + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + , + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Preferences… + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 4 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuTitle + Services + + MenuItemTag + 0 + MenuItemTitle + Services + + MenuItem 5 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 6 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + h + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Hide NewApplication + + MenuItem 7 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + h + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Hide Others + + MenuItem 8 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Show All + + MenuItem 9 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + + MenuItemTag + 0 + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + n + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + New + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + o + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Open… + + MenuItem 10 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + P + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Page Setup... + MenuItemTooltip + + + MenuItem 11 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + p + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Print… + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Clear Menu + + MenuTitle + Open Recent + + MenuItemTag + 0 + MenuItemTitle + Open Recent + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 4 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + w + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Close + + MenuItem 5 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + w + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Close All + + MenuItem 6 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + s + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Save + + MenuItem 7 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + S + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Save As… + + MenuItem 8 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Revert to Saved + + MenuItem 9 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuTitle + File + + MenuItemTag + 0 + MenuItemTitle + File + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + z + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Undo + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + Z + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Redo + + MenuItem 10 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + : + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Show Spelling… + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + ; + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Check Spelling + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Check Spelling While Typing + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Check Grammar With Spelling + + MenuTitle + Spelling and Grammar + + MenuItemTag + 0 + MenuItemTitle + Spelling and Grammar + + MenuItem 11 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 1 + MenuItemTitle + Smart Copy/Paste + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 2 + MenuItemTitle + Smart Quotes + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 3 + MenuItemTitle + Smart Links + + MenuTitle + Substitutions + + MenuItemTag + 0 + MenuItemTitle + Substitutions + + MenuItem 12 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Start Speaking + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Stop Speaking + + MenuTitle + Speech + + MenuItemTag + 0 + MenuItemTitle + Speech + + MenuItem 13 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 14 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Special Characters… + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + x + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Cut + + MenuItem 4 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + c + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Copy + + MenuItem 5 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + v + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Paste + + MenuItem 6 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Delete + + MenuItem 7 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + a + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Select All + + MenuItem 8 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + + + MenuItem 9 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + f + MenuItemState + 0 + MenuItemTag + 1 + MenuItemTitle + Find… + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + g + MenuItemState + 0 + MenuItemTag + 2 + MenuItemTitle + Find Next + + MenuItem 2 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + G + MenuItemState + 0 + MenuItemTag + 3 + MenuItemTitle + Find Previous + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + e + MenuItemState + 0 + MenuItemTag + 7 + MenuItemTitle + Use Selection for Find + + MenuItem 4 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + j + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Jump to Selection + + MenuTitle + Find + + MenuItemTag + 0 + MenuItemTitle + Find + + MenuTitle + Edit + + MenuItemTag + 0 + MenuItemTitle + Edit + + MenuItem 3 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + t + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Show Fonts + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + C + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Show Colors + + MenuTitle + Format + + MenuItemTag + 0 + MenuItemTitle + Format + + MenuItem 4 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + t + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Show Toolbar + + MenuItem 1 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + Customize Toolbar… + + MenuTitle + View + + MenuItemTag + 0 + MenuItemTitle + View + + MenuItem 5 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + + MenuItemState + 0 + MenuItemSubmenu + + MenuItem 0 + + MenuItemIndentationLevel + 0 + MenuItemIsAlternate + + MenuItemIsEnabled + + MenuItemIsSeparator + + MenuItemKeyEquivalent + ? + MenuItemState + 0 + MenuItemTag + 0 + MenuItemTitle + NewApplication Help + + MenuTitle + Help + + MenuItemTag + 0 + MenuItemTitle + Help + + MenuTitle + AMainMenu + + Window 0 + + WindowContent + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSTableView + ViewIsHidden + + + + ViewSubView 1 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 2 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 3 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 4 + + ViewIsHidden + + + + ViewSubView 1 + + ViewIsHidden + + + ViewSubView 10 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 1 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 2 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + + ViewSubView 11 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 2 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + HaHa + CellValue + HaHa + + ControlTag + 0 + ControlType + NSTextField + ControlValue + HaHa + ViewIsHidden + + + ViewSubView 3 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + Still Haven't Found What I'm Searching For + CellValue + Still Haven't Found What I'm Searching For + + ControlTag + 0 + ControlType + NSSearchField + ControlValue + Still Haven't Found What I'm Searching For + ViewIsHidden + + + ViewSubView 4 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + Once upon a time + CellValue + Once upon a time + + ControlTag + 0 + ControlType + NSTextField + ControlValue + Once upon a time + ViewIsHidden + + + ViewSubView 5 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + CheckMate! + CellValue + 1 + + ControlTag + 0 + ControlType + NSButton + ControlValue + 1 + ViewIsHidden + + + ViewSubView 6 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + + CellValue + 50 + + ControlTag + 0 + ControlType + NSSlider + ControlValue + 50 + ViewIsHidden + + + ViewSubView 7 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + Cancel + CellValue + 0 + + ControlTag + 0 + ControlType + NSButton + ControlValue + 0 + ViewIsHidden + + + ViewSubView 8 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSColorWell + ViewIsHidden + + + ViewSubView 9 + + ViewIsHidden + + + + WindowIsMain + + WindowIsVisible + + WindowTitle + Window + + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingView.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingView.tiff new file mode 100644 index 00000000..228df732 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingView.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.5.6.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.5.6.tiff new file mode 100644 index 00000000..9179576e Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.5.6.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff new file mode 100644 index 00000000..60c362af Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.gtmUTState b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.gtmUTState new file mode 100644 index 00000000..27dd08e7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.gtmUTState @@ -0,0 +1,291 @@ + + + + + $GTMArchive + GTMUnitTestingArchive + $GTMVersion + 1 + WindowContent + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSTableView + ViewIsHidden + + + + ViewSubView 1 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 2 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 3 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 4 + + ViewIsHidden + + + + ViewSubView 1 + + ViewIsHidden + + + ViewSubView 10 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 1 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + ViewSubView 2 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSScroller + ViewIsHidden + + + + ViewSubView 11 + + ViewIsHidden + + ViewSubView 0 + + ViewIsHidden + + + + ViewSubView 2 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + HaHa + CellValue + HaHa + + ControlTag + 0 + ControlType + NSTextField + ControlValue + HaHa + ViewIsHidden + + + ViewSubView 3 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + Still Haven't Found What I'm Searching For + CellValue + Still Haven't Found What I'm Searching For + + ControlTag + 0 + ControlType + NSSearchField + ControlValue + Still Haven't Found What I'm Searching For + ViewIsHidden + + + ViewSubView 4 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + Once upon a time + CellValue + Once upon a time + + ControlTag + 0 + ControlType + NSTextField + ControlValue + Once upon a time + ViewIsHidden + + + ViewSubView 5 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + CheckMate! + CellValue + 1 + + ControlTag + 0 + ControlType + NSButton + ControlValue + 1 + ViewIsHidden + + + ViewSubView 6 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 1 + CellTag + 0 + CellTitle + + CellValue + 50 + + ControlTag + 0 + ControlType + NSSlider + ControlValue + 50 + ViewIsHidden + + + ViewSubView 7 + + ControlIsEnabled + + ControlSelectedCell + + CellState + 0 + CellTag + 0 + CellTitle + Cancel + CellValue + 0 + + ControlTag + 0 + ControlType + NSButton + ControlValue + 0 + ViewIsHidden + + + ViewSubView 8 + + ControlIsEnabled + + ControlTag + 0 + ControlType + NSColorWell + ViewIsHidden + + + ViewSubView 9 + + ViewIsHidden + + + + WindowIsMain + + WindowIsVisible + + WindowTitle + Window + + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.tiff b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.tiff new file mode 100644 index 00000000..63f56492 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/UnitTesting/TestData/GTMUnitTestingWindow.tiff differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugLeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugLeopardOrLater.xcconfig new file mode 100644 index 00000000..b00a6cc5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugLeopardOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// DebugLeopardOrLater.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// on Leopard or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// Leopard or later +#include "../subconfig/LeopardOrLater.xcconfig" + +// Debug settings +#include "../subconfig/Debug.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig new file mode 100644 index 00000000..a0904125 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// DebugSnowLeopardOrLater.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// on SnowLeopard or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// SnowLeopard or later +#include "../subconfig/SnowLeopardOrLater.xcconfig" + +// Debug settings +#include "../subconfig/Debug.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugTigerOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugTigerOrLater.xcconfig new file mode 100644 index 00000000..34b7b1c8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugTigerOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// DebugTigerOrLater.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// on Tiger or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// Tiger or later +#include "../subconfig/TigerOrLater.xcconfig" + +// Debug settings +#include "../subconfig/Debug.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone.xcconfig new file mode 100644 index 00000000..6067fffe --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone.xcconfig @@ -0,0 +1,26 @@ +// +// DebugiPhone.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// for iPhone. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This file is deprecated, please use the version specific one instead. +// + +#include "DebugiPhone20.xcconfig" + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone20.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone20.xcconfig new file mode 100644 index 00000000..7424704e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone20.xcconfig @@ -0,0 +1,37 @@ +// +// DebugiPhone20.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// for iPhone OS 2.0. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone settings +#include "../subconfig/iPhone20.xcconfig" + +// Release settings +#include "../subconfig/Debug.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone21.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone21.xcconfig new file mode 100644 index 00000000..18c923ad --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/DebugiPhone21.xcconfig @@ -0,0 +1,37 @@ +// +// DebugiPhone21.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// for iPhone OS 2.1. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone settings +#include "../subconfig/iPhone21.xcconfig" + +// Release settings +#include "../subconfig/Debug.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig new file mode 100644 index 00000000..31ac835d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseLeopardOrLater.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// on Leopard or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// Leopard or later +#include "../subconfig/LeopardOrLater.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig new file mode 100644 index 00000000..0d240698 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseSnowLeopardOrLater.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// on SnowLeopard or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// SnowLeopard or later +#include "../subconfig/SnowLeopardOrLater.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig new file mode 100644 index 00000000..93019129 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseTigerOrLater.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// on Tiger or later. +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// Tiger or later +#include "../subconfig/TigerOrLater.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone.xcconfig new file mode 100644 index 00000000..49c11414 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone.xcconfig @@ -0,0 +1,26 @@ +// +// ReleaseiPhone.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// for iPhone. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This file is deprecated, please use the version specific one instead. +// + +#include "ReleaseiPhone20.xcconfig" + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone20.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone20.xcconfig new file mode 100644 index 00000000..8d31ead0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone20.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseiPhone20.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// for iPhone OS 2.0. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone Settings. +#include "../subconfig/iPhone20.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone21.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone21.xcconfig new file mode 100644 index 00000000..8a9a0c3e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Project/ReleaseiPhone21.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseiPhone21.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// for iPhone OS 2.1. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// +// This is a _Configuration_ Xcode config file for use in the "Based on" popup +// of the project configuration editor. Do _not_ use this as the config base +// and individual Xcode target, there are other configuration files for that +// purpose. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone Settings. +#include "../subconfig/iPhone21.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" + +// Merge settings +#include "../subconfig/GTMMerge.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/DebugUnittest.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/DebugUnittest.xcconfig new file mode 100644 index 00000000..3f4d342f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/DebugUnittest.xcconfig @@ -0,0 +1,29 @@ +// +// DebugUnittest.xcconfig +// +// Xcode configuration file for a debug unittest target. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Unittests are loadable bundles +#include "../subconfig/Unittest.xcconfig" + +// See comments in ReleaseUnittest.xcconfig regarding BUNDLE_LOADER and +// how it should be set if you are running into link errors. \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundle.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundle.xcconfig new file mode 100644 index 00000000..8b824d7c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundle.xcconfig @@ -0,0 +1,30 @@ +// +// LoadableBundle.xcconfig +// +// Xcode configuration file for a loadable bundle target. Usually a Cocoa +// plugin or similar. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Bundles should not have their external symbols stripped. +STRIP_STYLE = non-global + +// Bundles need to be position independent +GCC_DYNAMIC_NO_PIC = NO diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundleGCSupported.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundleGCSupported.xcconfig new file mode 100644 index 00000000..aa8d5a7f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/LoadableBundleGCSupported.xcconfig @@ -0,0 +1,30 @@ +// +// LoadableBundleGCSupported.xcconfig +// +// Xcode configuration file for a loadable bundle target that supports garbage +// collection. Usually a Cocoa plugin or similar. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Include the basic Loadable Bundle config +#include "LoadableBundle.xcconfig" + +// Include the GC flag(s) +#include "../subconfig/GCSupported.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/ReleaseUnittest.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/ReleaseUnittest.xcconfig new file mode 100644 index 00000000..f9a85d35 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/ReleaseUnittest.xcconfig @@ -0,0 +1,37 @@ +// +// ReleaseUnittest.xcconfig +// +// Xcode configuration file for a release unittest target. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Unittests are loadable bundles +#include "../subconfig/Unittest.xcconfig" + +// When running OCUnit tests in Release mode the unittests BUNDLE_LOADER +// is probably stripped (or at least it will be if they are using our +// config files). In that case the Unittest will fail to link because +// the symbols have been removed from the bundle's loader's symbol table. +// This flag tells the unittest to trust that the values will be available +// at runtime (or error out) and not to force an error at link time. +// Do NOT set BUNDLE_LOADER (Bundle Loader) setting in a release unittest target +// because you will run into interesting link issues +// "indirect symbol table entry n past the end of the symbol table" +OTHER_LDFLAGS = $(OTHER_LDFLAGS) -undefined dynamic_lookup diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibrary.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibrary.xcconfig new file mode 100644 index 00000000..7c37d50b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibrary.xcconfig @@ -0,0 +1,29 @@ +// +// SharedLibrary.xcconfig +// +// Xcode configuration file for a shared library target. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Dynamic libs need to be position independent +GCC_DYNAMIC_NO_PIC = NO + +// Dynamic libs should not have their external symbols stripped. +STRIP_STYLE = non-global \ No newline at end of file diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibraryGCSupported.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibraryGCSupported.xcconfig new file mode 100644 index 00000000..74ab9076 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/SharedLibraryGCSupported.xcconfig @@ -0,0 +1,30 @@ +// +// SharedLibraryGCSupported.xcconfig +// +// Xcode configuration file for a shared library target that support garbage +// collection. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Include the basic Shared Library config +#include "SharedLibrary.xcconfig" + +// Include the GC flag(s) +#include "../subconfig/GCSupported.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibrary.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibrary.xcconfig new file mode 100644 index 00000000..df1016be --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibrary.xcconfig @@ -0,0 +1,30 @@ +// +// StaticLibrary.xcconfig +// +// Xcode configuration file for a static library target. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Static libs can be included in bundles so make them position independent +GCC_DYNAMIC_NO_PIC = NO + +// Static libs should not have their internal globals or external symbols +// stripped. +STRIP_STYLE = debugging diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibraryGCSupported.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibraryGCSupported.xcconfig new file mode 100644 index 00000000..07ea1d51 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/Target/StaticLibraryGCSupported.xcconfig @@ -0,0 +1,30 @@ +// +// StaticLibraryGCSupported.xcconfig +// +// Xcode configuration file for a static library target that supports garbage +// collection. +// +// This is a _Target_ config file, for use in the "Based on" popup of the +// settings dialog for a target. Do not attempt to apply this as the base +// of an Xcode configuration in the project settings dialog. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Include the basic Static Library config +#include "StaticLibrary.xcconfig" + +// Include the GC flag(s) +#include "../subconfig/GCSupported.xcconfig" diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverage.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverage.xcconfig new file mode 100644 index 00000000..438d5c6a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverage.xcconfig @@ -0,0 +1,25 @@ +// +// CodeCoverage.xcconfig +// +// Xcode configuration file for building executables that need code coverage. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Static Code Coverage +#include "CodeCoverageStatic.xcconfig" + +// Need gcov library +OTHER_LDFLAGS = ${OTHER_LDFLAGS} -lgcov diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverageStatic.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverageStatic.xcconfig new file mode 100644 index 00000000..f6cca92e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/CodeCoverageStatic.xcconfig @@ -0,0 +1,24 @@ +// +// CodeCoverageStatic.xcconfig +// +// Xcode configuration file for building static libs that need code coverage. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + + +// For measuring code coverage +GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES +GCC_GENERATE_TEST_COVERAGE_FILES = YES diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Debug.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Debug.xcconfig new file mode 100644 index 00000000..7d54d612 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Debug.xcconfig @@ -0,0 +1,47 @@ +// +// Debug.xcconfig +// +// General Xcode configuration file for Debug targets. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// No optimization +GCC_OPTIMIZATION_LEVEL = 0 + +// Deployment postprocessing is what triggers Xcode to strip, turn it off +DEPLOYMENT_POSTPROCESSING = NO + +// Dead code stripping off +DEAD_CODE_STRIPPING = NO + +// Debug symbols should be on obviously +GCC_GENERATE_DEBUGGING_SYMBOLS = YES + +// Turn off warnings about uninitialized autos +// can only be done when GCC_OPTIMIZATION_LEVEL is actually optimizing +GCC_WARN_UNINITIALIZED_AUTOS = NO + +// Turns on special C++ STL checks to "encourage" good STL use +GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS = _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS DEBUG=1 + +// Turns on stack protection on debug builds for Leopard and above +GTM_CONFIGURATION_OTHER_CFLAGS = -fstack-protector -fstack-protector-all +// Stack protection doesn't exist on Tiger +GTM_CONFIGURATION_OTHER_CFLAGS[sdk=macosx10.4*] = + +// And is really broken on the iPhone Device. Works on simulator though. +// rdar://639430 Xcode generates bad Arm code if -fstack-protector -fstack-protector-all +GTM_CONFIGURATION_OTHER_CFLAGS[sdk=iphoneos*] = diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GCSupported.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GCSupported.xcconfig new file mode 100644 index 00000000..74bd027a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GCSupported.xcconfig @@ -0,0 +1,23 @@ +// +// GCSupported.xcconfig +// +// Xcode configuration file for making a build Garbage Collection enabled. +// Use the *GCSupported specific configs in the Target folder. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// enable garbage collection (but don't require it) +GCC_ENABLE_OBJC_GC = supported diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GTMMerge.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GTMMerge.xcconfig new file mode 100644 index 00000000..5ab141e5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/GTMMerge.xcconfig @@ -0,0 +1,42 @@ +// +// GTMMerge.xcconfig +// +// Xcode configuration file that merges other xcconfig settings. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Xcode doesn't allow you to "inherit" settings with includes so you always +// end up overriding settings accidentally. To avoid this, we instead +// allow you to define settings at different levels +// (GENERAL, PLATFORM (iPhone/Mac), CONFIGURATION (Release/Debug) and we merge +// those together here. +// We DO NOT inherit OTHER_CPLUSPLUSFLAGS because OTHER_CPLUSPLUSFLAGS by default +// takes on OTHER_CFLAGS settings, and we don't want those applied to our +// C++ files. OTHER_CFLAGS is the only way to set C specific settings on our +// C files that we don't want to have applied to our C++ files such as +// -Wold-style-definition +// If you would like to add your own custom settings to the base GTM ones +// please use the GTM_HOST_* settings. These are left empty by GTM and are +// for the host app to fill in. For example if you wanted to have stack +// protection turned on for both debug and release builds you could set +// GTM_HOST_OTHER_CFLAGS = -fstack-protector -fstack-protector-all +// in your own settings files, and then include the QSB ones. + +WARNING_CFLAGS = $(inherited) $(GTM_GENERAL_WARNING_CFLAGS) $(GTM_PLATFORM_WARNING_CFLAGS) $(GTM_CONFIGURATION_WARNING_CFLAGS) $(GTM_HOST_WARNING_CFLAGS) +OTHER_CFLAGS = $(inherited) $(GTM_GENERAL_OTHER_CFLAGS) $(GTM_PLATFORM_OTHER_CFLAGS) $(GTM_CONFIGURATION_OTHER_CFLAGS) $(GTM_HOST_OTHER_CFLAGS) +OTHER_CPLUSPLUSFLAGS = $(GTM_GENERAL_OTHER_CPLUSPLUSFLAGS) $(GTM_PLATFORM_OTHER_CPLUSPLUSFLAGS) $(GTM_CONFIGURATION_OTHER_CPLUSPLUSFLAGS) $(GTM_HOST_OTHER_CPLUSPLUSFLAGS) +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GTM_GENERAL_GCC_PREPROCESSOR_DEFINITIONS) $(GTM_PLATFORM_GCC_PREPROCESSOR_DEFINITIONS) $(GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS) $(GTM_HOST_GCC_PREPROCESSOR_DEFINITIONS) +OTHER_LDFLAGS = $(inherited) $(GTM_GENERAL_OTHER_LDFLAGS) $(GTM_PLATFORM_OTHER_LDFLAGS) $(GTM_CONFIGURATION_OTHER_LDFLAGS) $(GTM_HOST_OTHER_LDFLAGS) diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/General.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/General.xcconfig new file mode 100644 index 00000000..dc3e64f5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/General.xcconfig @@ -0,0 +1,172 @@ +// +// General.xcconfig +// +// Xcode configuration file for general build settings applicable to all +// projects and targets. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// NOTE: as of Xcode 3.1, for iPhone development, the two SDKs you can match are: +// SDK_NAME iphoneos2.0 +// SDK_NAME iphoneos2.1 +// SDK_NAME iphonesimulator2.0 +// SDK_NAME iphonesimulator2.1 +// for Mac OS developement, the values are: +// SDK_NAME macosx10.4 +// SDK_NAME macosx10.5 +// SDK_NAME macosx10.6 + +// Build for PPC and Intel (Leopard/SnowLeopard gets 64 bit also) +// Note that you can't build 10.5 with using SenTestingKit on ppc64 with +// SnowLeopard XCode because it doesn't ship with a ppc64 version of +// SenTestingKit. For this reason we are NOT building/testing GTM +// with ppc64 at this time. We override the 10.5 setting in the project +// file to turn it off. +ARCHS[sdk=macosx10.4*] = i386 ppc +ARCHS[sdk=macosx10.5*] = i386 x86_64 ppc ppc64 +ARCHS[sdk=macosx10.6*] = i386 x86_64 ppc + +// Build for arm for iPhone or Intel for the iPhone Simulator +ARCHS[sdk=iphoneos*] = armv6 +ARCHS[sdk=iphonesimulator*] = i386 + +// Build only the active architecture on iphone device targets +ONLY_ACTIVE_ARCH[sdk=iphoneos*] = YES + +// iPhone currently deploys on 10.5 only +MACOSX_DEPLOYMENT_TARGET[sdk=iphone*] = 10.5 + +// We want our pngs compressed when they are copied +COMPRESS_PNG_FILES = YES + +// Zerolink prevents link warnings so turn it off +ZERO_LINK = NO + +// Prebinding considered unhelpful in 10.3 and later +PREBINDING = NO + +// Work around Xcode bugs by using external strip. See: +// http://lists.apple.com/archives/Xcode-users/2006/Feb/msg00050.html +SEPARATE_STRIP = YES + +// Force C99 dialect +GCC_C_LANGUAGE_STANDARD = c99 + +// Obj-C exceptions are needed for @synchronized(self) +GCC_ENABLE_OBJC_EXCEPTIONS = YES + +// not sure why apple defaults this on, but it's pretty risky +ALWAYS_SEARCH_USER_PATHS = NO + +// Turn on position dependent code for most cases (overridden where appropriate) +GCC_DYNAMIC_NO_PIC = YES + +// For ObjC++ we want C++ cdtors called +GCC_OBJC_CALL_CXX_CDTORS = YES + +// Use Obj-C fast dispatch +GCC_FAST_OBJC_DISPATCH = YES + +// Warn on implicit data conversions in 64bit builds +GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64*] = YES + +// Strictest warning policy that we can do +// Options intentionally turned off +// http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html +// -Wsystem-headers - since we can't fix them we are going to assume they're ok +// -Wtraditional - we are compiling with c99, so we don't care about trad +// -Wdeclaration-after-statement - we are compiling with c99 which allows this +// -Wpadded - lots of structures will get padded, so although this warning may +// be useful to show us badly padded structures, it causes to many +// warnings to be on generally. +// -Wunreachable-code - several macros use the do {} while (0) which always +// flags this. e.g. all the ST... macros for unittesting +// -Wredundant-decls - we sometimes use redundant decls to add an attribute +// to a function/method (i.e. +// -Waggregate-return - NSPoint, NSRect etc are often returned as aggregates +// -Wshorten-64-to-32 - this is defined in the 64 bit build settings +// -Wcast-qual - Would love to turn this on, but causes issues when converting +// CFTypes to NSTypes and also has issues with some external +// libraries (notably zlib) +// -Wundef - we conditionalize on TARGET_OS_IPHONE which is only defined +// in the iPhoneSDK making us unable to turn this warning on. +// -Wstrict-prototypes - breaks the GTM_METHOD_CHECK macro +// -Wcast-align - causes a whole pile of problems buildng with iPhoneSDK + +// Objective C warnings +// http://gcc.gnu.org/onlinedocs/gcc/Objective_002dC-and-Objective_002dC_002b_002b-Dialect-Options.html +// -Wassign-intercept - this really is more informational than a warning. +// -Wselector - the system headers define lots of methods with the same selector +// rendering this mostly useless to us +// -Wstrict-selector-match - the system headers define lots of methods with the +// same selector rendering this mostly useless to us +// Not being used currently because of Radar 5978978 +// GTM_GENERAL_WARNING_OBJC_ONLY_FLAGS=-Wundeclared-selector + +// C Only Warnings +GTM_GENERAL_OTHER_CFLAGS = -Wdiv-by-zero -Wbad-function-cast -Wnested-externs -Wold-style-definition + +// C++ Only Warnings +GTM_GENERAL_OTHER_CPLUSPLUSFLAGS = -Wabi -Wctor-dtor-privacy -Wstrict-null-sentinel -Wsign-promo +GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = YES +GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES +GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES +GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES + +// General C/C++/ObjC/ObjC++ warnings +// These are generally ordered in easiest to hardest to support. +// If you are transitioning, you can turn on the levels one level at a time +// in your project file by editing GTM_GENERAL_WARNING_CFLAGS and only +// including the warning levels that you currently are compiling against. +// GTM should always compile with full warnings. +GTM_GENERAL_WARNING_CFLAGS1 = -Wall -Wendif-labels -Winvalid-pch -Wformat=2 -Wmissing-format-attribute -Wwrite-strings -Wstack-protector -Wstrict-aliasing=2 +GTM_GENERAL_WARNING_CFLAGS2 = -Wpacked -Wmissing-field-initializers +GTM_EXTRA_WARNING_OVERRIDE_CFLAGS = -Wno-unused-parameter -Wno-sign-compare +GTM_GENERAL_WARNING_CFLAGS3 = -Wextra $(GTM_EXTRA_WARNING_OVERRIDE_CFLAGS) -Wpointer-arith -Wdisabled-optimization -Wfloat-equal +GTM_GENERAL_WARNING_CFLAGS = $(GTM_GENERAL_WARNING_CFLAGS1) $(GTM_GENERAL_WARNING_CFLAGS2) $(GTM_GENERAL_WARNING_CFLAGS3) + +// GCC_WARN_UNINITIALIZED_AUTOS is defined in the release/debug xcconfigs. +GCC_WARN_CHECK_SWITCH_STATEMENTS = YES +GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES +GCC_WARN_ABOUT_MISSING_NEWLINE = YES +GCC_TREAT_WARNINGS_AS_ERRORS = YES +GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_MISSING_PARENTHESES = YES +GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES +GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES +GCC_WARN_UNKNOWN_PRAGMAS = YES +GCC_WARN_UNUSED_LABEL = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VALUE = YES +GCC_WARN_UNUSED_VARIABLE = YES +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES +// We don't turn on shadow and sign comparisons because too many 3rd party +// libaries don't compile with them turned on (sign compare rarely catches +// errors, but shadow is very useful). +// NOTE: sign compare is also controlled by -Wextra, we we override it above. +// GCC_WARN_SHADOW = YES +// GCC_WARN_SIGN_COMPARE = YES + +GCC_WARN_PEDANTIC = NO +GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO +GCC_WARN_PROTOTYPE_CONVERSION = NO +GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO +GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = NO +GCC_WARN_UNUSED_PARAMETER = NO +// Use of Gestalt requires 4 char constants (amongst other things) +GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/LeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/LeopardOrLater.xcconfig new file mode 100644 index 00000000..c0f75bc8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/LeopardOrLater.xcconfig @@ -0,0 +1,25 @@ +// +// LeopardOrLater.xcconfig +// +// Xcode configuration file for projects targeting 10.5 Leopard or later. These +// settings produce a Universal binary compatible with 10.5 for PPC and Intel. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Default SDK and minimum OS version is 10.5 +SDKROOT = ${DEVELOPER_SDK_DIR}/MacOSX10.5.sdk +MACOSX_DEPLOYMENT_TARGET = 10.5 +GCC_VERSION = 4.0 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Release.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Release.xcconfig new file mode 100644 index 00000000..4c5ad8ac --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Release.xcconfig @@ -0,0 +1,45 @@ +// +// Release.xcconfig +// +// General Xcode configuration file for Release targets. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Optimize for space and size (Apple recommendation) +GCC_OPTIMIZATION_LEVEL = s + +// Deploment postprocessing is what triggers Xcode to strip +DEPLOYMENT_POSTPROCESSING = YES + +// No symbols +GCC_GENERATE_DEBUGGING_SYMBOLS = NO + +// Dead code strip does not affect ObjC code but can help for C +DEAD_CODE_STRIPPING = YES + +// ASSERT going away in release tends to create unused vars. +// init-self can only be turned on when optimizations are on +GTM_CONFIGURATION_WARNING_CFLAGS = -Wno-unused-variable -Winit-self -Wno-extra + +// NDEBUG is used by things like assert.h, so define it for general compat. +GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 + +// Give us warnings about uninitialized autos +// can only be done when GCC_OPTIMIZATION_LEVEL is actually optimizing +GCC_WARN_UNINITIALIZED_AUTOS = YES + +// When we strip we want to strip all symbols in release, but save externals. +STRIP_STYLE = all diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig new file mode 100644 index 00000000..0a7475e9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig @@ -0,0 +1,26 @@ +// +// SnowLeopardOrLater.xcconfig +// +// Xcode configuration file for projects targeting 10.6 SnowLeopard or later. +// These settings produce a Universal binary compatible with 10.6 for +// PPC and Intel. +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Default SDK and minimum OS version is 10.6 +SDKROOT = ${DEVELOPER_SDK_DIR}/MacOSX10.6.sdk +MACOSX_DEPLOYMENT_TARGET = 10.6 +GCC_VERSION = 4.0 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/TigerOrLater.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/TigerOrLater.xcconfig new file mode 100644 index 00000000..bc0f8f45 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/TigerOrLater.xcconfig @@ -0,0 +1,25 @@ +// +// TigerOrLater.xcconfig +// +// Xcode configuration file for projects targeting 10.4 Tiger or later. These +// settings produce a Universal binary compatible with 10.4 for PPC and Intel. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Default SDK and minimum OS version is 10.4 +SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk +MACOSX_DEPLOYMENT_TARGET = 10.4 +GCC_VERSION = 4.0 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Unittest.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Unittest.xcconfig new file mode 100644 index 00000000..96121eee --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/Unittest.xcconfig @@ -0,0 +1,33 @@ +// +// Unittest.xcconfig +// +// Xcode configuration file for a basic unittest targets. Use the debug or +// release build specific configs in the Target folder. +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// Unittests are loadable bundles +#include "../Target/LoadableBundle.xcconfig" + +// Force C99 dialect with GNU extensions (needed for OCUnit) +GCC_C_LANGUAGE_STANDARD = gnu99 + +// Deploment postprocessing is what triggers Xcode to strip, we don't strip +// unittests +DEPLOYMENT_POSTPROCESSING = NO + +// Most common unittests will be objective-c +WRAPPER_EXTENSION = octest diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone20.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone20.xcconfig new file mode 100644 index 00000000..0f92c95b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone20.xcconfig @@ -0,0 +1,24 @@ +// +// iPhone20.xcconfig +// +// Xcode configuration file for building a Debug target on iPhone OS 2.0 +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// Set default SDK. +SDKROOT = iphoneos2.0 + +// iPhone currently deploys on 10.5 only +MACOSX_DEPLOYMENT_TARGET = 10.5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone21.xcconfig b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone21.xcconfig new file mode 100644 index 00000000..61c59edb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/subconfig/iPhone21.xcconfig @@ -0,0 +1,24 @@ +// +// iPhone21.xcconfig +// +// Xcode configuration file for building a Debug target on iPhone OS 2.1 +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// Set default SDK. +SDKROOT = iphoneos2.1 + +// iPhone currently deploys on 10.5 only +MACOSX_DEPLOYMENT_TARGET = 10.5 diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/xcconfigs-readme.txt b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/xcconfigs-readme.txt new file mode 100644 index 00000000..87a6dd7b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/XcodeConfig/xcconfigs-readme.txt @@ -0,0 +1,53 @@ +Xcode Configs are sort of a black art, any time you have a set of rules, you +quickly hit a few exceptions. + +The main goal of using these is as follow: + +Edit your Project level build settings by removing as much as possible, and +then set the per Configuration settings to one of the project xcode config +files w/in the Project subfolder here. This will batch setup the project to +build Debug/Release with a specific SDK. + +If you are building a Shared Library, Loadable Bundle (Framework) or UnitTest +you will need to apply a further Xcode Config file at the target level. You do +this again by clearing most of the settings on the target, and just setting the +build config for that target to be the match from the Target subfolder here. + +To see an example of this, look at CoverStory +(http://code.google.com/p/coverstory) or Vidnik +(http://code.google.com/p/vidnik). + + +The common exception...If you need to have a few targets build w/ different +SDKs, then you hit the most common of the exceptions. For these, you'd need +the top level config not to set some things, the simplest way to do this seems +to be to remove as many of the settings from the project file, and make new +wrapper xcconfig files that inclue both the project level and target level +setting and set them on the targets (yes, this is like the MetroWerks days +where you can quickly explode in a what seems like N^2 (or worse) number of +config files. With a little luck, future versions of Xcode might have some +support to make mixing SDKs easier. + +Remember: When using the configs at any given layer, make sure you set them for +each build configuration you need (not just the active one). + +Many of the build settings are more than just yes/no flags and take +a list of values that you may want to change at different levels. +Xcode doesn't allow you to "inherit" settings with includes so you always +end up overriding settings accidentally. To avoid this, we instead +allow you to define settings at different levels +(GENERAL, PLATFORM (iPhone/Mac), CONFIGURATION (Release/Debug). +We do this by setting a GTM version of the setting (so for OTHER_CFLAGS it's +GTM_XXX_OTHER_CFLAGS where xxx is GENERAL, PLATFORM or CONFIGURATION depending +at what level the flag is set. These are all merged together in the +GTMMerge.xcconfig. Do not modify the base setting (OTHER_CFLAGS) instead modify +the GTM one at the level you want it modified. + +The major place this may affect you is that we have really tightened down on +the warnings. To make it easier for you to move your code onto the new +xcconfig files, we have split the warnings up into three categories, which in +general you can think of as easy, moderate and extreme. If you run into a lot +of warnings when you compile, look at changing the GTM_GENERAL_WARNING_CFLAGS +setting to only include lower levels (eg GTM_GENERAL_WARNING_CFLAGS1) and see +if that makes it easier on you. Look inside General.xcconfig and search for +GTM_GENERAL_WARNING_CFLAGS1 for more info. diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.h new file mode 100644 index 00000000..828f05aa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.h @@ -0,0 +1,328 @@ +// +// GTMABAddressBook.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// These classes wrap up the iPhone AddressBook 'C' API in a manner very +// similar to that found on Mac OS X. They differ only in that none of these +// routines throws, and some of the types are different as necessitated by +// the APIs that they wrap. These wrappers also protect you from a number +// of issues in the AddressBook API (as of iPhone SDK 2.0/2.1) +// +// Note that there is a strings file that you may want to localize +// (GTMABAddressBook.strings). +// +// If things seem strange, it may be due to one of the following radars: +// 6240394 AddressBook framework constants not initialized until +// ABCreateAddressBook called +// -- CLOSED as designed +// 6208390 Integer and real values don't work in ABMultiValueRefs +// (and this isn't part of the title, but dictionaries don't work +// either) +// 6207605 RecordIDs for people and groups are not unique in AddressBook +// -- CLOSED as designed +// 6204021 kABGroupNameProperty and kABPersonFirstNameProperty have the same +// value +// 6203982 ABPersonCopyLocalizedPropertyName returns name for +// kABGroupNameProperty +// 6203961 ABPersonGetTypeOfProperty returns a type for kABGroupNameProperty +// 6203854 ABMultiValues hash to their address +// 6203836 ABRecords hash to their address +// -- CLOSED behaves correctly +// 6203606 Need CFTypeIDs for AddressBook CFTypes +// 6202868 ABPersonSetImageData should validate image data +// 6202860 Passing nil person into ABGroupAddMember crashes +// -- CLOSED behaves correctly +// 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash +// -- CLOSED behaves correctly +// 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert values +// past end +// 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes +// -- CLOSED behaves correctly +// 6201258 Adding a NULL record using ABAddressBookAddRecord crashes +// -- CLOSED behaves correctly +// 6201046 ABRecordSetValue returns true even if you pass in a bad type for a +// value +// 6201005 ABRecordRemoveValue returns true for value that aren't in the record +// -- CLOSED behaves correctly +// 6200703 ABAddressBookAddRecord doesn't add an item to the people array until +// it's saved +// 6200638 ABAddressBookHasUnsavedChanges doesn't work + +#import +#import +#import "GTMDefines.h" + +#if !GTM_IPHONE_SDK +#error This file is for iPhone use only use ABAddressBook on Mac OS X +#endif + +@class GTMABPerson; +@class GTMABGroup; +@class GTMABRecord; + +GTM_EXTERN NSString *const kGTMABUnknownPropertyName; + +// Wrapper for an AddressBook on iPhone +@interface GTMABAddressBook : NSObject { + @private + ABAddressBookRef addressBook_; +} + +// Returns a new instance of an address book. ++ (GTMABAddressBook *)addressBook; + +// Return the address book reference +- (ABAddressBookRef)addressBookRef; + +// Saves changes made since the last save +// Return YES if successful (or there was no change) +- (BOOL)save; + +// Saves changes made since the last save +// Return YES if successful (or there was no change) +- (BOOL)saveAndReturnError:(NSError **)error; + +// Returns YES if there are unsaved changes +// The unsaved changes flag is automatically set when changes are made +// As of iPhone 2.1, this does not work, and will always return NO. +// Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work +- (BOOL)hasUnsavedChanges; + +// Reverts any changes that have been made and resets the unsaved flag +// Be sure to read notes for -hasUnsavedChanges and -people and -groups. +- (void)revert; + +// Returns a GTMABPerson matching an ID +// Returns nil if the record could not be found +- (GTMABPerson *)personForId:(ABRecordID)uniqueId; + +// Returns a GTMABGroup matching an ID +// Returns nil if the record could not be found +- (GTMABGroup *)groupForId:(ABRecordID)uniqueId; + +// Adds a record (ABPerson or ABGroup) to the AddressBook database +// Be sure to read notes for -people and -group. +- (BOOL)addRecord:(GTMABRecord *)record; + +// Removes a record (ABPerson or ABGroup) from the AddressBook database +- (BOOL)removeRecord:(GTMABRecord *)record; + +// Returns an array (GTMABPerson) of all the people in the AddressBook database +// As of iPhone 2.1, this array will not contain new entries until you save +// the address book. +// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array +// until it's saved +- (NSArray *)people; + +// Returns an array of all the groups (GTMABGroup) in the AddressBook database +// As of iPhone 2.1, this array will not contain new entries until you save +// the address book. +// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array +// until it's saved +- (NSArray *)groups; + +// Returns a localized name for a given label ++ (NSString *)localizedLabel:(CFStringRef)label; + +@end + +// Wrapper for a ABRecord on iPhone. +// A abstract class. Instantiate one of the concrete subclasses, GTMABPerson or +// GTMABGroup. +@interface GTMABRecord : NSObject { + @private + ABRecordRef record_; +} + +// Create a record with a recordRef. +// Since GTMABRecord is an abstract base class, attempting to create one +// of these directly will throw an exception. Use with one of the concrete +// subclasses. ++ (id)recordWithRecord:(ABRecordRef)record; + +// Designated initializer +// Since GTMABRecord is an abstract base class, attempting to create one +// of these directly will throw an exception. Use with one of the concrete +// subclasses. +- (id)initWithRecord:(ABRecordRef)record; + +// Return our recordRef +- (ABRecordRef)recordRef; + +// Return the recordID for the record +- (ABRecordID)recordID; + +// Returns the value of a given property. +// The type of the value depends on the property type. +- (id)valueForProperty:(ABPropertyID)property; + +// Set the value of a given property. +// The type of the value must match the property type. +// Returns YES if value set properly +- (BOOL)setValue:(id)value forProperty:(ABPropertyID)property; + +// Removes the value for the property +// Returns yes if value removed +- (BOOL)removeValueForProperty:(ABPropertyID)property; + +// returns a human friendly name for the record +- (NSString *)compositeName; + +// returns the type of a property ++ (ABPropertyType)typeOfProperty:(ABPropertyID)property; + +// returns a human friendly localized name for a property ++ (NSString *)localizedPropertyName:(ABPropertyID)property; +@end + +// Wrapper for an ABPerson on iPhone +@interface GTMABPerson : GTMABRecord + +// Creates a person with a first name and a last name. ++ (GTMABPerson *)personWithFirstName:(NSString *)first + lastName:(NSString *)last; + +// Sets image data for a person. Data must be to a block of data that +// will create a valid UIImage. +- (BOOL)setImageData:(NSData *)data; + +// Returns the image data. +- (NSData *)imageData; + +// Returns the image for a person +- (UIImage *)image; + +// Sets a the image for a person +- (BOOL)setImage:(UIImage *)image; + +// Returns the format in with names are composited ++ (ABPersonCompositeNameFormat)compositeNameFormat; +@end + +// Wrapper for a ABGroup on iPhone +@interface GTMABGroup : GTMABRecord +// Create a new group named |name| ++ (GTMABGroup *)groupNamed:(NSString *)name; + +// Return an array of members (GTMABPerson) +- (NSArray *)members; + +// Add a member to a group +- (BOOL)addMember:(GTMABPerson *)person; + +// Remove a member from a group +- (BOOL)removeMember:(GTMABPerson *)person; +@end + +// GTMABMultiValue does not supprt NSFastEnumeration because in +// the Apple frameworks it returns identifiers which are already NSStrings. +// In our case identifiers aren't NS types, and it doesn't make sense +// to convert them to NSNumbers just to convert them back so you can +// actually get at the values and labels. +// Instead we supply valueEnumerator and labelEnumerator which you can +// fast enumerate on to get values and labels directly. +@interface GTMABMultiValue : NSObject { + @protected + ABMultiValueRef multiValue_; +} + +// Create a multi value +- (id)initWithMultiValue:(ABMultiValueRef)multiValue; + +// return it's ref +- (ABMultiValueRef)multiValueRef; + +// Returns the number of value/label pairs +- (NSUInteger)count; + +// Returns a value at a given index +// Returns nil if index is out of bounds +- (id)valueAtIndex:(NSUInteger)idx; + +// Returns a label at a given index +// Returns nil if index is out of bounds +- (NSString *)labelAtIndex:(NSUInteger)idx; + +// Returns an identifier at a given index +// Returns kABMultiValueInvalidIdentifier if index is out of bounds +- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx; + +// Returns the index of a given identifier +// Returns NSNotFound if not found +- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier; + +// Type of the contents of this multivalue +- (ABPropertyType)propertyType; + +// Returns the value for a given identifier +// Returns nil if the identifier is not found +- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier; + +// Returns the value for a given identifier +// Returns nil if the identifier is not found +- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)identifier; + +// Returns an enumerator for enumerating through values +- (NSEnumerator *)valueEnumerator; + +// Returns an enumerator for enumerating through labels +- (NSEnumerator *)labelEnumerator; + +@end + +@interface GTMABMutableMultiValue : GTMABMultiValue { + @private + // Use unsigned long here instead of NSUInteger because that's what + // NSFastEnumeration Protocol wants currently (iPhone 2.1) + unsigned long mutations_; +} + +// Create a new mutable multivalue with a given type ++ (id)valueWithPropertyType:(ABPropertyType)type; + +// Create a new mutable multivalue with a given type +- (id)initWithPropertyType:(ABPropertyType)type; + +// Create a new mutable multivalue based on |multiValue| +- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue; + +// Adds a value with its label +// Returns the identifier if successful, kABMultiValueInvalidIdentifier +// otherwise. +- (ABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label; + +// Insert a value/label pair at a given index +// Returns the identifier if successful. kABMultiValueInvalidIdentifier +// otherwise +// If index is out of bounds, returns kABMultiValueInvalidIdentifier. +- (ABMultiValueIdentifier)insertValue:(id)value + withLabel:(CFStringRef)label + atIndex:(NSUInteger)index; + +// Removes a value/label pair at a given index +// Returns NO if index out of bounds +- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)index; + +// Replaces a value at a given index +// Returns NO if index out of bounds +- (BOOL)replaceValueAtIndex:(NSUInteger)index withValue:(id)value; + +// Replaces a label at a given index +// Returns NO if index out of bounds +- (BOOL)replaceLabelAtIndex:(NSUInteger)index withLabel:(CFStringRef)label; + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.m new file mode 100644 index 00000000..05dc27f5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.m @@ -0,0 +1,903 @@ +// +// GTMAddressBook.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMABAddressBook.h" +#import "GTMGarbageCollection.h" + +NSString *const kGTMABUnknownPropertyName = @"UNKNOWN_PROPERTY"; + +typedef struct { + ABPropertyType pType; + Class class; +} TypeClassNameMap; + +@interface GTMABMultiValue () +- (unsigned long*)mutations; +@end + +@interface GTMABMutableMultiValue () +// Checks to see if a value is a valid type to be stored in this multivalue +- (BOOL)checkValueType:(id)value; +@end + +@interface GTMABMultiValueEnumerator : NSEnumerator { + @private + __weak ABMultiValueRef ref_; // ref_ cached from enumeree_ + GTMABMultiValue *enumeree_; + unsigned long mutations_; + NSUInteger count_; + NSUInteger index_; + BOOL useLabels_; +} ++ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree; ++ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree; +- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels; +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(id *)stackbuf + count:(NSUInteger)len; +@end + +@implementation GTMABAddressBook ++ (GTMABAddressBook *)addressBook { + return [[[self alloc] init] autorelease]; +} + +- (id)init { + if ((self = [super init])) { + addressBook_ = ABAddressBookCreate(); + if (!addressBook_) { + // COV_NF_START + [self release]; + self = nil; + // COV_NF_END + } + } + return self; +} + +- (void)dealloc { + if (addressBook_) { + CFRelease(addressBook_); + } + [super dealloc]; +} + +- (BOOL)save { + return [self saveAndReturnError:NULL]; +} + +- (BOOL)saveAndReturnError:(NSError **)error { + CFErrorRef cfError = NULL; + bool wasGood = ABAddressBookSave(addressBook_, &cfError); + GTMCFAutorelease(cfError); + if (error) { + *error = (NSError *)cfError; // COV_NF_LINE + } + return wasGood ? YES : NO; +} + +- (BOOL)hasUnsavedChanges { + return ABAddressBookHasUnsavedChanges(addressBook_); +} + +- (void)revert { + ABAddressBookRevert(addressBook_); +} + +- (BOOL)addRecord:(GTMABRecord *)record { + // Note: we check for bad data here because of radar + // 6201258 Adding a NULL record using ABAddressBookAddRecord crashes + if (!record) return NO; + CFErrorRef cfError = NULL; + bool wasGood = ABAddressBookAddRecord(addressBook_, + [record recordRef], &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (BOOL)removeRecord:(GTMABRecord *)record { + // Note: we check for bad data here because of radar + // 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes + if (!record) return NO; + CFErrorRef cfError = NULL; + bool wasGood = ABAddressBookRemoveRecord(addressBook_, + [record recordRef], &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (NSArray *)people { + NSArray *people + = GTMCFAutorelease(ABAddressBookCopyArrayOfAllPeople(addressBook_)); + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[people count]]; + for (id person in people) { + [result addObject:[GTMABPerson recordWithRecord:person]]; + } + return result; +} + +- (NSArray *)groups { + NSArray *groups + = GTMCFAutorelease(ABAddressBookCopyArrayOfAllGroups(addressBook_)); + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[groups count]]; + for (id group in groups) { + [result addObject:[GTMABGroup recordWithRecord:group]]; + } + return result; +} + +- (ABAddressBookRef)addressBookRef { + return addressBook_; +} + +- (GTMABPerson *)personForId:(ABRecordID)uniqueId { + GTMABPerson *person = nil; + ABRecordRef ref = ABAddressBookGetPersonWithRecordID(addressBook_, uniqueId); + if (ref) { + person = [GTMABPerson recordWithRecord:ref]; + } + return person; +} + +- (GTMABGroup *)groupForId:(ABRecordID)uniqueId { + GTMABGroup *group = nil; + ABRecordRef ref = ABAddressBookGetGroupWithRecordID(addressBook_, uniqueId); + if (ref) { + group = [GTMABGroup recordWithRecord:ref]; + } + return group; +} + ++ (NSString *)localizedLabel:(CFStringRef)label { + return GTMCFAutorelease(ABAddressBookCopyLocalizedLabel(label)); +} + +@end + +@implementation GTMABRecord ++ (id)recordWithRecord:(ABRecordRef)record { + return [[[self alloc] initWithRecord:record] autorelease]; +} + +- (id)initWithRecord:(ABRecordRef)record { + if ((self = [super init])) { + if ([self class] == [GTMABRecord class]) { + [self autorelease]; + [self doesNotRecognizeSelector:_cmd]; + } + if (!record) { + [self release]; + self = nil; + } else { + record_ = CFRetain(record); + } + } + return self; +} + +- (NSUInteger)hash { + // This really isn't completely valid due to + // 6203836 ABRecords hash to their address + // but it's the best we can do without knowing what properties + // are in a record, and we don't have an API for that. + return CFHash(record_); +} + +- (BOOL)isEqual:(id)object { + // This really isn't completely valid due to + // 6203836 ABRecords hash to their address + // but it's the best we can do without knowing what properties + // are in a record, and we don't have an API for that. + return [object respondsToSelector:@selector(recordRef)] + && CFEqual(record_, [object recordRef]); +} + +- (void)dealloc { + if (record_) { + CFRelease(record_); + } + [super dealloc]; +} + +- (ABRecordRef)recordRef { + return record_; +} + +- (ABRecordID)recordID { + return ABRecordGetRecordID(record_); +} + +- (id)valueForProperty:(ABPropertyID)property { + id value = GTMCFAutorelease(ABRecordCopyValue(record_, property)); + if (value) { + if ([[self class] typeOfProperty:property] & kABMultiValueMask) { + value = [[[GTMABMultiValue alloc] initWithMultiValue:value] autorelease]; + } + } + return value; +} + +- (BOOL)setValue:(id)value forProperty:(ABPropertyID)property { + if (!value) return NO; + // We check the type here because of + // Radar 6201046 ABRecordSetValue returns true even if you pass in a bad type + // for a value + TypeClassNameMap fullTypeMap[] = { + { kABStringPropertyType, [NSString class] }, + { kABIntegerPropertyType, [NSNumber class] }, + { kABRealPropertyType, [NSNumber class] }, + { kABDateTimePropertyType, [NSDate class] }, + { kABDictionaryPropertyType, [NSDictionary class] }, + { kABMultiStringPropertyType, [GTMABMultiValue class] }, + { kABMultiRealPropertyType, [GTMABMultiValue class] }, + { kABMultiDateTimePropertyType, [GTMABMultiValue class] }, + { kABMultiDictionaryPropertyType, [GTMABMultiValue class] } + }; + ABPropertyType type = [[self class] typeOfProperty:property]; + BOOL wasFound = NO; + for (size_t i = 0; i < sizeof(fullTypeMap) / sizeof(TypeClassNameMap); ++i) { + if (fullTypeMap[i].pType == type) { + wasFound = YES; + if (![[value class] isSubclassOfClass:fullTypeMap[i].class]) { + return NO; + } + } + } + if (!wasFound) { + return NO; + } + if (type & kABMultiValueMask) { + value = (id)[value multiValueRef]; + } + CFErrorRef cfError = nil; + bool wasGood = ABRecordSetValue(record_, property, (CFTypeRef)value, &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (BOOL)removeValueForProperty:(ABPropertyID)property { + CFErrorRef cfError = nil; + // We check to see if the value is in the property because of: + // Radar 6201005 ABRecordRemoveValue returns true for value that aren't + // in the record + id value = [self valueForProperty:property]; + bool wasGood = value && ABRecordRemoveValue(record_, property, &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (NSString *)compositeName { + return GTMCFAutorelease(ABRecordCopyCompositeName(record_)); +} + +// COV_NF_START +// Both of these methods are to be overridden by their subclasses ++ (ABPropertyType)typeOfProperty:(ABPropertyID)property { + [self doesNotRecognizeSelector:_cmd]; + return kABInvalidPropertyType; +} + ++ (NSString *)localizedPropertyName:(ABPropertyID)property { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} +// COV_NF_END +@end + +@implementation GTMABPerson + ++ (GTMABPerson *)personWithFirstName:(NSString *)first + lastName:(NSString *)last { + GTMABPerson *person = [[[self alloc] init] autorelease]; + if (person) { + BOOL isGood = YES; + if (first) { + isGood = [person setValue:first forProperty:kABPersonFirstNameProperty]; + } + if (isGood && last) { + isGood = [person setValue:last forProperty:kABPersonLastNameProperty]; + } + if (!isGood) { + // COV_NF_START + // Marked as NF because I don't know how to force an error + [person release]; + person = nil; + // COV_NF_END + } + } + return person; +} + +- (id)init { + ABRecordRef person = ABPersonCreate(); + self = [super initWithRecord:person]; + if (person) { + CFRelease(person); + } + return self; +} + +- (BOOL)setImageData:(NSData *)data { + CFErrorRef cfError = NULL; + bool wasGood = NO; + if (!data) { + wasGood = ABPersonRemoveImageData([self recordRef], &cfError); + } else { + // We verify that the data is good because of: + // Radar 6202868 ABPersonSetImageData should validate image data + UIImage *image = [UIImage imageWithData:data]; + wasGood = image && ABPersonSetImageData([self recordRef], + (CFDataRef)data, &cfError); + } + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (UIImage *)image { + return [UIImage imageWithData:[self imageData]]; +} + +- (BOOL)setImage:(UIImage *)image { + NSData *data = UIImagePNGRepresentation(image); + return [self setImageData:data]; +} + +- (NSData *)imageData { + return GTMCFAutorelease(ABPersonCopyImageData([self recordRef])); +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@ %@ %d", + [self class], + [self valueForProperty:kABPersonFirstNameProperty], + [self valueForProperty:kABPersonLastNameProperty], + [self recordID]]; +} + ++ (NSString *)localizedPropertyName:(ABPropertyID)property { + return GTMCFAutorelease(ABPersonCopyLocalizedPropertyName(property)); +} + ++ (ABPersonCompositeNameFormat)compositeNameFormat { + return ABPersonGetCompositeNameFormat(); +} + ++ (ABPropertyType)typeOfProperty:(ABPropertyID)property { + return ABPersonGetTypeOfProperty(property); +} +@end + +@implementation GTMABGroup + ++ (GTMABGroup *)groupNamed:(NSString *)name { + GTMABGroup *group = [[[self alloc] init] autorelease]; + if (group) { + if (![group setValue:name forProperty:kABGroupNameProperty]) { + // COV_NF_START + // Can't get setValue to fail for me + [group release]; + group = nil; + // COV_NF_END + } + } + return group; +} + +- (id)init { + ABRecordRef group = ABGroupCreate(); + self = [super initWithRecord:group]; + if (group) { + CFRelease(group); + } + return self; +} + +- (NSArray *)members { + NSArray *people + = GTMCFAutorelease(ABGroupCopyArrayOfAllMembers([self recordRef])); + NSMutableArray *gtmPeople = [NSMutableArray arrayWithCapacity:[people count]]; + for (id person in people) { + [gtmPeople addObject:[GTMABPerson recordWithRecord:(ABRecordRef)person]]; + } + return gtmPeople; +} + +- (BOOL)addMember:(GTMABPerson *)person { + CFErrorRef cfError = nil; + // We check for person because of + // Radar 6202860 Passing nil person into ABGroupAddMember crashes + bool wasGood = person && ABGroupAddMember([self recordRef], + [person recordRef], &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + +- (BOOL)removeMember:(GTMABPerson *)person { + CFErrorRef cfError = nil; + // We check for person because of + // Radar 6202860 Passing nil person into ABGroupAddMember crashes + // (I know this is remove, but it crashes there too) + bool wasGood = person && ABGroupRemoveMember([self recordRef], + [person recordRef], &cfError); + if (cfError) { + // COV_NF_START + _GTMDevLog(@"Error in [%@ %@]: %@", + [self class], NSStringFromSelector(_cmd), cfError); + CFRelease(cfError); + // COV_NF_END + } + return wasGood ? YES : NO; +} + ++ (ABPropertyType)typeOfProperty:(ABPropertyID)property { + ABPropertyType type = kABInvalidPropertyType; + if (property == kABGroupNameProperty) { + type = kABStringPropertyType; + } + return type; +} + ++ (NSString *)localizedPropertyName:(ABPropertyID)property { + NSString *name = kGTMABUnknownPropertyName; + if (property == kABGroupNameProperty) { + name = NSLocalizedStringFromTable(@"Name", + @"GTMABAddressBook", + @"name property"); + } + return name; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %@ %d", + [self class], + [self valueForProperty:kABGroupNameProperty], + [self recordID]]; +} +@end + +@implementation GTMABMultiValue +- (id)init { + // Call super init and release so we don't leak + [[super init] autorelease]; + [self doesNotRecognizeSelector:_cmd]; + return nil; // COV_NF_LINE +} + +- (id)initWithMultiValue:(ABMultiValueRef)multiValue { + if ((self = [super init])) { + if (!multiValue) { + [self release]; + self = nil; + } else { + multiValue_ = CFRetain(multiValue); + } + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + return [[GTMABMultiValue alloc] initWithMultiValue:multiValue_]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + return [[GTMABMutableMultiValue alloc] initWithMultiValue:multiValue_]; +} + +- (NSUInteger)hash { + // I'm implementing hash instead of using CFHash(multiValue_) because + // 6203854 ABMultiValues hash to their address + NSUInteger count = [self count]; + NSUInteger hash = 0; + for (NSUInteger i = 0; i < count; ++i) { + NSString *label = [self labelAtIndex:i]; + id value = [self valueAtIndex:i]; + hash += [label hash]; + hash += [value hash]; + } + return hash; +} + +- (BOOL)isEqual:(id)object { + // I'm implementing isEqual instea of using CFEquals(multiValue,...) because + // 6203854 ABMultiValues hash to their address + // and it appears CFEquals just calls through to hash to compare them. + BOOL isEqual = NO; + if ([object respondsToSelector:@selector(multiValueRef)]) { + isEqual = multiValue_ == [object multiValueRef]; + if (!isEqual) { + NSUInteger count = [self count]; + NSUInteger objCount = [object count]; + isEqual = count == objCount; + for (NSUInteger i = 0; isEqual && i < count; ++i) { + NSString *label = [self labelAtIndex:i]; + NSString *objLabel = [object labelAtIndex:i]; + isEqual = [label isEqual:objLabel]; + if (isEqual) { + id value = [self valueAtIndex:i]; + id objValue = [object valueAtIndex:i]; + isEqual = [value isEqual:objValue]; + } + } + } + } + return isEqual; +} + +- (void)dealloc { + if (multiValue_) { + CFRelease(multiValue_); + } + [super dealloc]; +} + +- (ABMultiValueRef)multiValueRef { + return multiValue_; +} + +- (NSUInteger)count { + return ABMultiValueGetCount(multiValue_); +} + +- (id)valueAtIndex:(NSUInteger)idx { + id value = nil; + if (idx < [self count]) { + value = GTMCFAutorelease(ABMultiValueCopyValueAtIndex(multiValue_, idx)); + ABPropertyType type = [self propertyType]; + if (type == kABIntegerPropertyType + || type == kABRealPropertyType + || type == kABDictionaryPropertyType) { + // This is because of + // 6208390 Integer and real values don't work in ABMultiValueRefs + // Apparently they forget to add a ref count on int, real and + // dictionary values in ABMultiValueCopyValueAtIndex, although they do + // remember them for all other types. + // Once they fix this, this will lead to a leak, but I figure the leak + // is better than the crash. Our unittests will test to make sure that + // this is the case, and once we find a system that has this fixed, we + // can conditionalize this code. Look for testRadar6208390 in + // GTMABAddressBookTest.m + // Also, search for 6208390 below and fix the fast enumerator to actually + // be somewhat performant when this is fixed. + [value retain]; + } + } + return value; +} + +- (NSString *)labelAtIndex:(NSUInteger)idx { + NSString *label = nil; + if (idx < [self count]) { + label = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(multiValue_, idx)); + } + return label; +} + +- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx { + ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; + if (idx < [self count]) { + identifier = ABMultiValueGetIdentifierAtIndex(multiValue_, idx); + } + return identifier; +} + +- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier { + NSUInteger idx = ABMultiValueGetIndexForIdentifier(multiValue_, identifier); + return idx == (NSUInteger)kCFNotFound ? (NSUInteger)NSNotFound : idx; +} + +- (ABPropertyType)propertyType { + return ABMultiValueGetPropertyType(multiValue_); +} + +- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier { + return [self valueAtIndex:[self indexForIdentifier:identifier]]; +} + +- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)identifier { + return [self labelAtIndex:[self indexForIdentifier:identifier]]; +} + +- (unsigned long*)mutations { + // We just need some constant non-zero value here so fast enumeration works. + // Dereferencing self should give us the isa which will stay constant + // over the enumeration. + return (unsigned long*)self; +} + +- (NSEnumerator *)valueEnumerator { + return [GTMABMultiValueEnumerator valueEnumeratorFor:self]; +} + +- (NSEnumerator *)labelEnumerator { + return [GTMABMultiValueEnumerator labelEnumeratorFor:self]; +} + +@end + +@implementation GTMABMutableMultiValue ++ (id)valueWithPropertyType:(ABPropertyType)type { + return [[[self alloc] initWithPropertyType:type] autorelease]; +} + +- (id)initWithPropertyType:(ABPropertyType)type { + ABMutableMultiValueRef ref = nil; + if (type != kABInvalidPropertyType) { + ref = ABMultiValueCreateMutable(type); + } + self = [super initWithMultiValue:ref]; + if (ref) { + CFRelease(ref); + } + return self; +} + +- (id)initWithMultiValue:(ABMultiValueRef)multiValue { + ABMutableMultiValueRef ref = nil; + if (multiValue) { + ref = ABMultiValueCreateMutableCopy(multiValue); + } + self = [super initWithMultiValue:ref]; + if (ref) { + CFRelease(ref); + } + return self; +} + +- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue { + return [super initWithMultiValue:multiValue]; +} + +- (BOOL)checkValueType:(id)value { + BOOL isGood = NO; + if (value) { + TypeClassNameMap singleValueTypeMap[] = { + { kABStringPropertyType, [NSString class] }, + { kABIntegerPropertyType, [NSNumber class] }, + { kABRealPropertyType, [NSNumber class] }, + { kABDateTimePropertyType, [NSDate class] }, + { kABDictionaryPropertyType, [NSDictionary class] }, + }; + ABPropertyType type = [self propertyType]; + for (size_t i = 0; + i < sizeof(singleValueTypeMap) / sizeof(TypeClassNameMap); ++i) { + if (singleValueTypeMap[i].pType == type) { + if ([[value class] isSubclassOfClass:singleValueTypeMap[i].class]) { + isGood = YES; + break; + } + } + } + } + return isGood; +} + +- (ABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label { + ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; + // We check label and value here because of + // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash + if (!label + || ![self checkValueType:value] + || !ABMultiValueAddValueAndLabel(multiValue_, + value, + label, + &identifier)) { + identifier = kABMultiValueInvalidIdentifier; + } else { + mutations_++; + } + return identifier; +} + +- (ABMultiValueIdentifier)insertValue:(id)value + withLabel:(CFStringRef)label + atIndex:(NSUInteger)idx { + ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; + // We perform a check here to ensure that we don't get bitten by + // Radar 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert + // values past end + NSUInteger count = [self count]; + // We check label and value here because of + // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash + if (idx > count + || !label + || ![self checkValueType:value] + || !ABMultiValueInsertValueAndLabelAtIndex(multiValue_, + value, + label, + idx, + &identifier)) { + identifier = kABMultiValueInvalidIdentifier; + } else { + mutations_++; + } + return identifier; +} + +- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)idx { + BOOL isGood = NO; + NSUInteger count = [self count]; + if (idx < count) { + if (ABMultiValueRemoveValueAndLabelAtIndex(multiValue_, + idx)) { + mutations_++; + isGood = YES; + } + } + return isGood; +} + +- (BOOL)replaceValueAtIndex:(NSUInteger)idx withValue:(id)value { + BOOL isGood = NO; + NSUInteger count = [self count]; + if (idx < count && [self checkValueType:value]) { + if (ABMultiValueReplaceValueAtIndex(multiValue_, + value, idx)) { + mutations_++; + isGood = YES; + } + } + return isGood; +} + +- (BOOL)replaceLabelAtIndex:(NSUInteger)idx withLabel:(CFStringRef)label{ + BOOL isGood = NO; + NSUInteger count = [self count]; + if (idx < count) { + if (ABMultiValueReplaceLabelAtIndex(multiValue_, + label, + idx)) { + mutations_++; + isGood = YES; + } + } + return isGood; +} + +- (unsigned long*)mutations { + return &mutations_; +} +@end + + +@implementation GTMABMultiValueEnumerator + ++ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree { + return [[[self alloc] initWithEnumeree:enumeree useLabels:NO] autorelease]; +} + ++ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree { + return [[[self alloc] initWithEnumeree:enumeree useLabels:YES] autorelease]; +} + +- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels { + if ((self = [super init])) { + if (enumeree) { + enumeree_ = [enumeree retain]; + useLabels_ = useLabels; + } else { + // COV_NF_START + // Since this is a private class where the enumeree creates us + // there is no way we should ever get here. + [self release]; + self = nil; + // COV_NF_END + } + } + return self; +} + +- (void)dealloc { + [enumeree_ release]; + [super dealloc]; +} + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(id *)stackbuf + count:(NSUInteger)len { + NSUInteger i; + if (!ref_) { + count_ = [enumeree_ count]; + ref_ = [enumeree_ multiValueRef]; + } + + for (i = 0; state->state < count_ && i < len; ++i, ++state->state) { + if (useLabels_) { + stackbuf[i] = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_, + state->state)); + } else { + // Yes this is slow, but necessary in light of radar 6208390 + // Once this is fixed we can go to something similar to the label + // case which should speed stuff up again. Hopefully anybody who wants + // real performance is willing to move down to the C API anyways. + stackbuf[i] = [enumeree_ valueAtIndex:state->state]; + } + } + + state->itemsPtr = stackbuf; + state->mutationsPtr = [enumeree_ mutations]; + return i; +} + +- (id)nextObject { + id value = nil; + if (!ref_) { + count_ = [enumeree_ count]; + mutations_ = *[enumeree_ mutations]; + ref_ = [enumeree_ multiValueRef]; + + } + if (mutations_ != *[enumeree_ mutations]) { + NSString *reason = [NSString stringWithFormat:@"*** Collection <%@> was " + "mutated while being enumerated", enumeree_]; + [[NSException exceptionWithName:NSGenericException + reason:reason + userInfo:nil] raise]; + } + if (index_ < count_) { + if (useLabels_) { + value = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_, + index_)); + } else { + // Yes this is slow, but necessary in light of radar 6208390 + // Once this is fixed we can go to something similar to the label + // case which should speed stuff up again. Hopefully anybody who wants + // real performance is willing to move down to the C API anyways. + value = [enumeree_ valueAtIndex:index_]; + } + index_ += 1; + } + return value; +} +@end + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.strings b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.strings new file mode 100644 index 00000000..b5e010e1 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBook.strings differ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBookTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBookTest.m new file mode 100644 index 00000000..17a30969 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMABAddressBookTest.m @@ -0,0 +1,608 @@ +// +// GTMAddressBookTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMABAddressBook.h" + +@interface GTMABAddressBookTest : GTMTestCase { + @private + GTMABAddressBook *book_; +} +@end + + +@implementation GTMABAddressBookTest +- (void)setUp { + // Create a book forcing it out of it's autorelease pool. + // I force it out of the release pool, so that we will see any errors + // for it immediately at teardown, and it will be clear which release + // caused us problems. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + book_ = [[GTMABAddressBook addressBook] retain]; + [pool release]; + STAssertNotNil(book_, nil); + STAssertFalse([book_ hasUnsavedChanges], nil); +} + +- (void)tearDown { + [book_ release]; +} + +- (void)testGenericAddressBook { + STAssertEqualObjects([GTMABAddressBook localizedLabel:kABHomeLabel], + @"home", + nil); + STAssertThrows([GTMABRecord recordWithRecord:nil], nil); +} + +- (void)testAddingAndRemovingPerson { + // Create a person + GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart" + lastName:@"Simpson"]; + STAssertNotNil(person, nil); + + // Add person + NSArray *people = [book_ people]; + STAssertFalse([people containsObject:person], nil); + STAssertTrue([book_ addRecord:person], nil); + + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + people = [book_ people]; + STAssertNotNil(people, nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people + // array until it's saved + // We will check to make sure it stays broken ;-) + STAssertFalse([people containsObject:person], nil); + + // Save book_ + STAssertTrue([book_ save], nil); + people = [book_ people]; + STAssertNotNil(people, nil); + STAssertTrue([people containsObject:person], nil); + + ABRecordID recordID = [person recordID]; + STAssertNotEquals(recordID, kABRecordInvalidID, nil); + + GTMABRecord *record = [book_ personForId:recordID]; + STAssertEqualObjects(record, person, nil); + + // Remove person + STAssertTrue([book_ removeRecord:person], nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + // Normally this next line would be STAssertFalse, however due to + // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people + // array until it's saved + // We will check to make sure it stays broken ;-) + STAssertTrue([people containsObject:person], nil); + + // Save Book + STAssertTrue([book_ save], nil); + people = [book_ people]; + STAssertFalse([book_ hasUnsavedChanges], nil); + STAssertFalse([people containsObject:person], nil); + record = [book_ personForId:recordID]; + STAssertNil(record, nil); + + // Revert book_ + STAssertTrue([book_ addRecord:person], nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + [book_ revert]; + STAssertFalse([book_ hasUnsavedChanges], nil); + + // Bogus data + STAssertFalse([book_ addRecord:nil], nil); + STAssertFalse([book_ removeRecord:nil], nil); + + STAssertNotNULL([book_ addressBookRef], nil); + +} + +- (void)testAddingAndRemovingGroup { + // Create a group + GTMABGroup *group = [GTMABGroup groupNamed:@"Test"]; + STAssertNotNil(group, nil); + + // Add group + NSArray *groups = [book_ groups]; + STAssertFalse([groups containsObject:group], nil); + STAssertTrue([book_ addRecord:group], nil); + + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + groups = [book_ groups]; + STAssertNotNil(groups, nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups + // array until it's saved + // We will check to make sure it stays broken ;-) + STAssertFalse([groups containsObject:group], nil); + + // Save book_ + STAssertTrue([book_ save], nil); + groups = [book_ groups]; + STAssertNotNil(groups, nil); + STAssertTrue([groups containsObject:group], nil); + + ABRecordID recordID = [group recordID]; + STAssertNotEquals(recordID, kABRecordInvalidID, nil); + + GTMABRecord *record = [book_ groupForId:recordID]; + STAssertEqualObjects(record, group, nil); + + // Remove group + STAssertTrue([book_ removeRecord:group], nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + // Normally this next line would be STAssertFalse, however due to + // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups + // array until it's saved + // We will check to make sure it stays broken ;-) + STAssertTrue([groups containsObject:group], nil); + + // Save Book + STAssertTrue([book_ save], nil); + groups = [book_ groups]; + STAssertFalse([book_ hasUnsavedChanges], nil); + STAssertFalse([groups containsObject:group], nil); + record = [book_ groupForId:recordID]; + STAssertNil(record, nil); + + // Revert book_ + STAssertTrue([book_ addRecord:group], nil); + // Normally this next line would be STAssertTrue, however due to + // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work + // We will check to make sure it stays broken ;-) + STAssertFalse([book_ hasUnsavedChanges], nil); + + [book_ revert]; + STAssertFalse([book_ hasUnsavedChanges], nil); +} + +- (void)testPerson { + GTMABPerson *person = [[[GTMABPerson alloc] initWithRecord:nil] autorelease]; + STAssertNil(person, nil); + person = [GTMABPerson personWithFirstName:@"Bart" + lastName:nil]; + STAssertNotNil(person, nil); + STAssertEqualObjects([person compositeName], @"Bart", nil); + NSString *firstName = [person valueForProperty:kABPersonFirstNameProperty]; + STAssertEqualObjects(firstName, @"Bart", nil); + NSString *lastName = [person valueForProperty:kABPersonLastNameProperty]; + STAssertNil(lastName, nil); + STAssertTrue([person removeValueForProperty:kABPersonFirstNameProperty], nil); + STAssertFalse([person removeValueForProperty:kABPersonFirstNameProperty], nil); + STAssertFalse([person removeValueForProperty:kABPersonLastNameProperty], nil); + STAssertFalse([person setValue:nil forProperty:kABPersonFirstNameProperty], nil); + STAssertFalse([person setValue:[NSNumber numberWithInt:1] + forProperty:kABPersonFirstNameProperty], nil); + STAssertFalse([person setValue:@"Bart" + forProperty:kABPersonBirthdayProperty], nil); + + ABPropertyType property + = [GTMABPerson typeOfProperty:kABPersonLastNameProperty]; + STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil); + + NSString *string + = [GTMABPerson localizedPropertyName:kABPersonLastNameProperty]; + STAssertEqualObjects(string, @"Last", nil); + + string = [GTMABPerson localizedPropertyName:kABRecordInvalidID]; + STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); + + string = [person description]; + STAssertNotNil(string, nil); + + ABPersonCompositeNameFormat format = [GTMABPerson compositeNameFormat]; + STAssertTrue(format == kABPersonCompositeNameFormatFirstNameFirst || + format == kABPersonCompositeNameFormatLastNameFirst, nil); + + NSData *data = [person imageData]; + STAssertNil(data, nil); + STAssertTrue([person setImageData:nil], nil); + data = [person imageData]; + STAssertNil(data, nil); + UIImage *image = [UIImage imageNamed:@"phone.png"]; + STAssertNotNil(image, nil); + data = UIImagePNGRepresentation(image); + STAssertTrue([person setImageData:data], nil); + NSData *data2 = [person imageData]; + STAssertEqualObjects(data, data2, nil); + STAssertTrue([person setImageData:nil], nil); + data = [person imageData]; + STAssertNil(data, nil); + + STAssertTrue([person setImage:image], nil); + UIImage *image2 = [person image]; + STAssertNotNil(image2, nil); + STAssertEqualObjects(UIImagePNGRepresentation(image), + UIImagePNGRepresentation(image2), nil); + + person = [GTMABPerson personWithFirstName:@"Bart" + lastName:@"Simpson"]; + + data = [NSData dataWithBytes:"a" length:1]; + STAssertFalse([person setImageData:data], nil); + + GTMABMutableMultiValue *value + = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType]; + STAssertNotNil(value, nil); + STAssertNotEquals([value addValue:@"222-222-2222" + withLabel:kABHomeLabel], + kABMultiValueInvalidIdentifier, nil); + STAssertNotEquals([value addValue:@"333-333-3333" + withLabel:kABWorkLabel], + kABMultiValueInvalidIdentifier, nil); + STAssertTrue([person setValue:value forProperty:kABPersonPhoneProperty], nil); + id value2 = [person valueForProperty:kABPersonPhoneProperty]; + STAssertNotNil(value2, nil); + STAssertEqualObjects(value, value2, nil); + STAssertEquals([value hash], [value2 hash], nil); + STAssertNotEquals([person hash], (NSUInteger)0, nil); +} + +- (void)testGroup { + GTMABGroup *group = [[[GTMABGroup alloc] initWithRecord:nil] autorelease]; + STAssertNil(group, nil); + group = [GTMABGroup groupNamed:@"TestGroup"]; + STAssertNotNil(group, nil); + STAssertEqualObjects([group compositeName], @"TestGroup", nil); + NSString *name = [group valueForProperty:kABGroupNameProperty]; + STAssertEqualObjects(name, @"TestGroup", nil); + NSString *lastName = [group valueForProperty:kABPersonLastNameProperty]; + STAssertNil(lastName, nil); + STAssertTrue([group removeValueForProperty:kABGroupNameProperty], nil); + STAssertFalse([group removeValueForProperty:kABGroupNameProperty], nil); + STAssertFalse([group removeValueForProperty:kABPersonLastNameProperty], nil); + STAssertFalse([group setValue:nil forProperty:kABGroupNameProperty], nil); + STAssertFalse([group setValue:[NSNumber numberWithInt:1] + forProperty:kABGroupNameProperty], nil); + STAssertFalse([group setValue:@"Bart" + forProperty:kABPersonBirthdayProperty], nil); + + ABPropertyType property = [GTMABGroup typeOfProperty:kABGroupNameProperty]; + STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil); + + property = [GTMABGroup typeOfProperty:kABPersonLastNameProperty]; + STAssertEquals(property, (ABPropertyType)kABInvalidPropertyType, nil); + + NSString *string = [GTMABGroup localizedPropertyName:kABGroupNameProperty]; + STAssertEqualObjects(string, @"Name", nil); + + string = [GTMABGroup localizedPropertyName:kABPersonLastNameProperty]; + STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); + + string = [GTMABGroup localizedPropertyName:kABRecordInvalidID]; + STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); + + string = [group description]; + STAssertNotNil(string, nil); + + // Adding and removing members + group = [GTMABGroup groupNamed:@"TestGroup2"]; + NSArray *members = [group members]; + STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); + + STAssertFalse([group addMember:nil], nil); + + members = [group members]; + STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); + + GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart" + lastName:@"Simpson"]; + STAssertNotNil(person, nil); + STAssertTrue([book_ addRecord:person], nil); + STAssertTrue([book_ save], nil); + STAssertTrue([group addMember:person], nil); + STAssertTrue([book_ addRecord:group], nil); + STAssertTrue([book_ save], nil); + members = [group members]; + STAssertEquals([members count], (NSUInteger)1, @"Members: %@", members); + STAssertTrue([group removeMember:person], nil); + STAssertFalse([group removeMember:person], nil); + STAssertFalse([group removeMember:nil], nil); + STAssertTrue([book_ removeRecord:group], nil); + STAssertTrue([book_ removeRecord:person], nil); + STAssertTrue([book_ save], nil); +} + + +- (void)testMultiValues { + STAssertThrows([[GTMABMultiValue alloc] init], nil); + STAssertThrows([[GTMABMutableMultiValue alloc] init], nil); + GTMABMultiValue *value = [[GTMABMultiValue alloc] initWithMultiValue:nil]; + STAssertNil(value, nil); + GTMABMutableMultiValue *mutValue + = [GTMABMutableMultiValue valueWithPropertyType:kABInvalidPropertyType]; + STAssertNil(mutValue, nil); + mutValue + = [[[GTMABMutableMultiValue alloc] + initWithMutableMultiValue:nil] autorelease]; + STAssertNil(mutValue, nil); + mutValue + = [[[GTMABMutableMultiValue alloc] + initWithMultiValue:nil] autorelease]; + STAssertNil(mutValue, nil); + const ABPropertyType types[] = { + kABStringPropertyType, + kABIntegerPropertyType, + kABRealPropertyType, + kABDateTimePropertyType, + kABDictionaryPropertyType, + kABMultiStringPropertyType, + kABMultiIntegerPropertyType, + kABMultiRealPropertyType, + kABMultiDateTimePropertyType, + kABMultiDictionaryPropertyType + }; + for (size_t i = 0; i < sizeof(types) / sizeof(ABPropertyType); ++i) { + mutValue = [GTMABMutableMultiValue valueWithPropertyType:types[i]]; + STAssertNotNil(mutValue, nil); + // Oddly the Apple APIs allow you to create a mutable multi value with + // either a property type of kABFooPropertyType or kABMultiFooPropertyType + // and apparently you get back basically the same thing. However if you + // ask a type that you created with kABMultiFooPropertyType for it's type + // it returns just kABFooPropertyType. + STAssertEquals([mutValue propertyType], + types[i] & ~kABMultiValueMask, nil); + } + mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType]; + STAssertNotNil(mutValue, nil); + value = [[mutValue copy] autorelease]; + STAssertEqualObjects([value class], [GTMABMultiValue class], nil); + mutValue = [[value mutableCopy] autorelease]; + STAssertEqualObjects([mutValue class], [GTMABMutableMultiValue class], nil); + STAssertEquals([mutValue count], (NSUInteger)0, nil); + STAssertNil([mutValue valueAtIndex:0], nil); + STAssertNil([mutValue labelAtIndex:0], nil); + STAssertEquals([mutValue identifierAtIndex:0], + kABMultiValueInvalidIdentifier, nil); + STAssertEquals([mutValue propertyType], + (ABPropertyType)kABStringPropertyType, nil); + ABMultiValueIdentifier ident = [mutValue addValue:nil + withLabel:kABHomeLabel]; + STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); + ident = [mutValue addValue:@"val1" + withLabel:nil]; + STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); + ident = [mutValue insertValue:@"val1" + withLabel:nil + atIndex:0]; + STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); + ident = [mutValue insertValue:nil + withLabel:kABHomeLabel + atIndex:0]; + STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); + ident = [mutValue addValue:@"val1" + withLabel:kABHomeLabel]; + STAssertNotEquals(ident, kABMultiValueInvalidIdentifier, nil); + ABMultiValueIdentifier identCheck = [mutValue identifierAtIndex:0]; + STAssertEquals(ident, identCheck, nil); + NSUInteger idx = [mutValue indexForIdentifier:ident]; + STAssertEquals(idx, (NSUInteger)0, nil); + STAssertTrue([mutValue replaceLabelAtIndex:0 + withLabel:kABWorkLabel], nil); + STAssertFalse([mutValue replaceLabelAtIndex:10 + withLabel:kABWorkLabel], nil); + STAssertTrue([mutValue replaceValueAtIndex:0 + withValue:@"newVal1"], nil); + STAssertFalse([mutValue replaceValueAtIndex:10 + withValue:@"newVal1"], nil); + + STAssertEqualObjects([mutValue valueForIdentifier:ident], @"newVal1", nil); + STAssertEqualObjects([mutValue labelForIdentifier:ident], + (NSString *)kABWorkLabel, nil); + + ABMultiValueIdentifier ident2 = [mutValue insertValue:@"val2" + withLabel:kABOtherLabel + atIndex:0]; + STAssertNotEquals(ident2, kABMultiValueInvalidIdentifier, nil); + STAssertNotEquals(ident2, ident, nil); + ABMultiValueIdentifier ident3 = [mutValue insertValue:@"val3" + withLabel:kABPersonPhoneMainLabel + atIndex:10]; + STAssertEquals(ident3, kABMultiValueInvalidIdentifier, nil); + NSUInteger idx3 = [mutValue indexForIdentifier:ident3]; + STAssertEquals(idx3, (NSUInteger)NSNotFound, nil); + STAssertTrue([mutValue removeValueAndLabelAtIndex:1], nil); + STAssertFalse([mutValue removeValueAndLabelAtIndex:1], nil); + + NSUInteger idx4 + = [mutValue indexForIdentifier:kABMultiValueInvalidIdentifier]; + STAssertEquals(idx4, (NSUInteger)NSNotFound, nil); + + STAssertNotNULL([mutValue multiValueRef], nil); + + // Enumerator test + mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABIntegerPropertyType]; + STAssertNotNil(mutValue, nil); + for (int i = 0; i < 100; i++) { + NSString *label = [NSString stringWithFormat:@"label %d", i]; + NSNumber *val = [NSNumber numberWithInt:i]; + STAssertNotEquals([mutValue addValue:val + withLabel:(CFStringRef)label], + kABMultiValueInvalidIdentifier, nil); + } + int count = 0; + for (NSString *label in [mutValue labelEnumerator]) { + NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; + STAssertEqualObjects(label, testLabel, nil); + } + count = 0; + value = [[mutValue copy] autorelease]; + for (NSNumber *val in [value valueEnumerator]) { + STAssertEqualObjects(val, [NSNumber numberWithInt:count++], nil); + } + + // Test messing with the values while we're enumerating them + NSEnumerator *labelEnum = [mutValue labelEnumerator]; + NSEnumerator *valueEnum = [mutValue valueEnumerator]; + STAssertNotNil(labelEnum, nil); + STAssertNotNil(valueEnum, nil); + STAssertNotNil([labelEnum nextObject], nil); + STAssertNotNil([valueEnum nextObject], nil); + STAssertTrue([mutValue removeValueAndLabelAtIndex:0], nil); + STAssertThrows([labelEnum nextObject], nil); + STAssertThrows([valueEnum nextObject], nil); + + // Test messing with the values while we're fast enumerating them + // Should throw an exception on the second access. + BOOL exceptionThrown = NO; + // Start at one because we removed index 0 above. + count = 1; + @try { + for (NSString *label in [mutValue labelEnumerator]) { + NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; + STAssertEqualObjects(label, testLabel, nil); + STAssertTrue([mutValue removeValueAndLabelAtIndex:50], nil); + } + } @catch(NSException *e) { + STAssertEqualObjects([e name], NSGenericException, @"Got %@ instead", e); + STAssertEquals(count, 2, + @"Should have caught it on the second access"); + exceptionThrown = YES; + } // COV_NF_LINE - because we always catch, this brace doesn't get exec'd + STAssertTrue(exceptionThrown, @"We should have thrown an exception" + @" because the values under the enumerator were modified"); + +} + +- (void)testRadar6208390 { + ABPropertyType types[] = { + kABStringPropertyType, + kABIntegerPropertyType, + kABRealPropertyType, + kABDateTimePropertyType, + kABDictionaryPropertyType + }; + for (size_t j = 0; j < sizeof(types) / sizeof(ABPropertyType); ++j) { + ABPropertyType type = types[j]; + ABMultiValueRef ref = ABMultiValueCreateMutable(type); + STAssertNotNULL(ref, nil); + NSString *label = [[NSString alloc] initWithString:@"label"]; + STAssertNotNil(label, nil); + id val = nil; + switch (type) { + case kABDictionaryPropertyType: + val = [[NSDictionary alloc] initWithObjectsAndKeys:@"1", @"1", nil]; + break; + + case kABStringPropertyType: + val = [[NSString alloc] initWithFormat:@"value %d"]; + break; + + case kABIntegerPropertyType: + case kABRealPropertyType: + val = [[NSNumber alloc] initWithInt:143]; + break; + + case kABDateTimePropertyType: + val = [[NSDate alloc] init]; + break; + } + STAssertNotNil(val, + @"Testing type %d, %@", type, val); + NSUInteger firstRetainCount = [val retainCount]; + STAssertNotEquals(firstRetainCount, + (NSUInteger)0, + @"Testing type %d, %@", type, val); + + ABMultiValueIdentifier identifier; + STAssertTrue(ABMultiValueAddValueAndLabel(ref, + val, + (CFStringRef)label, + &identifier), + @"Testing type %d, %@", type, val); + NSUInteger secondRetainCount = [val retainCount]; + STAssertEquals(firstRetainCount + 1, + secondRetainCount, + @"Testing type %d, %@", type, val); + [label release]; + [val release]; + NSUInteger thirdRetainCount = [val retainCount]; + STAssertEquals(firstRetainCount, + thirdRetainCount, + @"Testing type %d, %@", type, val); + + id oldVal = val; + val = (id)ABMultiValueCopyValueAtIndex(ref, 0); + NSUInteger fourthRetainCount = [val retainCount]; + + // kABDictionaryPropertyTypes appear to do an actual copy, so the retain + // count checking trick won't work. We only check the retain count if + // we didn't get a new version. + if (val == oldVal) { + if (type == kABIntegerPropertyType + || type == kABRealPropertyType) { + // We are verifying that yes indeed 6208390 is still broken + STAssertEquals(fourthRetainCount, + thirdRetainCount, + @"Testing type %d, %@. If you see this error it may " + @"be time to update the code to change retain behaviors" + @"with this os version", type, val); + } else { + STAssertEquals(fourthRetainCount, + thirdRetainCount + 1, + @"Testing type %d, %@", type, val); + [val release]; + } + } else { + [val release]; + } + CFRelease(ref); + } +} + +// Globals used by testRadar6240394. +static ABPropertyID gGTMTestID; +static const ABPropertyID *gGTMTestIDPtr; + +void __attribute__((constructor))SetUpIDForTestRadar6240394(void) { + // These must be set up BEFORE ABAddressBookCreate is called. + gGTMTestID = kABPersonLastNameProperty; + gGTMTestIDPtr = &kABPersonLastNameProperty; +} + +- (void)testRadar6240394 { + // As of iPhone SDK 2.1, the property IDs aren't initialized until + // ABAddressBookCreate is actually called. They will return zero until + // then. Logged as radar 6240394. + STAssertEquals(gGTMTestID, 0, @"If this isn't zero, Apple has fixed 6240394"); + (void)ABAddressBookCreate(); + STAssertEquals(*gGTMTestIDPtr, kABPersonLastNameProperty, + @"If this doesn't work, something else has broken"); +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.h b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.h new file mode 100644 index 00000000..cb2d206c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.h @@ -0,0 +1,24 @@ +// +// GTMUIFont+LineHeight.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import + +@interface UIFont (GTMLineHeight) +- (CGFloat)gtm_lineHeight; +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.m new file mode 100644 index 00000000..74f8a8fe --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeight.m @@ -0,0 +1,25 @@ +// +// GTMUIFont+LineHeight.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMUIFont+LineHeight.h" + +@implementation UIFont (GTMLineHeight) +- (CGFloat)gtm_lineHeight { + return [@"Fake line with gjy" sizeWithFont:self].height; +} +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeightTest.m b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeightTest.m new file mode 100644 index 00000000..8da28eb0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/externals/google-toolbox-for-mac/iPhone/GTMUIFont+LineHeightTest.m @@ -0,0 +1,40 @@ +// +// GTMUIFont+LineHeightTest.m +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMSenTestCase.h" +#import "GTMUIFont+LineHeight.h" + +@interface GTMUIFontLineHeightTest : GTMTestCase +@end + + +@implementation GTMUIFontLineHeightTest + +- (void)testLineHeight { + UIFont *font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; + STAssertNotNil(font, nil); + STAssertGreaterThanOrEqual([font gtm_lineHeight], (CGFloat)5.0, nil); + + UIFont *fontSmall = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]]; + STAssertNotNil(fontSmall, nil); + STAssertGreaterThanOrEqual([fontSmall gtm_lineHeight], (CGFloat)5.0, nil); + + STAssertGreaterThan([font gtm_lineHeight], [fontSmall gtm_lineHeight], nil); +} + +@end diff --git a/thirdparty/google-breakpad/r318/src/common/mac/file_id.cc b/thirdparty/google-breakpad/r318/src/common/mac/file_id.cc new file mode 100644 index 00000000..ebb8c40e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/file_id.cc @@ -0,0 +1,101 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// file_id.cc: Return a unique identifier for a file +// +// See file_id.h for documentation +// +// Author: Dan Waylonis + +#include +#include +#include + +#include "common/mac/file_id.h" +#include "common/mac/macho_id.h" + +using MacFileUtilities::MachoID; + +namespace google_breakpad { + +FileID::FileID(const char *path) { + strlcpy(path_, path, sizeof(path_)); +} + +bool FileID::FileIdentifier(unsigned char identifier[16]) { + int fd = open(path_, O_RDONLY); + if (fd == -1) + return false; + + MD5_CTX md5; + MD5_Init(&md5); + + // Read 4k x 2 bytes at a time. This is faster than just 4k bytes, but + // doesn't seem to be an unreasonable size for the stack. + unsigned char buffer[4096 * 2]; + size_t buffer_size = sizeof(buffer); + while ((buffer_size = read(fd, buffer, buffer_size) > 0)) { + MD5_Update(&md5, buffer, buffer_size); + } + + close(fd); + MD5_Final(identifier, &md5); + + return true; +} + +bool FileID::MachoIdentifier(int cpu_type, unsigned char identifier[16]) { + MachoID macho(path_); + + if (macho.UUIDCommand(cpu_type, identifier)) + return true; + + return macho.MD5(cpu_type, identifier); +} + +// static +void FileID::ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length) { + int buffer_idx = 0; + for (int idx = 0; (buffer_idx < buffer_length) && (idx < 16); ++idx) { + int hi = (identifier[idx] >> 4) & 0x0F; + int lo = (identifier[idx]) & 0x0F; + + if (idx == 4 || idx == 6 || idx == 8 || idx == 10) + buffer[buffer_idx++] = '-'; + + buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; + buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; + } + + // NULL terminate + buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/mac/file_id.h b/thirdparty/google-breakpad/r318/src/common/mac/file_id.h new file mode 100644 index 00000000..eb06b0d6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/file_id.h @@ -0,0 +1,78 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// file_id.h: Return a unique identifier for a file +// +// Author: Dan Waylonis + +#ifndef COMMON_MAC_FILE_ID_H__ +#define COMMON_MAC_FILE_ID_H__ + +#include + +namespace google_breakpad { + +class FileID { + public: + FileID(const char *path); + ~FileID() {}; + + // Load the identifier for the file path specified in the constructor into + // |identifier|. Return false if the identifier could not be created for the + // file. + // The current implementation will return the MD5 hash of the file's bytes. + bool FileIdentifier(unsigned char identifier[16]); + + // Treat the file as a mach-o file that will contain one or more archicture. + // Accepted values for |cpu_type| (e.g., CPU_TYPE_X86 or CPU_TYPE_POWERPC) + // are listed in /usr/include/mach/machine.h. + // If |cpu_type| is 0, then the native cpu type is used. + // Returns false if opening the file failed or if the |cpu_type| is not + // present in the file. + // Return the unique identifier in |identifier|. + // The current implementation will look for the (in order of priority): + // LC_UUID, LC_ID_DYLIB, or MD5 hash of the given |cpu_type|. + bool MachoIdentifier(int cpu_type, unsigned char identifier[16]); + + // Convert the |identifier| data to a NULL terminated string. The string will + // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE). + // The |buffer| should be at least 37 bytes long to receive all of the data + // and termination. Shorter buffers will contain truncated data. + static void ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length); + + private: + // Storage for the path specified + char path_[PATH_MAX]; +}; + +} // namespace google_breakpad + +#endif // COMMON_MAC_FILE_ID_H__ + diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_id.cc b/thirdparty/google-breakpad/r318/src/common/mac/macho_id.cc new file mode 100644 index 00000000..160f6ed7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_id.cc @@ -0,0 +1,366 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_id.cc: Functions to gather identifying information from a macho file +// +// See macho_id.h for documentation +// +// Author: Dan Waylonis + +extern "C" { // necessary for Leopard + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +} + +#include "common/mac/macho_id.h" +#include "common/mac/macho_walker.h" +#include "common/mac/macho_utilities.h" + +namespace MacFileUtilities { + +MachoID::MachoID(const char *path) { + strlcpy(path_, path, sizeof(path_)); + file_ = open(path, O_RDONLY); +} + +MachoID::~MachoID() { + if (file_ != -1) + close(file_); +} + +// The CRC info is from http://en.wikipedia.org/wiki/Adler-32 +// With optimizations from http://www.zlib.net/ + +// The largest prime smaller than 65536 +#define MOD_ADLER 65521 +// MAX_BLOCK is the largest n such that 255n(n+1)/2 + (n+1)(MAX_BLOCK-1) <= 2^32-1 +#define MAX_BLOCK 5552 + +void MachoID::UpdateCRC(unsigned char *bytes, size_t size) { +// Unrolled loops for summing +#define DO1(buf,i) {sum1 += (buf)[i]; sum2 += sum1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + // Split up the crc + uint32_t sum1 = crc_ & 0xFFFF; + uint32_t sum2 = (crc_ >> 16) & 0xFFFF; + + // Do large blocks + while (size >= MAX_BLOCK) { + size -= MAX_BLOCK; + int block_count = MAX_BLOCK / 16; + do { + DO16(bytes); + bytes += 16; + } while (--block_count); + sum1 %= MOD_ADLER; + sum2 %= MOD_ADLER; + } + + // Do remaining bytes + if (size) { + while (size >= 16) { + size -= 16; + DO16(bytes); + bytes += 16; + } + while (size--) { + sum1 += *bytes++; + sum2 += sum1; + } + sum1 %= MOD_ADLER; + sum2 %= MOD_ADLER; + crc_ = (sum2 << 16) | sum1; + } +} + +void MachoID::UpdateMD5(unsigned char *bytes, size_t size) { + MD5_Update(&md5_context_, bytes, size); +} + +void MachoID::UpdateSHA1(unsigned char *bytes, size_t size) { + SHA_Update(&sha1_context_, bytes, size); +} + +void MachoID::Update(MachoWalker *walker, unsigned long offset, size_t size) { + if (!update_function_ || !size) + return; + + // Read up to 4k bytes at a time + unsigned char buffer[4096]; + size_t buffer_size; + off_t file_offset = offset; + while (size > 0) { + if (size > sizeof(buffer)) { + buffer_size = sizeof(buffer); + size -= buffer_size; + } else { + buffer_size = size; + size = 0; + } + + if (!walker->ReadBytes(buffer, buffer_size, file_offset)) + return; + + (this->*update_function_)(buffer, buffer_size); + file_offset += buffer_size; + } +} + +bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) { + struct breakpad_uuid_command uuid_cmd; + MachoWalker walker(path_, UUIDWalkerCB, &uuid_cmd); + + uuid_cmd.cmd = 0; + if (!walker.WalkHeader(cpu_type)) + return false; + + // If we found the command, we'll have initialized the uuid_command + // structure + if (uuid_cmd.cmd == LC_UUID) { + memcpy(bytes, uuid_cmd.uuid, sizeof(uuid_cmd.uuid)); + return true; + } + + return false; +} + +bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) { + struct dylib_command dylib_cmd; + MachoWalker walker(path_, IDWalkerCB, &dylib_cmd); + + dylib_cmd.cmd = 0; + if (!walker.WalkHeader(cpu_type)) + return false; + + // If we found the command, we'll have initialized the dylib_command + // structure + if (dylib_cmd.cmd == LC_ID_DYLIB) { + // Take the hashed filename, version, and compatability version bytes + // to form the first 12 bytes, pad the rest with zeros + + // create a crude hash of the filename to generate the first 4 bytes + identifier[0] = 0; + identifier[1] = 0; + identifier[2] = 0; + identifier[3] = 0; + + for (int j = 0, i = strlen(path_)-1; i >= 0 && path_[i]!='/'; ++j, --i) { + identifier[j%4] += path_[i]; + } + + identifier[4] = (dylib_cmd.dylib.current_version >> 24) & 0xFF; + identifier[5] = (dylib_cmd.dylib.current_version >> 16) & 0xFF; + identifier[6] = (dylib_cmd.dylib.current_version >> 8) & 0xFF; + identifier[7] = dylib_cmd.dylib.current_version & 0xFF; + identifier[8] = (dylib_cmd.dylib.compatibility_version >> 24) & 0xFF; + identifier[9] = (dylib_cmd.dylib.compatibility_version >> 16) & 0xFF; + identifier[10] = (dylib_cmd.dylib.compatibility_version >> 8) & 0xFF; + identifier[11] = dylib_cmd.dylib.compatibility_version & 0xFF; + identifier[12] = (cpu_type >> 24) & 0xFF; + identifier[13] = (cpu_type >> 16) & 0xFF; + identifier[14] = (cpu_type >> 8) & 0xFF; + identifier[15] = cpu_type & 0xFF; + + return true; + } + + return false; +} + +uint32_t MachoID::Adler32(int cpu_type) { + MachoWalker walker(path_, WalkerCB, this); + update_function_ = &MachoID::UpdateCRC; + crc_ = 0; + + if (!walker.WalkHeader(cpu_type)) + return 0; + + return crc_; +} + +bool MachoID::MD5(int cpu_type, unsigned char identifier[16]) { + MachoWalker walker(path_, WalkerCB, this); + update_function_ = &MachoID::UpdateMD5; + + if (MD5_Init(&md5_context_)) { + if (!walker.WalkHeader(cpu_type)) + return false; + + MD5_Final(identifier, &md5_context_); + return true; + } + + return false; +} + +bool MachoID::SHA1(int cpu_type, unsigned char identifier[16]) { + MachoWalker walker(path_, WalkerCB, this); + update_function_ = &MachoID::UpdateSHA1; + + if (SHA_Init(&sha1_context_)) { + if (!walker.WalkHeader(cpu_type)) + return false; + + SHA_Final(identifier, &sha1_context_); + return true; + } + + return false; +} + +// static +bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context) { + MachoID *macho_id = (MachoID *)context; + + if (cmd->cmd == LC_SEGMENT) { + struct segment_command seg; + + if (!walker->ReadBytes(&seg, sizeof(seg), offset)) + return false; + + if (swap) + swap_segment_command(&seg, NXHostByteOrder()); + + struct mach_header_64 header; + off_t header_offset; + + if (!walker->CurrentHeader(&header, &header_offset)) + return false; + + // Process segments that have sections: + // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) + offset += sizeof(struct segment_command); + struct section sec; + for (unsigned long i = 0; i < seg.nsects; ++i) { + if (!walker->ReadBytes(&sec, sizeof(sec), offset)) + return false; + + if (swap) + swap_section(&sec, 1, NXHostByteOrder()); + + // sections of type S_ZEROFILL are "virtual" and contain no data + // in the file itself + if ((sec.flags & SECTION_TYPE) != S_ZEROFILL && sec.offset != 0) + macho_id->Update(walker, header_offset + sec.offset, sec.size); + + offset += sizeof(struct section); + } + } else if (cmd->cmd == LC_SEGMENT_64) { + struct segment_command_64 seg64; + + if (!walker->ReadBytes(&seg64, sizeof(seg64), offset)) + return false; + + if (swap) + breakpad_swap_segment_command_64(&seg64, NXHostByteOrder()); + + struct mach_header_64 header; + off_t header_offset; + + if (!walker->CurrentHeader(&header, &header_offset)) + return false; + + // Process segments that have sections: + // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) + offset += sizeof(struct segment_command_64); + struct section_64 sec64; + for (unsigned long i = 0; i < seg64.nsects; ++i) { + if (!walker->ReadBytes(&sec64, sizeof(sec64), offset)) + return false; + + if (swap) + breakpad_swap_section_64(&sec64, 1, NXHostByteOrder()); + + // sections of type S_ZEROFILL are "virtual" and contain no data + // in the file itself + if ((sec64.flags & SECTION_TYPE) != S_ZEROFILL && sec64.offset != 0) + macho_id->Update(walker, header_offset + sec64.offset, sec64.size); + + offset += sizeof(struct section_64); + } + } + + // Continue processing + return true; +} + +// static +bool MachoID::UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context) { + if (cmd->cmd == LC_UUID) { + struct breakpad_uuid_command *uuid_cmd = + (struct breakpad_uuid_command *)context; + + if (!walker->ReadBytes(uuid_cmd, sizeof(struct breakpad_uuid_command), + offset)) + return false; + + if (swap) + breakpad_swap_uuid_command(uuid_cmd, NXHostByteOrder()); + + return false; + } + + // Continue processing + return true; +} + +// static +bool MachoID::IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context) { + if (cmd->cmd == LC_ID_DYLIB) { + struct dylib_command *dylib_cmd = (struct dylib_command *)context; + + if (!walker->ReadBytes(dylib_cmd, sizeof(struct dylib_command), offset)) + return false; + + if (swap) + swap_dylib_command(dylib_cmd, NXHostByteOrder()); + + return false; + } + + // Continue processing + return true; +} + +} // namespace MacFileUtilities diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_id.h b/thirdparty/google-breakpad/r318/src/common/mac/macho_id.h new file mode 100644 index 00000000..039bba38 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_id.h @@ -0,0 +1,124 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_id.h: Functions to gather identifying information from a macho file +// +// Author: Dan Waylonis + +#ifndef COMMON_MAC_MACHO_ID_H__ +#define COMMON_MAC_MACHO_ID_H__ + +#include +#include +#include +#include + +namespace MacFileUtilities { + +class MachoWalker; + +class MachoID { + public: + MachoID(const char *path); + ~MachoID(); + + // For the given |cpu_type|, return a UUID from the LC_UUID command. + // Return false if there isn't a LC_UUID command. + bool UUIDCommand(int cpu_type, unsigned char identifier[16]); + + // For the given |cpu_type|, return a UUID from the LC_ID_DYLIB command. + // Return false if there isn't a LC_ID_DYLIB command. + bool IDCommand(int cpu_type, unsigned char identifier[16]); + + // For the given |cpu_type|, return the Adler32 CRC for the mach-o data + // segment(s). + // Return 0 on error (e.g., if the file is not a mach-o file) + uint32_t Adler32(int cpu_type); + + // For the given |cpu_type|, return the MD5 for the mach-o data segment(s). + // Return true on success, false otherwise + bool MD5(int cpu_type, unsigned char identifier[16]); + + // For the given |cpu_type|, return the SHA1 for the mach-o data segment(s). + // Return true on success, false otherwise + bool SHA1(int cpu_type, unsigned char identifier[16]); + + private: + // Signature of class member function to be called with data read from file + typedef void (MachoID::*UpdateFunction)(unsigned char *bytes, size_t size); + + // Update the CRC value by examining |size| |bytes| and applying the algorithm + // to each byte. + void UpdateCRC(unsigned char *bytes, size_t size); + + // Update the MD5 value by examining |size| |bytes| and applying the algorithm + // to each byte. + void UpdateMD5(unsigned char *bytes, size_t size); + + // Update the SHA1 value by examining |size| |bytes| and applying the + // algorithm to each byte. + void UpdateSHA1(unsigned char *bytes, size_t size); + + // Bottleneck for update routines + void Update(MachoWalker *walker, unsigned long offset, size_t size); + + // The callback from the MachoWalker for CRC, MD5, and SHA1 + static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context); + + // The callback from the MachoWalker for LC_UUID + static bool UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context); + + // The callback from the MachoWalker for LC_ID_DYLIB + static bool IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, + bool swap, void *context); + + // File path + char path_[PATH_MAX]; + + // File descriptor + int file_; + + // The current crc value + uint32_t crc_; + + // The MD5 context + MD5_CTX md5_context_; + + // The SHA1 context + SHA_CTX sha1_context_; + + // The current update to call from the Update callback + UpdateFunction update_function_; +}; + +} // namespace MacFileUtilities + +#endif // COMMON_MAC_MACHO_ID_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.cc b/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.cc new file mode 100644 index 00000000..d25de5c8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.cc @@ -0,0 +1,89 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_utilties.cc: Utilities for dealing with mach-o files +// +// Author: Dave Camp + +#include "common/mac/macho_utilities.h" + +void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc, + enum NXByteOrder target_byte_order) +{ + uc->cmd = NXSwapLong(uc->cmd); + uc->cmdsize = NXSwapLong(uc->cmdsize); +} + +void breakpad_swap_segment_command_64(struct segment_command_64 *sg, + enum NXByteOrder target_byte_order) +{ + sg->cmd = NXSwapLong(sg->cmd); + sg->cmdsize = NXSwapLong(sg->cmdsize); + + sg->vmaddr = NXSwapLongLong(sg->vmaddr); + sg->vmsize = NXSwapLongLong(sg->vmsize); + sg->fileoff = NXSwapLongLong(sg->fileoff); + sg->filesize = NXSwapLongLong(sg->filesize); + + sg->maxprot = NXSwapLong(sg->maxprot); + sg->initprot = NXSwapLong(sg->initprot); + sg->nsects = NXSwapLong(sg->nsects); + sg->flags = NXSwapLong(sg->flags); +} + +void breakpad_swap_mach_header_64(struct mach_header_64 *mh, + enum NXByteOrder target_byte_order) +{ + mh->magic = NXSwapLong(mh->magic); + mh->cputype = NXSwapLong(mh->cputype); + mh->cpusubtype = NXSwapLong(mh->cpusubtype); + mh->filetype = NXSwapLong(mh->filetype); + mh->ncmds = NXSwapLong(mh->ncmds); + mh->sizeofcmds = NXSwapLong(mh->sizeofcmds); + mh->flags = NXSwapLong(mh->flags); + mh->reserved = NXSwapLong(mh->reserved); +} + +void breakpad_swap_section_64(struct section_64 *s, + uint32_t nsects, + enum NXByteOrder target_byte_order) +{ + for (uint32_t i = 0; i < nsects; i++) { + s[i].addr = NXSwapLongLong(s[i].addr); + s[i].size = NXSwapLongLong(s[i].size); + + s[i].offset = NXSwapLong(s[i].offset); + s[i].align = NXSwapLong(s[i].align); + s[i].reloff = NXSwapLong(s[i].reloff); + s[i].nreloc = NXSwapLong(s[i].nreloc); + s[i].flags = NXSwapLong(s[i].flags); + s[i].reserved1 = NXSwapLong(s[i].reserved1); + s[i].reserved2 = NXSwapLong(s[i].reserved2); + } +} diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.h b/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.h new file mode 100644 index 00000000..f74e93aa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_utilities.h @@ -0,0 +1,90 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_utilities.h: Utilities for dealing with mach-o files +// +// Author: Dave Camp + +#ifndef COMMON_MAC_MACHO_UTILITIES_H__ +#define COMMON_MAC_MACHO_UTILITIES_H__ + +#include +#include + +/* Some #defines and structs that aren't defined in older SDKs */ +#ifndef CPU_ARCH_ABI64 +# define CPU_ARCH_ABI64 0x01000000 +#endif + +#ifndef CPU_TYPE_X86 +# define CPU_TYPE_X86 CPU_TYPE_I386 +#endif + +#ifndef CPU_TYPE_POWERPC64 +# define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) +#endif + +#ifndef LC_UUID +# define LC_UUID 0x1b /* the uuid */ +#endif + +#if TARGET_CPU_X86 +# define BREAKPAD_MACHINE_THREAD_STATE i386_THREAD_STATE +#else +# define BREAKPAD_MACHINE_THREAD_STATE MACHINE_THREAD_STATE +#endif + +// The uuid_command struct/swap routines were added during the 10.4 series. +// Their presence isn't guaranteed. +struct breakpad_uuid_command { + uint32_t cmd; /* LC_UUID */ + uint32_t cmdsize; /* sizeof(struct uuid_command) */ + uint8_t uuid[16]; /* the 128-bit uuid */ +}; + +void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc, + enum NXByteOrder target_byte_order); + +// Older SDKs defines thread_state_data_t as an int[] instead +// of the natural_t[] it should be. +typedef natural_t breakpad_thread_state_data_t[THREAD_STATE_MAX]; + +// The 64-bit swap routines were added during the 10.4 series, their +// presence isn't guaranteed. +void breakpad_swap_segment_command_64(struct segment_command_64 *sg, + enum NXByteOrder target_byte_order); + +void breakpad_swap_mach_header_64(struct mach_header_64 *mh, + enum NXByteOrder target_byte_order); + +void breakpad_swap_section_64(struct section_64 *s, + uint32_t nsects, + enum NXByteOrder target_byte_order); + +#endif diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.cc b/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.cc new file mode 100644 index 00000000..dd2c3b39 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.cc @@ -0,0 +1,243 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_walker.cc: Iterate over the load commands in a mach-o file +// +// See macho_walker.h for documentation +// +// Author: Dan Waylonis + +extern "C" { // necessary for Leopard + #include + #include + #include + #include + #include + #include + #include +} + +#include "common/mac/macho_walker.h" +#include "common/mac/macho_utilities.h" + +namespace MacFileUtilities { + +MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback, + void *context) + : callback_(callback), + callback_context_(context) { + file_ = open(path, O_RDONLY); +} + +MachoWalker::~MachoWalker() { + if (file_ != -1) + close(file_); +} + +int MachoWalker::ValidateCPUType(int cpu_type) { + // If the user didn't specify, try to use the local architecture. If that + // fails, use the base type for the executable. + if (cpu_type == 0) { + const NXArchInfo *arch = NXGetLocalArchInfo(); + if (arch) + cpu_type = arch->cputype; + else +#if __ppc__ + cpu_type = CPU_TYPE_POWERPC; +#elif __i386__ + cpu_type = CPU_TYPE_X86; +#else +#error Unknown architecture -- are you on a PDP-11? +#endif + } + + return cpu_type; +} + +bool MachoWalker::WalkHeader(int cpu_type) { + int valid_cpu_type = ValidateCPUType(cpu_type); + off_t offset; + if (FindHeader(valid_cpu_type, offset)) { + if (cpu_type & CPU_ARCH_ABI64) + return WalkHeader64AtOffset(offset); + + return WalkHeaderAtOffset(offset); + } + + return false; +} + +bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) { + return pread(file_, buffer, size, offset) == (ssize_t)size; +} + +bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) { + if (current_header_) { + memcpy(header, current_header_, sizeof(mach_header_64)); + *offset = current_header_offset_; + return true; + } + + return false; +} + +bool MachoWalker::FindHeader(int cpu_type, off_t &offset) { + int valid_cpu_type = ValidateCPUType(cpu_type); + // Read the magic bytes that's common amongst all mach-o files + uint32_t magic; + if (!ReadBytes(&magic, sizeof(magic), 0)) + return false; + + offset = sizeof(magic); + + // Figure out what type of file we've got + bool is_fat = false; + if (magic == FAT_MAGIC || magic == FAT_CIGAM) { + is_fat = true; + } + else if (magic != MH_MAGIC && magic != MH_CIGAM && magic != MH_MAGIC_64 && + magic != MH_CIGAM_64) { + return false; + } + + if (!is_fat) { + // If we don't have a fat header, check if the cpu type matches the single + // header + cpu_type_t header_cpu_type; + if (!ReadBytes(&header_cpu_type, sizeof(header_cpu_type), offset)) + return false; + + if (magic == MH_CIGAM || magic == MH_CIGAM_64) + header_cpu_type = NXSwapInt(header_cpu_type); + + if (valid_cpu_type != header_cpu_type) + return false; + + offset = 0; + return true; + } else { + // Read the fat header and find an appropriate architecture + offset = 0; + struct fat_header fat; + if (!ReadBytes(&fat, sizeof(fat), offset)) + return false; + + if (NXHostByteOrder() != NX_BigEndian) + swap_fat_header(&fat, NXHostByteOrder()); + + offset += sizeof(fat); + + // Search each architecture for the desired one + struct fat_arch arch; + for (uint32_t i = 0; i < fat.nfat_arch; ++i) { + if (!ReadBytes(&arch, sizeof(arch), offset)) + return false; + + if (NXHostByteOrder() != NX_BigEndian) + swap_fat_arch(&arch, 1, NXHostByteOrder()); + + if (arch.cputype == valid_cpu_type) { + offset = arch.offset; + return true; + } + + offset += sizeof(arch); + } + } + + return false; +} + +bool MachoWalker::WalkHeaderAtOffset(off_t offset) { + struct mach_header header; + if (!ReadBytes(&header, sizeof(header), offset)) + return false; + + bool swap = (header.magic == MH_CIGAM); + if (swap) + swap_mach_header(&header, NXHostByteOrder()); + + // Copy the data into the mach_header_64 structure. Since the 32-bit and + // 64-bit only differ in the last field (reserved), this is safe to do. + struct mach_header_64 header64; + memcpy((void *)&header64, (const void *)&header, sizeof(header)); + header64.reserved = 0; + + current_header_ = &header64; + current_header_size_ = sizeof(header); // 32-bit, not 64-bit + current_header_offset_ = offset; + offset += current_header_size_; + bool result = WalkHeaderCore(offset, header.ncmds, swap); + current_header_ = NULL; + current_header_size_ = 0; + current_header_offset_ = 0; + return result; +} + +bool MachoWalker::WalkHeader64AtOffset(off_t offset) { + struct mach_header_64 header; + if (!ReadBytes(&header, sizeof(header), offset)) + return false; + + bool swap = (header.magic == MH_CIGAM_64); + if (swap) + breakpad_swap_mach_header_64(&header, NXHostByteOrder()); + + current_header_ = &header; + current_header_size_ = sizeof(header); + current_header_offset_ = offset; + offset += current_header_size_; + bool result = WalkHeaderCore(offset, header.ncmds, swap); + current_header_ = NULL; + current_header_size_ = 0; + current_header_offset_ = 0; + return result; +} + +bool MachoWalker::WalkHeaderCore(off_t offset, uint32_t number_of_commands, + bool swap) { + for (uint32_t i = 0; i < number_of_commands; ++i) { + struct load_command cmd; + if (!ReadBytes(&cmd, sizeof(cmd), offset)) + return false; + + if (swap) + swap_load_command(&cmd, NXHostByteOrder()); + + // Call the user callback + if (callback_ && !callback_(this, &cmd, offset, swap, callback_context_)) + break; + + offset += cmd.cmdsize; + } + + return true; +} + +} // namespace MacFileUtilities diff --git a/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.h b/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.h new file mode 100644 index 00000000..6445a4f4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/macho_walker.h @@ -0,0 +1,106 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// macho_walker.h: Iterate over the load commands in a mach-o file +// +// Author: Dan Waylonis + +#ifndef COMMON_MAC_MACHO_WALKER_H__ +#define COMMON_MAC_MACHO_WALKER_H__ + +#include +#include + +namespace MacFileUtilities { + +class MachoWalker { + public: + // A callback function executed when a new load command is read. If no + // further processing of load commands is desired, return false. Otherwise, + // return true. + // |cmd| is the current command, and |offset| is the location relative to the + // beginning of the file (not header) where the command was read. If |swap| + // is set, then any command data (other than the returned load_command) should + // be swapped when read + typedef bool (*LoadCommandCallback)(MachoWalker *walker, load_command *cmd, + off_t offset, bool swap, void *context); + + MachoWalker(const char *path, LoadCommandCallback callback, void *context); + MachoWalker(int file_descriptor, LoadCommandCallback callback, void *context); + ~MachoWalker(); + + // Begin walking the header for |cpu_type|. If |cpu_type| is 0, then the + // native cpu type is used. Otherwise, accepted values are listed in + // /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or CPU_TYPE_POWERPC). + // Returns false if opening the file failed or if the |cpu_type| is not + // present in the file. + bool WalkHeader(int cpu_type); + + // Locate (if any) the header offset for |cpu_type| and return in |offset|. + // Return true if found, false otherwise. + bool FindHeader(int cpu_type, off_t &offset); + + // Read |size| bytes from the opened file at |offset| into |buffer| + bool ReadBytes(void *buffer, size_t size, off_t offset); + + // Return the current header and header offset + bool CurrentHeader(struct mach_header_64 *header, off_t *offset); + + private: + // Validate the |cpu_type| + int ValidateCPUType(int cpu_type); + + // Process an individual header starting at |offset| from the start of the + // file. Return true if successful, false otherwise. + bool WalkHeaderAtOffset(off_t offset); + bool WalkHeader64AtOffset(off_t offset); + + // Bottleneck for walking the load commands + bool WalkHeaderCore(off_t offset, uint32_t number_of_commands, bool swap); + + // File descriptor to the opened file + int file_; + + // User specified callback & context + LoadCommandCallback callback_; + void *callback_context_; + + // Current header, size, and offset. The mach_header_64 is used for both + // 32-bit and 64-bit headers because they only differ in their last field + // (reserved). By adding the |current_header_size_| and the + // |current_header_offset_|, you can determine the offset in the file just + // after the header. + struct mach_header_64 *current_header_; + unsigned long current_header_size_; + off_t current_header_offset_; +}; + +} // namespace MacFileUtilities + +#endif // COMMON_MAC_MACHO_WALKER_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.cc b/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.cc new file mode 100644 index 00000000..bdf3336c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "processor/scoped_ptr.h" +#include "common/mac/string_utilities.h" + +namespace MacStringUtils { + +using google_breakpad::scoped_array; + +std::string ConvertToString(CFStringRef str) { + CFIndex length = CFStringGetLength(str); + std::string result; + + if (!length) + return result; + + CFIndex maxUTF8Length = + CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + scoped_array buffer(new UInt8[maxUTF8Length + 1]); + CFIndex actualUTF8Length; + CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingUTF8, 0, + false, buffer.get(), maxUTF8Length, &actualUTF8Length); + buffer[actualUTF8Length] = 0; + result.assign((const char *)buffer.get()); + + return result; +} + +unsigned int IntegerValueAtIndex(string &str, unsigned int idx) { + string digits("0123456789"), temp; + unsigned int start = 0; + unsigned int end; + unsigned int found = 0; + unsigned int result = 0; + + for (; found <= idx; ++found) { + end = str.find_first_not_of(digits, start); + + if (end == string::npos) + end = str.size(); + + temp = str.substr(start, end - start); + + if (found == idx) { + result = atoi(temp.c_str()); + } + + start = str.find_first_of(digits, end + 1); + + if (start == string::npos) + break; + } + + return result; +} + +} // namespace MacStringUtils diff --git a/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.h b/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.h new file mode 100644 index 00000000..6d89c834 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/mac/string_utilities.h @@ -0,0 +1,52 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// string_utilities.h: Utilities for strings for Mac platform + +#ifndef COMMON_MAC_STRING_UTILITIES_H__ +#define COMMON_MAC_STRING_UTILITIES_H__ + +#include + +#include + +namespace MacStringUtils { + +using std::string; + +// Convert a CoreFoundation string into a std::string +string ConvertToString(CFStringRef str); + +// Return the idx'th decimal integer in str, separated by non-decimal-digits +// E.g., str = 10.4.8, idx = 1 -> 4 +unsigned int IntegerValueAtIndex(string &str, unsigned int idx); + +} // namespace MacStringUtils + +#endif // COMMON_MAC_STRING_UTILITIES_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/md5.c b/thirdparty/google-breakpad/r318/src/common/md5.c new file mode 100644 index 00000000..7fc198af --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/md5.c @@ -0,0 +1,246 @@ +/* + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include + +#include "common/md5.h" + +#ifndef WORDS_BIGENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + u32 t; + do { + t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(u32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +static void MD5Transform(u32 buf[4], u32 const in[16]); + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + u32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((u32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((u32 *) ctx->in)[14] = ctx->bits[0]; + ((u32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (u32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(u32 buf[4], u32 const in[16]) +{ + register u32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/thirdparty/google-breakpad/r318/src/common/md5.h b/thirdparty/google-breakpad/r318/src/common/md5.h new file mode 100644 index 00000000..dbf4893c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/md5.h @@ -0,0 +1,31 @@ +// Copyright 2007 Google Inc. All Rights Reserved. +// Author: liuli@google.com (Liu Li) +#ifndef COMMON_MD5_H__ +#define COMMON_MD5_H__ + +#include + +typedef uint32_t u32; +typedef uint8_t u8; + +struct MD5Context { + u32 buf[4]; + u32 bits[2]; + u8 in[64]; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void MD5Init(struct MD5Context *ctx); + +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len); + +void MD5Final(unsigned char digest[16], struct MD5Context *ctx); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_MD5_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.cc b/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.cc new file mode 100644 index 00000000..816d744c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.cc @@ -0,0 +1,681 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/solaris/dump_symbols.h" +#include "common/solaris/file_id.h" +#include "common/solaris/guid_creator.h" +#include "processor/scoped_ptr.h" + +// This namespace contains helper functions. +namespace { + +using std::make_pair; + +#if defined(_LP64) +typedef Elf64_Sym Elf_Sym; +#else +typedef Elf32_Sym Elf_Sym; +#endif + +// Symbol table entry from stabs. Sun CC specific. +struct slist { + // String table index. + unsigned int n_strx; + // Stab type. + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; + +// Symbol table entry +struct SymbolEntry { + // Offset from the start of the file. + GElf_Addr offset; + // Function size. + GElf_Word size; +}; + +// Infomation of a line. +struct LineInfo { + // Offset from start of the function. + // Load from stab symbol. + GElf_Off rva_to_func; + // Offset from base of the loading binary. + GElf_Off rva_to_base; + // Size of the line. + // The first line: equals to rva_to_func. + // The other lines: the difference of rva_to_func of the line and + // rva_to_func of the previous N_SLINE. + uint32_t size; + // Line number. + uint32_t line_num; +}; + +// Information of a function. +struct FuncInfo { + // Name of the function. + const char *name; + // Offset from the base of the loading address. + GElf_Off rva_to_base; + // Virtual address of the function. + // Load from stab symbol. + GElf_Addr addr; + // Size of the function. + // Equal to rva_to_func of the last function line. + uint32_t size; + // Total size of stack parameters. + uint32_t stack_param_size; + // Line information array. + std::vector line_info; +}; + +// Information of a source file. +struct SourceFileInfo { + // Name of the source file. + const char *name; + // Starting address of the source file. + GElf_Addr addr; + // Id of the source file. + int source_id; + // Functions information. + std::vector func_info; +}; + +struct CompareString { + bool operator()(const char *s1, const char *s2) const { + return strcmp(s1, s2) < 0; + } +}; + +typedef std::map SymbolMap; + +// Information of a symbol table. +// This is the root of all types of symbol. +struct SymbolInfo { + std::vector source_file_info; + // Symbols information. + SymbolMap symbol_entries; +}; + +// Stab section name. +const char *kStabName = ".stab"; + +// Stab str section name. +const char *kStabStrName = ".stabstr"; + +// Symtab section name. +const char *kSymtabName = ".symtab"; + +// Strtab section name. +const char *kStrtabName = ".strtab"; + +// Default buffer lenght for demangle. +const int demangleLen = 20000; + +// Offset to the string table. +u_int64_t stringOffset = 0; + +// Update the offset to the start of the string index of the next +// object module for every N_ENDM stabs. +inline void RecalculateOffset(struct slist* cur_list, char *stabstr) { + while ((--cur_list)->n_strx == 0) ; + stringOffset += cur_list->n_strx; + + char *temp = stabstr + stringOffset; + while (*temp != '\0') { + ++stringOffset; + ++temp; + } + // Skip the extra '\0' + ++stringOffset; +} + +// Demangle using demangle library on Solaris. +std::string Demangle(const char *mangled) { + int status = 0; + std::string str(mangled); + char *demangled = (char *)malloc(demangleLen); + + if (!demangled) { + fprintf(stderr, "no enough memory.\n"); + goto out; + } + + if ((status = cplus_demangle(mangled, demangled, demangleLen)) == + DEMANGLE_ESPACE) { + fprintf(stderr, "incorrect demangle.\n"); + goto out; + } + + str = demangled; + free(demangled); + +out: + return str; +} + +bool WriteFormat(int fd, const char *fmt, ...) { + va_list list; + char buffer[4096]; + ssize_t expected, written; + va_start(list, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, list); + expected = strlen(buffer); + written = write(fd, buffer, strlen(buffer)); + va_end(list); + return expected == written; +} + +bool IsValidElf(const GElf_Ehdr *elf_header) { + return memcmp(elf_header, ELFMAG, SELFMAG) == 0; +} + +static bool FindSectionByName(Elf *elf, const char *name, + int shstrndx, + GElf_Shdr *shdr) { + assert(name != NULL); + + if (strlen(name) == 0) + return false; + + Elf_Scn *scn = NULL; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, shdr) == (GElf_Shdr *)0) { + fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0)); + return false; + } + + const char *section_name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (!section_name) { + fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1)); + continue; + } + + if (strcmp(section_name, name) == 0) + return true; + } + + return false; +} + +// The parameter size is used for FPO-optimized code, and +// this is all tied up with the debugging data for Windows x86. +// Set it to 0 on Solaris. +int LoadStackParamSize(struct slist *list, + struct slist *list_end, + struct FuncInfo *func_info) { + struct slist *cur_list = list; + int step = 1; + while (cur_list < list_end && cur_list->n_type == N_PSYM) { + ++cur_list; + ++step; + } + + func_info->stack_param_size = 0; + return step; +} + +int LoadLineInfo(struct slist *list, + struct slist *list_end, + struct FuncInfo *func_info) { + struct slist *cur_list = list; + do { + // Skip non line information. + while (cur_list < list_end && cur_list->n_type != N_SLINE) { + // Only exit when got another function, or source file, or end stab. + if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO || + cur_list->n_type == N_ENDM) { + return cur_list - list; + } + ++cur_list; + } + struct LineInfo line; + while (cur_list < list_end && cur_list->n_type == N_SLINE) { + line.rva_to_func = cur_list->n_value; + // n_desc is a signed short + line.line_num = (unsigned short)cur_list->n_desc; + func_info->line_info.push_back(line); + ++cur_list; + } + if (cur_list == list_end && cur_list->n_type == N_ENDM) + break; + } while (list < list_end); + + return cur_list - list; +} + +int LoadFuncSymbols(struct slist *list, + struct slist *list_end, + char *stabstr, + GElf_Word base, + struct SourceFileInfo *source_file_info) { + struct slist *cur_list = list; + assert(cur_list->n_type == N_SO); + ++cur_list; + + source_file_info->func_info.clear(); + while (cur_list < list_end) { + // Go until the function symbol. + while (cur_list < list_end && cur_list->n_type != N_FUN) { + if (cur_list->n_type == N_SO) { + return cur_list - list; + } + ++cur_list; + if (cur_list->n_type == N_ENDM) + RecalculateOffset(cur_list, stabstr); + continue; + } + while (cur_list->n_type == N_FUN) { + struct FuncInfo func_info; + memset(&func_info, 0, sizeof(func_info)); + func_info.name = stabstr + cur_list->n_strx + stringOffset; + // The n_value field is always 0 from stab generated by Sun CC. + // TODO(Alfred): Find the correct value. + func_info.addr = cur_list->n_value; + ++cur_list; + if (cur_list->n_type == N_ENDM) + RecalculateOffset(cur_list, stabstr); + if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM && + cur_list->n_type != N_FUN) { + // Stack parameter size. + cur_list += LoadStackParamSize(cur_list, list_end, &func_info); + // Line info. + cur_list += LoadLineInfo(cur_list, list_end, &func_info); + } + if (cur_list < list_end && cur_list->n_type == N_ENDM) + RecalculateOffset(cur_list, stabstr); + // Functions in this module should have address bigger than the module + // starting address. + // + // These two values are always 0 with Sun CC. + // TODO(Alfred): Get the correct value or remove the condition statement. + if (func_info.addr >= source_file_info->addr) { + source_file_info->func_info.push_back(func_info); + } + } + } + return cur_list - list; +} + +// Compute size and rva information based on symbols loaded from stab section. +bool ComputeSizeAndRVA(struct SymbolInfo *symbols) { + std::vector *sorted_files = + &(symbols->source_file_info); + SymbolMap *symbol_entries = &(symbols->symbol_entries); + for (size_t i = 0; i < sorted_files->size(); ++i) { + struct SourceFileInfo &source_file = (*sorted_files)[i]; + std::vector *sorted_functions = &(source_file.func_info); + int func_size = sorted_functions->size(); + + for (size_t j = 0; j < func_size; ++j) { + struct FuncInfo &func_info = (*sorted_functions)[j]; + int line_count = func_info.line_info.size(); + + // Discard the ending part of the name. + std::string func_name(func_info.name); + std::string::size_type last_colon = func_name.find_first_of(':'); + if (last_colon != std::string::npos) + func_name = func_name.substr(0, last_colon); + + // Fine the symbol offset from the loading address and size by name. + SymbolMap::const_iterator it = symbol_entries->find(func_name.c_str()); + if (it->second) { + func_info.rva_to_base = it->second->offset; + func_info.size = (line_count == 0) ? 0 : it->second->size; + } else { + func_info.rva_to_base = 0; + func_info.size = 0; + } + + // Compute function and line size. + for (size_t k = 0; k < line_count; ++k) { + struct LineInfo &line_info = func_info.line_info[k]; + + line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base; + if (k == line_count - 1) { + line_info.size = func_info.size - line_info.rva_to_func; + } else { + struct LineInfo &next_line = func_info.line_info[k + 1]; + line_info.size = next_line.rva_to_func - line_info.rva_to_func; + } + } // for each line. + } // for each function. + } // for each source file. + for (SymbolMap::iterator it = symbol_entries->begin(); + it != symbol_entries->end(); ++it) { + free(it->second); + } + return true; +} + +bool LoadAllSymbols(const GElf_Shdr *stab_section, + const GElf_Shdr *stabstr_section, + GElf_Word base, + struct SymbolInfo *symbols) { + if (stab_section == NULL || stabstr_section == NULL) + return false; + + char *stabstr = + reinterpret_cast(stabstr_section->sh_offset + base); + struct slist *lists = + reinterpret_cast(stab_section->sh_offset + base); + int nstab = stab_section->sh_size / sizeof(struct slist); + int source_id = 0; + + // First pass, load all symbols from the object file. + for (int i = 0; i < nstab; ) { + int step = 1; + struct slist *cur_list = lists + i; + if (cur_list->n_type == N_SO) { + // FUNC
+ struct SourceFileInfo source_file_info; + source_file_info.name = stabstr + cur_list->n_strx + stringOffset; + // The n_value field is always 0 from stab generated by Sun CC. + // TODO(Alfred): Find the correct value. + source_file_info.addr = cur_list->n_value; + if (strchr(source_file_info.name, '.')) + source_file_info.source_id = source_id++; + else + source_file_info.source_id = -1; + step = LoadFuncSymbols(cur_list, lists + nstab - 1, stabstr, + base, &source_file_info); + symbols->source_file_info.push_back(source_file_info); + } + i += step; + } + // Second pass, compute the size of functions and lines. + return ComputeSizeAndRVA(symbols); +} + +bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols, + void *obj_base) { + GElf_Word base = reinterpret_cast(obj_base); + + const GElf_Shdr *sections = + reinterpret_cast(elf_header->e_shoff + base); + GElf_Shdr stab_section; + if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx, + &stab_section)) { + fprintf(stderr, "Stab section not found.\n"); + return false; + } + GElf_Shdr stabstr_section; + if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx, + &stabstr_section)) { + fprintf(stderr, "Stabstr section not found.\n"); + return false; + } + GElf_Shdr symtab_section; + if (!FindSectionByName(elf, kSymtabName, elf_header->e_shstrndx, + &symtab_section)) { + fprintf(stderr, "Symtab section not found.\n"); + return false; + } + GElf_Shdr strtab_section; + if (!FindSectionByName(elf, kStrtabName, elf_header->e_shstrndx, + &strtab_section)) { + fprintf(stderr, "Strtab section not found.\n"); + return false; + } + + Elf_Sym *symbol = (Elf_Sym *)((char *)base + symtab_section.sh_offset); + for (int i = 0; i < symtab_section.sh_size/symtab_section.sh_entsize; ++i) { + struct SymbolEntry *symbol_entry = + (struct SymbolEntry *)malloc(sizeof(struct SymbolEntry)); + const char *name = reinterpret_cast( + strtab_section.sh_offset + (GElf_Word)base + symbol->st_name); + symbol_entry->offset = symbol->st_value; + symbol_entry->size = symbol->st_size; + symbols->symbol_entries.insert(make_pair(name, symbol_entry)); + ++symbol; + } + + + // Load symbols. + return LoadAllSymbols(&stab_section, &stabstr_section, base, symbols); +} + +bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) { + const char *arch_name = NULL; + if (arch == EM_386) + arch_name = "x86"; + else if (arch == EM_X86_64) + arch_name = "x86_64"; + else if (arch == EM_SPARC32PLUS) + arch_name = "SPARC_32+"; + else { + printf("Please add more ARCH support\n"); + return false; + } + + unsigned char identifier[16]; + google_breakpad::FileID file_id(obj_file.c_str()); + if (file_id.ElfFileIdentifier(identifier)) { + char identifier_str[40]; + file_id.ConvertIdentifierToString(identifier, + identifier_str, sizeof(identifier_str)); + std::string filename = obj_file; + size_t slash_pos = obj_file.find_last_of("/"); + if (slash_pos != std::string::npos) + filename = obj_file.substr(slash_pos + 1); + return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name, + identifier_str, filename.c_str()); + } + return false; +} + +bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) { + for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { + if (symbols.source_file_info[i].source_id != -1) { + const char *name = symbols.source_file_info[i].name; + if (!WriteFormat(fd, "FILE %d %s\n", + symbols.source_file_info[i].source_id, name)) + return false; + } + } + return true; +} + +bool WriteOneFunction(int fd, int source_id, + const struct FuncInfo &func_info){ + // Discard the ending part of the name. + std::string func_name(func_info.name); + std::string::size_type last_colon = func_name.find_last_of(':'); + if (last_colon != std::string::npos) + func_name = func_name.substr(0, last_colon); + func_name = Demangle(func_name.c_str()); + + if (func_info.size <= 0) + return true; + + // rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit). + if (WriteFormat(fd, "FUNC %llx %x %d %s\n", + (long long)func_info.rva_to_base, + func_info.size, + func_info.stack_param_size, + func_name.c_str())) { + for (size_t i = 0; i < func_info.line_info.size(); ++i) { + const struct LineInfo &line_info = func_info.line_info[i]; + if (line_info.line_num == 0) + return true; + if (!WriteFormat(fd, "%llx %x %d %d\n", + (long long)line_info.rva_to_base, + line_info.size, + line_info.line_num, + source_id)) + return false; + } + return true; + } + return false; +} + +bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) { + for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { + const struct SourceFileInfo &file_info = symbols.source_file_info[i]; + for (size_t j = 0; j < file_info.func_info.size(); ++j) { + const struct FuncInfo &func_info = file_info.func_info[j]; + if (!WriteOneFunction(fd, file_info.source_id, func_info)) + return false; + } + } + return true; +} + +bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) { + return WriteSourceFileInfo(fd, symbols) && + WriteFunctionInfo(fd, symbols); +} + +// +// FDWrapper +// +// Wrapper class to make sure opened file is closed. +// +class FDWrapper { + public: + explicit FDWrapper(int fd) : + fd_(fd) { + } + ~FDWrapper() { + if (fd_ != -1) + close(fd_); + } + int get() { + return fd_; + } + int release() { + int fd = fd_; + fd_ = -1; + return fd; + } + private: + int fd_; +}; + +// +// MmapWrapper +// +// Wrapper class to make sure mapped regions are unmapped. +// +class MmapWrapper { + public: + MmapWrapper(void *mapped_address, size_t mapped_size) : + base_(mapped_address), size_(mapped_size) { + } + ~MmapWrapper() { + if (base_ != NULL) { + assert(size_ > 0); + munmap((char *)base_, size_); + } + } + void release() { + base_ = NULL; + size_ = 0; + } + + private: + void *base_; + size_t size_; +}; + +} // namespace + +namespace google_breakpad { + +class AutoElfEnder { + public: + AutoElfEnder(Elf *elf) : elf_(elf) {} + ~AutoElfEnder() { if (elf_) elf_end(elf_); } + private: + Elf *elf_; +}; + + +bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, int sym_fd) { + if (elf_version(EV_CURRENT) == EV_NONE) { + fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0)); + return false; + } + + int obj_fd = open(obj_file.c_str(), O_RDONLY); + if (obj_fd < 0) + return false; + FDWrapper obj_fd_wrapper(obj_fd); + struct stat st; + if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) + return false; + void *obj_base = mmap(NULL, st.st_size, + PROT_READ, MAP_PRIVATE, obj_fd, 0); + if (obj_base == MAP_FAILED)) + return false; + MmapWrapper map_wrapper(obj_base, st.st_size); + GElf_Ehdr elf_header; + Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL); + AutoElfEnder elfEnder(elf); + + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) { + fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1)); + return false; + } + + if (!IsValidElf(&elf_header)) { + fprintf(stderr, "header magic doesn't match\n"); + return false; + } + struct SymbolInfo symbols; + if (!LoadSymbols(elf, &elf_header, &symbols, obj_base)) + return false; + // Write to symbol file. + if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) && + DumpStabSymbols(sym_fd, symbols)) + return true; + + return false; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.h b/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.h new file mode 100644 index 00000000..7f4baadc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/dump_symbols.h @@ -0,0 +1,49 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// dump_symbols.cc: Implements a Solaris stab debugging format dumper. +// +// Author: Alfred Peng + +#ifndef COMMON_SOLARIS_DUMP_SYMBOLS_H__ +#define COMMON_SOLARIS_DUMP_SYMBOLS_H__ + +#include + +namespace google_breakpad { + +class DumpSymbols { + public: + bool WriteSymbolFile(const std::string &obj_file, + int sym_fd); +}; + +} // namespace google_breakpad + +#endif // COMMON_SOLARIS_DUMP_SYMBOLS_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/file_id.cc b/thirdparty/google-breakpad/r318/src/common/solaris/file_id.cc new file mode 100644 index 00000000..643a1462 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/file_id.cc @@ -0,0 +1,197 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// file_id.cc: Return a unique identifier for a file +// +// See file_id.h for documentation +// +// Author: Alfred Peng + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/md5.h" +#include "common/solaris/file_id.h" +#include "common/solaris/message_output.h" +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +class AutoElfEnder { + public: + AutoElfEnder(Elf *elf) : elf_(elf) {} + ~AutoElfEnder() { if (elf_) elf_end(elf_); } + private: + Elf *elf_; +}; + +// Find the text section in elf object file. +// Return the section start address and the size. +static bool FindElfTextSection(int fd, const void *elf_base, + const void **text_start, + int *text_size) { + assert(text_start); + assert(text_size); + + *text_start = NULL; + *text_size = 0; + + if (elf_version(EV_CURRENT) == EV_NONE) { + print_message2(2, "elf_version() failed: %s\n", elf_errmsg(0)); + return false; + } + + GElf_Ehdr elf_header; + lseek(fd, 0L, 0); + Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + AutoElfEnder elfEnder(elf); + + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) { + print_message2(2, "failed to read elf header: %s\n", elf_errmsg(-1)); + return false; + } + + if (elf_header.e_ident[EI_MAG0] != ELFMAG0 || + elf_header.e_ident[EI_MAG1] != ELFMAG1 || + elf_header.e_ident[EI_MAG2] != ELFMAG2 || + elf_header.e_ident[EI_MAG3] != ELFMAG3) { + print_message1(2, "header magic doesn't match\n"); + return false; + } + + static const char kTextSectionName[] = ".text"; + const GElf_Shdr *text_section = NULL; + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == (GElf_Shdr *)0) { + print_message2(2, "failed to read section header: %s\n", elf_errmsg(0)); + return false; + } + + if (shdr.sh_type == SHT_PROGBITS) { + const char *section_name = elf_strptr(elf, elf_header.e_shstrndx, + shdr.sh_name); + if (!section_name) { + print_message2(2, "Section name error: %s\n", elf_errmsg(-1)); + continue; + } + + if (strcmp(section_name, kTextSectionName) == 0) { + text_section = &shdr; + break; + } + } + } + if (text_section != NULL && text_section->sh_size > 0) { + *text_start = (char *)elf_base + text_section->sh_offset; + *text_size = text_section->sh_size; + return true; + } + + return false; +} + +FileID::FileID(const char *path) { + strcpy(path_, path); +} + +class AutoCloser { + public: + AutoCloser(int fd) : fd_(fd) {} + ~AutoCloser() { if (fd_) close(fd_); } + private: + int fd_; +}; + +bool FileID::ElfFileIdentifier(unsigned char identifier[16]) { + int fd = 0; + if ((fd = open(path_, O_RDONLY)) < 0) + return false; + + AutoCloser autocloser(fd); + struct stat st; + if (fstat(fd, &st) != 0 || st.st_size <= 0) + return false; + + void *base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (base == MAP_FAILED) + return false; + + bool success = false; + const void *text_section = NULL; + int text_size = 0; + + if (FindElfTextSection(fd, base, &text_section, &text_size)) { + MD5Context md5; + MD5Init(&md5); + MD5Update(&md5, (const unsigned char *)text_section, text_size); + MD5Final(identifier, &md5); + success = true; + } + + munmap((char *)base, st.st_size); + return success; +} + +// static +bool FileID::ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length) { + if (buffer_length < 34) + return false; + + int buffer_idx = 0; + for (int idx = 0; idx < 16; ++idx) { + int hi = (identifier[idx] >> 4) & 0x0F; + int lo = (identifier[idx]) & 0x0F; + + buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; + buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; + } + + // Add an extra "0" by the end. + buffer[buffer_idx++] = '0'; + + // NULL terminate + buffer[buffer_idx] = 0; + + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/file_id.h b/thirdparty/google-breakpad/r318/src/common/solaris/file_id.h new file mode 100644 index 00000000..375e8575 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/file_id.h @@ -0,0 +1,66 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// file_id.h: Return a unique identifier for a file +// +// Author: Alfred Peng + +#ifndef COMMON_SOLARIS_FILE_ID_H__ +#define COMMON_SOLARIS_FILE_ID_H__ + +#include + +namespace google_breakpad { + +class FileID { + public: + FileID(const char *path); + ~FileID() {}; + + // Load the identifier for the elf file path specified in the constructor into + // |identifier|. Return false if the identifier could not be created for the + // file. + // The current implementation will return the MD5 hash of the file's bytes. + bool ElfFileIdentifier(unsigned char identifier[16]); + + // Convert the |identifier| data to a NULL terminated string. The string will + // be formatted as a MDCVInfoPDB70 struct. + // The |buffer| should be at least 34 bytes long to receive all of the data + // and termination. Shorter buffers will return false. + static bool ConvertIdentifierToString(const unsigned char identifier[16], + char *buffer, int buffer_length); + + private: + // Storage for the path specified + char path_[PATH_MAX]; +}; + +} // namespace google_breakpad + +#endif // COMMON_SOLARIS_FILE_ID_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.cc b/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.cc new file mode 100644 index 00000000..70940259 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include + +#include +#include +#include + +#include "common/solaris/guid_creator.h" + +// +// GUIDGenerator +// +// This class is used to generate random GUID. +// Currently use random number to generate a GUID. This should be OK since +// we don't expect crash to happen very offen. +// +class GUIDGenerator { + public: + GUIDGenerator() { + srandom(time(NULL)); + } + + bool CreateGUID(GUID *guid) const { + guid->data1 = random(); + guid->data2 = (u_int16_t)(random()); + guid->data3 = (u_int16_t)(random()); + *reinterpret_cast(&guid->data4[0]) = random(); + *reinterpret_cast(&guid->data4[4]) = random(); + return true; + } +}; + +// Guid generator. +const GUIDGenerator kGuidGenerator; + +bool CreateGUID(GUID *guid) { + return kGuidGenerator.CreateGUID(guid); +}; + +// Parse guid to string. +bool GUIDToString(const GUID *guid, char *buf, int buf_len) { + // Should allow more space the the max length of GUID. + assert(buf_len > kGUIDStringLength); + int num = snprintf(buf, buf_len, kGUIDFormatString, + guid->data1, guid->data2, guid->data3, + *reinterpret_cast(&(guid->data4[0])), + *reinterpret_cast(&(guid->data4[4]))); + if (num != kGUIDStringLength) + return false; + + buf[num] = '\0'; + return true; +} diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.h b/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.h new file mode 100644 index 00000000..4aee3a1c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/guid_creator.h @@ -0,0 +1,50 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#ifndef COMMON_SOLARIS_GUID_CREATOR_H__ +#define COMMON_SOLARIS_GUID_CREATOR_H__ + +#include "google_breakpad/common/minidump_format.h" + +typedef MDGUID GUID; + +// Format string for parsing GUID. +#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x" +// Length of GUID string. Don't count the ending '\0'. +#define kGUIDStringLength 36 + +// Create a guid. +bool CreateGUID(GUID *guid); + +// Get the string from guid. +bool GUIDToString(const GUID *guid, char *buf, int buf_len); + +#endif // COMMON_SOLARIS_GUID_CREATOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/solaris/message_output.h b/thirdparty/google-breakpad/r318/src/common/solaris/message_output.h new file mode 100644 index 00000000..3e3b1d46 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/solaris/message_output.h @@ -0,0 +1,54 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#ifndef COMMON_SOLARIS_MESSAGE_OUTPUT_H__ +#define COMMON_SOLARIS_MESSAGE_OUTPUT_H__ + +namespace google_breakpad { + +const int MESSAGE_MAX = 1000; + +// Message output macros. +// snprintf doesn't operate heap on Solaris, while printf and fprintf do. +// Use snprintf here to avoid heap allocation. +#define print_message1(std, message) \ + char buffer[MESSAGE_MAX]; \ + int len = snprintf(buffer, MESSAGE_MAX, message); \ + write(std, buffer, len) + +#define print_message2(std, message, para) \ + char buffer[MESSAGE_MAX]; \ + int len = snprintf(buffer, MESSAGE_MAX, message, para); \ + write(std, buffer, len); + +} // namespace google_breakpad + +#endif // COMMON_SOLARIS_MESSAGE_OUTPUT_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/string_conversion.cc b/thirdparty/google-breakpad/r318/src/common/string_conversion.cc new file mode 100644 index 00000000..50054ebc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/string_conversion.cc @@ -0,0 +1,155 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "common/convert_UTF.h" +#include "processor/scoped_ptr.h" +#include "common/string_conversion.h" +#include + +namespace google_breakpad { + +using std::string; +using std::vector; + +void UTF8ToUTF16(const char *in, vector *out) { + size_t source_length = strlen(in); + const UTF8 *source_ptr = reinterpret_cast(in); + const UTF8 *source_end_ptr = source_ptr + source_length; + // Erase the contents and zero fill to the expected size + out->empty(); + out->insert(out->begin(), source_length, 0); + u_int16_t *target_ptr = &(*out)[0]; + u_int16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(u_int16_t); + ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr, + &target_ptr, target_end_ptr, + strictConversion); + + // Resize to be the size of the # of converted characters + NULL + out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0); +} + +int UTF8ToUTF16Char(const char *in, int in_length, u_int16_t out[2]) { + const UTF8 *source_ptr = reinterpret_cast(in); + const UTF8 *source_end_ptr = source_ptr + sizeof(char); + u_int16_t *target_ptr = out; + u_int16_t *target_end_ptr = target_ptr + 2 * sizeof(u_int16_t); + out[0] = out[1] = 0; + + // Process one character at a time + while (1) { + ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr, + &target_ptr, target_end_ptr, + strictConversion); + + if (result == conversionOK) + return source_ptr - reinterpret_cast(in); + + // Add another character to the input stream and try again + source_ptr = reinterpret_cast(in); + ++source_end_ptr; + + if (source_end_ptr > reinterpret_cast(in) + in_length) + break; + } + + return 0; +} + +void UTF32ToUTF16(const wchar_t *in, vector *out) { + size_t source_length = wcslen(in); + const UTF32 *source_ptr = reinterpret_cast(in); + const UTF32 *source_end_ptr = source_ptr + source_length; + // Erase the contents and zero fill to the expected size + out->empty(); + out->insert(out->begin(), source_length, 0); + u_int16_t *target_ptr = &(*out)[0]; + u_int16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(u_int16_t); + ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr, + &target_ptr, target_end_ptr, + strictConversion); + + // Resize to be the size of the # of converted characters + NULL + out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0); +} + +void UTF32ToUTF16Char(wchar_t in, u_int16_t out[2]) { + const UTF32 *source_ptr = reinterpret_cast(&in); + const UTF32 *source_end_ptr = source_ptr + 1; + u_int16_t *target_ptr = out; + u_int16_t *target_end_ptr = target_ptr + 2 * sizeof(u_int16_t); + out[0] = out[1] = 0; + ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr, + &target_ptr, target_end_ptr, + strictConversion); + + if (result != conversionOK) { + out[0] = out[1] = 0; + } +} + +static inline u_int16_t Swap(u_int16_t value) { + return (value >> 8) | (value << 8); +} + +string UTF16ToUTF8(const vector &in, bool swap) { + const UTF16 *source_ptr = &in[0]; + scoped_ptr source_buffer; + + // If we're to swap, we need to make a local copy and swap each byte pair + if (swap) { + int idx = 0; + source_buffer.reset(new u_int16_t[in.size()]); + UTF16 *source_buffer_ptr = source_buffer.get(); + for (vector::const_iterator it = in.begin(); + it != in.end(); ++it, ++idx) + source_buffer_ptr[idx] = Swap(*it); + + source_ptr = source_buffer.get(); + } + + // The maximum expansion would be 4x the size of the input string. + const UTF16 *source_end_ptr = source_ptr + in.size(); + int target_capacity = in.size() * 4; + scoped_array target_buffer(new UTF8[target_capacity]); + UTF8 *target_ptr = target_buffer.get(); + UTF8 *target_end_ptr = target_ptr + target_capacity; + ConversionResult result = ConvertUTF16toUTF8(&source_ptr, source_end_ptr, + &target_ptr, target_end_ptr, + strictConversion); + + if (result == conversionOK) { + const char *targetPtr = reinterpret_cast(target_buffer.get()); + string result(targetPtr); + return result; + } + + return ""; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/string_conversion.h b/thirdparty/google-breakpad/r318/src/common/string_conversion.h new file mode 100644 index 00000000..d51f46bb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/string_conversion.h @@ -0,0 +1,66 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// string_conversion.h: Conversion between different UTF-8/16/32 encodings. + +#ifndef COMMON_STRING_CONVERSION_H__ +#define COMMON_STRING_CONVERSION_H__ + +#include +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::vector; + +// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the +// conversion failed, |out| will be zero length. +void UTF8ToUTF16(const char *in, vector *out); + +// Convert at least one character (up to a maximum of |in_length|) from |in| +// to UTF-16 into |out|. Return the number of characters consumed from |in|. +// Any unused characters in |out| will be initialized to 0. No memory will +// be allocated by this routine. +int UTF8ToUTF16Char(const char *in, int in_length, u_int16_t out[2]); + +// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the +// conversion failed, |out| will be zero length. +void UTF32ToUTF16(const wchar_t *in, vector *out); + +// Convert |in| to UTF-16 into |out|. Any unused characters in |out| will be +// initialized to 0. No memory will be allocated by this routine. +void UTF32ToUTF16Char(wchar_t in, u_int16_t out[2]); + +// Convert |in| to UTF-8. If |swap| is true, swap bytes before converting. +std::string UTF16ToUTF8(const vector &in, bool swap); + +} // namespace google_breakpad + +#endif // COMMON_STRING_CONVERSION_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/windows/guid_string.cc b/thirdparty/google-breakpad/r318/src/common/windows/guid_string.cc new file mode 100644 index 00000000..b7f877e6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/guid_string.cc @@ -0,0 +1,76 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// guid_string.cc: Convert GUIDs to strings. +// +// See guid_string.h for documentation. + +#include + +#include "common/windows/string_utils-inl.h" + +#include "common/windows/guid_string.h" + +namespace google_breakpad { + +// static +wstring GUIDString::GUIDToWString(GUID *guid) { + wchar_t guid_string[37]; + swprintf( + guid_string, sizeof(guid_string) / sizeof(guid_string[0]), + L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], + guid->Data4[3], guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7]); + + // remove when VC++7.1 is no longer supported + guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0'; + + return wstring(guid_string); +} + +// static +wstring GUIDString::GUIDToSymbolServerWString(GUID *guid) { + wchar_t guid_string[33]; + swprintf( + guid_string, sizeof(guid_string) / sizeof(guid_string[0]), + L"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], + guid->Data4[3], guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7]); + + // remove when VC++7.1 is no longer supported + guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0'; + + return wstring(guid_string); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/windows/guid_string.h b/thirdparty/google-breakpad/r318/src/common/windows/guid_string.h new file mode 100644 index 00000000..f8aa8a23 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/guid_string.h @@ -0,0 +1,58 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// guid_string.cc: Convert GUIDs to strings. + +#ifndef COMMON_WINDOWS_GUID_STRING_H__ +#define COMMON_WINDOWS_GUID_STRING_H__ + +#include + +#include + +namespace google_breakpad { + +using std::wstring; + +class GUIDString { + public: + // Converts guid to a string in the format recommended by RFC 4122 and + // returns the string. + static wstring GUIDToWString(GUID *guid); + + // Converts guid to a string formatted as uppercase hexadecimal, with + // no separators, and returns the string. This is the format used for + // symbol server identifiers, although identifiers have an age tacked + // on to the string. + static wstring GUIDToSymbolServerWString(GUID *guid); +}; + +} // namespace google_breakpad + +#endif // COMMON_WINDOWS_GUID_STRING_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/windows/http_upload.cc b/thirdparty/google-breakpad/r318/src/common/windows/http_upload.cc new file mode 100644 index 00000000..2f9ffa92 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/http_upload.cc @@ -0,0 +1,393 @@ +// 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 + +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include + +#include "common/windows/string_utils-inl.h" + +#include "common/windows/http_upload.h" + +namespace google_breakpad { + +using std::ifstream; +using std::ios; + +static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)"; + +// Helper class which closes an internet handle when it goes away +class HTTPUpload::AutoInternetHandle { + public: + explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {} + ~AutoInternetHandle() { + if (handle_) { + InternetCloseHandle(handle_); + } + } + + HINTERNET get() { return handle_; } + + private: + HINTERNET handle_; +}; + +// static +bool HTTPUpload::SendRequest(const wstring &url, + const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + wstring *response_body, + int *response_code) { + if (response_code) { + *response_code = 0; + } + + // TODO(bryner): support non-ASCII parameter names + if (!CheckParameters(parameters)) { + return false; + } + + // Break up the URL and make sure we can handle it + wchar_t scheme[16], host[256], path[256]; + URL_COMPONENTS components; + memset(&components, 0, sizeof(components)); + components.dwStructSize = sizeof(components); + components.lpszScheme = scheme; + components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]); + components.lpszHostName = host; + components.dwHostNameLength = sizeof(host) / sizeof(host[0]); + components.lpszUrlPath = path; + components.dwUrlPathLength = sizeof(path) / sizeof(path[0]); + if (!InternetCrackUrl(url.c_str(), static_cast(url.size()), + 0, &components)) { + return false; + } + bool secure = false; + if (wcscmp(scheme, L"https") == 0) { + secure = true; + } else if (wcscmp(scheme, L"http") != 0) { + return false; + } + + AutoInternetHandle internet(InternetOpen(kUserAgent, + INTERNET_OPEN_TYPE_PRECONFIG, + NULL, // proxy name + NULL, // proxy bypass + 0)); // flags + if (!internet.get()) { + return false; + } + + AutoInternetHandle connection(InternetConnect(internet.get(), + host, + components.nPort, + NULL, // user name + NULL, // password + INTERNET_SERVICE_HTTP, + 0, // flags + NULL)); // context + if (!connection.get()) { + return false; + } + + DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0; + AutoInternetHandle request(HttpOpenRequest(connection.get(), + L"POST", + path, + NULL, // version + NULL, // referer + NULL, // agent type + http_open_flags, + NULL)); // context + if (!request.get()) { + return false; + } + + wstring boundary = GenerateMultipartBoundary(); + wstring content_type_header = GenerateRequestHeader(boundary); + HttpAddRequestHeaders(request.get(), + content_type_header.c_str(), + static_cast(-1), + HTTP_ADDREQ_FLAG_ADD); + + string request_body; + if (!GenerateRequestBody(parameters, upload_file, + file_part_name, boundary, &request_body)) { + return false; + } + + if (!HttpSendRequest(request.get(), NULL, 0, + const_cast(request_body.data()), + static_cast(request_body.size()))) { + return false; + } + + // The server indicates a successful upload with HTTP status 200. + wchar_t http_status[4]; + DWORD http_status_size = sizeof(http_status); + if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE, + static_cast(&http_status), &http_status_size, + 0)) { + return false; + } + + int http_response = wcstol(http_status, NULL, 10); + if (response_code) { + *response_code = http_response; + } + + bool result = (http_response == 200); + + if (result) { + result = ReadResponse(request.get(), response_body); + } + + return result; +} + +// static +bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) { + bool has_content_length_header = false; + wchar_t content_length[32]; + DWORD content_length_size = sizeof(content_length); + DWORD claimed_size = 0; + string response_body; + + if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH, + static_cast(&content_length), + &content_length_size, 0)) { + has_content_length_header = true; + claimed_size = wcstol(content_length, NULL, 10); + response_body.reserve(claimed_size); + } + + + DWORD bytes_available; + DWORD total_read = 0; + bool return_code; + + while ((return_code = InternetQueryDataAvailable(request, &bytes_available, + 0, 0) != 0) && + bytes_available > 0) { + vector response_buffer(bytes_available); + DWORD size_read; + + if ((return_code = InternetReadFile(request, &response_buffer[0], + bytes_available, &size_read) != 0) && + size_read > 0) { + total_read += size_read; + response_body.append(&response_buffer[0], size_read); + } else { + break; + } + } + + bool succeeded = return_code && (!has_content_length_header || + (total_read == claimed_size)); + if (succeeded && response) { + *response = UTF8ToWide(response_body); + } + + return succeeded; +} + +// static +wstring HTTPUpload::GenerateMultipartBoundary() { + // The boundary has 27 '-' characters followed by 16 hex digits + static const wchar_t kBoundaryPrefix[] = L"---------------------------"; + static const int kBoundaryLength = 27 + 16 + 1; + + // Generate some random numbers to fill out the boundary + int r0 = rand(); + int r1 = rand(); + + wchar_t temp[kBoundaryLength]; + swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1); + + // remove when VC++7.1 is no longer supported + temp[kBoundaryLength - 1] = L'\0'; + + return wstring(temp); +} + +// static +wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) { + wstring header = L"Content-Type: multipart/form-data; boundary="; + header += boundary; + return header; +} + +// static +bool HTTPUpload::GenerateRequestBody(const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + const wstring &boundary, + string *request_body) { + vector contents; + GetFileContents(upload_file, &contents); + if (contents.empty()) { + return false; + } + + string boundary_str = WideToUTF8(boundary); + if (boundary_str.empty()) { + return false; + } + + request_body->clear(); + + // Append each of the parameter pairs as a form-data part + for (map::const_iterator pos = parameters.begin(); + pos != parameters.end(); ++pos) { + request_body->append("--" + boundary_str + "\r\n"); + request_body->append("Content-Disposition: form-data; name=\"" + + WideToUTF8(pos->first) + "\"\r\n\r\n" + + WideToUTF8(pos->second) + "\r\n"); + } + + // Now append the upload file as a binary (octet-stream) part + string filename_utf8 = WideToUTF8(upload_file); + if (filename_utf8.empty()) { + return false; + } + + string file_part_name_utf8 = WideToUTF8(file_part_name); + if (file_part_name_utf8.empty()) { + return false; + } + + request_body->append("--" + boundary_str + "\r\n"); + request_body->append("Content-Disposition: form-data; " + "name=\"" + file_part_name_utf8 + "\"; " + "filename=\"" + filename_utf8 + "\"\r\n"); + request_body->append("Content-Type: application/octet-stream\r\n"); + request_body->append("\r\n"); + + if (!contents.empty()) { + request_body->append(&(contents[0]), contents.size()); + } + request_body->append("\r\n"); + request_body->append("--" + boundary_str + "--\r\n"); + return true; +} + +// static +void HTTPUpload::GetFileContents(const wstring &filename, + vector *contents) { + // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a + // wchar_t* filename, so use _wfopen directly in that case. For VC8 and + // later, _wfopen has been deprecated in favor of _wfopen_s, which does + // not exist in earlier versions, so let the ifstream open the file itself. +#if _MSC_VER >= 1400 // MSVC 2005/8 + ifstream file; + file.open(filename.c_str(), ios::binary); +#else // _MSC_VER >= 1400 + ifstream file(_wfopen(filename.c_str(), L"rb")); +#endif // _MSC_VER >= 1400 + if (file.is_open()) { + file.seekg(0, ios::end); + int length = file.tellg(); + contents->resize(length); + if (length != 0) { + file.seekg(0, ios::beg); + file.read(&((*contents)[0]), length); + } + file.close(); + } else { + contents->clear(); + } +} + +// static +wstring HTTPUpload::UTF8ToWide(const string &utf8) { + if (utf8.length() == 0) { + return wstring(); + } + + // compute the length of the buffer we'll need + int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); + + if (charcount == 0) { + return wstring(); + } + + // convert + wchar_t* buf = new wchar_t[charcount]; + MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount); + wstring result(buf); + delete[] buf; + return result; +} + +// static +string HTTPUpload::WideToUTF8(const wstring &wide) { + if (wide.length() == 0) { + return string(); + } + + // compute the length of the buffer we'll need + int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, + NULL, 0, NULL, NULL); + if (charcount == 0) { + return string(); + } + + // convert + char *buf = new char[charcount]; + WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount, + NULL, NULL); + + string result(buf); + delete[] buf; + return result; +} + +// static +bool HTTPUpload::CheckParameters(const map ¶meters) { + for (map::const_iterator pos = parameters.begin(); + pos != parameters.end(); ++pos) { + const wstring &str = pos->first; + if (str.size() == 0) { + return false; // disallow empty parameter names + } + for (unsigned int i = 0; i < str.size(); ++i) { + wchar_t c = str[i]; + if (c < 32 || c == '"' || c > 127) { + return false; + } + } + } + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/windows/http_upload.h b/thirdparty/google-breakpad/r318/src/common/windows/http_upload.h new file mode 100644 index 00000000..a1ba7ae1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/http_upload.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST +// request using wininet. It currently supports requests that contain +// a set of string parameters (key/value pairs), and a file to upload. + +#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H__ +#define COMMON_WINDOWS_HTTP_UPLOAD_H__ + +#pragma warning( push ) +// Disable exception handler warnings. +#pragma warning( disable : 4530 ) + +#include +#include + +#include +#include +#include + +namespace google_breakpad { + +using std::string; +using std::wstring; +using std::map; +using std::vector; + +class HTTPUpload { + public: + // Sends the given set of parameters, along with the contents of + // upload_file, as a multipart POST request to the given URL. + // file_part_name contains the name of the file part of the request + // (i.e. it corresponds to the name= attribute on an . + // Parameter names must contain only printable ASCII characters, + // and may not contain a quote (") character. + // Only HTTP(S) URLs are currently supported. Returns true on success. + // If the request is successful and response_body is non-NULL, + // the response body will be returned in response_body. + // If response_code is non-NULL, it will be set to the HTTP response code + // received (or 0 if the request failed before getting an HTTP response). + static bool SendRequest(const wstring &url, + const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + wstring *response_body, + int *response_code); + + private: + class AutoInternetHandle; + + // Retrieves the HTTP response. If NULL is passed in for response, + // this merely checks (via the return value) that we were successfully + // able to retrieve exactly as many bytes of content in the response as + // were specified in the Content-Length header. + static bool HTTPUpload::ReadResponse(HINTERNET request, wstring* response); + + // Generates a new multipart boundary for a POST request + static wstring GenerateMultipartBoundary(); + + // Generates a HTTP request header for a multipart form submit. + static wstring GenerateRequestHeader(const wstring &boundary); + + // Given a set of parameters, an upload filename, and a file part name, + // generates a multipart request body string with these parameters + // and minidump contents. Returns true on success. + static bool GenerateRequestBody(const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, + const wstring &boundary, + string *request_body); + + // Fills the supplied vector with the contents of filename. + static void GetFileContents(const wstring &filename, vector *contents); + + // Converts a UTF8 string to UTF16. + static wstring UTF8ToWide(const string &utf8); + + // Converts a UTF16 string to UTF8. + static string WideToUTF8(const wstring &wide); + + // Checks that the given list of parameters has only printable + // ASCII characters in the parameter name, and does not contain + // any quote (") characters. Returns true if so. + static bool CheckParameters(const map ¶meters); + + // No instances of this class should be created. + // Disallow all constructors, destructors, and operator=. + HTTPUpload(); + explicit HTTPUpload(const HTTPUpload &); + void operator=(const HTTPUpload &); + ~HTTPUpload(); +}; + +} // namespace google_breakpad + +#pragma warning( pop ) + +#endif // COMMON_WINDOWS_HTTP_UPLOAD_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.cc b/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.cc new file mode 100644 index 00000000..0392627f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.cc @@ -0,0 +1,800 @@ +// 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 +#include +#include +#include + +#include "common/windows/string_utils-inl.h" + +#include "common/windows/pdb_source_line_writer.h" +#include "common/windows/guid_string.h" + +// This constant may be missing from DbgHelp.h. See the documentation for +// IDiaSymbol::get_undecoratedNameEx. +#ifndef UNDNAME_NO_ECSU +#define UNDNAME_NO_ECSU 0x8000 // Suppresses enum/class/struct/union. +#endif // UNDNAME_NO_ECSU + +namespace google_breakpad { + +PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) { +} + +PDBSourceLineWriter::~PDBSourceLineWriter() { +} + +bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) { + Close(); + + if (FAILED(CoInitialize(NULL))) { + fprintf(stderr, "CoInitialize failed\n"); + return false; + } + + CComPtr data_source; + if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) { + fprintf(stderr, "CoCreateInstance CLSID_DiaSource failed " + "(msdia80.dll unregistered?)\n"); + return false; + } + + switch (format) { + case PDB_FILE: + if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { + fprintf(stderr, "loadDataFromPdb failed\n"); + return false; + } + break; + case EXE_FILE: + if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { + fprintf(stderr, "loadDataForExe failed\n"); + return false; + } + break; + case ANY_FILE: + if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { + if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { + fprintf(stderr, "loadDataForPdb and loadDataFromExe failed\n"); + return false; + } + } + break; + default: + fprintf(stderr, "Unknown file format\n"); + return false; + } + + if (FAILED(data_source->openSession(&session_))) { + fprintf(stderr, "openSession failed\n"); + } + + return true; +} + +bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) { + // The line number format is: + // + CComPtr line; + ULONG count; + + while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) { + DWORD rva; + if (FAILED(line->get_relativeVirtualAddress(&rva))) { + fprintf(stderr, "failed to get line rva\n"); + return false; + } + + DWORD length; + if (FAILED(line->get_length(&length))) { + fprintf(stderr, "failed to get line code length\n"); + return false; + } + + DWORD source_id; + if (FAILED(line->get_sourceFileId(&source_id))) { + fprintf(stderr, "failed to get line source file id\n"); + return false; + } + + DWORD line_num; + if (FAILED(line->get_lineNumber(&line_num))) { + fprintf(stderr, "failed to get line number\n"); + return false; + } + + fprintf(output_, "%x %x %d %d\n", rva, length, line_num, source_id); + line.Release(); + } + return true; +} + +bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function) { + // The function format is: + // FUNC
+ DWORD rva; + if (FAILED(function->get_relativeVirtualAddress(&rva))) { + fprintf(stderr, "couldn't get rva\n"); + return false; + } + + ULONGLONG length; + if (FAILED(function->get_length(&length))) { + fprintf(stderr, "failed to get function length\n"); + return false; + } + + if (length == 0) { + // Silently ignore zero-length functions, which can infrequently pop up. + return true; + } + + CComBSTR name; + int stack_param_size; + if (!GetSymbolFunctionName(function, &name, &stack_param_size)) { + return false; + } + + // If the decorated name didn't give the parameter size, try to + // calculate it. + if (stack_param_size < 0) { + stack_param_size = GetFunctionStackParamSize(function); + } + + fprintf(output_, "FUNC %x %" WIN_STRING_FORMAT_LL "x %x %ws\n", + rva, length, stack_param_size, name); + + CComPtr lines; + if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) { + return false; + } + + if (!PrintLines(lines)) { + return false; + } + return true; +} + +bool PDBSourceLineWriter::PrintSourceFiles() { + CComPtr global; + if (FAILED(session_->get_globalScope(&global))) { + fprintf(stderr, "get_globalScope failed\n"); + return false; + } + + CComPtr compilands; + if (FAILED(global->findChildren(SymTagCompiland, NULL, + nsNone, &compilands))) { + fprintf(stderr, "findChildren failed\n"); + return false; + } + + CComPtr compiland; + ULONG count; + while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { + CComPtr source_files; + if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) { + return false; + } + CComPtr file; + while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) { + DWORD file_id; + if (FAILED(file->get_uniqueId(&file_id))) { + return false; + } + + CComBSTR file_name; + if (FAILED(file->get_fileName(&file_name))) { + return false; + } + + fwprintf(output_, L"FILE %d %s\n", file_id, file_name); + file.Release(); + } + compiland.Release(); + } + return true; +} + +bool PDBSourceLineWriter::PrintFunctions() { + CComPtr symbols; + if (FAILED(session_->getSymbolsByAddr(&symbols))) { + fprintf(stderr, "failed to get symbol enumerator\n"); + return false; + } + + CComPtr symbol; + if (FAILED(symbols->symbolByAddr(1, 0, &symbol))) { + fprintf(stderr, "failed to enumerate symbols\n"); + return false; + } + + DWORD rva_last = 0; + if (FAILED(symbol->get_relativeVirtualAddress(&rva_last))) { + fprintf(stderr, "failed to get symbol rva\n"); + return false; + } + + ULONG count; + do { + DWORD tag; + if (FAILED(symbol->get_symTag(&tag))) { + fprintf(stderr, "failed to get symbol tag\n"); + return false; + } + + // For a given function, DIA seems to give either a symbol with + // SymTagFunction or SymTagPublicSymbol, but not both. This means + // that PDBSourceLineWriter will output either a FUNC or PUBLIC line, + // but not both. + if (tag == SymTagFunction) { + if (!PrintFunction(symbol)) { + return false; + } + } else if (tag == SymTagPublicSymbol) { + if (!PrintCodePublicSymbol(symbol)) { + return false; + } + } + symbol.Release(); + } while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1); + + return true; +} + +bool PDBSourceLineWriter::PrintFrameData() { + // It would be nice if it were possible to output frame data alongside the + // associated function, as is done with line numbers, but the DIA API + // doesn't make it possible to get the frame data in that way. + + CComPtr tables; + if (FAILED(session_->getEnumTables(&tables))) + return false; + + // Pick up the first table that supports IDiaEnumFrameData. + CComPtr frame_data_enum; + CComPtr table; + ULONG count; + while (!frame_data_enum && + SUCCEEDED(tables->Next(1, &table, &count)) && + count == 1) { + table->QueryInterface(_uuidof(IDiaEnumFrameData), + reinterpret_cast(&frame_data_enum)); + table.Release(); + } + if (!frame_data_enum) + return false; + + DWORD last_type = -1; + DWORD last_rva = -1; + DWORD last_code_size = 0; + DWORD last_prolog_size = -1; + + CComPtr frame_data; + while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) && + count == 1) { + DWORD type; + if (FAILED(frame_data->get_type(&type))) + return false; + + DWORD rva; + if (FAILED(frame_data->get_relativeVirtualAddress(&rva))) + return false; + + DWORD code_size; + if (FAILED(frame_data->get_lengthBlock(&code_size))) + return false; + + DWORD prolog_size; + if (FAILED(frame_data->get_lengthProlog(&prolog_size))) + return false; + + // epliog_size is always 0. + DWORD epilog_size = 0; + + // parameter_size is the size of parameters passed on the stack. If any + // parameters are not passed on the stack (such as in registers), their + // sizes will not be included in parameter_size. + DWORD parameter_size; + if (FAILED(frame_data->get_lengthParams(¶meter_size))) + return false; + + DWORD saved_register_size; + if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size))) + return false; + + DWORD local_size; + if (FAILED(frame_data->get_lengthLocals(&local_size))) + return false; + + // get_maxStack can return S_FALSE, just use 0 in that case. + DWORD max_stack_size = 0; + if (FAILED(frame_data->get_maxStack(&max_stack_size))) + return false; + + // get_programString can return S_FALSE, indicating that there is no + // program string. In that case, check whether %ebp is used. + HRESULT program_string_result; + CComBSTR program_string; + if (FAILED(program_string_result = frame_data->get_program( + &program_string))) { + return false; + } + + // get_allocatesBasePointer can return S_FALSE, treat that as though + // %ebp is not used. + BOOL allocates_base_pointer = FALSE; + if (program_string_result != S_OK) { + if (FAILED(frame_data->get_allocatesBasePointer( + &allocates_base_pointer))) { + return false; + } + } + + // Only print out a line if type, rva, code_size, or prolog_size have + // changed from the last line. It is surprisingly common (especially in + // system library PDBs) for DIA to return a series of identical + // IDiaFrameData objects. For kernel32.pdb from Windows XP SP2 on x86, + // this check reduces the size of the dumped symbol file by a third. + if (type != last_type || rva != last_rva || code_size != last_code_size || + prolog_size != last_prolog_size) { + fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ", + type, rva, code_size, prolog_size, epilog_size, + parameter_size, saved_register_size, local_size, max_stack_size, + program_string_result == S_OK); + if (program_string_result == S_OK) { + fprintf(output_, "%ws\n", program_string); + } else { + fprintf(output_, "%d\n", allocates_base_pointer); + } + + last_type = type; + last_rva = rva; + last_code_size = code_size; + last_prolog_size = prolog_size; + } + + frame_data.Release(); + } + + return true; +} + +bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) { + BOOL is_code; + if (FAILED(symbol->get_code(&is_code))) { + return false; + } + if (!is_code) { + return true; + } + + DWORD rva; + if (FAILED(symbol->get_relativeVirtualAddress(&rva))) { + return false; + } + + CComBSTR name; + int stack_param_size; + if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) { + return false; + } + + fprintf(output_, "PUBLIC %x %x %ws\n", rva, + stack_param_size > 0 ? stack_param_size : 0, name); + return true; +} + +bool PDBSourceLineWriter::PrintPDBInfo() { + PDBModuleInfo info; + if (!GetModuleInfo(&info)) { + return false; + } + + // Hard-code "windows" for the OS because that's the only thing that makes + // sense for PDB files. (This might not be strictly correct for Windows CE + // support, but we don't care about that at the moment.) + fprintf(output_, "MODULE windows %ws %ws %ws\n", + info.cpu.c_str(), info.debug_identifier.c_str(), + info.debug_file.c_str()); + + return true; +} + +// wcstol_positive_strict is sort of like wcstol, but much stricter. string +// should be a buffer pointing to a null-terminated string containing only +// decimal digits. If the entire string can be converted to an integer +// without overflowing, and there are no non-digit characters before the +// result is set to the value and this function returns true. Otherwise, +// this function returns false. This is an alternative to the strtol, atoi, +// and scanf families, which are not as strict about input and in some cases +// don't provide a good way for the caller to determine if a conversion was +// successful. +static bool wcstol_positive_strict(wchar_t *string, int *result) { + int value = 0; + for (wchar_t *c = string; *c != '\0'; ++c) { + int last_value = value; + value *= 10; + // Detect overflow. + if (value / 10 != last_value || value < 0) { + return false; + } + if (*c < '0' || *c > '9') { + return false; + } + unsigned int c_value = *c - '0'; + last_value = value; + value += c_value; + // Detect overflow. + if (value < last_value) { + return false; + } + // Forbid leading zeroes unless the string is just "0". + if (value == 0 && *(c+1) != '\0') { + return false; + } + } + *result = value; + return true; +} + +// static +bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function, + BSTR *name, + int *stack_param_size) { + *stack_param_size = -1; + const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS | + UNDNAME_NO_FUNCTION_RETURNS | + UNDNAME_NO_ALLOCATION_MODEL | + UNDNAME_NO_ALLOCATION_LANGUAGE | + UNDNAME_NO_THISTYPE | + UNDNAME_NO_ACCESS_SPECIFIERS | + UNDNAME_NO_THROW_SIGNATURES | + UNDNAME_NO_MEMBER_TYPE | + UNDNAME_NO_RETURN_UDT_MODEL | + UNDNAME_NO_ECSU; + + // Use get_undecoratedNameEx to get readable C++ names with arguments. + if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) { + if (function->get_name(name) != S_OK) { + fprintf(stderr, "failed to get function name\n"); + return false; + } + // If a name comes from get_name because no undecorated form existed, + // it's already formatted properly to be used as output. Don't do any + // additional processing. + // + // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's. + // This will result in calling get_name for some C++ symbols, so + // all of the parameter and return type information may not be included in + // the name string. + } else { + // C++ uses a bogus "void" argument for functions and methods that don't + // take any parameters. Take it out of the undecorated name because it's + // ugly and unnecessary. + const wchar_t *replace_string = L"(void)"; + const size_t replace_length = wcslen(replace_string); + const wchar_t *replacement_string = L"()"; + size_t length = wcslen(*name); + if (length >= replace_length) { + wchar_t *name_end = *name + length - replace_length; + if (wcscmp(name_end, replace_string) == 0) { + WindowsStringUtils::safe_wcscpy(name_end, replace_length, + replacement_string); + length = wcslen(*name); + } + } + + // Undecorate names used for stdcall and fastcall. These names prefix + // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it + // with '@' followed by the number of bytes of parameters, in decimal. + // If such a name is found, take note of the size and undecorate it. + // Only do this for names that aren't C++, which is determined based on + // whether the undecorated name contains any ':' or '(' characters. + if (!wcschr(*name, ':') && !wcschr(*name, '(') && + (*name[0] == '_' || *name[0] == '@')) { + wchar_t *last_at = wcsrchr(*name + 1, '@'); + if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) { + // If this function adheres to the fastcall convention, it accepts up + // to the first 8 bytes of parameters in registers (%ecx and %edx). + // We're only interested in the stack space used for parameters, so + // so subtract 8 and don't let the size go below 0. + if (*name[0] == '@') { + if (*stack_param_size > 8) { + *stack_param_size -= 8; + } else { + *stack_param_size = 0; + } + } + + // Undecorate the name by moving it one character to the left in its + // buffer, and terminating it where the last '@' had been. + WindowsStringUtils::safe_wcsncpy(*name, length, + *name + 1, last_at - *name - 1); + } else if (*name[0] == '_') { + // This symbol's name is encoded according to the cdecl rules. The + // name doesn't end in a '@' character followed by a decimal positive + // integer, so it's not a stdcall name. Strip off the leading + // underscore. + WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length); + } + } + } + + return true; +} + +// static +int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) { + // This implementation is highly x86-specific. + + // Gather the symbols corresponding to data. + CComPtr data_children; + if (FAILED(function->findChildren(SymTagData, NULL, nsNone, + &data_children))) { + return 0; + } + + // lowest_base is the lowest %ebp-relative byte offset used for a parameter. + // highest_end is one greater than the highest offset (i.e. base + length). + // Stack parameters are assumed to be contiguous, because in reality, they + // are. + int lowest_base = INT_MAX; + int highest_end = INT_MIN; + + CComPtr child; + DWORD count; + while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) { + // If any operation fails at this point, just proceed to the next child. + // Use the next_child label instead of continue because child needs to + // be released before it's reused. Declare constructable/destructable + // types early to avoid gotos that cross initializations. + CComPtr child_type; + + // DataIsObjectPtr is only used for |this|. Because |this| can be passed + // as a stack parameter, look for it in addition to traditional + // parameters. + DWORD child_kind; + if (FAILED(child->get_dataKind(&child_kind)) || + (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) { + goto next_child; + } + + // Only concentrate on register-relative parameters. Parameters may also + // be enregistered (passed directly in a register), but those don't + // consume any stack space, so they're not of interest. + DWORD child_location_type; + if (FAILED(child->get_locationType(&child_location_type)) || + child_location_type != LocIsRegRel) { + goto next_child; + } + + // Of register-relative parameters, the only ones that make any sense are + // %ebp- or %esp-relative. Note that MSVC's debugging information always + // gives parameters as %ebp-relative even when a function doesn't use a + // traditional frame pointer and stack parameters are accessed relative to + // %esp, so just look for %ebp-relative parameters. If you wanted to + // access parameters, you'd probably want to treat these %ebp-relative + // offsets as if they were relative to %esp before a function's prolog + // executed. + DWORD child_register; + if (FAILED(child->get_registerId(&child_register)) || + child_register != CV_REG_EBP) { + goto next_child; + } + + LONG child_register_offset; + if (FAILED(child->get_offset(&child_register_offset))) { + goto next_child; + } + + // IDiaSymbol::get_type can succeed but still pass back a NULL value. + if (FAILED(child->get_type(&child_type)) || !child_type) { + goto next_child; + } + + ULONGLONG child_length; + if (FAILED(child_type->get_length(&child_length))) { + goto next_child; + } + + int child_end = child_register_offset + static_cast(child_length); + if (child_register_offset < lowest_base) { + lowest_base = child_register_offset; + } + if (child_end > highest_end) { + highest_end = child_end; + } + +next_child: + child.Release(); + } + + int param_size = 0; + // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest + // possible address to find a stack parameter before executing a function's + // prolog (see above). Some optimizations cause parameter offsets to be + // lower than 4, but we're not concerned with those because we're only + // looking for parameters contained in addresses higher than where the + // return address is stored. + if (lowest_base < 4) { + lowest_base = 4; + } + if (highest_end > lowest_base) { + // All stack parameters are pushed as at least 4-byte quantities. If the + // last type was narrower than 4 bytes, promote it. This assumes that all + // parameters' offsets are 4-byte-aligned, which is always the case. Only + // worry about the last type, because we're not summing the type sizes, + // just looking at the lowest and highest offsets. + int remainder = highest_end % 4; + if (remainder) { + highest_end += 4 - remainder; + } + + param_size = highest_end - lowest_base; + } + + return param_size; +} + +bool PDBSourceLineWriter::WriteMap(FILE *map_file) { + output_ = map_file; + + bool ret = PrintPDBInfo() && + PrintSourceFiles() && + PrintFunctions() && + PrintFrameData(); + + output_ = NULL; + return ret; +} + +void PDBSourceLineWriter::Close() { + session_.Release(); +} + +bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) { + if (!info) { + return false; + } + + info->debug_file.clear(); + info->debug_identifier.clear(); + info->cpu.clear(); + + CComPtr global; + if (FAILED(session_->get_globalScope(&global))) { + return false; + } + + // All CPUs in CV_CPU_TYPE_e (cvconst.h) below 0x10 are x86. There's no + // single specific constant to use. + DWORD platform; + if (SUCCEEDED(global->get_platform(&platform)) && platform < 0x10) { + info->cpu = L"x86"; + } else { + // Unexpected, but handle gracefully. + info->cpu = L"unknown"; + } + + // DWORD* and int* are not compatible. This is clean and avoids a cast. + DWORD age; + if (FAILED(global->get_age(&age))) { + return false; + } + + bool uses_guid; + if (!UsesGUID(&uses_guid)) { + return false; + } + + if (uses_guid) { + GUID guid; + if (FAILED(global->get_guid(&guid))) { + return false; + } + + // Use the same format that the MS symbol server uses in filesystem + // hierarchies. + wchar_t age_string[9]; + swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]), + L"%x", age); + + // remove when VC++7.1 is no longer supported + age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0'; + + info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid); + info->debug_identifier.append(age_string); + } else { + DWORD signature; + if (FAILED(global->get_signature(&signature))) { + return false; + } + + // Use the same format that the MS symbol server uses in filesystem + // hierarchies. + wchar_t identifier_string[17]; + swprintf(identifier_string, + sizeof(identifier_string) / sizeof(identifier_string[0]), + L"%08X%x", signature, age); + + // remove when VC++7.1 is no longer supported + identifier_string[sizeof(identifier_string) / + sizeof(identifier_string[0]) - 1] = L'\0'; + + info->debug_identifier = identifier_string; + } + + CComBSTR debug_file_string; + if (FAILED(global->get_symbolsFileName(&debug_file_string))) { + return false; + } + info->debug_file = + WindowsStringUtils::GetBaseName(wstring(debug_file_string)); + + return true; +} + +bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) { + if (!uses_guid) + return false; + + CComPtr global; + if (FAILED(session_->get_globalScope(&global))) + return false; + + GUID guid; + if (FAILED(global->get_guid(&guid))) + return false; + + DWORD signature; + if (FAILED(global->get_signature(&signature))) + return false; + + // There are two possibilities for guid: either it's a real 128-bit GUID + // as identified in a code module by a new-style CodeView record, or it's + // a 32-bit signature (timestamp) as identified by an old-style record. + // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h. + // + // Because DIA doesn't provide a way to directly determine whether a module + // uses a GUID or a 32-bit signature, this code checks whether the first 32 + // bits of guid are the same as the signature, and if the rest of guid is + // zero. If so, then with a pretty high degree of certainty, there's an + // old-style CodeView record in use. This method will only falsely find an + // an old-style CodeView record if a real 128-bit GUID has its first 32 + // bits set the same as the module's signature (timestamp) and the rest of + // the GUID is set to 0. This is highly unlikely. + + GUID signature_guid = {signature}; // 0-initializes other members + *uses_guid = !IsEqualGUID(guid, signature_guid); + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.h b/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.h new file mode 100644 index 00000000..e91d0737 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/pdb_source_line_writer.h @@ -0,0 +1,163 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// PDBSourceLineWriter uses a pdb file produced by Visual C++ to output +// a line/address map for use with BasicSourceLineResolver. + +#ifndef _PDB_SOURCE_LINE_WRITER_H__ +#define _PDB_SOURCE_LINE_WRITER_H__ + +#include + +#include + +struct IDiaEnumLineNumbers; +struct IDiaSession; +struct IDiaSymbol; + +namespace google_breakpad { + +using std::wstring; + +// A structure that carries information that identifies a pdb file. +struct PDBModuleInfo { + public: + // The basename of the pdb file from which information was loaded. + wstring debug_file; + + // The pdb's identifier. For recent pdb files, the identifier consists + // of the pdb's guid, in uppercase hexadecimal form without any dashes + // or separators, followed immediately by the pdb's age, also in + // uppercase hexadecimal form. For older pdb files which have no guid, + // the identifier is the pdb's 32-bit signature value, in zero-padded + // hexadecimal form, followed immediately by the pdb's age, in lowercase + // hexadecimal form. + wstring debug_identifier; + + // A string identifying the cpu that the pdb is associated with. + // Currently, this may be "x86" or "unknown". + wstring cpu; +}; + +class PDBSourceLineWriter { + public: + enum FileFormat { + PDB_FILE, // a .pdb file containing debug symbols + EXE_FILE, // a .exe or .dll file + ANY_FILE // try PDB_FILE and then EXE_FILE + }; + + explicit PDBSourceLineWriter(); + ~PDBSourceLineWriter(); + + // Opens the given file. For executable files, the corresponding pdb + // file must be available; Open will be if it is not. + // If there is already a pdb file open, it is automatically closed. + // Returns true on success. + bool Open(const wstring &file, FileFormat format); + + // Locates the pdb file for the given executable (exe or dll) file, + // and opens it. If there is already a pdb file open, it is automatically + // closed. Returns true on success. + bool OpenExecutable(const wstring &exe_file); + + // Writes a map file from the current pdb file to the given file stream. + // Returns true on success. + bool WriteMap(FILE *map_file); + + // Closes the current pdb file and its associated resources. + void Close(); + + // Retrieves information about the module's debugging file. Returns + // true on success and false on failure. + bool GetModuleInfo(PDBModuleInfo *info); + + // Sets uses_guid to true if the opened file uses a new-style CodeView + // record with a 128-bit GUID, or false if the opened file uses an old-style + // CodeView record. When no GUID is available, a 32-bit signature should be + // used to identify the module instead. If the information cannot be + // determined, this method returns false. + bool UsesGUID(bool *uses_guid); + + private: + // Outputs the line/address pairs for each line in the enumerator. + // Returns true on success. + bool PrintLines(IDiaEnumLineNumbers *lines); + + // Outputs a function address and name, followed by its source line list. + // Returns true on success. + bool PrintFunction(IDiaSymbol *function); + + // Outputs all functions as described above. Returns true on success. + bool PrintFunctions(); + + // Outputs all of the source files in the session's pdb file. + // Returns true on success. + bool PrintSourceFiles(); + + // Outputs all of the frame information necessary to construct stack + // backtraces in the absence of frame pointers. Returns true on success. + bool PrintFrameData(); + + // Outputs a single public symbol address and name, if the symbol corresponds + // to a code address. Returns true on success. If symbol is does not + // correspond to code, returns true without outputting anything. + bool PrintCodePublicSymbol(IDiaSymbol *symbol); + + // Outputs a line identifying the PDB file that is being dumped, along with + // its uuid and age. + bool PrintPDBInfo(); + + // Returns the function name for a symbol. If possible, the name is + // undecorated. If the symbol's decorated form indicates the size of + // parameters on the stack, this information is returned in stack_param_size. + // Returns true on success. If the symbol doesn't encode parameter size + // information, stack_param_size is set to -1. + static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name, + int *stack_param_size); + + // Returns the number of bytes of stack space used for a function's + // parameters. function must have the tag SymTagFunction. In the event of + // a failure, returns 0, which is also a valid number of bytes. + static int GetFunctionStackParamSize(IDiaSymbol *function); + + // The session for the currently-open pdb file. + CComPtr session_; + + // The current output file for this WriteMap invocation. + FILE *output_; + + // Disallow copy ctor and operator= + PDBSourceLineWriter(const PDBSourceLineWriter&); + void operator=(const PDBSourceLineWriter&); +}; + +} // namespace google_breakpad + +#endif // _PDB_SOURCE_LINE_WRITER_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/windows/string_utils-inl.h b/thirdparty/google-breakpad/r318/src/common/windows/string_utils-inl.h new file mode 100644 index 00000000..6f650812 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/string_utils-inl.h @@ -0,0 +1,139 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// string_utils-inl.h: Safer string manipulation on Windows, supporting +// pre-MSVC8 environments. + +#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H__ +#define COMMON_WINDOWS_STRING_UTILS_INL_H__ + +#include +#include + +#include + +// The "ll" printf format size specifier corresponding to |long long| was +// intrudced in MSVC8. Earlier versions did not provide this size specifier, +// but "I64" can be used to print 64-bit types. Don't use "I64" where "ll" +// is available, in the event of oddball systems where |long long| is not +// 64 bits wide. +#if _MSC_VER >= 1400 // MSVC 2005/8 +#define WIN_STRING_FORMAT_LL "ll" +#else // MSC_VER >= 1400 +#define WIN_STRING_FORMAT_LL "I64" +#endif // MSC_VER >= 1400 + +// A nonconforming version of swprintf, without the length argument, was +// included with the CRT prior to MSVC8. Although a conforming version was +// also available via an overload, it is not reliably chosen. _snwprintf +// behaves as a standards-confirming swprintf should, so force the use of +// _snwprintf when using older CRTs. +#if _MSC_VER < 1400 // MSVC 2005/8 +#define swprintf _snwprintf +#else +// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently, +// it takes the same argument list as swprintf. +#define swprintf swprintf_s +#endif // MSC_VER < 1400 + +namespace google_breakpad { + +using std::string; +using std::wstring; + +class WindowsStringUtils { + public: + // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does + // not fail if source is longer than destination_size. The destination + // buffer is always 0-terminated. + static void safe_wcscpy(wchar_t *destination, size_t destination_size, + const wchar_t *source); + + // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot + // be passed directly, and pre-MSVC8, this will not fail if source or count + // are longer than destination_size. The destination buffer is always + // 0-terminated. + static void safe_wcsncpy(wchar_t *destination, size_t destination_size, + const wchar_t *source, size_t count); + + // Performs multi-byte to wide character conversion on C++ strings, using + // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8). Returns false on failure, + // without setting wcs. + static bool safe_mbstowcs(const string &mbs, wstring *wcs); + + // Returns the base name of a file, e.g. strips off the path. + static wstring GetBaseName(const wstring &filename); + + private: + // Disallow instantiation and other object-based operations. + WindowsStringUtils(); + WindowsStringUtils(const WindowsStringUtils&); + ~WindowsStringUtils(); + void operator=(const WindowsStringUtils&); +}; + +// static +inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination, + size_t destination_size, + const wchar_t *source) { +#if _MSC_VER >= 1400 // MSVC 2005/8 + wcscpy_s(destination, destination_size, source); +#else // _MSC_VER >= 1400 + // Pre-MSVC 2005/8 doesn't have wcscpy_s. Simulate it with wcsncpy. + // wcsncpy doesn't 0-terminate the destination buffer if the source string + // is longer than size. Ensure that the destination is 0-terminated. + wcsncpy(destination, source, destination_size); + if (destination && destination_size) + destination[destination_size - 1] = 0; +#endif // _MSC_VER >= 1400 +} + +// static +inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination, + size_t destination_size, + const wchar_t *source, + size_t count) { +#if _MSC_VER >= 1400 // MSVC 2005/8 + wcsncpy_s(destination, destination_size, source, count); +#else // _MSC_VER >= 1400 + // Pre-MSVC 2005/8 doesn't have wcsncpy_s. Simulate it with wcsncpy. + // wcsncpy doesn't 0-terminate the destination buffer if the source string + // is longer than size. Ensure that the destination is 0-terminated. + if (destination_size < count) + count = destination_size; + + wcsncpy(destination, source, count); + if (destination && count) + destination[count - 1] = 0; +#endif // _MSC_VER >= 1400 +} + +} // namespace google_breakpad + +#endif // COMMON_WINDOWS_STRING_UTILS_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/common/windows/string_utils.cc b/thirdparty/google-breakpad/r318/src/common/windows/string_utils.cc new file mode 100644 index 00000000..5d464802 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/common/windows/string_utils.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "common/windows/string_utils-inl.h" + +namespace google_breakpad { + +// static +wstring WindowsStringUtils::GetBaseName(const wstring &filename) { + wstring base_name(filename); + size_t slash_pos = base_name.find_last_of(L"/\\"); + if (slash_pos != wstring::npos) { + base_name.erase(0, slash_pos + 1); + } + return base_name; +} + +// static +bool WindowsStringUtils::safe_mbstowcs(const string &mbs, wstring *wcs) { + assert(wcs); + + // First, determine the length of the destination buffer. + size_t wcs_length; + +#if _MSC_VER >= 1400 // MSVC 2005/8 + errno_t err; + if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) { + return false; + } +#else // _MSC_VER >= 1400 + if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) < 0) { + return false; + } + + // Leave space for the 0-terminator. + ++wcs_length; +#endif // _MSC_VER >= 1400 + + // TODO(mmentovai): move scoped_ptr into common and use it for wcs_c. + wchar_t *wcs_c = new wchar_t[wcs_length]; + + // Now, convert. +#if _MSC_VER >= 1400 // MSVC 2005/8 + if ((err = mbstowcs_s(NULL, wcs_c, wcs_length, mbs.c_str(), + _TRUNCATE)) != 0) { + delete[] wcs_c; + return false; + } +#else // _MSC_VER >= 1400 + if (mbstowcs(wcs_c, mbs.c_str(), mbs.length()) < 0) { + delete[] wcs_c; + return false; + } + + // Ensure presence of 0-terminator. + wcs_c[wcs_length - 1] = '\0'; +#endif // _MSC_VER >= 1400 + + *wcs = wcs_c; + delete[] wcs_c; + return true; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/config.h b/thirdparty/google-breakpad/r318/src/config.h new file mode 100644 index 00000000..297bfc19 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/config.h @@ -0,0 +1,56 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +#define PACKAGE "breakpad" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "opensource@google.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "breakpad" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "breakpad 0.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "breakpad" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.1" diff --git a/thirdparty/google-breakpad/r318/src/config.h.in b/thirdparty/google-breakpad/r318/src/config.h.in new file mode 100644 index 00000000..6b4c3e48 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/config.h.in @@ -0,0 +1,55 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/breakpad_types.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/breakpad_types.h new file mode 100644 index 00000000..926b47f2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/breakpad_types.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* breakpad_types.h: Precise-width types + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file ensures that types u_intN_t are defined for N = 8, 16, 32, and + * 64. Types of precise widths are crucial to the task of writing data + * structures on one platform and reading them on another. + * + * Author: Mark Mentovai */ + +#ifndef GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ +#define GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ + +#ifndef _WIN32 + +#include +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif /* __STDC_FORMAT_MACROS */ +#include + +#if defined(__SUNPRO_CC) || (defined(__GNUC__) && defined(__sun__)) +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; +#endif + +#else /* !_WIN32 */ + +#include + +typedef unsigned __int8 u_int8_t; +typedef unsigned __int16 u_int16_t; +typedef unsigned __int32 u_int32_t; +typedef unsigned __int64 u_int64_t; + +#endif /* !_WIN32 */ + +typedef struct { + u_int64_t high; + u_int64_t low; +} u_int128_t; + +typedef u_int64_t breakpad_time_t; + +/* Try to get PRIx64 from inttypes.h, but if it's not defined, fall back to + * llx, which is the format string for "long long" - this is a 64-bit + * integral type on many systems. */ +#ifndef PRIx64 +#define PRIx64 "llx" +#endif /* !PRIx64 */ + +#endif /* GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_amd64.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_amd64.h new file mode 100644 index 00000000..75dae7dd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_amd64.h @@ -0,0 +1,231 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on amd64. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ + + +/* + * AMD64 support, see WINNT.H + */ + +typedef struct { + u_int16_t control_word; + u_int16_t status_word; + u_int8_t tag_word; + u_int8_t reserved1; + u_int16_t error_opcode; + u_int32_t error_offset; + u_int16_t error_selector; + u_int16_t reserved2; + u_int32_t data_offset; + u_int16_t data_selector; + u_int16_t reserved3; + u_int32_t mx_csr; + u_int32_t mx_csr_mask; + u_int128_t float_registers[8]; + u_int128_t xmm_registers[16]; + u_int8_t reserved4[96]; +} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */ + +#define MD_CONTEXT_AMD64_VR_COUNT 26 + +typedef struct { + /* + * Register parameter home addresses. + */ + u_int64_t p1_home; + u_int64_t p2_home; + u_int64_t p3_home; + u_int64_t p4_home; + u_int64_t p5_home; + u_int64_t p6_home; + + /* The next field determines the layout of the structure, and which parts + * of it are populated */ + u_int32_t context_flags; + u_int32_t mx_csr; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int16_t cs; + + /* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */ + u_int16_t ds; + u_int16_t es; + u_int16_t fs; + u_int16_t gs; + + /* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */ + u_int16_t ss; + u_int32_t eflags; + + /* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */ + u_int64_t dr0; + u_int64_t dr1; + u_int64_t dr2; + u_int64_t dr3; + u_int64_t dr6; + u_int64_t dr7; + + /* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */ + u_int64_t rax; + u_int64_t rcx; + u_int64_t rdx; + u_int64_t rbx; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int64_t rsp; + + /* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */ + u_int64_t rbp; + u_int64_t rsi; + u_int64_t rdi; + u_int64_t r8; + u_int64_t r9; + u_int64_t r10; + u_int64_t r11; + u_int64_t r12; + u_int64_t r13; + u_int64_t r14; + u_int64_t r15; + + /* The next register is included with MD_CONTEXT_AMD64_CONTROL */ + u_int64_t rip; + + /* The next set of registers are included with + * MD_CONTEXT_AMD64_FLOATING_POINT + */ + union { + MDXmmSaveArea32AMD64 flt_save; + struct { + u_int128_t header[2]; + u_int128_t legacy[8]; + u_int128_t xmm0; + u_int128_t xmm1; + u_int128_t xmm2; + u_int128_t xmm3; + u_int128_t xmm4; + u_int128_t xmm5; + u_int128_t xmm6; + u_int128_t xmm7; + u_int128_t xmm8; + u_int128_t xmm9; + u_int128_t xmm10; + u_int128_t xmm11; + u_int128_t xmm12; + u_int128_t xmm13; + u_int128_t xmm14; + u_int128_t xmm15; + } sse_registers; + }; + + u_int128_t vector_register[MD_CONTEXT_AMD64_VR_COUNT]; + u_int64_t vector_control; + + /* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */ + u_int64_t debug_control; + u_int64_t last_branch_to_rip; + u_int64_t last_branch_from_rip; + u_int64_t last_exception_to_rip; + u_int64_t last_exception_from_rip; + +} MDRawContextAMD64; /* CONTEXT */ + +/* For (MDRawContextAMD64).context_flags. These values indicate the type of + * context stored in the structure. The high 26 bits identify the CPU, the + * low 6 bits identify the type of context saved. */ +#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001) + /* CONTEXT_CONTROL */ +#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002) + /* CONTEXT_INTEGER */ +#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004) + /* CONTEXT_SEGMENTS */ +#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008) + /* CONTEXT_FLOATING_POINT */ +#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010) + /* CONTEXT_DEBUG_REGISTERS */ +/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it + * I think it really means CONTEXT_FLOATING_POINT. + */ + +#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \ + MD_CONTEXT_AMD64_INTEGER | \ + MD_CONTEXT_AMD64_FLOATING_POINT) + /* CONTEXT_FULL */ + +#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \ + MD_CONTEXT_AMD64_SEGMENTS | \ + MD_CONTEXT_X86_DEBUG_REGISTERS) + /* CONTEXT_ALL */ + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc.h new file mode 100644 index 00000000..038e921a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc.h @@ -0,0 +1,163 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on ppc. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +/* + * Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X' + * mach/ppc/_types.h + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ + +#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32 + +typedef struct { + /* fpregs is a double[32] in mach/ppc/_types.h, but a u_int64_t is used + * here for precise sizing. */ + u_int64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT]; + u_int32_t fpscr_pad; + u_int32_t fpscr; /* Status/control */ +} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */ + + +#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32 + +typedef struct { + /* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h + * exposes them as four 32-bit quantities. */ + u_int128_t save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT]; + u_int128_t save_vscr; /* Status/control */ + u_int32_t save_pad5[4]; + u_int32_t save_vrvalid; /* Identifies which vector registers are saved */ + u_int32_t save_pad6[7]; +} MDVectorSaveAreaPPC; /* ppc_vector_state */ + + +#define MD_CONTEXT_PPC_GPR_COUNT 32 + +/* Use the same 32-bit alignment when accessing this structure from 64-bit code + * as is used natively in 32-bit code. #pragma pack is a MSVC extension + * supported by gcc. */ +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#pragma pack(4) +#else +#pragma pack(push, 4) +#endif + +typedef struct { + /* context_flags is not present in ppc_thread_state, but it aids + * identification of MDRawContextPPC among other raw context types, + * and it guarantees alignment when we get to float_save. */ + u_int32_t context_flags; + + u_int32_t srr0; /* Machine status save/restore: stores pc + * (instruction) */ + u_int32_t srr1; /* Machine status save/restore: stores msr + * (ps, program/machine state) */ + /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is + * used for brevity. */ + u_int32_t gpr[MD_CONTEXT_PPC_GPR_COUNT]; + u_int32_t cr; /* Condition */ + u_int32_t xer; /* Integer (fiXed-point) exception */ + u_int32_t lr; /* Link */ + u_int32_t ctr; /* Count */ + u_int32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */ + u_int32_t vrsave; /* Vector save */ + + /* float_save and vector_save aren't present in ppc_thread_state, but + * are represented in separate structures that still define a thread's + * context. */ + MDFloatingSaveAreaPPC float_save; + MDVectorSaveAreaPPC vector_save; +} MDRawContextPPC; /* Based on ppc_thread_state */ + +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#pragma pack(0) +#else +#pragma pack(pop) +#endif + +/* For (MDRawContextPPC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_PPC 0x20000000 +#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) +#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) +#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020) + +#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE +#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \ + MD_CONTEXT_PPC_FLOATING_POINT | \ + MD_CONTEXT_PPC_VECTOR) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc64.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc64.h new file mode 100644 index 00000000..a788e5d1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_ppc64.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2008, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on ppc64. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Neal Sidhwaney */ + + +/* + * Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X' + * mach/ppc/_types.h + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ + +#include "minidump_cpu_ppc.h" + +// these types are the same in ppc64 & ppc +typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64; +typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64; + +#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT + +typedef struct { + /* context_flags is not present in ppc_thread_state, but it aids + * identification of MDRawContextPPC among other raw context types, + * and it guarantees alignment when we get to float_save. */ + u_int64_t context_flags; + + u_int64_t srr0; /* Machine status save/restore: stores pc + * (instruction) */ + u_int64_t srr1; /* Machine status save/restore: stores msr + * (ps, program/machine state) */ + /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is + * used for brevity. */ + u_int64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT]; + u_int64_t cr; /* Condition */ + u_int64_t xer; /* Integer (fiXed-point) exception */ + u_int64_t lr; /* Link */ + u_int64_t ctr; /* Count */ + u_int64_t vrsave; /* Vector save */ + + /* float_save and vector_save aren't present in ppc_thread_state, but + * are represented in separate structures that still define a thread's + * context. */ + MDFloatingSaveAreaPPC float_save; + MDVectorSaveAreaPPC vector_save; +} MDRawContextPPC64; /* Based on ppc_thread_state */ + +/* For (MDRawContextPPC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_PPC 0x20000000 +#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) +#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) +#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020) + +#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE +#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \ + MD_CONTEXT_PPC_FLOATING_POINT | \ + MD_CONTEXT_PPC_VECTOR) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_sparc.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_sparc.h new file mode 100644 index 00000000..ee95b64e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_sparc.h @@ -0,0 +1,158 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on sparc. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai + * Change to split into its own file: Neal Sidhwaney */ + +/* + * SPARC support, see (solaris)sys/procfs_isa.h also + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ + +#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32 + +typedef struct { + + /* FPU floating point regs */ + u_int64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT]; + + u_int64_t filler; + u_int64_t fsr; /* FPU status register */ +} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */ + +#define MD_CONTEXT_SPARC_GPR_COUNT 32 + +typedef struct { + /* The next field determines the layout of the structure, and which parts + * of it are populated + */ + u_int32_t context_flags; + u_int32_t flag_pad; + /* + * General register access (SPARC). + * Don't confuse definitions here with definitions in . + * Registers are 32 bits for ILP32, 64 bits for LP64. + * SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit + */ + + /* 32 Integer working registers */ + + /* g_r[0-7] global registers(g0-g7) + * g_r[8-15] out registers(o0-o7) + * g_r[16-23] local registers(l0-l7) + * g_r[24-31] in registers(i0-i7) + */ + u_int64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT]; + + /* several control registers */ + + /* Processor State register(PSR) for SPARC V7/V8 + * Condition Code register (CCR) for SPARC V9 + */ + u_int64_t ccr; + + u_int64_t pc; /* Program Counter register (PC) */ + u_int64_t npc; /* Next Program Counter register (nPC) */ + u_int64_t y; /* Y register (Y) */ + + /* Address Space Identifier register (ASI) for SPARC V9 + * WIM for SPARC V7/V8 + */ + u_int64_t asi; + + /* Floating-Point Registers State register (FPRS) for SPARC V9 + * TBR for for SPARC V7/V8 + */ + u_int64_t fprs; + + /* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */ + MDFloatingSaveAreaSPARC float_save; + +} MDRawContextSPARC; /* CONTEXT_SPARC */ + +/* For (MDRawContextSPARC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ +#define MD_CONTEXT_SPARC 0x10000000 +#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001) +#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002) +#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004) +#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008) + +#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \ + MD_CONTEXT_SPARC_INTEGER) + +#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \ + MD_CONTEXT_SAPARC_FLOATING_POINT | \ + MD_CONTEXT_SAPARC_EXTRA) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_x86.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_x86.h new file mode 100644 index 00000000..4dbc0e9a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_cpu_x86.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on x86. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by ensuring + * ensuring that all members are aligned on their natural boundaries. In + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ + +#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80 + /* SIZE_OF_80387_REGISTERS */ + +typedef struct { + u_int32_t control_word; + u_int32_t status_word; + u_int32_t tag_word; + u_int32_t error_offset; + u_int32_t error_selector; + u_int32_t data_offset; + u_int32_t data_selector; + + /* register_area contains eight 80-bit (x87 "long double") quantities for + * floating-point registers %st0 (%mm0) through %st7 (%mm7). */ + u_int8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE]; + u_int32_t cr0_npx_state; +} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */ + + +#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512 + /* MAXIMUM_SUPPORTED_EXTENSION */ + +typedef struct { + /* The next field determines the layout of the structure, and which parts + * of it are populated */ + u_int32_t context_flags; + + /* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */ + u_int32_t dr0; + u_int32_t dr1; + u_int32_t dr2; + u_int32_t dr3; + u_int32_t dr6; + u_int32_t dr7; + + /* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */ + MDFloatingSaveAreaX86 float_save; + + /* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */ + u_int32_t gs; + u_int32_t fs; + u_int32_t es; + u_int32_t ds; + /* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */ + u_int32_t edi; + u_int32_t esi; + u_int32_t ebx; + u_int32_t edx; + u_int32_t ecx; + u_int32_t eax; + + /* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */ + u_int32_t ebp; + u_int32_t eip; + u_int32_t cs; /* WinNT.h says "must be sanitized" */ + u_int32_t eflags; /* WinNT.h says "must be sanitized" */ + u_int32_t esp; + u_int32_t ss; + + /* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS. + * It contains vector (MMX/SSE) registers. It it laid out in the + * format used by the fxsave and fsrstor instructions, so it includes + * a copy of the x87 floating-point registers as well. See FXSAVE in + * "Intel Architecture Software Developer's Manual, Volume 2." */ + u_int8_t extended_registers[ + MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE]; +} MDRawContextX86; /* CONTEXT */ + +/* For (MDRawContextX86).context_flags. These values indicate the type of + * context stored in the structure. The high 26 bits identify the CPU, the + * low 6 bits identify the type of context saved. */ +#define MD_CONTEXT_X86 0x00010000 + /* CONTEXT_i386, CONTEXT_i486: identifies CPU */ +#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001) + /* CONTEXT_CONTROL */ +#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002) + /* CONTEXT_INTEGER */ +#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004) + /* CONTEXT_SEGMENTS */ +#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008) + /* CONTEXT_FLOATING_POINT */ +#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010) + /* CONTEXT_DEBUG_REGISTERS */ +#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020) + /* CONTEXT_EXTENDED_REGISTERS */ + +#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \ + MD_CONTEXT_X86_INTEGER | \ + MD_CONTEXT_X86_SEGMENTS) + /* CONTEXT_FULL */ + +#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \ + MD_CONTEXT_X86_FLOATING_POINT | \ + MD_CONTEXT_X86_DEBUG_REGISTERS | \ + MD_CONTEXT_X86_EXTENDED_REGISTERS) + /* CONTEXT_ALL */ + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_linux.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_linux.h new file mode 100644 index 00000000..d52c7519 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_linux.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_linux.h: A definition of exception codes for + * Linux + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +/* For (MDException).exception_code. These values come from bits/signum.h. + */ +typedef enum { + MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */ + MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */ + MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */ + MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */ + MD_EXCEPTION_CODE_LIN_SIGURG = 23, + /* Urgent condition on socket (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25, + /* File size limit exceeded (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */ + MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */ + MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */ + MD_EXCEPTION_CODE_LIN_SIGSYS = 31 /* Bad system call */ +} MDExceptionCodeLinux; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_mac.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_mac.h new file mode 100644 index 00000000..5fba44ca --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_mac.h @@ -0,0 +1,193 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_mac.h: A definition of exception codes for Mac + * OS X + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X + * support. Based on Darwin/Mac OS X' mach/exception_types.h. This is + * what Mac OS X calls an "exception", not a "code". */ +typedef enum { + /* Exception code. The high 16 bits of exception_code contains one of + * these values. */ + MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */ + /* EXC_BAD_ACCESS */ + MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */ + /* EXC_BAD_INSTRUCTION */ + MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */ + /* EXC_ARITHMETIC */ + MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */ + /* EXC_EMULATION */ + MD_EXCEPTION_MAC_SOFTWARE = 5, + /* EXC_SOFTWARE */ + MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */ + /* EXC_BREAKPOINT */ + MD_EXCEPTION_MAC_SYSCALL = 7, + /* EXC_SYSCALL */ + MD_EXCEPTION_MAC_MACH_SYSCALL = 8, + /* EXC_MACH_SYSCALL */ + MD_EXCEPTION_MAC_RPC_ALERT = 9 + /* EXC_RPC_ALERT */ +} MDExceptionMac; + +/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X + * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and + * mach/i386/exception.h. This is what Mac OS X calls a "code". */ +typedef enum { + /* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values + * from mach/kern_return.h. */ + MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1, + /* KERN_INVALID_ADDRESS */ + MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2, + /* KERN_PROTECTION_FAILURE */ + MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8, + /* KERN_NO_ACCESS */ + MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9, + /* KERN_MEMORY_FAILURE */ + MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10, + /* KERN_MEMORY_ERROR */ + + /* With MD_EXCEPTION_SOFTWARE */ + MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */ + MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */ + MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */ + + /* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101, + /* EXC_PPC_VM_PROT_READ */ + MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102, + /* EXC_PPC_BADSPACE */ + MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103, + /* EXC_PPC_UNALIGNED */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1, + /* EXC_PPC_INVALID_SYSCALL */ + MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2, + /* EXC_PPC_UNIPL_INST */ + MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3, + /* EXC_PPC_PRIVINST */ + MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4, + /* EXC_PPC_PRIVREG */ + MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5, + /* EXC_PPC_TRACE */ + MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6, + /* EXC_PPC_PERFMON */ + + /* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1, + /* EXC_PPC_OVERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2, + /* EXC_PPC_ZERO_DIVIDE */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3, + /* EXC_FLT_INEXACT */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4, + /* EXC_PPC_FLT_ZERO_DIVIDE */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5, + /* EXC_PPC_FLT_UNDERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6, + /* EXC_PPC_FLT_OVERFLOW */ + MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7, + /* EXC_PPC_FLT_NOT_A_NUMBER */ + + /* With MD_EXCEPTION_MAC_EMULATION on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8, + /* EXC_PPC_NOEMULATION */ + MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9, + /* EXC_PPC_ALTIVECASSIST */ + + /* With MD_EXCEPTION_MAC_SOFTWARE on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */ + MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */ + + /* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */ + MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt + * values below. */ + MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */ + + /* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */ + MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */ + MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */ + MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */ + MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */ + MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */ + MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */ + MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */ + MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */ + + /* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */ + MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */ + MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */ + + /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw + * x86 interrupt codes. Most of these are mapped to other Mach + * exceptions and codes, are handled, or should not occur in user space. + * A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */ + /* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */ + /* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */ + /* EXC_I386_NMIFLT = 2: should not occur in user space */ + /* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */ + /* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */ + /* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */ + /* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */ + /* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */ + /* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */ + /* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */ + MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10, + /* EXC_INVTSSFLT */ + MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11, + /* EXC_SEGNPFLT */ + MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12, + /* EXC_STKFLT */ + MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13, + /* EXC_GPFLT */ + /* EXC_I386_PGFLT = 14: should not occur in user space */ + /* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */ + MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17 + /* EXC_ALIGNFLT (for vector operations) */ + /* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */ + /* EXC_I386_ENDPERR = 33: should not occur */ +} MDExceptionCodeMac; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_solaris.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_solaris.h new file mode 100644 index 00000000..d48632ac --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_solaris.h @@ -0,0 +1,94 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_solaris.h: A definition of exception codes for + * Solaris + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h + */ +typedef enum { + MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */ + MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */ + MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */ + MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */ + MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */ + MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */ + MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */ + MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */ + MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */ + MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */ + MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */ + MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */ + MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */ + MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */ + MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */ + MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */ + MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */ + MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */ + MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */ + MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */ + MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */ + MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */ + MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */ + MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occured */ + MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */ + MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */ + MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */ + MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */ + MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */ + MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */ + MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */ + MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */ + MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */ + MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */ + MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */ + MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */ + MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */ + MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */ + MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */ + MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */ + MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */ + MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */ + MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */ +} MDExceptionCodeSolaris; + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_win32.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_win32.h new file mode 100644 index 00000000..7fd4bc4f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_exception_win32.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_exception_win32.h: Definitions of exception codes for + * Win32 platform + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Author: Mark Mentovai + * Split into its own file: Neal Sidhwaney */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +/* For (MDException).exception_code. These values come from WinBase.h + * and WinNT.h (names beginning with EXCEPTION_ are in WinBase.h, + * they are STATUS_ in WinNT.h). */ +typedef enum { + MD_EXCEPTION_CODE_WIN_CONTROL_C = 0x40010005, + /* DBG_CONTROL_C */ + MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001, + /* EXCEPTION_GUARD_PAGE */ + MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002, + /* EXCEPTION_DATATYPE_MISALIGNMENT */ + MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003, + /* EXCEPTION_BREAKPOINT */ + MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004, + /* EXCEPTION_SINGLE_STEP */ + MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION = 0xc0000005, + /* EXCEPTION_ACCESS_VIOLATION */ + MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR = 0xc0000006, + /* EXCEPTION_IN_PAGE_ERROR */ + MD_EXCEPTION_CODE_WIN_INVALID_HANDLE = 0xc0000008, + /* EXCEPTION_INVALID_HANDLE */ + MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION = 0xc000001d, + /* EXCEPTION_ILLEGAL_INSTRUCTION */ + MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION = 0xc0000025, + /* EXCEPTION_NONCONTINUABLE_EXCEPTION */ + MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION = 0xc0000026, + /* EXCEPTION_INVALID_DISPOSITION */ + MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED = 0xc000008c, + /* EXCEPTION_BOUNDS_EXCEEDED */ + MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND = 0xc000008d, + /* EXCEPTION_FLT_DENORMAL_OPERAND */ + MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO = 0xc000008e, + /* EXCEPTION_FLT_DIVIDE_BY_ZERO */ + MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT = 0xc000008f, + /* EXCEPTION_FLT_INEXACT_RESULT */ + MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION = 0xc0000090, + /* EXCEPTION_FLT_INVALID_OPERATION */ + MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW = 0xc0000091, + /* EXCEPTION_FLT_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK = 0xc0000092, + /* EXCEPTION_FLT_STACK_CHECK */ + MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW = 0xc0000093, + /* EXCEPTION_FLT_UNDERFLOW */ + MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094, + /* EXCEPTION_INT_DIVIDE_BY_ZERO */ + MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095, + /* EXCEPTION_INT_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096, + /* EXCEPTION_PRIV_INSTRUCTION */ + MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd, + /* EXCEPTION_STACK_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194 + /* EXCEPTION_POSSIBLE_DEADLOCK */ +} MDExceptionCodeWin; + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_format.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_format.h new file mode 100644 index 00000000..4d9e767f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_format.h @@ -0,0 +1,721 @@ +/* Copyright (c) 2006, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * These definitions may be extended to support handling minidump files + * for other CPUs and other operating systems. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably in terms of interoperability with minidumps + * produced by DbgHelp on Windows, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. DbgHelp + * on Windows is assumed to be the reference implementation; this file + * seeks to provide a cross-platform compatible implementation. To avoid + * collisions with the types and values defined and used by DbgHelp in the + * event that this implementation is used on Windows, each type and value + * defined here is given a new name, beginning with "MD". Names of the + * equivalent types and values in the Windows Platform SDK are given in + * comments. + * + * Author: Mark Mentovai */ + + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + + +#if defined(_MSC_VER) +/* Disable "zero-sized array in struct/union" warnings when compiling in + * MSVC. DbgHelp.h does this too. */ +#pragma warning(push) +#pragma warning(disable:4200) +#endif /* _MSC_VER */ + + +/* + * guiddef.h + */ + +typedef struct { + u_int32_t data1; + u_int16_t data2; + u_int16_t data3; + u_int8_t data4[8]; +} MDGUID; /* GUID */ + + +/* + * WinNT.h + */ + +/* Non-x86 CPU identifiers found in the high 26 bits of + * (MDRawContext*).context_flags. These aren't used by Breakpad, but are + * defined here for reference, to avoid assigning values that conflict + * (although some values already conflict). */ +#define MD_CONTEXT_IA64 0x00080000 /* CONTEXT_IA64 */ +#define MD_CONTEXT_AMD64 0x00100000 /* CONTEXT_AMD64 */ +/* Additional values from winnt.h in the Windows CE 5.0 SDK: */ +#define MD_CONTEXT_SHX 0x000000c0 /* CONTEXT_SH4 (Super-H, includes SH3) */ +#define MD_CONTEXT_ARM 0x00000040 /* CONTEXT_ARM (0x40 bit set in SHx?) */ +#define MD_CONTEXT_MIPS 0x00010000 /* CONTEXT_R4000 (same value as x86?) */ +#define MD_CONTEXT_ALPHA 0x00020000 /* CONTEXT_ALPHA */ + +#define MD_CONTEXT_CPU_MASK 0xffffffc0 + + +/* This is a base type for MDRawContextX86 and MDRawContextPPC. This + * structure should never be allocated directly. The actual structure type + * can be determined by examining the context_flags field. */ +typedef struct { + u_int32_t context_flags; +} MDRawContextBase; + +#include "minidump_cpu_sparc.h" +#include "minidump_cpu_x86.h" +#include "minidump_cpu_ppc.h" +#include "minidump_cpu_ppc64.h" +#include "minidump_cpu_amd64.h" + + +/* + * WinVer.h + */ + + +typedef struct { + u_int32_t signature; + u_int32_t struct_version; + u_int32_t file_version_hi; + u_int32_t file_version_lo; + u_int32_t product_version_hi; + u_int32_t product_version_lo; + u_int32_t file_flags_mask; /* Identifies valid bits in fileFlags */ + u_int32_t file_flags; + u_int32_t file_os; + u_int32_t file_type; + u_int32_t file_subtype; + u_int32_t file_date_hi; + u_int32_t file_date_lo; +} MDVSFixedFileInfo; /* VS_FIXEDFILEINFO */ + +/* For (MDVSFixedFileInfo).signature */ +#define MD_VSFIXEDFILEINFO_SIGNATURE 0xfeef04bd + /* VS_FFI_SIGNATURE */ + +/* For (MDVSFixedFileInfo).version */ +#define MD_VSFIXEDFILEINFO_VERSION 0x00010000 + /* VS_FFI_STRUCVERSION */ + +/* For (MDVSFixedFileInfo).file_flags_mask and + * (MDVSFixedFileInfo).file_flags */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG 0x00000001 + /* VS_FF_DEBUG */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRERELEASE 0x00000002 + /* VS_FF_PRERELEASE */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PATCHED 0x00000004 + /* VS_FF_PATCHED */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRIVATEBUILD 0x00000008 + /* VS_FF_PRIVATEBUILD */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_INFOINFERRED 0x00000010 + /* VS_FF_INFOINFERRED */ +#define MD_VSFIXEDFILEINFO_FILE_FLAGS_SPECIALBUILD 0x00000020 + /* VS_FF_SPECIALBUILD */ + +/* For (MDVSFixedFileInfo).file_os: high 16 bits */ +#define MD_VSFIXEDFILEINFO_FILE_OS_UNKNOWN 0 /* VOS_UNKNOWN */ +#define MD_VSFIXEDFILEINFO_FILE_OS_DOS (1 << 16) /* VOS_DOS */ +#define MD_VSFIXEDFILEINFO_FILE_OS_OS216 (2 << 16) /* VOS_OS216 */ +#define MD_VSFIXEDFILEINFO_FILE_OS_OS232 (3 << 16) /* VOS_OS232 */ +#define MD_VSFIXEDFILEINFO_FILE_OS_NT (4 << 16) /* VOS_NT */ +#define MD_VSFIXEDFILEINFO_FILE_OS_WINCE (5 << 16) /* VOS_WINCE */ +/* Low 16 bits */ +#define MD_VSFIXEDFILEINFO_FILE_OS__BASE 0 /* VOS__BASE */ +#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS16 1 /* VOS__WINDOWS16 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__PM16 2 /* VOS__PM16 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__PM32 3 /* VOS__PM32 */ +#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32 4 /* VOS__WINDOWS32 */ + +/* For (MDVSFixedFileInfo).file_type */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_UNKNOWN 0 /* VFT_UNKNOWN */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_APP 1 /* VFT_APP */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_DLL 2 /* VFT_DLL */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_DRV 3 /* VFT_DLL */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_FONT 4 /* VFT_FONT */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_VXD 5 /* VFT_VXD */ +#define MD_VSFIXEDFILEINFO_FILE_TYPE_STATIC_LIB 7 /* VFT_STATIC_LIB */ + +/* For (MDVSFixedFileInfo).file_subtype */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN 0 + /* VFT2_UNKNOWN */ +/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_DRV */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_PRINTER 1 + /* VFT2_DRV_PRINTER */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_KEYBOARD 2 + /* VFT2_DRV_KEYBOARD */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_LANGUAGE 3 + /* VFT2_DRV_LANGUAGE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_DISPLAY 4 + /* VFT2_DRV_DISPLAY */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_MOUSE 5 + /* VFT2_DRV_MOUSE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_NETWORK 6 + /* VFT2_DRV_NETWORK */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SYSTEM 7 + /* VFT2_DRV_SYSTEM */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INSTALLABLE 8 + /* VFT2_DRV_INSTALLABLE */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SOUND 9 + /* VFT2_DRV_SOUND */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_COMM 10 + /* VFT2_DRV_COMM */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INPUTMETHOD 11 + /* VFT2_DRV_INPUTMETHOD */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_VERSIONED_PRINTER 12 + /* VFT2_DRV_VERSIONED_PRINTER */ +/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_FONT */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_RASTER 1 + /* VFT2_FONT_RASTER */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_VECTOR 2 + /* VFT2_FONT_VECTOR */ +#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_TRUETYPE 3 + /* VFT2_FONT_TRUETYPE */ + + +/* + * DbgHelp.h + */ + + +/* An MDRVA is an offset into the minidump file. The beginning of the + * MDRawHeader is at offset 0. */ +typedef u_int32_t MDRVA; /* RVA */ + +typedef struct { + u_int32_t data_size; + MDRVA rva; +} MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */ + + +typedef struct { + /* The base address of the memory range on the host that produced the + * minidump. */ + u_int64_t start_of_memory_range; + + MDLocationDescriptor memory; +} MDMemoryDescriptor; /* MINIDUMP_MEMORY_DESCRIPTOR */ + + +typedef struct { + u_int32_t signature; + u_int32_t version; + u_int32_t stream_count; + MDRVA stream_directory_rva; /* A |stream_count|-sized array of + * MDRawDirectory structures. */ + u_int32_t checksum; /* Can be 0. In fact, that's all that's + * been found in minidump files. */ + u_int32_t time_date_stamp; /* time_t */ + u_int64_t flags; +} MDRawHeader; /* MINIDUMP_HEADER */ + +/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the + * low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION. Per the + * documentation, the high 16 bits are implementation-specific. */ +#define MD_HEADER_SIGNATURE 0x504d444d /* 'PMDM' */ + /* MINIDUMP_SIGNATURE */ +#define MD_HEADER_VERSION 0x0000a793 /* 42899 */ + /* MINIDUMP_VERSION */ + +/* For (MDRawHeader).flags: */ +typedef enum { + /* MD_NORMAL is the standard type of minidump. It includes full + * streams for the thread list, module list, exception, system info, + * and miscellaneous info. A memory list stream is also present, + * pointing to the same stack memory contained in the thread list, + * as well as a 256-byte region around the instruction address that + * was executing when the exception occurred. Stack memory is from + * 4 bytes below a thread's stack pointer up to the top of the + * memory region encompassing the stack. */ + MD_NORMAL = 0x00000000, + MD_WITH_DATA_SEGS = 0x00000001, + MD_WITH_FULL_MEMORY = 0x00000002, + MD_WITH_HANDLE_DATA = 0x00000004, + MD_FILTER_MEMORY = 0x00000008, + MD_SCAN_MEMORY = 0x00000010, + MD_WITH_UNLOADED_MODULES = 0x00000020, + MD_WITH_INDIRECTLY_REFERENCED_MEMORY = 0x00000040, + MD_FILTER_MODULE_PATHS = 0x00000080, + MD_WITH_PROCESS_THREAD_DATA = 0x00000100, + MD_WITH_PRIVATE_READ_WRITE_MEMORY = 0x00000200, + MD_WITHOUT_OPTIONAL_DATA = 0x00000400, + MD_WITH_FULL_MEMORY_INFO = 0x00000800, + MD_WITH_THREAD_INFO = 0x00001000, + MD_WITH_CODE_SEGS = 0x00002000 +} MDType; /* MINIDUMP_TYPE */ + + +typedef struct { + u_int32_t stream_type; + MDLocationDescriptor location; +} MDRawDirectory; /* MINIDUMP_DIRECTORY */ + +/* For (MDRawDirectory).stream_type */ +typedef enum { + MD_UNUSED_STREAM = 0, + MD_RESERVED_STREAM_0 = 1, + MD_RESERVED_STREAM_1 = 2, + MD_THREAD_LIST_STREAM = 3, /* MDRawThreadList */ + MD_MODULE_LIST_STREAM = 4, /* MDRawModuleList */ + MD_MEMORY_LIST_STREAM = 5, /* MDRawMemoryList */ + MD_EXCEPTION_STREAM = 6, /* MDRawExceptionStream */ + MD_SYSTEM_INFO_STREAM = 7, /* MDRawSystemInfo */ + MD_THREAD_EX_LIST_STREAM = 8, + MD_MEMORY_64_LIST_STREAM = 9, + MD_COMMENT_STREAM_A = 10, + MD_COMMENT_STREAM_W = 11, + MD_HANDLE_DATA_STREAM = 12, + MD_FUNCTION_TABLE_STREAM = 13, + MD_UNLOADED_MODULE_LIST_STREAM = 14, + MD_MISC_INFO_STREAM = 15, /* MDRawMiscInfo */ + MD_LAST_RESERVED_STREAM = 0x0000ffff, + + /* Breakpad extension types. 0x4767 = "Gg" */ + MD_BREAKPAD_INFO_STREAM = 0x47670001, /* MDRawBreakpadInfo */ + MD_ASSERTION_INFO_STREAM = 0x47670002 /* MDRawAssertionInfo */ +} MDStreamType; /* MINIDUMP_STREAM_TYPE */ + + +typedef struct { + u_int32_t length; /* Length of buffer in bytes (not characters), + * excluding 0-terminator */ + u_int16_t buffer[1]; /* UTF-16-encoded, 0-terminated */ +} MDString; /* MINIDUMP_STRING */ + +static const size_t MDString_minsize = offsetof(MDString, buffer[0]); + + +typedef struct { + u_int32_t thread_id; + u_int32_t suspend_count; + u_int32_t priority_class; + u_int32_t priority; + u_int64_t teb; /* Thread environment block */ + MDMemoryDescriptor stack; + MDLocationDescriptor thread_context; /* MDRawContext[CPU] */ +} MDRawThread; /* MINIDUMP_THREAD */ + + +typedef struct { + u_int32_t number_of_threads; + MDRawThread threads[1]; +} MDRawThreadList; /* MINIDUMP_THREAD_LIST */ + +static const size_t MDRawThreadList_minsize = offsetof(MDRawThreadList, + threads[0]); + + +typedef struct { + u_int64_t base_of_image; + u_int32_t size_of_image; + u_int32_t checksum; /* 0 if unknown */ + u_int32_t time_date_stamp; /* time_t */ + MDRVA module_name_rva; /* MDString, pathname or filename */ + MDVSFixedFileInfo version_info; + + /* The next field stores a CodeView record and is populated when a module's + * debug information resides in a PDB file. It identifies the PDB file. */ + MDLocationDescriptor cv_record; + + /* The next field is populated when a module's debug information resides + * in a DBG file. It identifies the DBG file. This field is effectively + * obsolete with modules built by recent toolchains. */ + MDLocationDescriptor misc_record; + + /* Alignment problem: reserved0 and reserved1 are defined by the platform + * SDK as 64-bit quantities. However, that results in a structure whose + * alignment is unpredictable on different CPUs and ABIs. If the ABI + * specifies full alignment of 64-bit quantities in structures (as ppc + * does), there will be padding between miscRecord and reserved0. If + * 64-bit quantities can be aligned on 32-bit boundaries (as on x86), + * this padding will not exist. (Note that the structure up to this point + * contains 1 64-bit member followed by 21 32-bit members.) + * As a workaround, reserved0 and reserved1 are instead defined here as + * four 32-bit quantities. This should be harmless, as there are + * currently no known uses for these fields. */ + u_int32_t reserved0[2]; + u_int32_t reserved1[2]; +} MDRawModule; /* MINIDUMP_MODULE */ + +/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to + * be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC). + * This doesn't occur on systems that don't tail-pad in this manner. Define + * this macro to be the usable size of the MDRawModule struct, and use it in + * place of sizeof(MDRawModule). */ +#define MD_MODULE_SIZE 108 + + +/* (MDRawModule).cv_record can reference MDCVInfoPDB20 or MDCVInfoPDB70. + * Ref.: http://www.debuginfo.com/articles/debuginfomatch.html + * MDCVInfoPDB70 is the expected structure type with recent toolchains. */ + +typedef struct { + u_int32_t signature; + u_int32_t offset; /* Offset to debug data (expect 0 in minidump) */ +} MDCVHeader; + +typedef struct { + MDCVHeader cv_header; + u_int32_t signature; /* time_t debug information created */ + u_int32_t age; /* revision of PDB file */ + u_int8_t pdb_file_name[1]; /* Pathname or filename of PDB file */ +} MDCVInfoPDB20; + +static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20, + pdb_file_name[0]); + +#define MD_CVINFOPDB20_SIGNATURE 0x3031424e /* cvHeader.signature = '01BN' */ + +typedef struct { + u_int32_t cv_signature; + MDGUID signature; /* GUID, identifies PDB file */ + u_int32_t age; /* Identifies incremental changes to PDB file */ + u_int8_t pdb_file_name[1]; /* Pathname or filename of PDB file, + * 0-terminated 8-bit character data (UTF-8?) */ +} MDCVInfoPDB70; + +static const size_t MDCVInfoPDB70_minsize = offsetof(MDCVInfoPDB70, + pdb_file_name[0]); + +#define MD_CVINFOPDB70_SIGNATURE 0x53445352 /* cvSignature = 'SDSR' */ + +typedef struct { + u_int32_t data1[2]; + u_int32_t data2; + u_int32_t data3; + u_int32_t data4; + u_int32_t data5[3]; + u_int8_t extra[2]; +} MDCVInfoELF; + +/* In addition to the two CodeView record formats above, used for linking + * to external pdb files, it is possible for debugging data to be carried + * directly in the CodeView record itself. These signature values will + * be found in the first 4 bytes of the CodeView record. Additional values + * not commonly experienced in the wild are given by "Microsoft Symbol and + * Type Information", http://www.x86.org/ftp/manuals/tools/sym.pdf, section + * 7.2. An in-depth description of the CodeView 4.1 format is given by + * "Undocumented Windows 2000 Secrets", Windows 2000 Debugging Support/ + * Microsoft Symbol File Internals/CodeView Subsections, + * http://www.rawol.com/features/undocumented/sbs-w2k-1-windows-2000-debugging-support.pdf + */ +#define MD_CVINFOCV41_SIGNATURE 0x3930424e /* '90BN', CodeView 4.10. */ +#define MD_CVINFOCV50_SIGNATURE 0x3131424e /* '11BN', CodeView 5.0, + * MS C7-format (/Z7). */ + +#define MD_CVINFOUNKNOWN_SIGNATURE 0xffffffff /* An unlikely value. */ + +/* (MDRawModule).miscRecord can reference MDImageDebugMisc. The Windows + * structure is actually defined in WinNT.h. This structure is effectively + * obsolete with modules built by recent toolchains. */ + +typedef struct { + u_int32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because + * this debug record type is mostly obsolete. */ + u_int32_t length; /* Length of entire MDImageDebugMisc structure */ + u_int8_t unicode; /* True if data is multibyte */ + u_int8_t reserved[3]; + u_int8_t data[1]; +} MDImageDebugMisc; /* IMAGE_DEBUG_MISC */ + +static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc, + data[0]); + + +typedef struct { + u_int32_t number_of_modules; + MDRawModule modules[1]; +} MDRawModuleList; /* MINIDUMP_MODULE_LIST */ + +static const size_t MDRawModuleList_minsize = offsetof(MDRawModuleList, + modules[0]); + + +typedef struct { + u_int32_t number_of_memory_ranges; + MDMemoryDescriptor memory_ranges[1]; +} MDRawMemoryList; /* MINIDUMP_MEMORY_LIST */ + +static const size_t MDRawMemoryList_minsize = offsetof(MDRawMemoryList, + memory_ranges[0]); + + +#define MD_EXCEPTION_MAXIMUM_PARAMETERS 15 + +typedef struct { + u_int32_t exception_code; /* Windows: MDExceptionCodeWin, + * Mac OS X: MDExceptionMac, + * Linux: MDExceptionCodeLinux. */ + u_int32_t exception_flags; /* Windows: 1 if noncontinuable, + Mac OS X: MDExceptionCodeMac. */ + u_int64_t exception_record; /* Address (in the minidump-producing host's + * memory) of another MDException, for + * nested exceptions. */ + u_int64_t exception_address; /* The address that caused the exception. + * Mac OS X: exception subcode (which is + * typically the address). */ + u_int32_t number_parameters; /* Number of valid elements in + * exception_information. */ + u_int32_t __align; + u_int64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS]; +} MDException; /* MINIDUMP_EXCEPTION */ + +#include "minidump_exception_win32.h" +#include "minidump_exception_mac.h" +#include "minidump_exception_linux.h" +#include "minidump_exception_solaris.h" + +typedef struct { + u_int32_t thread_id; /* Thread in which the exception + * occurred. Corresponds to + * (MDRawThread).thread_id. */ + u_int32_t __align; + MDException exception_record; + MDLocationDescriptor thread_context; /* MDRawContext[CPU] */ +} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */ + + +typedef union { + struct { + u_int32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ + u_int32_t version_information; /* cpuid 1: eax */ + u_int32_t feature_information; /* cpuid 1: edx */ + u_int32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ + } x86_cpu_info; + struct { + u_int64_t processor_features[2]; + } other_cpu_info; +} MDCPUInformation; /* CPU_INFORMATION */ + + +typedef struct { + /* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO + * structure as returned by GetSystemInfo */ + u_int16_t processor_architecture; + u_int16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */ + u_int16_t processor_revision; /* x86: 0xMMSS, where MM=model, + * SS=stepping */ + + u_int8_t number_of_processors; + u_int8_t product_type; /* Windows: VER_NT_* from WinNT.h */ + + /* The next 5 fields are from the OSVERSIONINFO structure as returned + * by GetVersionEx */ + u_int32_t major_version; + u_int32_t minor_version; + u_int32_t build_number; + u_int32_t platform_id; + MDRVA csd_version_rva; /* MDString further identifying the + * host OS. + * Windows: name of the installed OS + * service pack. + * Mac OS X: the Apple OS build number + * (sw_vers -buildVersion). + * Linux: uname -srvmo */ + + u_int16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */ + u_int16_t reserved2; + + MDCPUInformation cpu; +} MDRawSystemInfo; /* MINIDUMP_SYSTEM_INFO */ + +/* For (MDRawSystemInfo).processor_architecture: */ +typedef enum { + MD_CPU_ARCHITECTURE_X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ + MD_CPU_ARCHITECTURE_MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ + MD_CPU_ARCHITECTURE_ALPHA = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ + MD_CPU_ARCHITECTURE_PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ + MD_CPU_ARCHITECTURE_SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX + * (Super-H) */ + MD_CPU_ARCHITECTURE_ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ + MD_CPU_ARCHITECTURE_IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ + MD_CPU_ARCHITECTURE_ALPHA64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ + MD_CPU_ARCHITECTURE_MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL + * (Microsoft Intermediate Language) */ + MD_CPU_ARCHITECTURE_AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ + MD_CPU_ARCHITECTURE_X86_WIN64 = 10, + /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ + MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */ + MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ +} MDCPUArchitecture; + +/* For (MDRawSystemInfo).platform_id: */ +typedef enum { + MD_OS_WIN32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ + MD_OS_WIN32_WINDOWS = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ + MD_OS_WIN32_NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ + MD_OS_WIN32_CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH + * (Windows CE, Windows Mobile, "Handheld") */ + + /* The following values are Breakpad-defined. */ + MD_OS_UNIX = 0x8000, /* Generic Unix-ish */ + MD_OS_MAC_OS_X = 0x8101, /* Mac OS X/Darwin */ + MD_OS_LINUX = 0x8201, /* Linux */ + MD_OS_SOLARIS = 0x8202 /* Solaris */ +} MDOSPlatform; + + +typedef struct { + u_int32_t size_of_info; /* Length of entire MDRawMiscInfo structure. */ + u_int32_t flags1; + + /* The next field is only valid if flags1 contains + * MD_MISCINFO_FLAGS1_PROCESS_ID. */ + u_int32_t process_id; + + /* The next 3 fields are only valid if flags1 contains + * MD_MISCINFO_FLAGS1_PROCESS_TIMES. */ + u_int32_t process_create_time; /* time_t process started */ + u_int32_t process_user_time; /* seconds of user CPU time */ + u_int32_t process_kernel_time; /* seconds of kernel CPU time */ + + /* The following fields are not present in MINIDUMP_MISC_INFO but are + * in MINIDUMP_MISC_INFO_2. When this struct is populated, these values + * may not be set. Use flags1 or sizeOfInfo to determine whether these + * values are present. These are only valid when flags1 contains + * MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO. */ + u_int32_t processor_max_mhz; + u_int32_t processor_current_mhz; + u_int32_t processor_mhz_limit; + u_int32_t processor_max_idle_state; + u_int32_t processor_current_idle_state; +} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO2 */ + +#define MD_MISCINFO_SIZE 24 +#define MD_MISCINFO2_SIZE 44 + +/* For (MDRawMiscInfo).flags1. These values indicate which fields in the + * MDRawMiscInfoStructure are valid. */ +typedef enum { + MD_MISCINFO_FLAGS1_PROCESS_ID = 0x00000001, + /* MINIDUMP_MISC1_PROCESS_ID */ + MD_MISCINFO_FLAGS1_PROCESS_TIMES = 0x00000002, + /* MINIDUMP_MISC1_PROCESS_TIMES */ + MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO = 0x00000004 + /* MINIDUMP_MISC1_PROCESSOR_POWER_INFO */ +} MDMiscInfoFlags1; + + +/* + * Breakpad extension types + */ + + +typedef struct { + /* validity is a bitmask with values from MDBreakpadInfoValidity, indicating + * which of the other fields in the structure are valid. */ + u_int32_t validity; + + /* Thread ID of the handler thread. dump_thread_id should correspond to + * the thread_id of an MDRawThread in the minidump's MDRawThreadList if + * a dedicated thread in that list was used to produce the minidump. If + * the MDRawThreadList does not contain a dedicated thread used to produce + * the minidump, this field should be set to 0 and the validity field + * must not contain MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID. */ + u_int32_t dump_thread_id; + + /* Thread ID of the thread that requested the minidump be produced. As + * with dump_thread_id, requesting_thread_id should correspond to the + * thread_id of an MDRawThread in the minidump's MDRawThreadList. For + * minidumps produced as a result of an exception, requesting_thread_id + * will be the same as the MDRawExceptionStream's thread_id field. For + * minidumps produced "manually" at the program's request, + * requesting_thread_id will indicate which thread caused the dump to be + * written. If the minidump was produced at the request of something + * other than a thread in the MDRawThreadList, this field should be set + * to 0 and the validity field must not contain + * MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID. */ + u_int32_t requesting_thread_id; +} MDRawBreakpadInfo; + +/* For (MDRawBreakpadInfo).validity: */ +typedef enum { + /* When set, the dump_thread_id field is valid. */ + MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID = 1 << 0, + + /* When set, the requesting_thread_id field is valid. */ + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID = 1 << 1 +} MDBreakpadInfoValidity; + +typedef struct { + /* expression, function, and file are 0-terminated UTF-16 strings. They + * may be truncated if necessary, but should always be 0-terminated when + * written to a file. + * Fixed-length strings are used because MiniDumpWriteDump doesn't offer + * a way for user streams to point to arbitrary RVAs for strings. */ + u_int16_t expression[128]; /* Assertion that failed... */ + u_int16_t function[128]; /* ...within this function... */ + u_int16_t file[128]; /* ...in this file... */ + u_int32_t line; /* ...at this line. */ + u_int32_t type; +} MDRawAssertionInfo; + +/* For (MDRawAssertionInfo).type: */ +typedef enum { + MD_ASSERTION_INFO_TYPE_UNKNOWN = 0, + + /* Used for assertions that would be raised by the MSVC CRT but are + * directed to an invalid parameter handler instead. */ + MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER, + + /* Used for assertions that would be raised by the MSVC CRT but are + * directed to a pure virtual call handler instead. */ + MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL +} MDAssertionInfoData; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ */ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_size.h b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_size.h new file mode 100644 index 00000000..918544b6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/common/minidump_size.h @@ -0,0 +1,107 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// minidump_size.h: Provides a C++ template for programmatic access to +// the sizes of various types defined in minidump_format.h. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ + +#include + +#include "google_breakpad/common/minidump_format.h" + +namespace google_breakpad { + +template +class minidump_size { + public: + static size_t size() { return sizeof(T); } +}; + +// Explicit specializations for variable-length types. The size returned +// for these should be the size for an object without its variable-length +// section. + +template<> +class minidump_size { + public: + static size_t size() { return MDString_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawThreadList_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDCVInfoPDB20_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDCVInfoPDB70_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDImageDebugMisc_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawModuleList_minsize; } +}; + +template<> +class minidump_size { + public: + static size_t size() { return MDRawMemoryList_minsize; } +}; + +// Explicit specialization for MDRawModule, for which sizeof may include +// tail-padding on some architectures but not others. + +template<> +class minidump_size { + public: + static size_t size() { return MD_MODULE_SIZE; } +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/basic_source_line_resolver.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/basic_source_line_resolver.h new file mode 100644 index 00000000..38759579 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/basic_source_line_resolver.h @@ -0,0 +1,114 @@ +// 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. + +// BasicSourceLineResolver implements SourceLineResolverInterface, using +// address map files produced by a compatible writer, e.g. PDBSourceLineWriter. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ + +// TODO: Platforms that have no hash_map can use map, at the likely cost of +// performance. +#ifdef __SUNPRO_CC +#define BSLR_NO_HASH_MAP +#endif // __SUNPRO_CC + +#ifdef BSLR_NO_HASH_MAP +#include +#else // BSLR_NO_HASH_MAP +#include +#endif // BSLR_NO_HASH_MAP + +#include "google_breakpad/processor/source_line_resolver_interface.h" + +namespace google_breakpad { + +using std::string; +#ifdef BSLR_NO_HASH_MAP +using std::map; +#else // BSLR_NO_HASH_MAP +using __gnu_cxx::hash_map; +#endif // BSLR_NO_HASH_MAP + +class BasicSourceLineResolver : public SourceLineResolverInterface { + public: + BasicSourceLineResolver(); + virtual ~BasicSourceLineResolver(); + + // SourceLineResolverInterface methods, see source_line_resolver_interface.h + // for more details. + + // Adds a module to this resolver, returning true on success. + // The given map_file is read into memory, and its symbols will be + // retained until the BasicSourceLineResolver is destroyed. + virtual bool LoadModule(const string &module_name, const string &map_file); + + // Exactly the same as above, except the given map_buffer is used + // for symbols. + virtual bool LoadModuleUsingMapBuffer(const string &module_name, + const string &map_buffer); + + + virtual bool HasModule(const string &module_name) const; + + virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const; + + private: + template class MemAddrMap; + struct Line; + struct Function; + struct PublicSymbol; + struct File; +#ifdef BSLR_NO_HASH_MAP + struct CompareString { + bool operator()(const string &s1, const string &s2) const; + }; +#else // BSLR_NO_HASH_MAP + struct HashString { + size_t operator()(const string &s) const; + }; +#endif // BSLR_NO_HASH_MAP + class Module; + + // All of the modules we've loaded +#ifdef BSLR_NO_HASH_MAP + typedef map ModuleMap; +#else // BSLR_NO_HASH_MAP + typedef hash_map ModuleMap; +#endif // BSLR_NO_HASH_MAP + ModuleMap *modules_; + + // Disallow unwanted copy ctor and assignment operator + BasicSourceLineResolver(const BasicSourceLineResolver&); + void operator=(const BasicSourceLineResolver&); +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/call_stack.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/call_stack.h new file mode 100644 index 00000000..21f595e7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/call_stack.h @@ -0,0 +1,77 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// call_stack.h: A call stack comprised of stack frames. +// +// This class manages a vector of stack frames. It is used instead of +// exposing the vector directly to allow the CallStack to own StackFrame +// pointers without having to publicly export the linked_ptr class. A +// CallStack must be composed of pointers instead of objects to allow for +// CPU-specific StackFrame subclasses. +// +// By convention, the stack frame at index 0 is the innermost callee frame, +// and the frame at the highest index in a call stack is the outermost +// caller. CallStack only allows stacks to be built by pushing frames, +// beginning with the innermost callee frame. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ + +#include + +namespace google_breakpad { + +using std::vector; + +struct StackFrame; +template class linked_ptr; + +class CallStack { + public: + CallStack() { Clear(); } + ~CallStack(); + + // Resets the CallStack to its initial empty state + void Clear(); + + const vector* frames() const { return &frames_; } + + private: + // Stackwalker is responsible for building the frames_ vector. + friend class Stackwalker; + + // Storage for pushed frames. + vector frames_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_module.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_module.h new file mode 100644 index 00000000..38ee956e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_module.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// code_module.h: Carries information about code modules that are loaded +// into a process. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +class CodeModule { + public: + virtual ~CodeModule() {} + + // The base address of this code module as it was loaded by the process. + // (u_int64_t)-1 on error. + virtual u_int64_t base_address() const = 0; + + // The size of the code module. 0 on error. + virtual u_int64_t size() const = 0; + + // The path or file name that the code module was loaded from. Empty on + // error. + virtual string code_file() const = 0; + + // An identifying string used to discriminate between multiple versions and + // builds of the same code module. This may contain a uuid, timestamp, + // version number, or any combination of this or other information, in an + // implementation-defined format. Empty on error. + virtual string code_identifier() const = 0; + + // The filename containing debugging information associated with the code + // module. If debugging information is stored in a file separate from the + // code module itself (as is the case when .pdb or .dSYM files are used), + // this will be different from code_file. If debugging information is + // stored in the code module itself (possibly prior to stripping), this + // will be the same as code_file. Empty on error. + virtual string debug_file() const = 0; + + // An identifying string similar to code_identifier, but identifies a + // specific version and build of the associated debug file. This may be + // the same as code_identifier when the debug_file and code_file are + // identical or when the same identifier is used to identify distinct + // debug and code files. + virtual string debug_identifier() const = 0; + + // A human-readable representation of the code module's version. Empty on + // error. + virtual string version() const = 0; + + // Creates a new copy of this CodeModule object, which the caller takes + // ownership of. The new CodeModule may be of a different concrete class + // than the CodeModule being copied, but will behave identically to the + // copied CodeModule as far as the CodeModule interface is concerned. + virtual const CodeModule* Copy() const = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_modules.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_modules.h new file mode 100644 index 00000000..29c55d4e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/code_modules.h @@ -0,0 +1,98 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// code_modules.h: Contains all of the CodeModule objects that were loaded +// into a single process. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ + +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +class CodeModule; + +class CodeModules { + public: + virtual ~CodeModules() {} + + // The number of contained CodeModule objects. + virtual unsigned int module_count() const = 0; + + // Random access to modules. Returns the module whose code is present + // at the address indicated by |address|. If no module is present at this + // address, returns NULL. Ownership of the returned CodeModule is retained + // by the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleForAddress(u_int64_t address) const = 0; + + // Returns the module corresponding to the main executable. If there is + // no main executable, returns NULL. Ownership of the returned CodeModule + // is retained by the CodeModules object; pointers returned by this method + // are valid for comparison with pointers returned by the other Get + // methods. + virtual const CodeModule* GetMainModule() const = 0; + + // Sequential access to modules. A sequence number of 0 corresponds to the + // module residing lowest in memory. If the sequence number is out of + // range, returns NULL. Ownership of the returned CodeModule is retained + // by the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleAtSequence( + unsigned int sequence) const = 0; + + // Sequential access to modules. This is similar to GetModuleAtSequence, + // except no ordering requirement is enforced. A CodeModules implementation + // may return CodeModule objects from GetModuleAtIndex in any order it + // wishes, provided that the order remain the same throughout the life of + // the CodeModules object. Typically, GetModuleAtIndex would be used by + // a caller to enumerate all CodeModule objects quickly when the enumeration + // does not require any ordering. If the index argument is out of range, + // returns NULL. Ownership of the returned CodeModule is retained by + // the CodeModules object; pointers returned by this method are valid for + // comparison with pointers returned by the other Get methods. + virtual const CodeModule* GetModuleAtIndex(unsigned int index) const = 0; + + // Creates a new copy of this CodeModules object, which the caller takes + // ownership of. The new object will also contain copies of the existing + // object's child CodeModule objects. The new CodeModules object may be of + // a different concrete class than the object being copied, but will behave + // identically to the copied object as far as the CodeModules and CodeModule + // interfaces are concerned, except that the order that GetModuleAtIndex + // returns objects in may differ between a copy and the original CodeModules + // object. + virtual const CodeModules* Copy() const = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/memory_region.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/memory_region.h new file mode 100644 index 00000000..1ac3fe8d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/memory_region.h @@ -0,0 +1,76 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// memory_region.h: Access to memory regions. +// +// A MemoryRegion provides virtual access to a range of memory. It is an +// abstraction allowing the actual source of memory to be independent of +// methods which need to access a virtual memory space. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ + + +#include "google_breakpad/common/breakpad_types.h" + + +namespace google_breakpad { + + +class MemoryRegion { + public: + virtual ~MemoryRegion() {} + + // The base address of this memory region. + virtual u_int64_t GetBase() = 0; + + // The size of this memory region. + virtual u_int32_t GetSize() = 0; + + // Access to data of various sizes within the memory region. address + // is a pointer to read, and it must lie within the memory region as + // defined by its base address and size. The location pointed to by + // value is set to the value at address. Byte-swapping is performed + // if necessary so that the value is appropriate for the running + // program. Returns true on success. Fails and returns false if address + // is out of the region's bounds (after considering the width of value), + // or for other types of errors. + virtual bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value) = 0; + virtual bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value) = 0; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump.h new file mode 100644 index 00000000..5c5dccc9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump.h @@ -0,0 +1,904 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump.h: A minidump reader. +// +// The basic structure of this module tracks the structure of the minidump +// file itself. At the top level, a minidump file is represented by a +// Minidump object. Like most other classes in this module, Minidump +// provides a Read method that initializes the object with information from +// the file. Most of the classes in this file are wrappers around the +// "raw" structures found in the minidump file itself, and defined in +// minidump_format.h. For example, each thread is represented by a +// MinidumpThread object, whose parameters are specified in an MDRawThread +// structure. A properly byte-swapped MDRawThread can be obtained from a +// MinidumpThread easily by calling its thread() method. +// +// Most of the module lazily reads only the portion of the minidump file +// necessary to fulfill the user's request. Calling Minidump::Read +// only reads the minidump's directory. The thread list is not read until +// it is needed, and even once it's read, the memory regions for each +// thread's stack aren't read until they're needed. This strategy avoids +// unnecessary file input, and allocating memory for data in which the user +// has no interest. Note that although memory allocations for a typical +// minidump file are not particularly large, it is possible for legitimate +// minidumps to be sizable. A full-memory minidump, for example, contains +// a snapshot of the entire mapped memory space. Even a normal minidump, +// with stack memory only, can be large if, for example, the dump was +// generated in response to a crash that occurred due to an infinite- +// recursion bug that caused the stack's limits to be exceeded. Finally, +// some users of this library will unfortunately find themselves in the +// position of having to process potentially-hostile minidumps that might +// attempt to cause problems by forcing the minidump processor to over- +// allocate memory. +// +// Memory management in this module is based on a strict +// you-don't-own-anything policy. The only object owned by the user is +// the top-level Minidump object, the creation and destruction of which +// must be the user's own responsibility. All other objects obtained +// through interaction with this module are ultimately owned by the +// Minidump object, and will be freed upon the Minidump object's destruction. +// Because memory regions can potentially involve large allocations, a +// FreeMemory method is provided by MinidumpMemoryRegion, allowing the user +// to release data when it is no longer needed. Use of this method is +// optional but recommended. If freed data is later required, it will +// be read back in from the minidump file again. +// +// There is one exception to this memory management policy: +// Minidump::ReadString will return a string object to the user, and the user +// is responsible for its deletion. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ + +#include + +#include +#include +#include + +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/memory_region.h" + + +namespace google_breakpad { + + +using std::map; +using std::string; +using std::vector; + + +class Minidump; +template class RangeMap; + + +// MinidumpObject is the base of all Minidump* objects except for Minidump +// itself. +class MinidumpObject { + public: + virtual ~MinidumpObject() {} + + bool valid() const { return valid_; } + + protected: + explicit MinidumpObject(Minidump* minidump); + + // Refers to the Minidump object that is the ultimate parent of this + // Some MinidumpObjects are owned by other MinidumpObjects, but at the + // root of the ownership tree is always a Minidump. The Minidump object + // is kept here for access to its seeking and reading facilities, and + // for access to data about the minidump file itself, such as whether + // it should be byte-swapped. + Minidump* minidump_; + + // MinidumpObjects are not valid when created. When a subclass populates + // its own fields, it can set valid_ to true. Accessors and mutators may + // wish to consider or alter the valid_ state as they interact with + // objects. + bool valid_; +}; + + +// This class exists primarily to provide a virtual destructor in a base +// class common to all objects that might be stored in +// Minidump::mStreamObjects. Some object types (MinidumpContext) will +// never be stored in Minidump::mStreamObjects, but are represented as +// streams and adhere to the same interface, and may be derived from +// this class. +class MinidumpStream : public MinidumpObject { + public: + virtual ~MinidumpStream() {} + + protected: + explicit MinidumpStream(Minidump* minidump); + + private: + // Populate (and validate) the MinidumpStream. minidump_ is expected + // to be positioned at the beginning of the stream, so that the next + // read from the minidump will be at the beginning of the stream. + // expected_size should be set to the stream's length as contained in + // the MDRawDirectory record or other identifying record. A class + // that implements MinidumpStream can compare expected_size to a + // known size as an integrity check. + virtual bool Read(u_int32_t expected_size) = 0; +}; + + +// MinidumpContext carries a CPU-specific MDRawContext structure, which +// contains CPU context such as register states. Each thread has its +// own context, and the exception record, if present, also has its own +// context. Note that if the exception record is present, the context it +// refers to is probably what the user wants to use for the exception +// thread, instead of that thread's own context. The exception thread's +// context (as opposed to the exception record's context) will contain +// context for the exception handler (which performs minidump generation), +// and not the context that caused the exception (which is probably what the +// user wants). +class MinidumpContext : public MinidumpStream { + public: + virtual ~MinidumpContext(); + + // Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC + // identifying the CPU type that the context was collected from. The + // returned value will identify the CPU only, and will have any other + // MD_CONTEXT_* bits masked out. Returns 0 on failure. + u_int32_t GetContextCPU() const; + + // Returns raw CPU-specific context data for the named CPU type. If the + // context data does not match the CPU type or does not exist, returns + // NULL. + const MDRawContextX86* GetContextX86() const; + const MDRawContextPPC* GetContextPPC() const; + const MDRawContextAMD64* GetContextAMD64() const; + const MDRawContextSPARC* GetContextSPARC() const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class MinidumpThread; + friend class MinidumpException; + + explicit MinidumpContext(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // Free the CPU-specific context structure. + void FreeContext(); + + // If the minidump contains a SYSTEM_INFO_STREAM, makes sure that the + // system info stream gives an appropriate CPU type matching the context + // CPU type in context_cpu_type. Returns false if the CPU type does not + // match. Returns true if the CPU type matches or if the minidump does + // not contain a system info stream. + bool CheckAgainstSystemInfo(u_int32_t context_cpu_type); + + // Store this separately because of the weirdo AMD64 context + u_int32_t context_flags_; + + // The CPU-specific context structure. + union { + MDRawContextBase* base; + MDRawContextX86* x86; + MDRawContextPPC* ppc; + MDRawContextAMD64* amd64; + // on Solaris SPARC, sparc is defined as a numeric constant, + // so variables can NOT be named as sparc + MDRawContextSPARC* ctx_sparc; + } context_; +}; + + +// MinidumpMemoryRegion does not wrap any MDRaw structure, and only contains +// a reference to an MDMemoryDescriptor. This object is intended to wrap +// portions of a minidump file that contain memory dumps. In normal +// minidumps, each MinidumpThread owns a MinidumpMemoryRegion corresponding +// to the thread's stack memory. MinidumpMemoryList also gives access to +// memory regions in its list as MinidumpMemoryRegions. This class +// adheres to MemoryRegion so that it may be used as a data provider to +// the Stackwalker family of classes. +class MinidumpMemoryRegion : public MinidumpObject, + public MemoryRegion { + public: + virtual ~MinidumpMemoryRegion(); + + static void set_max_bytes(u_int32_t max_bytes) { max_bytes_ = max_bytes; } + static u_int32_t max_bytes() { return max_bytes_; } + + // Returns a pointer to the base of the memory region. Returns the + // cached value if available, otherwise, reads the minidump file and + // caches the memory region. + const u_int8_t* GetMemory(); + + // The address of the base of the memory region. + u_int64_t GetBase(); + + // The size, in bytes, of the memory region. + u_int32_t GetSize(); + + // Frees the cached memory region, if cached. + void FreeMemory(); + + // Obtains the value of memory at the pointer specified by address. + bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value); + bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class MinidumpThread; + friend class MinidumpMemoryList; + + explicit MinidumpMemoryRegion(Minidump* minidump); + + // Identify the base address and size of the memory region, and the + // location it may be found in the minidump file. + void SetDescriptor(MDMemoryDescriptor* descriptor); + + // Implementation for GetMemoryAtAddress + template bool GetMemoryAtAddressInternal(u_int64_t address, + T* value); + + // The largest memory region that will be read from a minidump. The + // default is 1MB. + static u_int32_t max_bytes_; + + // Base address and size of the memory region, and its position in the + // minidump file. + MDMemoryDescriptor* descriptor_; + + // Cached memory. + vector* memory_; +}; + + +// MinidumpThread contains information about a thread of execution, +// including a snapshot of the thread's stack and CPU context. For +// the thread that caused an exception, the context carried by +// MinidumpException is probably desired instead of the CPU context +// provided here. +class MinidumpThread : public MinidumpObject { + public: + virtual ~MinidumpThread(); + + const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; } + MinidumpMemoryRegion* GetMemory(); + MinidumpContext* GetContext(); + + // The thread ID is used to determine if a thread is the exception thread, + // so a special getter is provided to retrieve this data from the + // MDRawThread structure. Returns false if the thread ID cannot be + // determined. + bool GetThreadID(u_int32_t *thread_id) const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // These objects are managed by MinidumpThreadList. + friend class MinidumpThreadList; + + explicit MinidumpThread(Minidump* minidump); + + // This works like MinidumpStream::Read, but is driven by + // MinidumpThreadList. No size checking is done, because + // MinidumpThreadList handles that directly. + bool Read(); + + MDRawThread thread_; + MinidumpMemoryRegion* memory_; + MinidumpContext* context_; +}; + + +// MinidumpThreadList contains all of the threads (as MinidumpThreads) in +// a process. +class MinidumpThreadList : public MinidumpStream { + public: + virtual ~MinidumpThreadList(); + + static void set_max_threads(u_int32_t max_threads) { + max_threads_ = max_threads; + } + static u_int32_t max_threads() { return max_threads_; } + + unsigned int thread_count() const { return valid_ ? thread_count_ : 0; } + + // Sequential access to threads. + MinidumpThread* GetThreadAtIndex(unsigned int index) const; + + // Random access to threads. + MinidumpThread* GetThreadByID(u_int32_t thread_id); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef map IDToThreadMap; + typedef vector MinidumpThreads; + + static const u_int32_t kStreamType = MD_THREAD_LIST_STREAM; + + explicit MinidumpThreadList(Minidump* aMinidump); + + bool Read(u_int32_t aExpectedSize); + + // The largest number of threads that will be read from a minidump. The + // default is 256. + static u_int32_t max_threads_; + + // Access to threads using the thread ID as the key. + IDToThreadMap id_to_thread_map_; + + // The list of threads. + MinidumpThreads* threads_; + u_int32_t thread_count_; +}; + + +// MinidumpModule wraps MDRawModule, which contains information about loaded +// code modules. Access is provided to various data referenced indirectly +// by MDRawModule, such as the module's name and a specification for where +// to locate debugging information for the module. +class MinidumpModule : public MinidumpObject, + public CodeModule { + public: + virtual ~MinidumpModule(); + + static void set_max_cv_bytes(u_int32_t max_cv_bytes) { + max_cv_bytes_ = max_cv_bytes; + } + static u_int32_t max_cv_bytes() { return max_cv_bytes_; } + + static void set_max_misc_bytes(u_int32_t max_misc_bytes) { + max_misc_bytes_ = max_misc_bytes; + } + static u_int32_t max_misc_bytes() { return max_misc_bytes_; } + + const MDRawModule* module() const { return valid_ ? &module_ : NULL; } + + // CodeModule implementation + virtual u_int64_t base_address() const { + return valid_ ? module_.base_of_image : static_cast(-1); + } + virtual u_int64_t size() const { return valid_ ? module_.size_of_image : 0; } + virtual string code_file() const; + virtual string code_identifier() const; + virtual string debug_file() const; + virtual string debug_identifier() const; + virtual string version() const; + virtual const CodeModule* Copy() const; + + // The CodeView record, which contains information to locate the module's + // debugging information (pdb). This is returned as u_int8_t* because + // the data can be of types MDCVInfoPDB20* or MDCVInfoPDB70*, or it may be + // of a type unknown to Breakpad, in which case the raw data will still be + // returned but no byte-swapping will have been performed. Check the + // record's signature in the first four bytes to differentiate between + // the various types. Current toolchains generate modules which carry + // MDCVInfoPDB70 by default. Returns a pointer to the CodeView record on + // success, and NULL on failure. On success, the optional |size| argument + // is set to the size of the CodeView record. + const u_int8_t* GetCVRecord(u_int32_t* size); + + // The miscellaneous debug record, which is obsolete. Current toolchains + // do not generate this type of debugging information (dbg), and this + // field is not expected to be present. Returns a pointer to the debugging + // record on success, and NULL on failure. On success, the optional |size| + // argument is set to the size of the debugging record. + const MDImageDebugMisc* GetMiscRecord(u_int32_t* size); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // These objects are managed by MinidumpModuleList. + friend class MinidumpModuleList; + + explicit MinidumpModule(Minidump* minidump); + + // This works like MinidumpStream::Read, but is driven by + // MinidumpModuleList. No size checking is done, because + // MinidumpModuleList handles that directly. + bool Read(); + + // Reads indirectly-referenced data, including the module name, CodeView + // record, and miscellaneous debugging record. This is necessary to allow + // MinidumpModuleList to fully construct MinidumpModule objects without + // requiring seeks to read a contiguous set of MinidumpModule objects. + // All auxiliary data should be available when Read is called, in order to + // allow the CodeModule getters to be const methods. + bool ReadAuxiliaryData(); + + // The largest number of bytes that will be read from a minidump for a + // CodeView record or miscellaneous debugging record, respectively. The + // default for each is 1024. + static u_int32_t max_cv_bytes_; + static u_int32_t max_misc_bytes_; + + // True after a successful Read. This is different from valid_, which is + // not set true until ReadAuxiliaryData also completes successfully. + // module_valid_ is only used by ReadAuxiliaryData and the functions it + // calls to determine whether the object is ready for auxiliary data to + // be read. + bool module_valid_; + + // True if debug info was read from the module. Certain modules + // may contain debug records in formats we don't support, + // so we can just set this to false to ignore them. + bool has_debug_info_; + + MDRawModule module_; + + // Cached module name. + const string* name_; + + // Cached CodeView record - this is MDCVInfoPDB20 or (likely) + // MDCVInfoPDB70, or possibly something else entirely. Stored as a u_int8_t + // because the structure contains a variable-sized string and its exact + // size cannot be known until it is processed. + vector* cv_record_; + + // If cv_record_ is present, cv_record_signature_ contains a copy of the + // CodeView record's first four bytes, for ease of determinining the + // type of structure that cv_record_ contains. + u_int32_t cv_record_signature_; + + // Cached MDImageDebugMisc (usually not present), stored as u_int8_t + // because the structure contains a variable-sized string and its exact + // size cannot be known until it is processed. + vector* misc_record_; +}; + + +// MinidumpModuleList contains all of the loaded code modules for a process +// in the form of MinidumpModules. It maintains a map of these modules +// so that it may easily provide a code module corresponding to a specific +// address. +class MinidumpModuleList : public MinidumpStream, + public CodeModules { + public: + virtual ~MinidumpModuleList(); + + static void set_max_modules(u_int32_t max_modules) { + max_modules_ = max_modules; + } + static u_int32_t max_modules() { return max_modules_; } + + // CodeModules implementation. + virtual unsigned int module_count() const { + return valid_ ? module_count_ : 0; + } + virtual const MinidumpModule* GetModuleForAddress(u_int64_t address) const; + virtual const MinidumpModule* GetMainModule() const; + virtual const MinidumpModule* GetModuleAtSequence( + unsigned int sequence) const; + virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const; + virtual const CodeModules* Copy() const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef vector MinidumpModules; + + static const u_int32_t kStreamType = MD_MODULE_LIST_STREAM; + + explicit MinidumpModuleList(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // The largest number of modules that will be read from a minidump. The + // default is 1024. + static u_int32_t max_modules_; + + // Access to modules using addresses as the key. + RangeMap *range_map_; + + MinidumpModules *modules_; + u_int32_t module_count_; +}; + + +// MinidumpMemoryList corresponds to a minidump's MEMORY_LIST_STREAM stream, +// which references the snapshots of all of the memory regions contained +// within the minidump. For a normal minidump, this includes stack memory +// (also referenced by each MinidumpThread, in fact, the MDMemoryDescriptors +// here and in MDRawThread both point to exactly the same data in a +// minidump file, conserving space), as well as a 256-byte snapshot of memory +// surrounding the instruction pointer in the case of an exception. Other +// types of minidumps may contain significantly more memory regions. Full- +// memory minidumps contain all of a process' mapped memory. +class MinidumpMemoryList : public MinidumpStream { + public: + virtual ~MinidumpMemoryList(); + + static void set_max_regions(u_int32_t max_regions) { + max_regions_ = max_regions; + } + static u_int32_t max_regions() { return max_regions_; } + + unsigned int region_count() const { return valid_ ? region_count_ : 0; } + + // Sequential access to memory regions. + MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index); + + // Random access to memory regions. Returns the region encompassing + // the address identified by address. + MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + typedef vector MemoryDescriptors; + typedef vector MemoryRegions; + + static const u_int32_t kStreamType = MD_MEMORY_LIST_STREAM; + + explicit MinidumpMemoryList(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + // The largest number of memory regions that will be read from a minidump. + // The default is 256. + static u_int32_t max_regions_; + + // Access to memory regions using addresses as the key. + RangeMap *range_map_; + + // The list of descriptors. This is maintained separately from the list + // of regions, because MemoryRegion doesn't own its MemoryDescriptor, it + // maintains a pointer to it. descriptors_ provides the storage for this + // purpose. + MemoryDescriptors *descriptors_; + + // The list of regions. + MemoryRegions *regions_; + u_int32_t region_count_; +}; + + +// MinidumpException wraps MDRawExceptionStream, which contains information +// about the exception that caused the minidump to be generated, if the +// minidump was generated in an exception handler called as a result of +// an exception. It also provides access to a MinidumpContext object, +// which contains the CPU context for the exception thread at the time +// the exception occurred. +class MinidumpException : public MinidumpStream { + public: + virtual ~MinidumpException(); + + const MDRawExceptionStream* exception() const { + return valid_ ? &exception_ : NULL; + } + + // The thread ID is used to determine if a thread is the exception thread, + // so a special getter is provided to retrieve this data from the + // MDRawExceptionStream structure. Returns false if the thread ID cannot + // be determined. + bool GetThreadID(u_int32_t *thread_id) const; + + MinidumpContext* GetContext(); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_EXCEPTION_STREAM; + + explicit MinidumpException(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + MDRawExceptionStream exception_; + MinidumpContext* context_; +}; + + +// MinidumpSystemInfo wraps MDRawSystemInfo and provides information about +// the system on which the minidump was generated. See also MinidumpMiscInfo. +class MinidumpSystemInfo : public MinidumpStream { + public: + virtual ~MinidumpSystemInfo(); + + const MDRawSystemInfo* system_info() const { + return valid_ ? &system_info_ : NULL; + } + + // GetOS and GetCPU return textual representations of the operating system + // and CPU that produced the minidump. Unlike most other Minidump* methods, + // they return string objects, not weak pointers. Defined values for + // GetOS() are "mac", "windows", and "linux". Defined values for GetCPU + // are "x86" and "ppc". These methods return an empty string when their + // values are unknown. + string GetOS(); + string GetCPU(); + + // I don't know what CSD stands for, but this field is documented as + // returning a textual representation of the OS service pack. On other + // platforms, this provides additional information about an OS version + // level beyond major.minor.micro. Returns NULL if unknown. + const string* GetCSDVersion(); + + // If a CPU vendor string can be determined, returns a pointer to it, + // otherwise, returns NULL. CPU vendor strings can be determined from + // x86 CPUs with CPUID 0. + const string* GetCPUVendor(); + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_SYSTEM_INFO_STREAM; + + explicit MinidumpSystemInfo(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + MDRawSystemInfo system_info_; + + // Textual representation of the OS service pack, for minidumps produced + // by MiniDumpWriteDump on Windows. + const string* csd_version_; + + // A string identifying the CPU vendor, if known. + const string* cpu_vendor_; +}; + + +// MinidumpMiscInfo wraps MDRawMiscInfo and provides information about +// the process that generated the minidump, and optionally additional system +// information. See also MinidumpSystemInfo. +class MinidumpMiscInfo : public MinidumpStream { + public: + const MDRawMiscInfo* misc_info() const { + return valid_ ? &misc_info_ : NULL; + } + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_MISC_INFO_STREAM; + + explicit MinidumpMiscInfo(Minidump* minidump_); + + bool Read(u_int32_t expected_size_); + + MDRawMiscInfo misc_info_; +}; + + +// MinidumpBreakpadInfo wraps MDRawBreakpadInfo, which is an optional stream in +// a minidump that provides additional information about the process state +// at the time the minidump was generated. +class MinidumpBreakpadInfo : public MinidumpStream { + public: + const MDRawBreakpadInfo* breakpad_info() const { + return valid_ ? &breakpad_info_ : NULL; + } + + // These thread IDs are used to determine if threads deserve special + // treatment, so special getters are provided to retrieve this data from + // the MDRawBreakpadInfo structure. The getters return false if the thread + // IDs cannot be determined. + bool GetDumpThreadID(u_int32_t *thread_id) const; + bool GetRequestingThreadID(u_int32_t *thread_id) const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class Minidump; + + static const u_int32_t kStreamType = MD_BREAKPAD_INFO_STREAM; + + explicit MinidumpBreakpadInfo(Minidump* minidump_); + + bool Read(u_int32_t expected_size_); + + MDRawBreakpadInfo breakpad_info_; +}; + + +// Minidump is the user's interface to a minidump file. It wraps MDRawHeader +// and provides access to the minidump's top-level stream directory. +class Minidump { + public: + // path is the pathname of a file containing the minidump. + explicit Minidump(const string& path); + + ~Minidump(); + + static void set_max_streams(u_int32_t max_streams) { + max_streams_ = max_streams; + } + static u_int32_t max_streams() { return max_streams_; } + + static void set_max_string_length(u_int32_t max_string_length) { + max_string_length_ = max_string_length; + } + static u_int32_t max_string_length() { return max_string_length_; } + + const MDRawHeader* header() const { return valid_ ? &header_ : NULL; } + + // Reads the minidump file's header and top-level stream directory. + // The minidump is expected to be positioned at the beginning of the + // header. Read() sets up the stream list and map, and validates the + // Minidump object. + bool Read(); + + // The next set of methods are stubs that call GetStream. They exist to + // force code generation of the templatized API within the module, and + // to avoid exposing an ugly API (GetStream needs to accept a garbage + // parameter). + MinidumpThreadList* GetThreadList(); + MinidumpModuleList* GetModuleList(); + MinidumpMemoryList* GetMemoryList(); + MinidumpException* GetException(); + MinidumpSystemInfo* GetSystemInfo(); + MinidumpMiscInfo* GetMiscInfo(); + MinidumpBreakpadInfo* GetBreakpadInfo(); + + // The next set of methods are provided for users who wish to access + // data in minidump files directly, while leveraging the rest of + // this class and related classes to handle the basic minidump + // structure and known stream types. + + unsigned int GetDirectoryEntryCount() const { + return valid_ ? header_.stream_count : 0; + } + const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const; + + // The next 2 methods are lower-level I/O routines. They use fd_. + + // Reads count bytes from the minidump at the current position into + // the storage area pointed to by bytes. bytes must be of sufficient + // size. After the read, the file position is advanced by count. + bool ReadBytes(void* bytes, size_t count); + + // Sets the position of the minidump file to offset. + bool SeekSet(off_t offset); + + // Returns the current position of the minidump file. + off_t Tell() { return valid_ ? lseek(fd_, 0, SEEK_CUR) : (off_t)-1; } + + // The next 2 methods are medium-level I/O routines. + + // ReadString returns a string which is owned by the caller! offset + // specifies the offset that a length-encoded string is stored at in the + // minidump file. + string* ReadString(off_t offset); + + // SeekToStreamType positions the file at the beginning of a stream + // identified by stream_type, and informs the caller of the stream's + // length by setting *stream_length. Because stream_map maps each stream + // type to only one stream in the file, this might mislead the user into + // thinking that the stream that this seeks to is the only stream with + // type stream_type. That can't happen for streams that these classes + // deal with directly, because they're only supposed to be present in the + // file singly, and that's verified when stream_map_ is built. Users who + // are looking for other stream types should be aware of this + // possibility, and consider using GetDirectoryEntryAtIndex (possibly + // with GetDirectoryEntryCount) if expecting multiple streams of the same + // type in a single minidump file. + bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length); + + bool swap() const { return valid_ ? swap_ : false; } + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + // MinidumpStreamInfo is used in the MinidumpStreamMap. It lets + // the Minidump object locate interesting streams quickly, and + // provides a convenient place to stash MinidumpStream objects. + struct MinidumpStreamInfo { + MinidumpStreamInfo() : stream_index(0), stream(NULL) {} + ~MinidumpStreamInfo() { delete stream; } + + // Index into the MinidumpDirectoryEntries vector + unsigned int stream_index; + + // Pointer to the stream if cached, or NULL if not yet populated + MinidumpStream* stream; + }; + + typedef vector MinidumpDirectoryEntries; + typedef map MinidumpStreamMap; + + template T* GetStream(T** stream); + + // Opens the minidump file, or if already open, seeks to the beginning. + bool Open(); + + // The largest number of top-level streams that will be read from a minidump. + // Note that streams are only read (and only consume memory) as needed, + // when directed by the caller. The default is 128. + static u_int32_t max_streams_; + + // The maximum length of a UTF-16 string that will be read from a minidump + // in 16-bit words. The default is 1024. UTF-16 strings are converted + // to UTF-8 when stored in memory, and each UTF-16 word will be represented + // by as many as 3 bytes in UTF-8. + static unsigned int max_string_length_; + + MDRawHeader header_; + + // The list of streams. + MinidumpDirectoryEntries* directory_; + + // Access to streams using the stream type as the key. + MinidumpStreamMap* stream_map_; + + // The pathname of the minidump file to process, set in the constructor. + const string path_; + + // The file descriptor for all file I/O. Used by ReadBytes and SeekSet. + // Set based on the |path_| member by Open, which is called by Read. + int fd_; + + // swap_ is true if the minidump file should be byte-swapped. If the + // minidump was produced by a CPU that is other-endian than the CPU + // processing the minidump, this will be true. If the two CPUs are + // same-endian, this will be false. + bool swap_; + + // Validity of the Minidump structure, false immediately after + // construction or after a failed Read(); true following a successful + // Read(). + bool valid_; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump_processor.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump_processor.h new file mode 100644 index 00000000..73447f97 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/minidump_processor.h @@ -0,0 +1,94 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +class Minidump; +class ProcessState; +class SourceLineResolverInterface; +class SymbolSupplier; +class SystemInfo; + +class MinidumpProcessor { + public: + // Return type for Process() + enum ProcessResult { + PROCESS_OK, // the minidump was processed successfully + PROCESS_ERROR, // there was an error processing the minidump + PROCESS_INTERRUPTED // processing was interrupted by the SymbolSupplier + }; + + // Initializes this MinidumpProcessor. supplier should be an + // implementation of the SymbolSupplier abstract base class. + MinidumpProcessor(SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + ~MinidumpProcessor(); + + // Processes the minidump file and fills process_state with the result. + ProcessResult Process(const string &minidump_file, + ProcessState *process_state); + + // Populates the cpu_* fields of the |info| parameter with textual + // representations of the CPU type that the minidump in |dump| was + // produced on. Returns false if this information is not available in + // the minidump. + static bool GetCPUInfo(Minidump *dump, SystemInfo *info); + + // Populates the os_* fields of the |info| parameter with textual + // representations of the operating system that the minidump in |dump| + // was produced on. Returns false if this information is not available in + // the minidump. + static bool GetOSInfo(Minidump *dump, SystemInfo *info); + + // Returns a textual representation of the reason that a crash occurred, + // if the minidump in dump was produced as a result of a crash. Returns + // an empty string if this information cannot be determined. If address + // is non-NULL, it will be set to contain the address that caused the + // exception, if this information is available. This will be a code + // address when the crash was caused by problems such as illegal + // instructions or divisions by zero, or a data address when the crash + // was caused by a memory access violation. + static string GetCrashReason(Minidump *dump, u_int64_t *address); + + private: + SymbolSupplier *supplier_; + SourceLineResolverInterface *resolver_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/process_state.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/process_state.h new file mode 100644 index 00000000..afbbb193 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/process_state.h @@ -0,0 +1,115 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// process_state.h: A snapshot of a process, in a fully-digested state. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ + +#include +#include +#include "google_breakpad/processor/system_info.h" +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; +using std::vector; + +class CallStack; +class CodeModules; + +class ProcessState { + public: + ProcessState() : modules_(NULL) { Clear(); } + ~ProcessState(); + + // Resets the ProcessState to its default values + void Clear(); + + // Accessors. See the data declarations below. + u_int32_t time_date_stamp() const { return time_date_stamp_; } + bool crashed() const { return crashed_; } + string crash_reason() const { return crash_reason_; } + u_int64_t crash_address() const { return crash_address_; } + int requesting_thread() const { return requesting_thread_; } + const vector* threads() const { return &threads_; } + const SystemInfo* system_info() const { return &system_info_; } + const CodeModules* modules() const { return modules_; } + + private: + // MinidumpProcessor is responsible for building ProcessState objects. + friend class MinidumpProcessor; + + // The time-date stamp of the minidump (time_t format) + u_int32_t time_date_stamp_; + + // True if the process crashed, false if the dump was produced outside + // of an exception handler. + bool crashed_; + + // If the process crashed, the type of crash. OS- and possibly CPU- + // specific. For example, "EXCEPTION_ACCESS_VIOLATION" (Windows), + // "EXC_BAD_ACCESS / KERN_INVALID_ADDRESS" (Mac OS X), "SIGSEGV" + // (other Unix). + string crash_reason_; + + // If the process crashed, and if crash_reason implicates memory, + // the memory address that caused the crash. For data access errors, + // this will be the data address that caused the fault. For code errors, + // this will be the address of the instruction that caused the fault. + u_int64_t crash_address_; + + // The index of the thread that requested a dump be written in the + // threads vector. If a dump was produced as a result of a crash, this + // will point to the thread that crashed. If the dump was produced as + // by user code without crashing, and the dump contains extended Breakpad + // information, this will point to the thread that requested the dump. + // If the dump was not produced as a result of an exception and no + // extended Breakpad information is present, this field will be set to -1, + // indicating that the dump thread is not available. + int requesting_thread_; + + // Stacks for each thread (except possibly the exception handler + // thread) at the time of the crash. + vector threads_; + + // OS and CPU information. + SystemInfo system_info_; + + // The modules that were loaded into the process represented by the + // ProcessState. + const CodeModules *modules_; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/source_line_resolver_interface.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/source_line_resolver_interface.h new file mode 100644 index 00000000..93ef85d2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/source_line_resolver_interface.h @@ -0,0 +1,82 @@ +// 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. + +// Abstract interface to return function/file/line info for a memory address. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::string; + +struct StackFrame; +struct StackFrameInfo; + +class SourceLineResolverInterface { + public: + typedef u_int64_t MemAddr; + + virtual ~SourceLineResolverInterface() {} + + // Adds a module to this resolver, returning true on success. + // + // module_name may be an arbitrary string. Typically, it will be the + // filename of the module, optionally with version identifiers. + // + // map_file should contain line/address mappings for this module. + virtual bool LoadModule(const string &module_name, + const string &map_file) = 0; + // Same as above, but takes the contents of a pre-read map buffer + virtual bool LoadModuleUsingMapBuffer(const string &module_name, + const string &map_buffer) = 0; + + // Returns true if a module with the given name has been loaded. + virtual bool HasModule(const string &module_name) const = 0; + + // Fills in the function_base, function_name, source_file_name, + // and source_line fields of the StackFrame. The instruction and + // module_name fields must already be filled in. Additional debugging + // information, if available, is returned. If the information is not + // available, returns NULL. A NULL return value does not indicate an + // error. The caller takes ownership of any returned StackFrameInfo + // object. + virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const = 0; + + protected: + // SourceLineResolverInterface cannot be instantiated except by subclasses + SourceLineResolverInterface() {} +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame.h new file mode 100644 index 00000000..b330f8ae --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame.h @@ -0,0 +1,84 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ + +#include +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +class CodeModule; + +using std::string; + +struct StackFrame { + StackFrame() + : instruction(), + module(NULL), + function_name(), + function_base(), + source_file_name(), + source_line(), + source_line_base() {} + virtual ~StackFrame() {} + + // The program counter location as an absolute virtual address. For the + // innermost called frame in a stack, this will be an exact program counter + // or instruction pointer value. For all other frames, this will be within + // the instruction that caused execution to branch to a called function, + // but may not necessarily point to the exact beginning of that instruction. + u_int64_t instruction; + + // The module in which the instruction resides. + const CodeModule *module; + + // The function name, may be omitted if debug symbols are not available. + string function_name; + + // The start address of the function, may be omitted if debug symbols + // are not available. + u_int64_t function_base; + + // The source file name, may be omitted if debug symbols are not available. + string source_file_name; + + // The (1-based) source line number, may be omitted if debug symbols are + // not available. + int source_line; + + // The start address of the source line, may be omitted if debug symbols + // are not available. + u_int64_t source_line_base; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame_cpu.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame_cpu.h new file mode 100644 index 00000000..70823b9c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stack_frame_cpu.h @@ -0,0 +1,153 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stack_frame_cpu.h: CPU-specific StackFrame extensions. +// +// These types extend the StackFrame structure to carry CPU-specific register +// state. They are defined in this header instead of stack_frame.h to +// avoid the need to include minidump_format.h when only the generic +// StackFrame type is needed. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ + +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stack_frame.h" + +namespace google_breakpad { + +struct StackFrameX86 : public StackFrame { + // ContextValidity has one entry for each relevant hardware pointer register + // (%eip and %esp) and one entry for each nonvolatile (callee-save) register. + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_EIP = 1 << 0, + CONTEXT_VALID_ESP = 1 << 1, + CONTEXT_VALID_EBP = 1 << 2, + CONTEXT_VALID_EBX = 1 << 3, + CONTEXT_VALID_ESI = 1 << 4, + CONTEXT_VALID_EDI = 1 << 5, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameX86() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextX86 context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFramePPC : public StackFrame { + // ContextValidity should eventually contain entries for the validity of + // other nonvolatile (callee-save) registers as in + // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently + // locate registers other than the ones listed here. + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_SRR0 = 1 << 0, + CONTEXT_VALID_GPR1 = 1 << 1, + CONTEXT_VALID_ALL = -1 + }; + + StackFramePPC() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextPPC context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFrameAMD64 : public StackFrame { + // ContextValidity has one entry for each relevant hardware pointer register + // (%rip and %rsp) and one entry for each nonvolatile (callee-save) register. + //FIXME: validate this list + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_RIP = 1 << 0, + CONTEXT_VALID_RSP = 1 << 1, + CONTEXT_VALID_RBP = 1 << 2, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameAMD64() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextAMD64 context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +struct StackFrameSPARC : public StackFrame { + // to be confirmed + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_PC = 1 << 0, + CONTEXT_VALID_SP = 1 << 1, + CONTEXT_VALID_FP = 1 << 2, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameSPARC() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextSPARC context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stackwalker.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stackwalker.h new file mode 100644 index 00000000..c463fd80 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/stackwalker.h @@ -0,0 +1,140 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker.h: Generic stackwalker. +// +// The Stackwalker class is an abstract base class providing common generic +// methods that apply to stacks from all systems. Specific implementations +// will extend this class by providing GetContextFrame and GetCallerFrame +// methods to fill in system-specific data in a StackFrame structure. +// Stackwalker assembles these StackFrame strucutres into a CallStack. +// +// Author: Mark Mentovai + + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ + +#include + +namespace google_breakpad { + +class CallStack; +class CodeModules; +template class linked_ptr; +class MemoryRegion; +class MinidumpContext; +class SourceLineResolverInterface; +struct StackFrame; +struct StackFrameInfo; +class SymbolSupplier; +class SystemInfo; + +using std::vector; + + +class Stackwalker { + public: + virtual ~Stackwalker() {} + + // Populates the given CallStack by calling GetContextFrame and + // GetCallerFrame. The frames are further processed to fill all available + // data. Returns true if the stackwalk completed, or false if it was + // interrupted by SymbolSupplier::GetSymbolFile(). + bool Walk(CallStack *stack); + + // Returns a new concrete subclass suitable for the CPU that a stack was + // generated on, according to the CPU type indicated by the context + // argument. If no suitable concrete subclass exists, returns NULL. + static Stackwalker* StackwalkerForCPU(const SystemInfo *system_info, + MinidumpContext *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + protected: + // system_info identifies the operating system, NULL or empty if unknown. + // memory identifies a MemoryRegion that provides the stack memory + // for the stack to walk. modules, if non-NULL, is a CodeModules + // object that is used to look up which code module each stack frame is + // associated with. supplier is an optional caller-supplied SymbolSupplier + // implementation. If supplier is NULL, source line info will not be + // resolved. resolver is an instance of SourceLineResolverInterface + // (see source_line_resolver_interface.h and basic_source_line_resolver.h). + // If resolver is NULL, source line info will not be resolved. + Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + // Information about the system that produced the minidump. Subclasses + // and the SymbolSupplier may find this information useful. + const SystemInfo *system_info_; + + // The stack memory to walk. Subclasses will require this region to + // get information from the stack. + MemoryRegion *memory_; + + // A list of modules, for populating each StackFrame's module information. + // This field is optional and may be NULL. + const CodeModules *modules_; + + private: + // Obtains the context frame, the innermost called procedure in a stack + // trace. Returns NULL on failure. GetContextFrame allocates a new + // StackFrame (or StackFrame subclass), ownership of which is taken by + // the caller. + virtual StackFrame* GetContextFrame() = 0; + + // Obtains a caller frame. Each call to GetCallerFrame should return the + // frame that called the last frame returned by GetContextFrame or + // GetCallerFrame. To aid this purpose, stack contains the CallStack + // made of frames that have already been walked. GetCallerFrame should + // return NULL on failure or when there are no more caller frames (when + // the end of the stack has been reached). GetCallerFrame allocates a new + // StackFrame (or StackFrame subclass), ownership of which is taken by + // the caller. + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) = 0; + + // The optional SymbolSupplier for resolving source line info. + SymbolSupplier *supplier_; + + // The SourceLineResolver implementation + SourceLineResolverInterface *resolver_; +}; + + +} // namespace google_breakpad + + +#endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/symbol_supplier.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/symbol_supplier.h new file mode 100644 index 00000000..7b9d00e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/symbol_supplier.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The caller may implement the SymbolSupplier abstract base class +// to provide symbols for a given module. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ + +#include + +namespace google_breakpad { + +using std::string; +class CodeModule; +class SystemInfo; + +class SymbolSupplier { + public: + // Result type for GetSymbolFile + enum SymbolResult { + // no symbols were found, but continue processing + NOT_FOUND, + + // symbols were found, and the path has been placed in symbol_file + FOUND, + + // stops processing the minidump immediately + INTERRUPT + }; + + virtual ~SymbolSupplier() {} + + // Retrieves the symbol file for the given CodeModule, placing the + // path in symbol_file if successful. system_info contains strings + // identifying the operating system and CPU; SymbolSupplier may use + // to help locate the symbol file. system_info may be NULL or its + // fields may be empty if these values are unknown. symbol_file + // must be a pointer to a valid string + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) = 0; + // Same as above, except also places symbol data into symbol_data. + // If symbol_data is NULL, the data is not returned. + // TODO(nealsid) Once we have symbol data caching behavior implemented + // investigate making all symbol suppliers implement all methods, + // and make this pure virtual + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data) = 0; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ diff --git a/thirdparty/google-breakpad/r318/src/google_breakpad/processor/system_info.h b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/system_info.h new file mode 100644 index 00000000..fdbdbfd6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/google_breakpad/processor/system_info.h @@ -0,0 +1,97 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// system_info.h: Information about the system that was running a program +// when a crash report was produced. +// +// Author: Mark Mentovai + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ +#define GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ + +#include + +namespace google_breakpad { + +using std::string; + +struct SystemInfo { + public: + SystemInfo() : os(), os_short(), os_version(), cpu(), cpu_info(), + cpu_count(0) {} + + // Resets the SystemInfo object to its default values. + void Clear() { + os.clear(); + os_short.clear(); + os_version.clear(); + cpu.clear(); + cpu_info.clear(); + cpu_count = 0; + } + + // A string identifying the operating system, such as "Windows NT", + // "Mac OS X", or "Linux". If the information is present in the dump but + // its value is unknown, this field will contain a numeric value. If + // the information is not present in the dump, this field will be empty. + string os; + + // A short form of the os string, using lowercase letters and no spaces, + // suitable for use in a filesystem. Possible values are "windows", + // "mac", and "linux". Empty if the information is not present in the dump + // or if the OS given by the dump is unknown. The values stored in this + // field should match those used by MinidumpSystemInfo::GetOS. + string os_short; + + // A string identifying the version of the operating system, such as + // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not + // contain this information, this field will be empty. + string os_version; + + // A string identifying the basic CPU family, such as "x86" or "ppc". + // If this information is present in the dump but its value is unknown, + // this field will contain a numeric value. If the information is not + // present in the dump, this field will be empty. The values stored in + // this field should match those used by MinidumpSystemInfo::GetCPU. + string cpu; + + // A string further identifying the specific CPU, such as + // "GenuineIntel level 6 model 13 stepping 8". If the information is not + // present in the dump, or additional identifying information is not + // defined for the CPU family, this field will be empty. + string cpu_info; + + // The number of processors in the system. Will be greater than one for + // multi-core systems. + int cpu_count; +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/.dirstamp b/thirdparty/google-breakpad/r318/src/processor/.deps/.dirstamp new file mode 100644 index 00000000..e69de29b diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/address_map_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/address_map_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/address_map_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/basic_code_modules.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_code_modules.Plo new file mode 100644 index 00000000..79f6454d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_code_modules.Plo @@ -0,0 +1,385 @@ +src/processor/basic_code_modules.lo src/processor/basic_code_modules.o: \ + src/processor/basic_code_modules.cc /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/sys/cdefs.h /usr/include/stdlib.h \ + /usr/include/available.h /usr/include/_types.h \ + /usr/include/sys/_types.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + src/processor/basic_code_modules.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + src/google_breakpad/processor/code_module.h \ + /usr/include/c++/4.0.0/string \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc src/processor/linked_ptr.h \ + src/processor/logging.h /usr/include/c++/4.0.0/iostream \ + /usr/include/c++/4.0.0/ostream /usr/include/c++/4.0.0/ios \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc src/processor/range_map-inl.h \ + src/processor/range_map.h /usr/include/c++/4.0.0/map \ + /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/sys/cdefs.h: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +src/processor/basic_code_modules.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +src/google_breakpad/processor/code_module.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/processor/linked_ptr.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/processor/range_map-inl.h: + +src/processor/range_map.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver.Plo new file mode 100644 index 00000000..1beffa48 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver.Plo @@ -0,0 +1,436 @@ +src/processor/basic_source_line_resolver.lo \ + src/processor/basic_source_line_resolver.o: \ + src/processor/basic_source_line_resolver.cc /usr/include/stdio.h \ + /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/string.h \ + /usr/include/sys/types.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/machine/endian.h /usr/include/i386/endian.h \ + /usr/include/sys/_endian.h /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/sys/_structs.h \ + /usr/include/sys/stat.h /usr/include/unistd.h /usr/include/sys/unistd.h \ + /usr/include/sys/select.h /usr/include/sys/_select.h \ + /usr/include/c++/4.0.0/map /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/alloca.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h \ + /usr/include/c++/4.0.0/cctype /usr/include/ctype.h \ + /usr/include/runetype.h /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + /usr/include/c++/4.0.0/utility /usr/include/c++/4.0.0/bits/stl_relops.h \ + /usr/include/c++/4.0.0/vector \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc src/processor/address_map-inl.h \ + src/processor/address_map.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/inttypes.h \ + src/processor/contained_range_map-inl.h \ + src/processor/contained_range_map.h src/processor/range_map-inl.h \ + src/processor/range_map.h \ + src/google_breakpad/processor/basic_source_line_resolver.h \ + /usr/include/c++/4.0.0/ext/hash_map \ + /usr/include/c++/4.0.0/ext/hashtable.h /usr/include/c++/4.0.0/iterator \ + /usr/include/c++/4.0.0/bits/stream_iterator.h \ + /usr/include/c++/4.0.0/ext/hash_fun.h \ + src/google_breakpad/processor/source_line_resolver_interface.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/stack_frame.h src/processor/linked_ptr.h \ + src/processor/scoped_ptr.h src/processor/stack_frame_info.h + +/usr/include/stdio.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/string.h: + +/usr/include/sys/types.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/sys/_structs.h: + +/usr/include/sys/stat.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/alloca.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +/usr/include/c++/4.0.0/utility: + +/usr/include/c++/4.0.0/bits/stl_relops.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/processor/address_map-inl.h: + +src/processor/address_map.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/inttypes.h: + +src/processor/contained_range_map-inl.h: + +src/processor/contained_range_map.h: + +src/processor/range_map-inl.h: + +src/processor/range_map.h: + +src/google_breakpad/processor/basic_source_line_resolver.h: + +/usr/include/c++/4.0.0/ext/hash_map: + +/usr/include/c++/4.0.0/ext/hashtable.h: + +/usr/include/c++/4.0.0/iterator: + +/usr/include/c++/4.0.0/bits/stream_iterator.h: + +/usr/include/c++/4.0.0/ext/hash_fun.h: + +src/google_breakpad/processor/source_line_resolver_interface.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/processor/stack_frame.h: + +src/processor/linked_ptr.h: + +src/processor/scoped_ptr.h: + +src/processor/stack_frame_info.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/basic_source_line_resolver_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/call_stack.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/call_stack.Plo new file mode 100644 index 00000000..16fe559b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/call_stack.Plo @@ -0,0 +1,301 @@ +src/processor/call_stack.lo src/processor/call_stack.o: \ + src/processor/call_stack.cc src/google_breakpad/processor/call_stack.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/stack_frame.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h + +src/google_breakpad/processor/call_stack.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/stack_frame.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/contained_range_map_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/contained_range_map_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/contained_range_map_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/logging.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/logging.Plo new file mode 100644 index 00000000..572dbc28 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/logging.Plo @@ -0,0 +1,365 @@ +src/processor/logging.lo src/processor/logging.o: \ + src/processor/logging.cc /usr/include/assert.h /usr/include/sys/cdefs.h \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/_types.h \ + /usr/include/sys/_types.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/errno.h /usr/include/sys/errno.h /usr/include/stdio.h \ + /usr/include/string.h /usr/include/time.h /usr/include/_structs.h \ + src/processor/logging.h /usr/include/c++/4.0.0/iostream \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/ostream /usr/include/c++/4.0.0/ios \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstring \ + /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/c++/4.0.0/cstdio \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/unistd.h /usr/include/sys/unistd.h \ + /usr/include/sys/select.h /usr/include/sys/_select.h \ + /usr/include/c++/4.0.0/cctype /usr/include/ctype.h \ + /usr/include/runetype.h /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/processor/pathname_stripper.h + +/usr/include/assert.h: + +/usr/include/sys/cdefs.h: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/errno.h: + +/usr/include/sys/errno.h: + +/usr/include/stdio.h: + +/usr/include/string.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/processor/pathname_stripper.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/minidump.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump.Plo new file mode 100644 index 00000000..4214a0f8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump.Plo @@ -0,0 +1,438 @@ +src/processor/minidump.lo src/processor/minidump.o: \ + src/processor/minidump.cc /usr/include/fcntl.h /usr/include/sys/fcntl.h \ + /usr/include/sys/_types.h /usr/include/sys/cdefs.h \ + /usr/include/machine/_types.h /usr/include/i386/_types.h \ + /usr/include/stdio.h /usr/include/_types.h /usr/include/string.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/sys/_structs.h \ + /usr/include/unistd.h /usr/include/sys/unistd.h \ + /usr/include/sys/select.h /usr/include/sys/appleapiopts.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/stdlib.h /usr/include/available.h \ + /usr/include/sys/wait.h /usr/include/sys/signal.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/machine/_structs.h \ + /usr/include/mach/i386/_structs.h /usr/include/sys/resource.h \ + /usr/include/machine/endian.h /usr/include/i386/endian.h \ + /usr/include/sys/_endian.h /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/map /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/c++/4.0.0/cctype /usr/include/ctype.h \ + /usr/include/runetype.h /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + /usr/include/c++/4.0.0/vector \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc src/processor/range_map-inl.h \ + src/processor/range_map.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/minidump.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/memory_region.h \ + src/processor/basic_code_module.h src/processor/basic_code_modules.h \ + src/processor/scoped_ptr.h + +/usr/include/fcntl.h: + +/usr/include/sys/fcntl.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/stdio.h: + +/usr/include/_types.h: + +/usr/include/string.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/processor/range_map-inl.h: + +src/processor/range_map.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/minidump.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/memory_region.h: + +src/processor/basic_code_module.h: + +src/processor/basic_code_modules.h: + +src/processor/scoped_ptr.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_dump.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_dump.Po new file mode 100644 index 00000000..d25636e0 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_dump.Po @@ -0,0 +1,420 @@ +src/processor/minidump_dump.o src/processor/minidump_dump.o: \ + src/processor/minidump_dump.cc /usr/include/c++/4.0.0/cstdio \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/stdio.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h src/google_breakpad/processor/minidump.h \ + /usr/include/unistd.h /usr/include/sys/unistd.h \ + /usr/include/sys/select.h /usr/include/sys/appleapiopts.h \ + /usr/include/sys/_structs.h /usr/include/sys/_select.h \ + /usr/include/c++/4.0.0/map /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/cstring /usr/include/string.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h \ + /usr/include/c++/4.0.0/cctype /usr/include/ctype.h \ + /usr/include/runetype.h /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/memory_region.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/stdio.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +src/google_breakpad/processor/minidump.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/_structs.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/memory_region.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor.Plo new file mode 100644 index 00000000..47031ede --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor.Plo @@ -0,0 +1,441 @@ +src/processor/minidump_processor.lo src/processor/minidump_processor.o: \ + src/processor/minidump_processor.cc /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/sys/cdefs.h /usr/include/stdlib.h \ + /usr/include/available.h /usr/include/_types.h \ + /usr/include/sys/_types.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + src/google_breakpad/processor/minidump_processor.h \ + /usr/include/c++/4.0.0/string \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/call_stack.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/minidump.h /usr/include/c++/4.0.0/map \ + /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/process_state.h \ + src/google_breakpad/processor/system_info.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc src/processor/scoped_ptr.h \ + src/processor/stackwalker_x86.h \ + src/google_breakpad/processor/stackwalker.h + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/sys/cdefs.h: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +src/google_breakpad/processor/minidump_processor.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/call_stack.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/minidump.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/processor/process_state.h: + +src/google_breakpad/processor/system_info.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/processor/scoped_ptr.h: + +src/processor/stackwalker_x86.h: + +src/google_breakpad/processor/stackwalker.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_processor_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_stackwalk.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_stackwalk.Po new file mode 100644 index 00000000..9ca4ce0b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/minidump_stackwalk.Po @@ -0,0 +1,469 @@ +src/processor/minidump_stackwalk.o src/processor/minidump_stackwalk.o: \ + src/processor/minidump_stackwalk.cc /usr/include/c++/4.0.0/cstdio \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/stdio.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/cstring /usr/include/string.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/basic_source_line_resolver.h \ + /usr/include/c++/4.0.0/ext/hash_map \ + /usr/include/c++/4.0.0/ext/hashtable.h /usr/include/c++/4.0.0/iterator \ + /usr/include/c++/4.0.0/ostream /usr/include/c++/4.0.0/ios \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc \ + /usr/include/c++/4.0.0/bits/stream_iterator.h \ + /usr/include/c++/4.0.0/ext/hash_fun.h \ + src/google_breakpad/processor/source_line_resolver_interface.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/minidump.h /usr/include/c++/4.0.0/map \ + /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/minidump_processor.h \ + src/google_breakpad/processor/process_state.h \ + src/google_breakpad/processor/system_info.h \ + src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/processor/stack_frame.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream src/processor/pathname_stripper.h \ + src/processor/scoped_ptr.h src/processor/simple_symbol_supplier.h \ + src/google_breakpad/processor/symbol_supplier.h + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/stdio.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/basic_source_line_resolver.h: + +/usr/include/c++/4.0.0/ext/hash_map: + +/usr/include/c++/4.0.0/ext/hashtable.h: + +/usr/include/c++/4.0.0/iterator: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +/usr/include/c++/4.0.0/bits/stream_iterator.h: + +/usr/include/c++/4.0.0/ext/hash_fun.h: + +src/google_breakpad/processor/source_line_resolver_interface.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/minidump.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/processor/minidump_processor.h: + +src/google_breakpad/processor/process_state.h: + +src/google_breakpad/processor/system_info.h: + +src/google_breakpad/processor/stack_frame_cpu.h: + +src/google_breakpad/processor/stack_frame.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +src/processor/pathname_stripper.h: + +src/processor/scoped_ptr.h: + +src/processor/simple_symbol_supplier.h: + +src/google_breakpad/processor/symbol_supplier.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper.Plo new file mode 100644 index 00000000..cd28c7ae --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper.Plo @@ -0,0 +1,280 @@ +src/processor/pathname_stripper.lo src/processor/pathname_stripper.o: \ + src/processor/pathname_stripper.cc src/processor/pathname_stripper.h \ + /usr/include/c++/4.0.0/string \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc + +src/processor/pathname_stripper.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/pathname_stripper_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/postfix_evaluator_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/postfix_evaluator_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/postfix_evaluator_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/process_state.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/process_state.Plo new file mode 100644 index 00000000..20be5192 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/process_state.Plo @@ -0,0 +1,308 @@ +src/processor/process_state.lo src/processor/process_state.o: \ + src/processor/process_state.cc \ + src/google_breakpad/processor/process_state.h \ + /usr/include/c++/4.0.0/string \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/system_info.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/code_modules.h + +src/google_breakpad/processor/process_state.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/system_info.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/code_modules.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/range_map_unittest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/range_map_unittest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/range_map_unittest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/simple_symbol_supplier.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/simple_symbol_supplier.Plo new file mode 100644 index 00000000..5cfe3a15 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/simple_symbol_supplier.Plo @@ -0,0 +1,395 @@ +src/processor/simple_symbol_supplier.lo \ + src/processor/simple_symbol_supplier.o: \ + src/processor/simple_symbol_supplier.cc /usr/include/sys/types.h \ + /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/i386/_types.h /usr/include/sys/_types.h \ + /usr/include/machine/_types.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/sys/_structs.h \ + /usr/include/sys/stat.h /usr/include/c++/4.0.0/algorithm \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/_types.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/alloca.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/new /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits /usr/include/c++/4.0.0/iostream \ + /usr/include/c++/4.0.0/ostream /usr/include/c++/4.0.0/ios \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/string \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc /usr/include/c++/4.0.0/fstream \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/basic_file.h \ + /usr/include/c++/4.0.0/bits/fstream.tcc \ + src/processor/simple_symbol_supplier.h /usr/include/c++/4.0.0/vector \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/symbol_supplier.h \ + src/google_breakpad/processor/code_module.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/inttypes.h \ + src/google_breakpad/processor/system_info.h src/processor/logging.h \ + src/processor/pathname_stripper.h + +/usr/include/sys/types.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/sys/_structs.h: + +/usr/include/sys/stat.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/_types.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/alloca.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +/usr/include/c++/4.0.0/fstream: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/basic_file.h: + +/usr/include/c++/4.0.0/bits/fstream.tcc: + +src/processor/simple_symbol_supplier.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/symbol_supplier.h: + +src/google_breakpad/processor/code_module.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/system_info.h: + +src/processor/logging.h: + +src/processor/pathname_stripper.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker.Plo new file mode 100644 index 00000000..7be34939 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker.Plo @@ -0,0 +1,454 @@ +src/processor/stackwalker.lo src/processor/stackwalker.o: \ + src/processor/stackwalker.cc /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/sys/cdefs.h /usr/include/stdlib.h \ + /usr/include/available.h /usr/include/_types.h \ + /usr/include/sys/_types.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + src/google_breakpad/processor/stackwalker.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/code_module.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/minidump.h /usr/include/c++/4.0.0/map \ + /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/source_line_resolver_interface.h \ + src/google_breakpad/processor/stack_frame.h \ + src/google_breakpad/processor/symbol_supplier.h \ + src/processor/linked_ptr.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc src/processor/scoped_ptr.h \ + src/processor/stack_frame_info.h src/processor/stackwalker_ppc.h \ + src/processor/stackwalker_sparc.h src/processor/stackwalker_x86.h \ + src/processor/stackwalker_amd64.h + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/sys/cdefs.h: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +src/google_breakpad/processor/stackwalker.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/code_module.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/minidump.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/processor/source_line_resolver_interface.h: + +src/google_breakpad/processor/stack_frame.h: + +src/google_breakpad/processor/symbol_supplier.h: + +src/processor/linked_ptr.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/processor/scoped_ptr.h: + +src/processor/stack_frame_info.h: + +src/processor/stackwalker_ppc.h: + +src/processor/stackwalker_sparc.h: + +src/processor/stackwalker_x86.h: + +src/processor/stackwalker_amd64.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_amd64.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_amd64.Plo new file mode 100644 index 00000000..a275c2c7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_amd64.Plo @@ -0,0 +1,414 @@ +src/processor/stackwalker_amd64.lo src/processor/stackwalker_amd64.o: \ + src/processor/stackwalker_amd64.cc src/processor/stackwalker_amd64.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/i386/_types.h /usr/include/sys/_types.h \ + /usr/include/machine/_types.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/sys/_structs.h \ + /usr/include/inttypes.h /usr/include/_types.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + src/google_breakpad/common/minidump_format.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/stackwalker.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/include/string.h /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/alloca.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/processor/stack_frame.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc + +src/processor/stackwalker_amd64.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/sys/_structs.h: + +/usr/include/inttypes.h: + +/usr/include/_types.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +src/google_breakpad/common/minidump_format.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/stackwalker.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/alloca.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/processor/stack_frame_cpu.h: + +src/google_breakpad/processor/stack_frame.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_ppc.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_ppc.Plo new file mode 100644 index 00000000..c18f5722 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_ppc.Plo @@ -0,0 +1,414 @@ +src/processor/stackwalker_ppc.lo src/processor/stackwalker_ppc.o: \ + src/processor/stackwalker_ppc.cc src/processor/stackwalker_ppc.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/sys/appleapiopts.h /usr/include/sys/cdefs.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/i386/_types.h /usr/include/sys/_types.h \ + /usr/include/machine/_types.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/sys/_structs.h \ + /usr/include/inttypes.h /usr/include/_types.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + src/google_breakpad/common/minidump_format.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/stackwalker.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/include/string.h /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/alloca.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/processor/stack_frame.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc + +src/processor/stackwalker_ppc.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/i386/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/sys/_structs.h: + +/usr/include/inttypes.h: + +/usr/include/_types.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +src/google_breakpad/common/minidump_format.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/stackwalker.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/alloca.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/processor/stack_frame_cpu.h: + +src/google_breakpad/processor/stack_frame.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_selftest.Po b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_selftest.Po new file mode 100644 index 00000000..9ce06a81 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_selftest.Po @@ -0,0 +1 @@ +# dummy diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_sparc.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_sparc.Plo new file mode 100644 index 00000000..e2afb958 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_sparc.Plo @@ -0,0 +1,415 @@ +src/processor/stackwalker_sparc.lo src/processor/stackwalker_sparc.o: \ + src/processor/stackwalker_sparc.cc \ + src/google_breakpad/processor/call_stack.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/cstring /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/_types.h /usr/include/sys/_types.h \ + /usr/include/sys/cdefs.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/sys/appleapiopts.h \ + /usr/include/machine/signal.h /usr/include/i386/signal.h \ + /usr/include/i386/_structs.h /usr/include/sys/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/unistd.h \ + /usr/include/sys/unistd.h /usr/include/sys/select.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/stack_frame.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/ostream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/bits/istream.tcc \ + src/processor/stackwalker_sparc.h \ + src/google_breakpad/processor/stackwalker.h + +src/google_breakpad/processor/call_stack.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/sys/cdefs.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/google_breakpad/processor/stack_frame_cpu.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/stack_frame.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +src/processor/stackwalker_sparc.h: + +src/google_breakpad/processor/stackwalker.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_x86.Plo b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_x86.Plo new file mode 100644 index 00000000..64d30066 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/.deps/stackwalker_x86.Plo @@ -0,0 +1,446 @@ +src/processor/stackwalker_x86.lo src/processor/stackwalker_x86.o: \ + src/processor/stackwalker_x86.cc src/processor/postfix_evaluator-inl.h \ + /usr/include/c++/4.0.0/sstream /usr/include/c++/4.0.0/istream \ + /usr/include/c++/4.0.0/ios /usr/include/c++/4.0.0/iosfwd \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h \ + /usr/include/c++/4.0.0/clocale /usr/include/locale.h \ + /usr/include/_locale.h /usr/include/sys/cdefs.h /usr/include/_types.h \ + /usr/include/sys/_types.h /usr/include/machine/_types.h \ + /usr/include/i386/_types.h /usr/include/c++/4.0.0/cstring \ + /usr/include/c++/4.0.0/cstddef \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h \ + /usr/include/string.h /usr/include/c++/4.0.0/cstdio \ + /usr/include/stdio.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/pthread_impl.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/_structs.h /usr/include/sys/_structs.h \ + /usr/include/unistd.h /usr/include/sys/unistd.h \ + /usr/include/sys/select.h /usr/include/sys/appleapiopts.h \ + /usr/include/sys/_select.h /usr/include/c++/4.0.0/cctype \ + /usr/include/ctype.h /usr/include/runetype.h \ + /usr/include/c++/4.0.0/bits/stringfwd.h \ + /usr/include/c++/4.0.0/bits/postypes.h /usr/include/c++/4.0.0/cwchar \ + /usr/include/c++/4.0.0/ctime /usr/include/wchar.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h \ + /usr/include/_wctype.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h \ + /usr/include/c++/4.0.0/bits/functexcept.h \ + /usr/include/c++/4.0.0/exception_defines.h \ + /usr/include/c++/4.0.0/exception \ + /usr/include/c++/4.0.0/bits/char_traits.h \ + /usr/include/c++/4.0.0/bits/stl_algobase.h \ + /usr/include/c++/4.0.0/climits \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h \ + /usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/machine/limits.h \ + /usr/include/i386/limits.h /usr/include/i386/_limits.h \ + /usr/include/sys/syslimits.h /usr/include/c++/4.0.0/cstdlib \ + /usr/include/stdlib.h /usr/include/available.h /usr/include/sys/wait.h \ + /usr/include/sys/signal.h /usr/include/machine/signal.h \ + /usr/include/i386/signal.h /usr/include/i386/_structs.h \ + /usr/include/machine/_structs.h /usr/include/mach/i386/_structs.h \ + /usr/include/sys/resource.h /usr/include/machine/endian.h \ + /usr/include/i386/endian.h /usr/include/sys/_endian.h \ + /usr/include/libkern/_OSByteOrder.h \ + /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \ + /usr/include/machine/types.h /usr/include/i386/types.h \ + /usr/include/c++/4.0.0/bits/stl_pair.h \ + /usr/include/c++/4.0.0/bits/cpp_type_traits.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.0.0/bits/concept_check.h \ + /usr/include/c++/4.0.0/bits/stl_iterator.h \ + /usr/include/c++/4.0.0/debug/debug.h /usr/include/c++/4.0.0/cassert \ + /usr/include/assert.h /usr/include/c++/4.0.0/bits/localefwd.h \ + /usr/include/c++/4.0.0/bits/ios_base.h \ + /usr/include/c++/4.0.0/bits/atomicity.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h \ + /usr/include/c++/4.0.0/bits/locale_classes.h \ + /usr/include/c++/4.0.0/string /usr/include/c++/4.0.0/memory \ + /usr/include/c++/4.0.0/bits/allocator.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h \ + /usr/include/c++/4.0.0/ext/new_allocator.h /usr/include/c++/4.0.0/new \ + /usr/include/c++/4.0.0/bits/stl_construct.h \ + /usr/include/c++/4.0.0/bits/stl_uninitialized.h \ + /usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.0.0/limits \ + /usr/include/c++/4.0.0/bits/stl_function.h \ + /usr/include/c++/4.0.0/bits/basic_string.h \ + /usr/include/c++/4.0.0/algorithm /usr/include/c++/4.0.0/bits/stl_algo.h \ + /usr/include/c++/4.0.0/bits/stl_heap.h \ + /usr/include/c++/4.0.0/bits/stl_tempbuf.h \ + /usr/include/c++/4.0.0/bits/basic_string.tcc \ + /usr/include/c++/4.0.0/streambuf \ + /usr/include/c++/4.0.0/bits/streambuf.tcc \ + /usr/include/c++/4.0.0/bits/basic_ios.h \ + /usr/include/c++/4.0.0/bits/streambuf_iterator.h \ + /usr/include/c++/4.0.0/bits/locale_facets.h \ + /usr/include/c++/4.0.0/cwctype /usr/include/wctype.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h \ + /usr/include/c++/4.0.0/bits/codecvt.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h \ + /usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h \ + /usr/include/c++/4.0.0/bits/basic_ios.tcc \ + /usr/include/c++/4.0.0/bits/istream.tcc /usr/include/c++/4.0.0/locale \ + /usr/include/c++/4.0.0/bits/locale_facets.tcc \ + /usr/include/c++/4.0.0/typeinfo /usr/include/c++/4.0.0/ostream \ + /usr/include/c++/4.0.0/bits/ostream.tcc \ + /usr/include/c++/4.0.0/bits/sstream.tcc \ + src/processor/postfix_evaluator.h /usr/include/c++/4.0.0/map \ + /usr/include/c++/4.0.0/bits/stl_tree.h \ + /usr/include/c++/4.0.0/bits/stl_map.h \ + /usr/include/c++/4.0.0/bits/stl_multimap.h \ + /usr/include/c++/4.0.0/vector /usr/include/c++/4.0.0/bits/stl_vector.h \ + /usr/include/c++/4.0.0/bits/stl_bvector.h \ + /usr/include/c++/4.0.0/bits/vector.tcc \ + src/google_breakpad/processor/memory_region.h \ + src/google_breakpad/common/breakpad_types.h /usr/include/sys/types.h \ + /usr/include/inttypes.h src/processor/logging.h \ + /usr/include/c++/4.0.0/iostream src/processor/stackwalker_x86.h \ + src/google_breakpad/common/minidump_format.h \ + src/google_breakpad/common/minidump_cpu_sparc.h \ + src/google_breakpad/common/minidump_cpu_x86.h \ + src/google_breakpad/common/minidump_cpu_ppc.h \ + src/google_breakpad/common/minidump_cpu_ppc64.h \ + src/google_breakpad/common/minidump_cpu_amd64.h \ + src/google_breakpad/common/minidump_exception_win32.h \ + src/google_breakpad/common/minidump_exception_mac.h \ + src/google_breakpad/common/minidump_exception_linux.h \ + src/google_breakpad/common/minidump_exception_solaris.h \ + src/google_breakpad/processor/stackwalker.h \ + src/google_breakpad/processor/call_stack.h \ + src/google_breakpad/processor/code_modules.h \ + src/google_breakpad/processor/stack_frame_cpu.h \ + src/google_breakpad/processor/stack_frame.h src/processor/linked_ptr.h \ + src/processor/stack_frame_info.h + +src/processor/postfix_evaluator-inl.h: + +/usr/include/c++/4.0.0/sstream: + +/usr/include/c++/4.0.0/istream: + +/usr/include/c++/4.0.0/ios: + +/usr/include/c++/4.0.0/iosfwd: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++config.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/os_defines.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++locale.h: + +/usr/include/c++/4.0.0/clocale: + +/usr/include/locale.h: + +/usr/include/_locale.h: + +/usr/include/sys/cdefs.h: + +/usr/include/_types.h: + +/usr/include/sys/_types.h: + +/usr/include/machine/_types.h: + +/usr/include/i386/_types.h: + +/usr/include/c++/4.0.0/cstring: + +/usr/include/c++/4.0.0/cstddef: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stddef.h: + +/usr/include/string.h: + +/usr/include/c++/4.0.0/cstdio: + +/usr/include/stdio.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++io.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/pthread_impl.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/_structs.h: + +/usr/include/sys/_structs.h: + +/usr/include/unistd.h: + +/usr/include/sys/unistd.h: + +/usr/include/sys/select.h: + +/usr/include/sys/appleapiopts.h: + +/usr/include/sys/_select.h: + +/usr/include/c++/4.0.0/cctype: + +/usr/include/ctype.h: + +/usr/include/runetype.h: + +/usr/include/c++/4.0.0/bits/stringfwd.h: + +/usr/include/c++/4.0.0/bits/postypes.h: + +/usr/include/c++/4.0.0/cwchar: + +/usr/include/c++/4.0.0/ctime: + +/usr/include/wchar.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdarg.h: + +/usr/include/_wctype.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/stdint.h: + +/usr/include/c++/4.0.0/bits/functexcept.h: + +/usr/include/c++/4.0.0/exception_defines.h: + +/usr/include/c++/4.0.0/exception: + +/usr/include/c++/4.0.0/bits/char_traits.h: + +/usr/include/c++/4.0.0/bits/stl_algobase.h: + +/usr/include/c++/4.0.0/climits: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/limits.h: + +/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/machine/limits.h: + +/usr/include/i386/limits.h: + +/usr/include/i386/_limits.h: + +/usr/include/sys/syslimits.h: + +/usr/include/c++/4.0.0/cstdlib: + +/usr/include/stdlib.h: + +/usr/include/available.h: + +/usr/include/sys/wait.h: + +/usr/include/sys/signal.h: + +/usr/include/machine/signal.h: + +/usr/include/i386/signal.h: + +/usr/include/i386/_structs.h: + +/usr/include/machine/_structs.h: + +/usr/include/mach/i386/_structs.h: + +/usr/include/sys/resource.h: + +/usr/include/machine/endian.h: + +/usr/include/i386/endian.h: + +/usr/include/sys/_endian.h: + +/usr/include/libkern/_OSByteOrder.h: + +/usr/include/libkern/i386/_OSByteOrder.h: + +/usr/include/alloca.h: + +/usr/include/machine/types.h: + +/usr/include/i386/types.h: + +/usr/include/c++/4.0.0/bits/stl_pair.h: + +/usr/include/c++/4.0.0/bits/cpp_type_traits.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.0.0/bits/concept_check.h: + +/usr/include/c++/4.0.0/bits/stl_iterator.h: + +/usr/include/c++/4.0.0/debug/debug.h: + +/usr/include/c++/4.0.0/cassert: + +/usr/include/assert.h: + +/usr/include/c++/4.0.0/bits/localefwd.h: + +/usr/include/c++/4.0.0/bits/ios_base.h: + +/usr/include/c++/4.0.0/bits/atomicity.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/atomic_word.h: + +/usr/include/c++/4.0.0/bits/locale_classes.h: + +/usr/include/c++/4.0.0/string: + +/usr/include/c++/4.0.0/memory: + +/usr/include/c++/4.0.0/bits/allocator.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/c++allocator.h: + +/usr/include/c++/4.0.0/ext/new_allocator.h: + +/usr/include/c++/4.0.0/new: + +/usr/include/c++/4.0.0/bits/stl_construct.h: + +/usr/include/c++/4.0.0/bits/stl_uninitialized.h: + +/usr/include/c++/4.0.0/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.0.0/limits: + +/usr/include/c++/4.0.0/bits/stl_function.h: + +/usr/include/c++/4.0.0/bits/basic_string.h: + +/usr/include/c++/4.0.0/algorithm: + +/usr/include/c++/4.0.0/bits/stl_algo.h: + +/usr/include/c++/4.0.0/bits/stl_heap.h: + +/usr/include/c++/4.0.0/bits/stl_tempbuf.h: + +/usr/include/c++/4.0.0/bits/basic_string.tcc: + +/usr/include/c++/4.0.0/streambuf: + +/usr/include/c++/4.0.0/bits/streambuf.tcc: + +/usr/include/c++/4.0.0/bits/basic_ios.h: + +/usr/include/c++/4.0.0/bits/streambuf_iterator.h: + +/usr/include/c++/4.0.0/bits/locale_facets.h: + +/usr/include/c++/4.0.0/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_base.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/ctype_inline.h: + +/usr/include/c++/4.0.0/bits/codecvt.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/time_members.h: + +/usr/include/c++/4.0.0/i686-apple-darwin9/bits/messages_members.h: + +/usr/include/c++/4.0.0/bits/basic_ios.tcc: + +/usr/include/c++/4.0.0/bits/istream.tcc: + +/usr/include/c++/4.0.0/locale: + +/usr/include/c++/4.0.0/bits/locale_facets.tcc: + +/usr/include/c++/4.0.0/typeinfo: + +/usr/include/c++/4.0.0/ostream: + +/usr/include/c++/4.0.0/bits/ostream.tcc: + +/usr/include/c++/4.0.0/bits/sstream.tcc: + +src/processor/postfix_evaluator.h: + +/usr/include/c++/4.0.0/map: + +/usr/include/c++/4.0.0/bits/stl_tree.h: + +/usr/include/c++/4.0.0/bits/stl_map.h: + +/usr/include/c++/4.0.0/bits/stl_multimap.h: + +/usr/include/c++/4.0.0/vector: + +/usr/include/c++/4.0.0/bits/stl_vector.h: + +/usr/include/c++/4.0.0/bits/stl_bvector.h: + +/usr/include/c++/4.0.0/bits/vector.tcc: + +src/google_breakpad/processor/memory_region.h: + +src/google_breakpad/common/breakpad_types.h: + +/usr/include/sys/types.h: + +/usr/include/inttypes.h: + +src/processor/logging.h: + +/usr/include/c++/4.0.0/iostream: + +src/processor/stackwalker_x86.h: + +src/google_breakpad/common/minidump_format.h: + +src/google_breakpad/common/minidump_cpu_sparc.h: + +src/google_breakpad/common/minidump_cpu_x86.h: + +src/google_breakpad/common/minidump_cpu_ppc.h: + +src/google_breakpad/common/minidump_cpu_ppc64.h: + +src/google_breakpad/common/minidump_cpu_amd64.h: + +src/google_breakpad/common/minidump_exception_win32.h: + +src/google_breakpad/common/minidump_exception_mac.h: + +src/google_breakpad/common/minidump_exception_linux.h: + +src/google_breakpad/common/minidump_exception_solaris.h: + +src/google_breakpad/processor/stackwalker.h: + +src/google_breakpad/processor/call_stack.h: + +src/google_breakpad/processor/code_modules.h: + +src/google_breakpad/processor/stack_frame_cpu.h: + +src/google_breakpad/processor/stack_frame.h: + +src/processor/linked_ptr.h: + +src/processor/stack_frame_info.h: diff --git a/thirdparty/google-breakpad/r318/src/processor/.dirstamp b/thirdparty/google-breakpad/r318/src/processor/.dirstamp new file mode 100644 index 00000000..e69de29b diff --git a/thirdparty/google-breakpad/r318/src/processor/address_map-inl.h b/thirdparty/google-breakpad/r318/src/processor/address_map-inl.h new file mode 100644 index 00000000..d88b4fcc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/address_map-inl.h @@ -0,0 +1,92 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// address_map-inl.h: Address map implementation. +// +// See address_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_ADDRESS_MAP_INL_H__ +#define PROCESSOR_ADDRESS_MAP_INL_H__ + +#include + +#include "processor/address_map.h" +#include "processor/logging.h" + +namespace google_breakpad { + +template +bool AddressMap::Store(const AddressType &address, + const EntryType &entry) { + // Ensure that the specified address doesn't conflict with something already + // in the map. + if (map_.find(address) != map_.end()) { + BPLOG(INFO) << "Store failed, address " << HexString(address) << + " is already present"; + return false; + } + + map_.insert(MapValue(address, entry)); + return true; +} + +template +bool AddressMap::Retrieve( + const AddressType &address, + EntryType *entry, AddressType *entry_address) const { + BPLOG_IF(ERROR, !entry) << "AddressMap::Retrieve requires |entry|"; + assert(entry); + + // upper_bound gives the first element whose key is greater than address, + // but we want the first element whose key is less than or equal to address. + // Decrement the iterator to get there, but not if the upper_bound already + // points to the beginning of the map - in that case, address is lower than + // the lowest stored key, so return false. + MapConstIterator iterator = map_.upper_bound(address); + if (iterator == map_.begin()) + return false; + --iterator; + + *entry = iterator->second; + if (entry_address) + *entry_address = iterator->first; + + return true; +} + +template +void AddressMap::Clear() { + map_.clear(); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_ADDRESS_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/address_map.h b/thirdparty/google-breakpad/r318/src/processor/address_map.h new file mode 100644 index 00000000..14139e7a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/address_map.h @@ -0,0 +1,80 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// address_map.h: Address maps. +// +// An address map contains a set of objects keyed by address. Objects are +// retrieved from the map by returning the object with the highest key less +// than or equal to the lookup key. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_ADDRESS_MAP_H__ +#define PROCESSOR_ADDRESS_MAP_H__ + +#include + +namespace google_breakpad { + +template +class AddressMap { + public: + AddressMap() : map_() {} + + // Inserts an entry into the map. Returns false without storing the entry + // if an entry is already stored in the map at the same address as specified + // by the address argument. + bool Store(const AddressType &address, const EntryType &entry); + + // Locates the entry stored at the highest address less than or equal to + // the address argument. If there is no such range, returns false. The + // entry is returned in entry, which is a required argument. If + // entry_address is not NULL, it will be set to the address that the entry + // was stored at. + bool Retrieve(const AddressType &address, + EntryType *entry, AddressType *entry_address) const; + + // Empties the address map, restoring it to the same state as when it was + // initially created. + void Clear(); + + private: + // Convenience types. + typedef std::map AddressToEntryMap; + typedef typename AddressToEntryMap::const_iterator MapConstIterator; + typedef typename AddressToEntryMap::value_type MapValue; + + // Maps the address of each entry to an EntryType. + AddressToEntryMap map_; +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_ADDRESS_MAP_H__ + diff --git a/thirdparty/google-breakpad/r318/src/processor/address_map_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/address_map_unittest.cc new file mode 100644 index 00000000..f64a8984 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/address_map_unittest.cc @@ -0,0 +1,196 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// address_map_unittest.cc: Unit tests for AddressMap. +// +// Author: Mark Mentovai + +#include +#include + +#include "processor/address_map-inl.h" +#include "processor/linked_ptr.h" +#include "processor/logging.h" + +#define ASSERT_TRUE(condition) \ + if (!(condition)) { \ + fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ + return false; \ + } + +#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition)) + +#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) + +namespace { + +using google_breakpad::AddressMap; +using google_breakpad::linked_ptr; + +// A CountedObject holds an int. A global (not thread safe!) count of +// allocated CountedObjects is maintained to help test memory management. +class CountedObject { + public: + explicit CountedObject(int id) : id_(id) { ++count_; } + ~CountedObject() { --count_; } + + static int count() { return count_; } + int id() const { return id_; } + + private: + static int count_; + int id_; +}; + +int CountedObject::count_; + +typedef int AddressType; +typedef AddressMap< AddressType, linked_ptr > TestMap; + +static bool DoAddressMapTest() { + ASSERT_EQ(CountedObject::count(), 0); + + TestMap test_map; + linked_ptr entry; + AddressType address; + + // Check that a new map is truly empty. + ASSERT_FALSE(test_map.Retrieve(0, &entry, &address)); + ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address)); + ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address)); + + // Check that Clear clears the map without leaking. + ASSERT_EQ(CountedObject::count(), 0); + ASSERT_TRUE(test_map.Store(1, + linked_ptr(new CountedObject(0)))); + ASSERT_TRUE(test_map.Retrieve(1, &entry, &address)); + ASSERT_EQ(CountedObject::count(), 1); + test_map.Clear(); + ASSERT_EQ(CountedObject::count(), 1); // still holding entry in this scope + + // Check that a cleared map is truly empty. + ASSERT_FALSE(test_map.Retrieve(0, &entry, &address)); + ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address)); + ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address)); + + // Check a single-element map. + ASSERT_TRUE(test_map.Store(10, + linked_ptr(new CountedObject(1)))); + ASSERT_FALSE(test_map.Retrieve(9, &entry, &address)); + ASSERT_TRUE(test_map.Retrieve(10, &entry, &address)); + ASSERT_EQ(CountedObject::count(), 1); + ASSERT_EQ(entry->id(), 1); + ASSERT_EQ(address, 10); + ASSERT_TRUE(test_map.Retrieve(11, &entry, &address)); + ASSERT_TRUE(test_map.Retrieve(11, &entry, NULL)); // NULL ok here + + // Add some more elements. + ASSERT_TRUE(test_map.Store(5, + linked_ptr(new CountedObject(2)))); + ASSERT_EQ(CountedObject::count(), 2); + ASSERT_TRUE(test_map.Store(20, + linked_ptr(new CountedObject(3)))); + ASSERT_TRUE(test_map.Store(15, + linked_ptr(new CountedObject(4)))); + ASSERT_FALSE(test_map.Store(10, + linked_ptr(new CountedObject(5)))); // already in map + ASSERT_TRUE(test_map.Store(16, + linked_ptr(new CountedObject(6)))); + ASSERT_TRUE(test_map.Store(14, + linked_ptr(new CountedObject(7)))); + + // Nothing was stored with a key under 5. Don't use ASSERT inside loops + // because it won't show exactly which key/entry/address failed. + for (AddressType key = 0; key < 5; ++key) { + if (test_map.Retrieve(key, &entry, &address)) { + fprintf(stderr, + "FAIL: retrieve %d expected false observed true @ %s:%d\n", + key, __FILE__, __LINE__); + return false; + } + } + + // Check everything that was stored. + const int id_verify[] = { 0, 0, 0, 0, 0, // unused + 2, 2, 2, 2, 2, // 5 - 9 + 1, 1, 1, 1, 7, // 10 - 14 + 4, 6, 6, 6, 6, // 15 - 19 + 3, 3, 3, 3, 3, // 20 - 24 + 3, 3, 3, 3, 3 }; // 25 - 29 + const AddressType address_verify[] = { 0, 0, 0, 0, 0, // unused + 5, 5, 5, 5, 5, // 5 - 9 + 10, 10, 10, 10, 14, // 10 - 14 + 15, 16, 16, 16, 16, // 15 - 19 + 20, 20, 20, 20, 20, // 20 - 24 + 20, 20, 20, 20, 20 }; // 25 - 29 + + for (AddressType key = 5; key < 30; ++key) { + if (!test_map.Retrieve(key, &entry, &address)) { + fprintf(stderr, + "FAIL: retrieve %d expected true observed false @ %s:%d\n", + key, __FILE__, __LINE__); + return false; + } + if (entry->id() != id_verify[key]) { + fprintf(stderr, + "FAIL: retrieve %d expected entry %d observed %d @ %s:%d\n", + key, id_verify[key], entry->id(), __FILE__, __LINE__); + return false; + } + if (address != address_verify[key]) { + fprintf(stderr, + "FAIL: retrieve %d expected address %d observed %d @ %s:%d\n", + key, address_verify[key], address, __FILE__, __LINE__); + return false; + } + } + + // The stored objects should still be in the map. + ASSERT_EQ(CountedObject::count(), 6); + + return true; +} + +static bool RunTests() { + if (!DoAddressMapTest()) + return false; + + // Leak check. + ASSERT_EQ(CountedObject::count(), 0); + + return true; +} + +} // namespace + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/basic_code_module.h b/thirdparty/google-breakpad/r318/src/processor/basic_code_module.h new file mode 100644 index 00000000..5c9f75f1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/basic_code_module.h @@ -0,0 +1,95 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// basic_code_module.h: Carries information about code modules that are loaded +// into a process. +// +// This is a basic concrete implementation of CodeModule. It cannot be +// instantiated directly, only based on other objects that implement +// the CodeModule interface. It exists to provide a CodeModule implementation +// a place to store information when the life of the original object (such as +// a MinidumpModule) cannot be guaranteed. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_BASIC_CODE_MODULE_H__ +#define PROCESSOR_BASIC_CODE_MODULE_H__ + +#include + +#include "google_breakpad/processor/code_module.h" + +namespace google_breakpad { + +using std::string; + +class BasicCodeModule : public CodeModule { + public: + // Creates a new BasicCodeModule given any existing CodeModule + // implementation. This is useful to make a copy of the data relevant to + // the CodeModule interface without requiring all of the resources that + // other CodeModule implementations may require. + explicit BasicCodeModule(const CodeModule *that) + : base_address_(that->base_address()), + size_(that->size()), + code_file_(that->code_file()), + code_identifier_(that->code_identifier()), + debug_file_(that->debug_file()), + debug_identifier_(that->debug_identifier()), + version_(that->version()) {} + virtual ~BasicCodeModule() {} + + // See code_module.h for descriptions of these methods and the associated + // members. + virtual u_int64_t base_address() const { return base_address_; } + virtual u_int64_t size() const { return size_; } + virtual string code_file() const { return code_file_; } + virtual string code_identifier() const { return code_identifier_; } + virtual string debug_file() const { return debug_file_; } + virtual string debug_identifier() const { return debug_identifier_; } + virtual string version() const { return version_; } + virtual const CodeModule* Copy() const { return new BasicCodeModule(this); } + + private: + u_int64_t base_address_; + u_int64_t size_; + string code_file_; + string code_identifier_; + string debug_file_; + string debug_identifier_; + string version_; + + // Disallow copy constructor and assignment operator. + BasicCodeModule(const BasicCodeModule &that); + void operator=(const BasicCodeModule &that); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_BASIC_CODE_MODULE_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.cc b/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.cc new file mode 100644 index 00000000..a21491c4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// basic_code_modules.cc: Contains all of the CodeModule objects that +// were loaded into a single process. +// +// See basic_code_modules.h for documentation. +// +// Author: Mark Mentovai + +#include + +#include "processor/basic_code_modules.h" +#include "google_breakpad/processor/code_module.h" +#include "processor/linked_ptr.h" +#include "processor/logging.h" +#include "processor/range_map-inl.h" + +namespace google_breakpad { + +BasicCodeModules::BasicCodeModules(const CodeModules *that) + : main_address_(0), + map_(new RangeMap >()) { + BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires " + "|that|"; + assert(that); + + const CodeModule *main_module = that->GetMainModule(); + if (main_module) + main_address_ = main_module->base_address(); + + unsigned int count = that->module_count(); + for (unsigned int module_sequence = 0; + module_sequence < count; + ++module_sequence) { + // Make a copy of the module and insert it into the map. Use + // GetModuleAtIndex because ordering is unimportant when slurping the + // entire list, and GetModuleAtIndex may be faster than + // GetModuleAtSequence. + const CodeModule *module = that->GetModuleAtIndex(module_sequence)->Copy(); + if (!map_->StoreRange(module->base_address(), module->size(), + linked_ptr(module))) { + BPLOG(ERROR) << "Module " << module->code_file() << + " could not be stored"; + } + } +} + +BasicCodeModules::~BasicCodeModules() { + delete map_; +} + +unsigned int BasicCodeModules::module_count() const { + return map_->GetCount(); +} + +const CodeModule* BasicCodeModules::GetModuleForAddress( + u_int64_t address) const { + linked_ptr module; + if (!map_->RetrieveRange(address, &module, NULL, NULL)) { + BPLOG(INFO) << "No module at " << HexString(address); + return NULL; + } + + return module.get(); +} + +const CodeModule* BasicCodeModules::GetMainModule() const { + return GetModuleForAddress(main_address_); +} + +const CodeModule* BasicCodeModules::GetModuleAtSequence( + unsigned int sequence) const { + linked_ptr module; + if (!map_->RetrieveRangeAtIndex(sequence, &module, NULL, NULL)) { + BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence; + return NULL; + } + + return module.get(); +} + +const CodeModule* BasicCodeModules::GetModuleAtIndex( + unsigned int index) const { + // This class stores everything in a RangeMap, without any more-efficient + // way to walk the list of CodeModule objects. Implement GetModuleAtIndex + // using GetModuleAtSequence, which meets all of the requirements, and + // in addition, guarantees ordering. + return GetModuleAtSequence(index); +} + +const CodeModules* BasicCodeModules::Copy() const { + return new BasicCodeModules(this); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.h b/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.h new file mode 100644 index 00000000..df87fc49 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/basic_code_modules.h @@ -0,0 +1,85 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// basic_code_modules.h: Contains all of the CodeModule objects that +// were loaded into a single process. +// +// This is a basic concrete implementation of CodeModules. It cannot be +// instantiated directly, only based on other objects that implement +// the CodeModules interface. It exists to provide a CodeModules +// implementation a place to store information when the life of the original +// object (such as a MinidumpModuleList) cannot be guaranteed. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_BASIC_CODE_MODULES_H__ +#define PROCESSOR_BASIC_CODE_MODULES_H__ + +#include "google_breakpad/processor/code_modules.h" + +namespace google_breakpad { + +template class linked_ptr; +template class RangeMap; + +class BasicCodeModules : public CodeModules { + public: + // Creates a new BasicCodeModules object given any existing CodeModules + // implementation. This is useful to make a copy of the data relevant to + // the CodeModules and CodeModule interfaces without requiring all of the + // resources that other implementations may require. A copy will be + // made of each contained CodeModule using CodeModule::Copy. + explicit BasicCodeModules(const CodeModules *that); + + virtual ~BasicCodeModules(); + + // See code_modules.h for descriptions of these methods. + virtual unsigned int module_count() const; + virtual const CodeModule* GetModuleForAddress(u_int64_t address) const; + virtual const CodeModule* GetMainModule() const; + virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const; + virtual const CodeModule* GetModuleAtIndex(unsigned int index) const; + virtual const CodeModules* Copy() const; + + private: + // The base address of the main module. + u_int64_t main_address_; + + // The map used to contain each CodeModule, keyed by each CodeModule's + // address range. + RangeMap > *map_; + + // Disallow copy constructor and assignment operator. + BasicCodeModules(const BasicCodeModules &that); + void operator=(const BasicCodeModules &that); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_BASIC_CODE_MODULES_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver.cc b/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver.cc new file mode 100644 index 00000000..bba86599 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver.cc @@ -0,0 +1,714 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "processor/address_map-inl.h" +#include "processor/contained_range_map-inl.h" +#include "processor/range_map-inl.h" + +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/stack_frame.h" +#include "processor/linked_ptr.h" +#include "processor/scoped_ptr.h" +#include "processor/stack_frame_info.h" + +using std::map; +using std::vector; +using std::make_pair; +#ifndef BSLR_NO_HASH_MAP +using __gnu_cxx::hash; +#endif // BSLR_NO_HASH_MAP + +namespace google_breakpad { + +struct BasicSourceLineResolver::Line { + Line(MemAddr addr, MemAddr code_size, int file_id, int source_line) + : address(addr) + , size(code_size) + , source_file_id(file_id) + , line(source_line) { } + + MemAddr address; + MemAddr size; + int source_file_id; + int line; +}; + +struct BasicSourceLineResolver::Function { + Function(const string &function_name, + MemAddr function_address, + MemAddr code_size, + int set_parameter_size) + : name(function_name), address(function_address), size(code_size), + parameter_size(set_parameter_size) { } + + string name; + MemAddr address; + MemAddr size; + + // The size of parameters passed to this function on the stack. + int parameter_size; + + RangeMap< MemAddr, linked_ptr > lines; +}; + +struct BasicSourceLineResolver::PublicSymbol { + PublicSymbol(const string& set_name, + MemAddr set_address, + int set_parameter_size) + : name(set_name), + address(set_address), + parameter_size(set_parameter_size) {} + + string name; + MemAddr address; + + // If the public symbol is used as a function entry point, parameter_size + // is set to the size of the parameters passed to the funciton on the + // stack, if known. + int parameter_size; +}; + +class BasicSourceLineResolver::Module { + public: + Module(const string &name) : name_(name) { } + + // Loads the given map file, returning true on success. Reads the + // map file into memory and calls LoadMapFromBuffer + bool LoadMap(const string &map_file); + + // Loads a map from the given buffer, returning true on success + bool LoadMapFromBuffer(const string &map_buffer); + + // Looks up the given relative address, and fills the StackFrame struct + // with the result. Additional debugging information, if available, is + // returned. If no additional information is available, returns NULL. + // A NULL return value is not an error. The caller takes ownership of + // any returned StackFrameInfo object. + StackFrameInfo* LookupAddress(StackFrame *frame) const; + + private: + friend class BasicSourceLineResolver; +#ifdef BSLR_NO_HASH_MAP + typedef map FileMap; +#else // BSLR_NO_HASH_MAP + typedef hash_map FileMap; +#endif // BSLR_NO_HASH_MAP + + // The types for stack_info_. This is equivalent to MS DIA's + // StackFrameTypeEnum. Each identifies a different type of frame + // information, although all are represented in the symbol file in the + // same format. These are used as indices to the stack_info_ array. + enum StackInfoTypes { + STACK_INFO_FPO = 0, + STACK_INFO_TRAP, // not used here + STACK_INFO_TSS, // not used here + STACK_INFO_STANDARD, + STACK_INFO_FRAME_DATA, + STACK_INFO_LAST, // must be the last sequentially-numbered item + STACK_INFO_UNKNOWN = -1 + }; + + // Splits line into at most max_tokens space-separated tokens, placing + // them in the tokens vector. line is a 0-terminated string that + // optionally ends with a newline character or combination, which will + // be removed. line must not contain any embedded '\n' or '\r' characters. + // If more tokens than max_tokens are present, the final token is placed + // into the vector without splitting it up at all. This modifies line as + // a side effect. Returns true if exactly max_tokens tokens are returned, + // and false if fewer are returned. This is not considered a failure of + // Tokenize, but may be treated as a failure if the caller expects an + // exact, as opposed to maximum, number of tokens. + static bool Tokenize(char *line, int max_tokens, vector *tokens); + + // Parses a file declaration + bool ParseFile(char *file_line); + + // Parses a function declaration, returning a new Function object. + Function* ParseFunction(char *function_line); + + // Parses a line declaration, returning a new Line object. + Line* ParseLine(char *line_line); + + // Parses a PUBLIC symbol declaration, storing it in public_symbols_. + // Returns false if an error occurs. + bool ParsePublicSymbol(char *public_line); + + // Parses a stack frame info declaration, storing it in stack_info_. + bool ParseStackInfo(char *stack_info_line); + + string name_; + FileMap files_; + RangeMap< MemAddr, linked_ptr > functions_; + AddressMap< MemAddr, linked_ptr > public_symbols_; + + // Each element in the array is a ContainedRangeMap for a type listed in + // StackInfoTypes. These are split by type because there may be overlaps + // between maps of different types, but some information is only available + // as certain types. + ContainedRangeMap< MemAddr, linked_ptr > + stack_info_[STACK_INFO_LAST]; +}; + +BasicSourceLineResolver::BasicSourceLineResolver() : modules_(new ModuleMap) { +} + +BasicSourceLineResolver::~BasicSourceLineResolver() { + ModuleMap::iterator it; + for (it = modules_->begin(); it != modules_->end(); ++it) { + delete it->second; + } + delete modules_; +} + +bool BasicSourceLineResolver::LoadModule(const string &module_name, + const string &map_file) { + // Make sure we don't already have a module with the given name. + if (modules_->find(module_name) != modules_->end()) { + BPLOG(INFO) << "Symbols for module " << module_name << " already loaded"; + return false; + } + + BPLOG(INFO) << "Loading symbols for module " << module_name << " from " << + map_file; + + Module *module = new Module(module_name); + if (!module->LoadMap(map_file)) { + delete module; + return false; + } + + modules_->insert(make_pair(module_name, module)); + return true; +} + +bool BasicSourceLineResolver::LoadModuleUsingMapBuffer( + const string &module_name, + const string &map_buffer) { + // Make sure we don't already have a module with the given name. + if (modules_->find(module_name) != modules_->end()) { + BPLOG(INFO) << "Symbols for module " << module_name << " already loaded"; + return false; + } + + BPLOG(INFO) << "Loading symbols for module " << module_name << " from buffer"; + + Module *module = new Module(module_name); + if (!module->LoadMapFromBuffer(map_buffer)) { + delete module; + return false; + } + + modules_->insert(make_pair(module_name, module)); + return true; +} + +bool BasicSourceLineResolver::HasModule(const string &module_name) const { + return modules_->find(module_name) != modules_->end(); +} + +StackFrameInfo* BasicSourceLineResolver::FillSourceLineInfo( + StackFrame *frame) const { + if (frame->module) { + ModuleMap::const_iterator it = modules_->find(frame->module->code_file()); + if (it != modules_->end()) { + return it->second->LookupAddress(frame); + } + } + return NULL; +} + +class AutoFileCloser { + public: + AutoFileCloser(FILE *file) : file_(file) {} + ~AutoFileCloser() { + if (file_) + fclose(file_); + } + + private: + FILE *file_; +}; + +bool BasicSourceLineResolver::Module::LoadMapFromBuffer( + const string &map_buffer) { + linked_ptr cur_func; + int line_number = 0; + const char *map_buffer_c_str = map_buffer.c_str(); + char *save_ptr; + + // set up our input buffer as a c-style string so we + // can we use strtok() + // have to copy because modifying the result of string::c_str is not + // permitted + size_t map_buffer_length = strlen(map_buffer_c_str); + char *map_buffer_chars = new char[map_buffer_length]; + if (map_buffer_chars == NULL) { + BPLOG(ERROR) << "Memory allocation of " << map_buffer_length << + " bytes failed"; + return false; + } + + strncpy(map_buffer_chars, map_buffer_c_str, map_buffer_length); + + if (map_buffer_chars[map_buffer_length - 1] == '\n') { + map_buffer_chars[map_buffer_length - 1] = '\0'; + } + char *buffer; + buffer = strtok_r(map_buffer_chars, "\r\n", &save_ptr); + + while (buffer != NULL) { + ++line_number; + + if (strncmp(buffer, "FILE ", 5) == 0) { + if (!ParseFile(buffer)) { + BPLOG(ERROR) << "ParseFile on buffer failed at " << + ":" << line_number; + delete [] map_buffer_chars; + return false; + } + } else if (strncmp(buffer, "STACK ", 6) == 0) { + if (!ParseStackInfo(buffer)) { + BPLOG(ERROR) << "ParseStackInfo failed at " << + ":" << line_number; + delete [] map_buffer_chars; + return false; + } + } else if (strncmp(buffer, "FUNC ", 5) == 0) { + cur_func.reset(ParseFunction(buffer)); + if (!cur_func.get()) { + BPLOG(ERROR) << "ParseFunction failed at " << + ":" << line_number; + delete [] map_buffer_chars; + return false; + } + // StoreRange will fail if the function has an invalid address or size. + // We'll silently ignore this, the function and any corresponding lines + // will be destroyed when cur_func is released. + functions_.StoreRange(cur_func->address, cur_func->size, cur_func); + } else if (strncmp(buffer, "PUBLIC ", 7) == 0) { + // Clear cur_func: public symbols don't contain line number information. + cur_func.reset(); + + if (!ParsePublicSymbol(buffer)) { + BPLOG(ERROR) << "ParsePublicSymbol failed at " << + ":" << line_number; + delete [] map_buffer_chars; + return false; + } + } else if (strncmp(buffer, "MODULE ", 7) == 0) { + // Ignore these. They're not of any use to BasicSourceLineResolver, + // which is fed modules by a SymbolSupplier. These lines are present to + // aid other tools in properly placing symbol files so that they can + // be accessed by a SymbolSupplier. + // + // MODULE + } else { + if (!cur_func.get()) { + BPLOG(ERROR) << "Found source line data without a function at " << + ":" << line_number; + delete [] map_buffer_chars; + return false; + } + Line *line = ParseLine(buffer); + if (!line) { + BPLOG(ERROR) << "ParseLine failed at " << line_number << " for " << + buffer; + delete [] map_buffer_chars; + return false; + } + cur_func->lines.StoreRange(line->address, line->size, + linked_ptr(line)); + } + + buffer = strtok_r(NULL, "\r\n", &save_ptr); + } + + return true; +} + +bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { + struct stat buf; + int error_code = stat(map_file.c_str(), &buf); + if (error_code == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not open " << map_file << + ", error " << error_code << ": " << error_string; + return false; + } + + off_t file_size = buf.st_size; + + // Allocate memory for file contents, plus a null terminator + // since we'll use strtok() on the contents. + char *file_buffer = new char[sizeof(char)*file_size + 1]; + + if (file_buffer == NULL) { + BPLOG(ERROR) << "Could not allocate memory for " << map_file; + return false; + } + + BPLOG(ERROR) << "Opening " << map_file; + + FILE *f = fopen(map_file.c_str(), "rt"); + if (!f) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not open " << map_file << + ", error " << error_code << ": " << error_string; + delete [] file_buffer; + return false; + } + + AutoFileCloser closer(f); + + int items_read = 0; + + items_read = fread(file_buffer, 1, file_size, f); + + if (items_read != file_size) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not slurp " << map_file << + ", error " << error_code << ": " << error_string; + delete [] file_buffer; + return false; + } + file_buffer[file_size] = '\0'; + string map_buffer(file_buffer); + delete [] file_buffer; + + return LoadMapFromBuffer(map_buffer); +} + +StackFrameInfo* BasicSourceLineResolver::Module::LookupAddress( + StackFrame *frame) const { + MemAddr address = frame->instruction - frame->module->base_address(); + + linked_ptr retrieved_info; + // Check for debugging info first, before any possible early returns. + // + // We only know about STACK_INFO_FRAME_DATA and STACK_INFO_FPO. Prefer + // them in this order. STACK_INFO_FRAME_DATA is the newer type that + // includes its own program string. STACK_INFO_FPO is the older type + // corresponding to the FPO_DATA struct. See stackwalker_x86.cc. + if (!stack_info_[STACK_INFO_FRAME_DATA].RetrieveRange(address, + &retrieved_info)) { + stack_info_[STACK_INFO_FPO].RetrieveRange(address, &retrieved_info); + } + + scoped_ptr frame_info; + if (retrieved_info.get()) { + frame_info.reset(new StackFrameInfo()); + frame_info->CopyFrom(*retrieved_info.get()); + } + + // First, look for a matching FUNC range. Use RetrieveNearestRange instead + // of RetrieveRange so that the nearest function can be compared to the + // nearest PUBLIC symbol if the address does not lie within the function. + // Having access to the highest function below address, even when address + // is outside of the function, is useful: if the function is higher than + // the nearest PUBLIC symbol, then it means that the PUBLIC symbols is not + // valid for the address, and no function information should be filled in. + // Using RetrieveNearestRange instead of RetrieveRange means that we need + // to verify that address is within the range before using a FUNC. + // + // If no FUNC containing the address is found, look for the nearest PUBLIC + // symbol, being careful not to use a public symbol at a lower address than + // the nearest FUNC. + int parameter_size = 0; + linked_ptr func; + linked_ptr public_symbol; + MemAddr function_base; + MemAddr function_size; + MemAddr public_address; + if (functions_.RetrieveNearestRange(address, &func, + &function_base, &function_size) && + address >= function_base && address < function_base + function_size) { + parameter_size = func->parameter_size; + + frame->function_name = func->name; + frame->function_base = frame->module->base_address() + function_base; + + linked_ptr line; + MemAddr line_base; + if (func->lines.RetrieveRange(address, &line, &line_base, NULL)) { + FileMap::const_iterator it = files_.find(line->source_file_id); + if (it != files_.end()) { + frame->source_file_name = files_.find(line->source_file_id)->second; + } + frame->source_line = line->line; + frame->source_line_base = frame->module->base_address() + line_base; + } + } else if (public_symbols_.Retrieve(address, + &public_symbol, &public_address) && + (!func.get() || public_address > function_base + function_size)) { + parameter_size = public_symbol->parameter_size; + + frame->function_name = public_symbol->name; + frame->function_base = frame->module->base_address() + public_address; + } else { + // No FUNC or PUBLIC data available. + return frame_info.release(); + } + + if (!frame_info.get()) { + // Even without a relevant STACK line, many functions contain information + // about how much space their parameters consume on the stack. Prefer + // the STACK stuff (above), but if it's not present, take the + // information from the FUNC or PUBLIC line. + frame_info.reset(new StackFrameInfo()); + frame_info->parameter_size = parameter_size; + frame_info->valid |= StackFrameInfo::VALID_PARAMETER_SIZE; + } + + return frame_info.release(); +} + +// static +bool BasicSourceLineResolver::Module::Tokenize(char *line, int max_tokens, + vector *tokens) { + tokens->clear(); + tokens->reserve(max_tokens); + + int remaining = max_tokens; + + // Split tokens on the space character. Look for newlines too to + // strip them out before exhausting max_tokens. + char *save_ptr; + char *token = strtok_r(line, " \r\n", &save_ptr); + while (token && --remaining > 0) { + tokens->push_back(token); + if (remaining > 1) + token = strtok_r(NULL, " \r\n", &save_ptr); + } + + // If there's anything left, just add it as a single token. + if (!remaining > 0) { + if ((token = strtok_r(NULL, "\r\n", &save_ptr))) { + tokens->push_back(token); + } + } + + return tokens->size() == static_cast(max_tokens); +} + +bool BasicSourceLineResolver::Module::ParseFile(char *file_line) { + // FILE + file_line += 5; // skip prefix + + vector tokens; + if (!Tokenize(file_line, 2, &tokens)) { + return false; + } + + int index = atoi(tokens[0]); + if (index < 0) { + return false; + } + + char *filename = tokens[1]; + if (!filename) { + return false; + } + + files_.insert(make_pair(index, string(filename))); + return true; +} + +BasicSourceLineResolver::Function* +BasicSourceLineResolver::Module::ParseFunction(char *function_line) { + // FUNC
+ function_line += 5; // skip prefix + + vector tokens; + if (!Tokenize(function_line, 4, &tokens)) { + return NULL; + } + + u_int64_t address = strtoull(tokens[0], NULL, 16); + u_int64_t size = strtoull(tokens[1], NULL, 16); + int stack_param_size = strtoull(tokens[2], NULL, 16); + char *name = tokens[3]; + + return new Function(name, address, size, stack_param_size); +} + +BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine( + char *line_line) { + //
+ vector tokens; + if (!Tokenize(line_line, 4, &tokens)) { + return NULL; + } + + u_int64_t address = strtoull(tokens[0], NULL, 16); + u_int64_t size = strtoull(tokens[1], NULL, 16); + int line_number = atoi(tokens[2]); + int source_file = atoi(tokens[3]); + if (line_number <= 0) { + return NULL; + } + + return new Line(address, size, source_file, line_number); +} + +bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) { + // PUBLIC
+ + // Skip "PUBLIC " prefix. + public_line += 7; + + vector tokens; + if (!Tokenize(public_line, 3, &tokens)) { + return false; + } + + u_int64_t address = strtoull(tokens[0], NULL, 16); + int stack_param_size = strtoull(tokens[1], NULL, 16); + char *name = tokens[2]; + + // A few public symbols show up with an address of 0. This has been seen + // in the dumped output of ntdll.pdb for symbols such as _CIlog, _CIpow, + // RtlDescribeChunkLZNT1, and RtlReserveChunkLZNT1. They would conflict + // with one another if they were allowed into the public_symbols_ map, + // but since the address is obviously invalid, gracefully accept them + // as input without putting them into the map. + if (address == 0) { + return true; + } + + linked_ptr symbol(new PublicSymbol(name, address, + stack_param_size)); + return public_symbols_.Store(address, symbol); +} + +bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) { + // STACK WIN + // + // + // + // If has_program_string is 1, the rest of the line is a program string. + // Otherwise, the final token tells whether the stack info indicates that + // a base pointer has been allocated. + // + // Expect has_program_string to be 1 when type is STACK_INFO_FRAME_DATA and + // 0 when type is STACK_INFO_FPO, but don't enforce this. + + // Skip "STACK " prefix. + stack_info_line += 6; + + vector tokens; + if (!Tokenize(stack_info_line, 12, &tokens)) + return false; + + // Only MSVC stack frame info is understood for now. + const char *platform = tokens[0]; + if (strcmp(platform, "WIN") != 0) + return false; + + int type = strtol(tokens[1], NULL, 16); + if (type < 0 || type > STACK_INFO_LAST - 1) + return false; + + u_int64_t rva = strtoull(tokens[2], NULL, 16); + u_int64_t code_size = strtoull(tokens[3], NULL, 16); + u_int32_t prolog_size = strtoul(tokens[4], NULL, 16); + u_int32_t epilog_size = strtoul(tokens[5], NULL, 16); + u_int32_t parameter_size = strtoul(tokens[6], NULL, 16); + u_int32_t saved_register_size = strtoul(tokens[7], NULL, 16); + u_int32_t local_size = strtoul(tokens[8], NULL, 16); + u_int32_t max_stack_size = strtoul(tokens[9], NULL, 16); + int has_program_string = strtoul(tokens[10], NULL, 16); + + const char *program_string = ""; + int allocates_base_pointer = 0; + if (has_program_string) { + program_string = tokens[11]; + } else { + allocates_base_pointer = strtoul(tokens[11], NULL, 16); + } + + // TODO(mmentovai): I wanted to use StoreRange's return value as this + // method's return value, but MSVC infrequently outputs stack info that + // violates the containment rules. This happens with a section of code + // in strncpy_s in test_app.cc (testdata/minidump2). There, problem looks + // like this: + // STACK WIN 4 4242 1a a 0 ... (STACK WIN 4 base size prolog 0 ...) + // STACK WIN 4 4243 2e 9 0 ... + // ContainedRangeMap treats these two blocks as conflicting. In reality, + // when the prolog lengths are taken into account, the actual code of + // these blocks doesn't conflict. However, we can't take the prolog lengths + // into account directly here because we'd wind up with a different set + // of range conflicts when MSVC outputs stack info like this: + // STACK WIN 4 1040 73 33 0 ... + // STACK WIN 4 105a 59 19 0 ... + // because in both of these entries, the beginning of the code after the + // prolog is at 0x1073, and the last byte of contained code is at 0x10b2. + // Perhaps we could get away with storing ranges by rva + prolog_size + // if ContainedRangeMap were modified to allow replacement of + // already-stored values. + + linked_ptr stack_frame_info( + new StackFrameInfo(prolog_size, + epilog_size, + parameter_size, + saved_register_size, + local_size, + max_stack_size, + allocates_base_pointer, + program_string)); + stack_info_[type].StoreRange(rva, code_size, stack_frame_info); + + return true; +} + +#ifdef BSLR_NO_HASH_MAP +bool BasicSourceLineResolver::CompareString::operator()( + const string &s1, const string &s2) const { + return strcmp(s1.c_str(), s2.c_str()) < 0; +} +#else // BSLR_NO_HASH_MAP +size_t BasicSourceLineResolver::HashString::operator()(const string &s) const { + return hash()(s.c_str()); +} +#endif // BSLR_NO_HASH_MAP + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver_unittest.cc new file mode 100644 index 00000000..95595a85 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/basic_source_line_resolver_unittest.cc @@ -0,0 +1,212 @@ +// 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 +#include +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/stack_frame.h" +#include "processor/linked_ptr.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" +#include "processor/stack_frame_info.h" + +#define ASSERT_TRUE(cond) \ + if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + return false; \ + } + +#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond)) + +#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) + +namespace { + +using std::string; +using google_breakpad::BasicSourceLineResolver; +using google_breakpad::CodeModule; +using google_breakpad::linked_ptr; +using google_breakpad::scoped_ptr; +using google_breakpad::StackFrame; +using google_breakpad::StackFrameInfo; + +class TestCodeModule : public CodeModule { + public: + TestCodeModule(string code_file) : code_file_(code_file) {} + virtual ~TestCodeModule() {} + + virtual u_int64_t base_address() const { return 0; } + virtual u_int64_t size() const { return 0x4000; } + virtual string code_file() const { return code_file_; } + virtual string code_identifier() const { return ""; } + virtual string debug_file() const { return ""; } + virtual string debug_identifier() const { return ""; } + virtual string version() const { return ""; } + virtual const CodeModule* Copy() const { + return new TestCodeModule(code_file_); + } + + private: + string code_file_; +}; + +static bool VerifyEmpty(const StackFrame &frame) { + ASSERT_TRUE(frame.function_name.empty()); + ASSERT_TRUE(frame.source_file_name.empty()); + ASSERT_EQ(frame.source_line, 0); + return true; +} + +static void ClearSourceLineInfo(StackFrame *frame) { + frame->function_name.clear(); + frame->module = NULL; + frame->source_file_name.clear(); + frame->source_line = 0; +} + +static bool RunTests() { + string testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/processor/testdata"; + + BasicSourceLineResolver resolver; + ASSERT_TRUE(resolver.LoadModule("module1", testdata_dir + "/module1.out")); + ASSERT_TRUE(resolver.HasModule("module1")); + ASSERT_TRUE(resolver.LoadModule("module2", testdata_dir + "/module2.out")); + ASSERT_TRUE(resolver.HasModule("module2")); + + TestCodeModule module1("module1"); + + StackFrame frame; + frame.instruction = 0x1000; + frame.module = NULL; + scoped_ptr frame_info(resolver.FillSourceLineInfo(&frame)); + ASSERT_FALSE(frame.module); + ASSERT_TRUE(frame.function_name.empty()); + ASSERT_EQ(frame.function_base, 0); + ASSERT_TRUE(frame.source_file_name.empty()); + ASSERT_EQ(frame.source_line, 0); + ASSERT_EQ(frame.source_line_base, 0); + + frame.module = &module1; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_EQ(frame.function_name, "Function1_1"); + ASSERT_TRUE(frame.module); + ASSERT_EQ(frame.module->code_file(), "module1"); + ASSERT_EQ(frame.function_base, 0x1000); + ASSERT_EQ(frame.source_file_name, "file1_1.cc"); + ASSERT_EQ(frame.source_line, 44); + ASSERT_EQ(frame.source_line_base, 0x1000); + ASSERT_TRUE(frame_info.get()); + ASSERT_FALSE(frame_info->allocates_base_pointer); + ASSERT_EQ(frame_info->program_string, + "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); + + ClearSourceLineInfo(&frame); + frame.instruction = 0x800; + frame.module = &module1; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_TRUE(VerifyEmpty(frame)); + ASSERT_FALSE(frame_info.get()); + + frame.instruction = 0x1280; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_EQ(frame.function_name, "Function1_3"); + ASSERT_TRUE(frame.source_file_name.empty()); + ASSERT_EQ(frame.source_line, 0); + ASSERT_TRUE(frame_info.get()); + ASSERT_FALSE(frame_info->allocates_base_pointer); + ASSERT_TRUE(frame_info->program_string.empty()); + + frame.instruction = 0x1380; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_EQ(frame.function_name, "Function1_4"); + ASSERT_TRUE(frame.source_file_name.empty()); + ASSERT_EQ(frame.source_line, 0); + ASSERT_TRUE(frame_info.get()); + ASSERT_FALSE(frame_info->allocates_base_pointer); + ASSERT_FALSE(frame_info->program_string.empty()); + + frame.instruction = 0x2000; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_FALSE(frame_info.get()); + + TestCodeModule module2("module2"); + + frame.instruction = 0x2181; + frame.module = &module2; + frame_info.reset(resolver.FillSourceLineInfo(&frame)); + ASSERT_EQ(frame.function_name, "Function2_2"); + ASSERT_EQ(frame.function_base, 0x2170); + ASSERT_TRUE(frame.module); + ASSERT_EQ(frame.module->code_file(), "module2"); + ASSERT_EQ(frame.source_file_name, "file2_2.cc"); + ASSERT_EQ(frame.source_line, 21); + ASSERT_EQ(frame.source_line_base, 0x2180); + ASSERT_TRUE(frame_info.get()); + ASSERT_EQ(frame_info->prolog_size, 1); + + frame.instruction = 0x216f; + resolver.FillSourceLineInfo(&frame); + ASSERT_EQ(frame.function_name, "Public2_1"); + + ClearSourceLineInfo(&frame); + frame.instruction = 0x219f; + frame.module = &module2; + resolver.FillSourceLineInfo(&frame); + ASSERT_TRUE(frame.function_name.empty()); + + frame.instruction = 0x21a0; + frame.module = &module2; + resolver.FillSourceLineInfo(&frame); + ASSERT_EQ(frame.function_name, "Public2_2"); + + ASSERT_FALSE(resolver.LoadModule("module3", + testdata_dir + "/module3_bad.out")); + ASSERT_FALSE(resolver.HasModule("module3")); + ASSERT_FALSE(resolver.LoadModule("module4", + testdata_dir + "/module4_bad.out")); + ASSERT_FALSE(resolver.HasModule("module4")); + ASSERT_FALSE(resolver.LoadModule("module5", + testdata_dir + "/invalid-filename")); + ASSERT_FALSE(resolver.HasModule("module5")); + ASSERT_FALSE(resolver.HasModule("invalid-module")); + return true; +} + +} // namespace + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + if (!RunTests()) { + return 1; + } + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/call_stack.cc b/thirdparty/google-breakpad/r318/src/processor/call_stack.cc new file mode 100644 index 00000000..e3276716 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/call_stack.cc @@ -0,0 +1,53 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// call_stack.cc: A call stack comprised of stack frames. +// +// See call_stack.h for documentation. +// +// Author: Mark Mentovai + +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/stack_frame.h" + +namespace google_breakpad { + +CallStack::~CallStack() { + Clear(); +} + +void CallStack::Clear() { + for (vector::const_iterator iterator = frames_.begin(); + iterator != frames_.end(); + ++iterator) { + delete *iterator; + } +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/contained_range_map-inl.h b/thirdparty/google-breakpad/r318/src/processor/contained_range_map-inl.h new file mode 100644 index 00000000..5cc498df --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/contained_range_map-inl.h @@ -0,0 +1,197 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// contained_range_map-inl.h: Hierarchically-organized range map implementation. +// +// See contained_range_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ +#define PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ + + +#include + +#include "processor/contained_range_map.h" +#include "processor/logging.h" + + +namespace google_breakpad { + + +template +ContainedRangeMap::~ContainedRangeMap() { + // Clear frees the children pointed to by the map, and frees the map itself. + Clear(); +} + + +template +bool ContainedRangeMap::StoreRange( + const AddressType &base, const AddressType &size, const EntryType &entry) { + AddressType high = base + size - 1; + + // Check for undersize or overflow. + if (size <= 0 || high < base) { + //TODO(nealsid) We are commenting this out in order to prevent + // excessive logging. We plan to move to better logging as this + // failure happens quite often and is expected(see comment in + // basic_source_line_resolver.cc:671). + // BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+" + // << HexString(size) << ", " << HexString(high); + return false; + } + + if (!map_) + map_ = new AddressToRangeMap(); + + MapIterator iterator_base = map_->lower_bound(base); + MapIterator iterator_high = map_->lower_bound(high); + MapIterator iterator_end = map_->end(); + + if (iterator_base == iterator_high && iterator_base != iterator_end && + base >= iterator_base->second->base_) { + // The new range is entirely within an existing child range. + + // If the new range's geometry is exactly equal to an existing child + // range's, it violates the containment rules, and an attempt to store + // it must fail. iterator_base->first contains the key, which was the + // containing child's high address. + if (iterator_base->second->base_ == base && iterator_base->first == high) { + // TODO(nealsid): See the TODO above on why this is commented out. +// BPLOG(INFO) << "StoreRange failed, identical range is already " +// "present: " << HexString(base) << "+" << HexString(size); + return false; + } + + // Pass the new range on to the child to attempt to store. + return iterator_base->second->StoreRange(base, size, entry); + } + + // iterator_high might refer to an irrelevant range: one whose base address + // is higher than the new range's high address. Set contains_high to true + // only if iterator_high refers to a range that is at least partially + // within the new range. + bool contains_high = iterator_high != iterator_end && + high >= iterator_high->second->base_; + + // If the new range encompasses any existing child ranges, it must do so + // fully. Partial containment isn't allowed. + if ((iterator_base != iterator_end && base > iterator_base->second->base_) || + (contains_high && high < iterator_high->first)) { + // TODO(mmentovai): Some symbol files will trip this check frequently + // on STACK lines. Too many messages will be produced. These are more + // suitable for a DEBUG channel than an INFO channel. + // BPLOG(INFO) << "StoreRange failed, new range partially contains " + // "existing range: " << HexString(base) << "+" << + // HexString(size); + return false; + } + + // When copying and erasing contained ranges, the "end" iterator needs to + // point one past the last item of the range to copy. If contains_high is + // false, the iterator's already in the right place; the increment is safe + // because contains_high can't be true if iterator_high == iterator_end. + if (contains_high) + ++iterator_high; + + // Optimization: if the iterators are equal, no child ranges would be + // moved. Create the new child range with a NULL map to conserve space + // in leaf nodes, of which there will be many. + AddressToRangeMap *child_map = NULL; + + if (iterator_base != iterator_high) { + // The children of this range that are contained by the new range must + // be transferred over to the new range. Create the new child range map + // and copy the pointers to range maps it should contain into it. + child_map = new AddressToRangeMap(iterator_base, iterator_high); + + // Remove the copied child pointers from this range's map of children. + map_->erase(iterator_base, iterator_high); + } + + // Store the new range in the map by its high address. Any children that + // the new child range contains were formerly children of this range but + // are now this range's grandchildren. Ownership of these is transferred + // to the new child range. + map_->insert(MapValue(high, + new ContainedRangeMap(base, entry, child_map))); + return true; +} + + +template +bool ContainedRangeMap::RetrieveRange( + const AddressType &address, EntryType *entry) const { + BPLOG_IF(ERROR, !entry) << "ContainedRangeMap::RetrieveRange requires " + "|entry|"; + assert(entry); + + // If nothing was ever stored, then there's nothing to retrieve. + if (!map_) + return false; + + // Get an iterator to the child range whose high address is equal to or + // greater than the supplied address. If the supplied address is higher + // than all of the high addresses in the range, then this range does not + // contain a child at address, so return false. If the supplied address + // is lower than the base address of the child range, then it is not within + // the child range, so return false. + MapConstIterator iterator = map_->lower_bound(address); + if (iterator == map_->end() || address < iterator->second->base_) + return false; + + // The child in iterator->second contains the specified address. Find out + // if it has a more-specific descendant that also contains it. If it does, + // it will set |entry| appropriately. If not, set |entry| to the child. + if (!iterator->second->RetrieveRange(address, entry)) + *entry = iterator->second->entry_; + + return true; +} + + +template +void ContainedRangeMap::Clear() { + if (map_) { + MapConstIterator end = map_->end(); + for (MapConstIterator child = map_->begin(); child != end; ++child) + delete child->second; + + delete map_; + map_ = NULL; + } +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/contained_range_map.h b/thirdparty/google-breakpad/r318/src/processor/contained_range_map.h new file mode 100644 index 00000000..f30016f3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/contained_range_map.h @@ -0,0 +1,145 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// contained_range_map.h: Hierarchically-organized range maps. +// +// A contained range map is similar to a standard range map, except it allows +// objects to be organized hierarchically. A contained range map allows +// objects to contain other objects. It is not sensitive to the order that +// objects are added to the map: larger, more general, containing objects +// may be added either before or after smaller, more specific, contained +// ones. +// +// Contained range maps guarantee that each object may only contain smaller +// objects than itself, and that a parent object may only contain child +// objects located entirely within the parent's address space. Attempts +// to introduce objects (via StoreRange) that violate these rules will fail. +// Retrieval (via RetrieveRange) always returns the most specific (smallest) +// object that contains the address being queried. Note that while it is +// not possible to insert two objects into a map that have exactly the same +// geometry (base address and size), it is possible to completely mask a +// larger object by inserting smaller objects that entirely fill the larger +// object's address space. +// +// Internally, contained range maps are implemented as a tree. Each tree +// node except for the root node describes an object in the map. Each node +// maintains its list of children in a map similar to a standard range map, +// keyed by the highest address that each child occupies. Each node's +// children occupy address ranges entirely within the node. The root node +// is the only node directly accessible to the user, and represents the +// entire address space. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_CONTAINED_RANGE_MAP_H__ +#define PROCESSOR_CONTAINED_RANGE_MAP_H__ + + +#include + + +namespace google_breakpad { + + +template +class ContainedRangeMap { + public: + // The default constructor creates a ContainedRangeMap with no geometry + // and no entry, and as such is only suitable for the root node of a + // ContainedRangeMap tree. + ContainedRangeMap() : base_(), entry_(), map_(NULL) {} + + ~ContainedRangeMap(); + + // Inserts a range into the map. If the new range is encompassed by + // an existing child range, the new range is passed into the child range's + // StoreRange method. If the new range encompasses any existing child + // ranges, those child ranges are moved to the new range, becoming + // grandchildren of this ContainedRangeMap. Returns false for a + // parameter error, or if the ContainedRangeMap hierarchy guarantees + // would be violated. + bool StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry); + + // Retrieves the most specific (smallest) descendant range encompassing + // the specified address. This method will only return entries held by + // child ranges, and not the entry contained by |this|. This is necessary + // to support a sparsely-populated root range. If no descendant range + // encompasses the address, returns false. + bool RetrieveRange(const AddressType &address, EntryType *entry) const; + + // Removes all children. Note that Clear only removes descendants, + // leaving the node on which it is called intact. Because the only + // meaningful things contained by a root node are descendants, this + // is sufficient to restore an entire ContainedRangeMap to its initial + // empty state when called on the root node. + void Clear(); + + private: + // AddressToRangeMap stores pointers. This makes reparenting simpler in + // StoreRange, because it doesn't need to copy entire objects. + typedef std::map AddressToRangeMap; + typedef typename AddressToRangeMap::const_iterator MapConstIterator; + typedef typename AddressToRangeMap::iterator MapIterator; + typedef typename AddressToRangeMap::value_type MapValue; + + // Creates a new ContainedRangeMap with the specified base address, entry, + // and initial child map, which may be NULL. This is only used internally + // by ContainedRangeMap when it creates a new child. + ContainedRangeMap(const AddressType &base, const EntryType &entry, + AddressToRangeMap *map) + : base_(base), entry_(entry), map_(map) {} + + // The base address of this range. The high address does not need to + // be stored, because it is used as the key to an object in its parent's + // map, and all ContainedRangeMaps except for the root range are contained + // within maps. The root range does not actually contain an entry, so its + // base_ field is meaningless, and the fact that it has no parent and thus + // no key is unimportant. For this reason, the base_ field should only be + // is accessed on child ContainedRangeMap objects, and never on |this|. + const AddressType base_; + + // The entry corresponding to this range. The root range does not + // actually contain an entry, so its entry_ field is meaningless. For + // this reason, the entry_ field should only be accessed on child + // ContainedRangeMap objects, and never on |this|. + const EntryType entry_; + + // The map containing child ranges, keyed by each child range's high + // address. This is a pointer to avoid allocating map structures for + // leaf nodes, where they are not needed. + AddressToRangeMap *map_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_CONTAINED_RANGE_MAP_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/contained_range_map_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/contained_range_map_unittest.cc new file mode 100644 index 00000000..6b65b4e1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/contained_range_map_unittest.cc @@ -0,0 +1,263 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// contained_range_map_unittest.cc: Unit tests for ContainedRangeMap +// +// Author: Mark Mentovai + +#include + +#include "processor/contained_range_map-inl.h" + +#include "processor/logging.h" + + +#define ASSERT_TRUE(condition) \ + if (!(condition)) { \ + fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ + return false; \ + } + +#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition)) + + +namespace { + + +using google_breakpad::ContainedRangeMap; + + +static bool RunTests() { + ContainedRangeMap crm; + + // First, do the StoreRange tests. This validates the containment + // rules. + ASSERT_TRUE (crm.StoreRange(10, 10, 1)); + ASSERT_FALSE(crm.StoreRange(10, 10, 2)); // exactly equal to 1 + ASSERT_FALSE(crm.StoreRange(11, 10, 3)); // begins inside 1 and extends up + ASSERT_FALSE(crm.StoreRange( 9, 10, 4)); // begins below 1 and ends inside + ASSERT_TRUE (crm.StoreRange(11, 9, 5)); // contained by existing + ASSERT_TRUE (crm.StoreRange(12, 7, 6)); + ASSERT_TRUE (crm.StoreRange( 9, 12, 7)); // contains existing + ASSERT_TRUE (crm.StoreRange( 9, 13, 8)); + ASSERT_TRUE (crm.StoreRange( 8, 14, 9)); + ASSERT_TRUE (crm.StoreRange(30, 3, 10)); + ASSERT_TRUE (crm.StoreRange(33, 3, 11)); + ASSERT_TRUE (crm.StoreRange(30, 6, 12)); // storable but totally masked + ASSERT_TRUE (crm.StoreRange(40, 8, 13)); // will be totally masked + ASSERT_TRUE (crm.StoreRange(40, 4, 14)); + ASSERT_TRUE (crm.StoreRange(44, 4, 15)); + ASSERT_FALSE(crm.StoreRange(32, 10, 16)); // begins in #10, ends in #14 + ASSERT_FALSE(crm.StoreRange(50, 0, 17)); // zero length + ASSERT_TRUE (crm.StoreRange(50, 10, 18)); + ASSERT_TRUE (crm.StoreRange(50, 1, 19)); + ASSERT_TRUE (crm.StoreRange(59, 1, 20)); + ASSERT_TRUE (crm.StoreRange(60, 1, 21)); + ASSERT_TRUE (crm.StoreRange(69, 1, 22)); + ASSERT_TRUE (crm.StoreRange(60, 10, 23)); + ASSERT_TRUE (crm.StoreRange(68, 1, 24)); + ASSERT_TRUE (crm.StoreRange(61, 1, 25)); + ASSERT_TRUE (crm.StoreRange(61, 8, 26)); + ASSERT_FALSE(crm.StoreRange(59, 9, 27)); + ASSERT_FALSE(crm.StoreRange(59, 10, 28)); + ASSERT_FALSE(crm.StoreRange(59, 11, 29)); + ASSERT_TRUE (crm.StoreRange(70, 10, 30)); + ASSERT_TRUE (crm.StoreRange(74, 2, 31)); + ASSERT_TRUE (crm.StoreRange(77, 2, 32)); + ASSERT_FALSE(crm.StoreRange(72, 6, 33)); + ASSERT_TRUE (crm.StoreRange(80, 3, 34)); + ASSERT_TRUE (crm.StoreRange(81, 1, 35)); + ASSERT_TRUE (crm.StoreRange(82, 1, 36)); + ASSERT_TRUE (crm.StoreRange(83, 3, 37)); + ASSERT_TRUE (crm.StoreRange(84, 1, 38)); + ASSERT_TRUE (crm.StoreRange(83, 1, 39)); + ASSERT_TRUE (crm.StoreRange(86, 5, 40)); + ASSERT_TRUE (crm.StoreRange(88, 1, 41)); + ASSERT_TRUE (crm.StoreRange(90, 1, 42)); + ASSERT_TRUE (crm.StoreRange(86, 1, 43)); + ASSERT_TRUE (crm.StoreRange(87, 1, 44)); + ASSERT_TRUE (crm.StoreRange(89, 1, 45)); + ASSERT_TRUE (crm.StoreRange(87, 4, 46)); + ASSERT_TRUE (crm.StoreRange(87, 3, 47)); + ASSERT_FALSE(crm.StoreRange(86, 2, 48)); + + // Each element in test_data contains the expected result when calling + // RetrieveRange on an address. + const int test_data[] = { + 0, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + 9, // 8 + 7, // 9 + 1, // 10 + 5, // 11 + 6, // 12 + 6, // 13 + 6, // 14 + 6, // 15 + 6, // 16 + 6, // 17 + 6, // 18 + 5, // 19 + 7, // 20 + 8, // 21 + 0, // 22 + 0, // 23 + 0, // 24 + 0, // 25 + 0, // 26 + 0, // 27 + 0, // 28 + 0, // 29 + 10, // 30 + 10, // 31 + 10, // 32 + 11, // 33 + 11, // 34 + 11, // 35 + 0, // 36 + 0, // 37 + 0, // 38 + 0, // 39 + 14, // 40 + 14, // 41 + 14, // 42 + 14, // 43 + 15, // 44 + 15, // 45 + 15, // 46 + 15, // 47 + 0, // 48 + 0, // 49 + 19, // 50 + 18, // 51 + 18, // 52 + 18, // 53 + 18, // 54 + 18, // 55 + 18, // 56 + 18, // 57 + 18, // 58 + 20, // 59 + 21, // 60 + 25, // 61 + 26, // 62 + 26, // 63 + 26, // 64 + 26, // 65 + 26, // 66 + 26, // 67 + 24, // 68 + 22, // 69 + 30, // 70 + 30, // 71 + 30, // 72 + 30, // 73 + 31, // 74 + 31, // 75 + 30, // 76 + 32, // 77 + 32, // 78 + 30, // 79 + 34, // 80 + 35, // 81 + 36, // 82 + 39, // 83 + 38, // 84 + 37, // 85 + 43, // 86 + 44, // 87 + 41, // 88 + 45, // 89 + 42, // 90 + 0, // 91 + 0, // 92 + 0, // 93 + 0, // 94 + 0, // 95 + 0, // 96 + 0, // 97 + 0, // 98 + 0 // 99 + }; + unsigned int test_high = sizeof(test_data) / sizeof(int); + + // Now, do the RetrieveRange tests. This further validates that the + // objects were stored properly and that retrieval returns the correct + // object. + // If GENERATE_TEST_DATA is defined, instead of the retrieval tests, a + // new test_data array will be printed. Exercise caution when doing this. + // Be sure to verify the results manually! +#ifdef GENERATE_TEST_DATA + printf(" const int test_data[] = {\n"); +#endif // GENERATE_TEST_DATA + + for (unsigned int address = 0; address < test_high; ++address) { + int value; + if (!crm.RetrieveRange(address, &value)) + value = 0; + +#ifndef GENERATE_TEST_DATA + // Don't use ASSERT inside the loop because it won't show the failed + // |address|, and the line number will always be the same. That makes + // it difficult to figure out which test failed. + if (value != test_data[address]) { + fprintf(stderr, "FAIL: retrieve %d expected %d observed %d @ %s:%d\n", + address, test_data[address], value, __FILE__, __LINE__); + return false; + } +#else // !GENERATE_TEST_DATA + printf(" %d%c%s // %d\n", value, + address == test_high - 1 ? ' ' : ',', + value < 10 ? " " : "", + address); +#endif // !GENERATE_TEST_DATA + } + +#ifdef GENERATE_TEST_DATA + printf(" };\n"); +#endif // GENERATE_TEST_DATA + + return true; +} + + +} // namespace + + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/linked_ptr.h b/thirdparty/google-breakpad/r318/src/processor/linked_ptr.h new file mode 100644 index 00000000..1a4ef7d4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/linked_ptr.h @@ -0,0 +1,193 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). + +#ifndef PROCESSOR_LINKED_PTR_H__ +#define PROCESSOR_LINKED_PTR_H__ + +namespace google_breakpad { + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) { + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true iff we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() { + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { depart(); capture(ptr); } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + // Release ownership of the pointed object and returns it. + // Sole ownership by this linked_ptr object is required. + T* release() { + bool last = link_.depart(); + T* v = value_; + value_ = NULL; + return v; + } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_LINKED_PTR_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/logging.cc b/thirdparty/google-breakpad/r318/src/processor/logging.cc new file mode 100644 index 00000000..8842df35 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/logging.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// logging.cc: Breakpad logging +// +// See logging.h for documentation. +// +// Author: Mark Mentovai + +#include +#include +#include +#include +#include + +#include "processor/logging.h" +#include "processor/pathname_stripper.h" + +namespace google_breakpad { + +LogStream::LogStream(std::ostream &stream, Severity severity, + const char *file, int line) + : stream_(stream) { + time_t clock; + time(&clock); + struct tm tm_struct; + localtime_r(&clock, &tm_struct); + char time_string[20]; + strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct); + + const char *severity_string = "UNKNOWN_SEVERITY"; + switch (severity) { + case SEVERITY_INFO: + severity_string = "INFO"; + break; + case SEVERITY_ERROR: + severity_string = "ERROR"; + break; + } + + stream_ << time_string << ": " << PathnameStripper::File(file) << ":" << + line << ": " << severity_string << ": "; +} + +LogStream::~LogStream() { + stream_ << std::endl; +} + +std::string HexString(u_int32_t number) { + char buffer[11]; + snprintf(buffer, sizeof(buffer), "0x%x", number); + return std::string(buffer); +} + +std::string HexString(u_int64_t number) { + char buffer[19]; + snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number); + return std::string(buffer); +} + +std::string HexString(int number) { + char buffer[19]; + snprintf(buffer, sizeof(buffer), "0x%x", number); + return std::string(buffer); +} + +int ErrnoString(std::string *error_string) { + assert(error_string); + + // strerror isn't necessarily thread-safe. strerror_r would be preferrable, + // but GNU libc uses a nonstandard strerror_r by default, which returns a + // char* (rather than an int success indicator) and doesn't necessarily + // use the supplied buffer. + error_string->assign(strerror(errno)); + return errno; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/logging.h b/thirdparty/google-breakpad/r318/src/processor/logging.h new file mode 100644 index 00000000..b638ff58 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/logging.h @@ -0,0 +1,153 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// logging.h: Breakpad logging +// +// Breakpad itself uses Breakpad logging with statements of the form: +// BPLOG(severity) << "message"; +// severity may be INFO, ERROR, or other values defined in this file. +// +// BPLOG is an overridable macro so that users can customize Breakpad's +// logging. Left at the default, logging messages are sent to stderr along +// with a timestamp and the source code location that produced a message. +// The streams may be changed by redefining BPLOG_*_STREAM, the logging +// behavior may be changed by redefining BPLOG_*, and the entire logging +// system may be overridden by redefining BPLOG(severity). These +// redefinitions may be passed to the preprocessor as a command-line flag +// (-D). +// +// If an additional header is required to override Breakpad logging, it can +// be specified by the BP_LOGGING_INCLUDE macro. If defined, this header +// will #include the header specified by that macro. +// +// If any initialization is needed before logging, it can be performed by +// a function called through the BPLOG_INIT macro. Each main function of +// an executable program in the Breakpad processor library calls +// BPLOG_INIT(&argc, &argv); before any logging can be performed; define +// BPLOG_INIT appropriately if initialization is required. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_LOGGING_H__ +#define PROCESSOR_LOGGING_H__ + +#include +#include + +#include "google_breakpad/common/breakpad_types.h" + +#ifdef BP_LOGGING_INCLUDE +#include BP_LOGGING_INCLUDE +#endif // BP_LOGGING_INCLUDE + +namespace google_breakpad { + +class LogStream { + public: + enum Severity { + SEVERITY_INFO, + SEVERITY_ERROR + }; + + // Begin logging a message to the stream identified by |stream|, at the + // indicated severity. The file and line parameters should be set so as to + // identify the line of source code that is producing a message. + LogStream(std::ostream &stream, Severity severity, + const char *file, int line); + + // Finish logging by printing a newline and flushing the output stream. + ~LogStream(); + + template std::ostream& operator<<(const T &t) { + return stream_ << t; + } + + private: + std::ostream &stream_; + + // Disallow copy constructor and assignment operator + explicit LogStream(const LogStream &that); + void operator=(const LogStream &that); +}; + +// This class is used to explicitly ignore values in the conditional logging +// macros. This avoids compiler warnings like "value computed is not used" +// and "statement has no effect". +class LogMessageVoidify { + public: + LogMessageVoidify() {} + + // This has to be an operator with a precedence lower than << but higher + // than ?: + void operator&(std::ostream &) {} +}; + +// Returns number formatted as a hexadecimal string, such as "0x7b". +std::string HexString(u_int32_t number); +std::string HexString(u_int64_t number); +std::string HexString(int number); + +// Returns the error code as set in the global errno variable, and sets +// error_string, a required argument, to a string describing that error +// code. +int ErrnoString(std::string *error_string); + +} // namespace google_breakpad + +#ifndef BPLOG_INIT +#define BPLOG_INIT(pargc, pargv) +#endif // BPLOG_INIT + +#ifndef BPLOG +#define BPLOG(severity) BPLOG_ ## severity +#endif // BPLOG + +#ifndef BPLOG_INFO +#ifndef BPLOG_INFO_STREAM +#define BPLOG_INFO_STREAM std::clog +#endif // BPLOG_INFO_STREAM +#define BPLOG_INFO google_breakpad::LogStream(BPLOG_INFO_STREAM, \ + google_breakpad::LogStream::SEVERITY_INFO, \ + __FILE__, __LINE__) +#endif // BPLOG_INFO + +#ifndef BPLOG_ERROR +#ifndef BPLOG_ERROR_STREAM +#define BPLOG_ERROR_STREAM std::cerr +#endif // BPLOG_ERROR_STREAM +#define BPLOG_ERROR google_breakpad::LogStream(BPLOG_ERROR_STREAM, \ + google_breakpad::LogStream::SEVERITY_ERROR, \ + __FILE__, __LINE__) +#endif // BPLOG_ERROR + +#define BPLOG_IF(severity, condition) \ + !(condition) ? (void) 0 : \ + google_breakpad::LogMessageVoidify() & BPLOG(severity) + +#endif // PROCESSOR_LOGGING_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump.cc b/thirdparty/google-breakpad/r318/src/processor/minidump.cc new file mode 100644 index 00000000..83944501 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump.cc @@ -0,0 +1,3679 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump.cc: A minidump reader. +// +// See minidump.h for documentation. +// +// Author: Mark Mentovai + + +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +typedef SSIZE_T ssize_t; +#define open _open +#define read _read +#define lseek _lseek +#else // _WIN32 +#define O_BINARY 0 +#endif // _WIN32 + +#include +#include +#include +#include + +#include "processor/range_map-inl.h" + +#include "google_breakpad/processor/minidump.h" +#include "processor/basic_code_module.h" +#include "processor/basic_code_modules.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" + + +namespace google_breakpad { + + +using std::numeric_limits; +using std::vector; + + +// +// Swapping routines +// +// Inlining these doesn't increase code size significantly, and it saves +// a whole lot of unnecessary jumping back and forth. +// + + +// Swapping an 8-bit quantity is a no-op. This function is only provided +// to account for certain templatized operations that require swapping for +// wider types but handle u_int8_t too +// (MinidumpMemoryRegion::GetMemoryAtAddressInternal). +static inline void Swap(u_int8_t* value) { +} + + +// Optimization: don't need to AND the furthest right shift, because we're +// shifting an unsigned quantity. The standard requires zero-filling in this +// case. If the quantities were signed, a bitmask whould be needed for this +// right shift to avoid an arithmetic shift (which retains the sign bit). +// The furthest left shift never needs to be ANDed bitmask. + + +static inline void Swap(u_int16_t* value) { + *value = (*value >> 8) | + (*value << 8); +} + + +static inline void Swap(u_int32_t* value) { + *value = (*value >> 24) | + ((*value >> 8) & 0x0000ff00) | + ((*value << 8) & 0x00ff0000) | + (*value << 24); +} + + +static inline void Swap(u_int64_t* value) { + u_int32_t* value32 = reinterpret_cast(value); + Swap(&value32[0]); + Swap(&value32[1]); + u_int32_t temp = value32[0]; + value32[0] = value32[1]; + value32[1] = temp; +} + + +// Given a pointer to a 128-bit int in the minidump data, set the "low" +// and "high" fields appropriately. +static void Normalize128(u_int128_t* value, bool is_big_endian) { + // The struct format is [high, low], so if the format is big-endian, + // the most significant bytes will already be in the high field. + if (!is_big_endian) { + u_int64_t temp = value->low; + value->low = value->high; + value->high = temp; + } +} + +// This just swaps each int64 half of the 128-bit value. +// The value should also be normalized by calling Normalize128(). +static void Swap(u_int128_t* value) { + Swap(&value->low); + Swap(&value->high); +} + + +static inline void Swap(MDLocationDescriptor* location_descriptor) { + Swap(&location_descriptor->data_size); + Swap(&location_descriptor->rva); +} + + +static inline void Swap(MDMemoryDescriptor* memory_descriptor) { + Swap(&memory_descriptor->start_of_memory_range); + Swap(&memory_descriptor->memory); +} + + +static inline void Swap(MDGUID* guid) { + Swap(&guid->data1); + Swap(&guid->data2); + Swap(&guid->data3); + // Don't swap guid->data4[] because it contains 8-bit quantities. +} + + +// +// Character conversion routines +// + + +// Standard wide-character conversion routines depend on the system's own +// idea of what width a wide character should be: some use 16 bits, and +// some use 32 bits. For the purposes of a minidump, wide strings are +// always represented with 16-bit UTF-16 chracters. iconv isn't available +// everywhere, and its interface varies where it is available. iconv also +// deals purely with char* pointers, so in addition to considering the swap +// parameter, a converter that uses iconv would also need to take the host +// CPU's endianness into consideration. It doesn't seems worth the trouble +// of making it a dependency when we don't care about anything but UTF-16. +static string* UTF16ToUTF8(const vector& in, + bool swap) { + scoped_ptr out(new string()); + + // Set the string's initial capacity to the number of UTF-16 characters, + // because the UTF-8 representation will always be at least this long. + // If the UTF-8 representation is longer, the string will grow dynamically. + out->reserve(in.size()); + + for (vector::const_iterator iterator = in.begin(); + iterator != in.end(); + ++iterator) { + // Get a 16-bit value from the input + u_int16_t in_word = *iterator; + if (swap) + Swap(&in_word); + + // Convert the input value (in_word) into a Unicode code point (unichar). + u_int32_t unichar; + if (in_word >= 0xdc00 && in_word <= 0xdcff) { + BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " << + HexString(in_word) << " without high"; + return NULL; + } else if (in_word >= 0xd800 && in_word <= 0xdbff) { + // High surrogate. + unichar = (in_word - 0xd7c0) << 10; + if (++iterator == in.end()) { + BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << + HexString(in_word) << " at end of string"; + return NULL; + } + u_int32_t high_word = in_word; + in_word = *iterator; + if (in_word < 0xdc00 || in_word > 0xdcff) { + BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << + HexString(high_word) << " without low " << + HexString(in_word); + return NULL; + } + unichar |= in_word & 0x03ff; + } else { + // The ordinary case, a single non-surrogate Unicode character encoded + // as a single 16-bit value. + unichar = in_word; + } + + // Convert the Unicode code point (unichar) into its UTF-8 representation, + // appending it to the out string. + if (unichar < 0x80) { + (*out) += unichar; + } else if (unichar < 0x800) { + (*out) += 0xc0 | (unichar >> 6); + (*out) += 0x80 | (unichar & 0x3f); + } else if (unichar < 0x10000) { + (*out) += 0xe0 | (unichar >> 12); + (*out) += 0x80 | ((unichar >> 6) & 0x3f); + (*out) += 0x80 | (unichar & 0x3f); + } else if (unichar < 0x200000) { + (*out) += 0xf0 | (unichar >> 18); + (*out) += 0x80 | ((unichar >> 12) & 0x3f); + (*out) += 0x80 | ((unichar >> 6) & 0x3f); + (*out) += 0x80 | (unichar & 0x3f); + } else { + BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " << + HexString(unichar) << " in UTF-8"; + return NULL; + } + } + + return out.release(); +} + + +// +// MinidumpObject +// + + +MinidumpObject::MinidumpObject(Minidump* minidump) + : minidump_(minidump), + valid_(false) { +} + + +// +// MinidumpStream +// + + +MinidumpStream::MinidumpStream(Minidump* minidump) + : MinidumpObject(minidump) { +} + + +// +// MinidumpContext +// + + +MinidumpContext::MinidumpContext(Minidump* minidump) + : MinidumpStream(minidump), + context_flags_(0), + context_() { +} + + +MinidumpContext::~MinidumpContext() { + FreeContext(); +} + + +bool MinidumpContext::Read(u_int32_t expected_size) { + valid_ = false; + + FreeContext(); + + // First, figure out what type of CPU this context structure is for. + // For some reason, the AMD64 Context doesn't have context_flags + // at the beginning of the structure, so special case it here. + if (expected_size == sizeof(MDRawContextAMD64)) { + BPLOG(INFO) << "MinidumpContext: looks like AMD64 context"; + + scoped_ptr context_amd64(new MDRawContextAMD64()); + if (!minidump_->ReadBytes(context_amd64.get(), + sizeof(MDRawContextAMD64))) { + BPLOG(ERROR) << "MinidumpContext could not read amd64 context"; + return false; + } + + if (minidump_->swap()) + Swap(&context_amd64->context_flags); + + u_int32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK; + + if (cpu_type != MD_CONTEXT_AMD64) { + //TODO: fall through to switch below? + // need a Tell method to be able to SeekSet back to beginning + // http://code.google.com/p/google-breakpad/issues/detail?id=224 + BPLOG(ERROR) << "MinidumpContext not actually amd64 context"; + return false; + } + + // Do this after reading the entire MDRawContext structure because + // GetSystemInfo may seek minidump to a new position. + if (!CheckAgainstSystemInfo(cpu_type)) { + BPLOG(ERROR) << "MinidumpContext amd64 does not match system info"; + return false; + } + + // Normalize the 128-bit types in the dump. + // Since this is AMD64, by definition, the values are little-endian. + for (unsigned int vr_index = 0; + vr_index < MD_CONTEXT_AMD64_VR_COUNT; + ++vr_index) + Normalize128(&context_amd64->vector_register[vr_index], false); + + if (minidump_->swap()) { + Swap(&context_amd64->p1_home); + Swap(&context_amd64->p2_home); + Swap(&context_amd64->p3_home); + Swap(&context_amd64->p4_home); + Swap(&context_amd64->p5_home); + Swap(&context_amd64->p6_home); + // context_flags is already swapped + Swap(&context_amd64->mx_csr); + Swap(&context_amd64->cs); + Swap(&context_amd64->ds); + Swap(&context_amd64->es); + Swap(&context_amd64->fs); + Swap(&context_amd64->ss); + Swap(&context_amd64->eflags); + Swap(&context_amd64->dr0); + Swap(&context_amd64->dr1); + Swap(&context_amd64->dr2); + Swap(&context_amd64->dr3); + Swap(&context_amd64->dr6); + Swap(&context_amd64->dr7); + Swap(&context_amd64->rax); + Swap(&context_amd64->rcx); + Swap(&context_amd64->rdx); + Swap(&context_amd64->rbx); + Swap(&context_amd64->rsp); + Swap(&context_amd64->rbp); + Swap(&context_amd64->rsi); + Swap(&context_amd64->rdi); + Swap(&context_amd64->r8); + Swap(&context_amd64->r9); + Swap(&context_amd64->r10); + Swap(&context_amd64->r11); + Swap(&context_amd64->r12); + Swap(&context_amd64->r13); + Swap(&context_amd64->r14); + Swap(&context_amd64->r15); + Swap(&context_amd64->rip); + //FIXME: I'm not sure what actually determines + // which member of the union {flt_save, sse_registers} + // is valid. We're not currently using either, + // but it would be good to have them swapped properly. + + for (unsigned int vr_index = 0; + vr_index < MD_CONTEXT_AMD64_VR_COUNT; + ++vr_index) + Swap(&context_amd64->vector_register[vr_index]); + Swap(&context_amd64->vector_control); + Swap(&context_amd64->debug_control); + Swap(&context_amd64->last_branch_to_rip); + Swap(&context_amd64->last_branch_from_rip); + Swap(&context_amd64->last_exception_to_rip); + Swap(&context_amd64->last_exception_from_rip); + } + + context_flags_ = context_amd64->context_flags; + + context_.amd64 = context_amd64.release(); + } + else { + u_int32_t context_flags; + if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { + BPLOG(ERROR) << "MinidumpContext could not read context flags"; + return false; + } + if (minidump_->swap()) + Swap(&context_flags); + + u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; + + // Allocate the context structure for the correct CPU and fill it. The + // casts are slightly unorthodox, but it seems better to do that than to + // maintain a separate pointer for each type of CPU context structure + // when only one of them will be used. + switch (cpu_type) { + case MD_CONTEXT_X86: { + if (expected_size != sizeof(MDRawContextX86)) { + BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " << + expected_size << " != " << sizeof(MDRawContextX86); + return false; + } + + scoped_ptr context_x86(new MDRawContextX86()); + + // Set the context_flags member, which has already been read, and + // read the rest of the structure beginning with the first member + // after context_flags. + context_x86->context_flags = context_flags; + + size_t flags_size = sizeof(context_x86->context_flags); + u_int8_t* context_after_flags = + reinterpret_cast(context_x86.get()) + flags_size; + if (!minidump_->ReadBytes(context_after_flags, + sizeof(MDRawContextX86) - flags_size)) { + BPLOG(ERROR) << "MinidumpContext could not read x86 context"; + return false; + } + + // Do this after reading the entire MDRawContext structure because + // GetSystemInfo may seek minidump to a new position. + if (!CheckAgainstSystemInfo(cpu_type)) { + BPLOG(ERROR) << "MinidumpContext x86 does not match system info"; + return false; + } + + if (minidump_->swap()) { + // context_x86->context_flags was already swapped. + Swap(&context_x86->dr0); + Swap(&context_x86->dr1); + Swap(&context_x86->dr2); + Swap(&context_x86->dr3); + Swap(&context_x86->dr6); + Swap(&context_x86->dr7); + Swap(&context_x86->float_save.control_word); + Swap(&context_x86->float_save.status_word); + Swap(&context_x86->float_save.tag_word); + Swap(&context_x86->float_save.error_offset); + Swap(&context_x86->float_save.error_selector); + Swap(&context_x86->float_save.data_offset); + Swap(&context_x86->float_save.data_selector); + // context_x86->float_save.register_area[] contains 8-bit quantities + // and does not need to be swapped. + Swap(&context_x86->float_save.cr0_npx_state); + Swap(&context_x86->gs); + Swap(&context_x86->fs); + Swap(&context_x86->es); + Swap(&context_x86->ds); + Swap(&context_x86->edi); + Swap(&context_x86->esi); + Swap(&context_x86->ebx); + Swap(&context_x86->edx); + Swap(&context_x86->ecx); + Swap(&context_x86->eax); + Swap(&context_x86->ebp); + Swap(&context_x86->eip); + Swap(&context_x86->cs); + Swap(&context_x86->eflags); + Swap(&context_x86->esp); + Swap(&context_x86->ss); + // context_x86->extended_registers[] contains 8-bit quantities and + // does not need to be swapped. + } + + context_.x86 = context_x86.release(); + + break; + } + + case MD_CONTEXT_PPC: { + if (expected_size != sizeof(MDRawContextPPC)) { + BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " << + expected_size << " != " << sizeof(MDRawContextPPC); + return false; + } + + scoped_ptr context_ppc(new MDRawContextPPC()); + + // Set the context_flags member, which has already been read, and + // read the rest of the structure beginning with the first member + // after context_flags. + context_ppc->context_flags = context_flags; + + size_t flags_size = sizeof(context_ppc->context_flags); + u_int8_t* context_after_flags = + reinterpret_cast(context_ppc.get()) + flags_size; + if (!minidump_->ReadBytes(context_after_flags, + sizeof(MDRawContextPPC) - flags_size)) { + BPLOG(ERROR) << "MinidumpContext could not read ppc context"; + return false; + } + + // Do this after reading the entire MDRawContext structure because + // GetSystemInfo may seek minidump to a new position. + if (!CheckAgainstSystemInfo(cpu_type)) { + BPLOG(ERROR) << "MinidumpContext ppc does not match system info"; + return false; + } + + // Normalize the 128-bit types in the dump. + // Since this is PowerPC, by definition, the values are big-endian. + for (unsigned int vr_index = 0; + vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; + ++vr_index) { + Normalize128(&context_ppc->vector_save.save_vr[vr_index], true); + } + + if (minidump_->swap()) { + // context_ppc->context_flags was already swapped. + Swap(&context_ppc->srr0); + Swap(&context_ppc->srr1); + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_PPC_GPR_COUNT; + ++gpr_index) { + Swap(&context_ppc->gpr[gpr_index]); + } + Swap(&context_ppc->cr); + Swap(&context_ppc->xer); + Swap(&context_ppc->lr); + Swap(&context_ppc->ctr); + Swap(&context_ppc->mq); + Swap(&context_ppc->vrsave); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; + ++fpr_index) { + Swap(&context_ppc->float_save.fpregs[fpr_index]); + } + // Don't swap context_ppc->float_save.fpscr_pad because it is only + // used for padding. + Swap(&context_ppc->float_save.fpscr); + for (unsigned int vr_index = 0; + vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; + ++vr_index) { + Swap(&context_ppc->vector_save.save_vr[vr_index]); + } + Swap(&context_ppc->vector_save.save_vscr); + // Don't swap the padding fields in vector_save. + Swap(&context_ppc->vector_save.save_vrvalid); + } + + context_.ppc = context_ppc.release(); + + break; + } + + case MD_CONTEXT_SPARC: { + if (expected_size != sizeof(MDRawContextSPARC)) { + BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " << + expected_size << " != " << sizeof(MDRawContextSPARC); + return false; + } + + scoped_ptr context_sparc(new MDRawContextSPARC()); + + // Set the context_flags member, which has already been read, and + // read the rest of the structure beginning with the first member + // after context_flags. + context_sparc->context_flags = context_flags; + + size_t flags_size = sizeof(context_sparc->context_flags); + u_int8_t* context_after_flags = + reinterpret_cast(context_sparc.get()) + flags_size; + if (!minidump_->ReadBytes(context_after_flags, + sizeof(MDRawContextSPARC) - flags_size)) { + BPLOG(ERROR) << "MinidumpContext could not read sparc context"; + return false; + } + + // Do this after reading the entire MDRawContext structure because + // GetSystemInfo may seek minidump to a new position. + if (!CheckAgainstSystemInfo(cpu_type)) { + BPLOG(ERROR) << "MinidumpContext sparc does not match system info"; + return false; + } + + if (minidump_->swap()) { + // context_sparc->context_flags was already swapped. + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_SPARC_GPR_COUNT; + ++gpr_index) { + Swap(&context_sparc->g_r[gpr_index]); + } + Swap(&context_sparc->ccr); + Swap(&context_sparc->pc); + Swap(&context_sparc->npc); + Swap(&context_sparc->y); + Swap(&context_sparc->asi); + Swap(&context_sparc->fprs); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; + ++fpr_index) { + Swap(&context_sparc->float_save.regs[fpr_index]); + } + Swap(&context_sparc->float_save.filler); + Swap(&context_sparc->float_save.fsr); + } + context_.ctx_sparc = context_sparc.release(); + + break; + } + + default: { + // Unknown context type + BPLOG(ERROR) << "MinidumpContext unknown context type " << + HexString(cpu_type); + return false; + break; + } + } + context_flags_ = context_flags; + } + + valid_ = true; + return true; +} + + +u_int32_t MinidumpContext::GetContextCPU() const { + if (!valid_) { + // Don't log a message, GetContextCPU can be legitimately called with + // valid_ false by FreeContext, which is called by Read. + return 0; + } + + return context_flags_ & MD_CONTEXT_CPU_MASK; +} + + +const MDRawContextX86* MinidumpContext::GetContextX86() const { + if (GetContextCPU() != MD_CONTEXT_X86) { + BPLOG(ERROR) << "MinidumpContext cannot get x86 context"; + return NULL; + } + + return context_.x86; +} + + +const MDRawContextPPC* MinidumpContext::GetContextPPC() const { + if (GetContextCPU() != MD_CONTEXT_PPC) { + BPLOG(ERROR) << "MinidumpContext cannot get ppc context"; + return NULL; + } + + return context_.ppc; +} + +const MDRawContextAMD64* MinidumpContext::GetContextAMD64() const { + if (GetContextCPU() != MD_CONTEXT_AMD64) { + BPLOG(ERROR) << "MinidumpContext cannot get amd64 context"; + return NULL; + } + + return context_.amd64; +} + +const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const { + if (GetContextCPU() != MD_CONTEXT_SPARC) { + BPLOG(ERROR) << "MinidumpContext cannot get sparc context"; + return NULL; + } + + return context_.ctx_sparc; +} + +void MinidumpContext::FreeContext() { + switch (GetContextCPU()) { + case MD_CONTEXT_X86: + delete context_.x86; + break; + + case MD_CONTEXT_PPC: + delete context_.ppc; + break; + + case MD_CONTEXT_AMD64: + delete context_.amd64; + break; + + case MD_CONTEXT_SPARC: + delete context_.ctx_sparc; + break; + + default: + // There is no context record (valid_ is false) or there's a + // context record for an unknown CPU (shouldn't happen, only known + // records are stored by Read). + break; + } + + context_flags_ = 0; + context_.base = NULL; +} + + +bool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) { + // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM, + // as this function just implements a sanity check. + MinidumpSystemInfo* system_info = minidump_->GetSystemInfo(); + if (!system_info) { + BPLOG(INFO) << "MinidumpContext could not be compared against " + "MinidumpSystemInfo"; + return true; + } + + // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info. + const MDRawSystemInfo* raw_system_info = system_info->system_info(); + if (!raw_system_info) { + BPLOG(INFO) << "MinidumpContext could not be compared against " + "MDRawSystemInfo"; + return false; + } + + MDCPUArchitecture system_info_cpu_type = static_cast( + raw_system_info->processor_architecture); + + // Compare the CPU type of the context record to the CPU type in the + // minidump's system info stream. + bool return_value = false; + switch (context_cpu_type) { + case MD_CONTEXT_X86: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 || + system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 || + system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) { + return_value = true; + } + break; + + case MD_CONTEXT_PPC: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC) + return_value = true; + break; + + case MD_CONTEXT_AMD64: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) + return_value = true; + break; + + case MD_CONTEXT_SPARC: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) + return_value = true; + break; + } + + BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << + HexString(context_cpu_type) << + " wrong for MinidumpSysmtemInfo CPU " << + HexString(system_info_cpu_type); + + return return_value; +} + + +void MinidumpContext::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpContext cannot print invalid data"; + return; + } + + switch (GetContextCPU()) { + case MD_CONTEXT_X86: { + const MDRawContextX86* context_x86 = GetContextX86(); + printf("MDRawContextX86\n"); + printf(" context_flags = 0x%x\n", + context_x86->context_flags); + printf(" dr0 = 0x%x\n", context_x86->dr0); + printf(" dr1 = 0x%x\n", context_x86->dr1); + printf(" dr2 = 0x%x\n", context_x86->dr2); + printf(" dr3 = 0x%x\n", context_x86->dr3); + printf(" dr6 = 0x%x\n", context_x86->dr6); + printf(" dr7 = 0x%x\n", context_x86->dr7); + printf(" float_save.control_word = 0x%x\n", + context_x86->float_save.control_word); + printf(" float_save.status_word = 0x%x\n", + context_x86->float_save.status_word); + printf(" float_save.tag_word = 0x%x\n", + context_x86->float_save.tag_word); + printf(" float_save.error_offset = 0x%x\n", + context_x86->float_save.error_offset); + printf(" float_save.error_selector = 0x%x\n", + context_x86->float_save.error_selector); + printf(" float_save.data_offset = 0x%x\n", + context_x86->float_save.data_offset); + printf(" float_save.data_selector = 0x%x\n", + context_x86->float_save.data_selector); + printf(" float_save.register_area[%2d] = 0x", + MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE); + for (unsigned int register_index = 0; + register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE; + ++register_index) { + printf("%02x", context_x86->float_save.register_area[register_index]); + } + printf("\n"); + printf(" float_save.cr0_npx_state = 0x%x\n", + context_x86->float_save.cr0_npx_state); + printf(" gs = 0x%x\n", context_x86->gs); + printf(" fs = 0x%x\n", context_x86->fs); + printf(" es = 0x%x\n", context_x86->es); + printf(" ds = 0x%x\n", context_x86->ds); + printf(" edi = 0x%x\n", context_x86->edi); + printf(" esi = 0x%x\n", context_x86->esi); + printf(" ebx = 0x%x\n", context_x86->ebx); + printf(" edx = 0x%x\n", context_x86->edx); + printf(" ecx = 0x%x\n", context_x86->ecx); + printf(" eax = 0x%x\n", context_x86->eax); + printf(" ebp = 0x%x\n", context_x86->ebp); + printf(" eip = 0x%x\n", context_x86->eip); + printf(" cs = 0x%x\n", context_x86->cs); + printf(" eflags = 0x%x\n", context_x86->eflags); + printf(" esp = 0x%x\n", context_x86->esp); + printf(" ss = 0x%x\n", context_x86->ss); + printf(" extended_registers[%3d] = 0x", + MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE); + for (unsigned int register_index = 0; + register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE; + ++register_index) { + printf("%02x", context_x86->extended_registers[register_index]); + } + printf("\n\n"); + + break; + } + + case MD_CONTEXT_PPC: { + const MDRawContextPPC* context_ppc = GetContextPPC(); + printf("MDRawContextPPC\n"); + printf(" context_flags = 0x%x\n", + context_ppc->context_flags); + printf(" srr0 = 0x%x\n", context_ppc->srr0); + printf(" srr1 = 0x%x\n", context_ppc->srr1); + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_PPC_GPR_COUNT; + ++gpr_index) { + printf(" gpr[%2d] = 0x%x\n", + gpr_index, context_ppc->gpr[gpr_index]); + } + printf(" cr = 0x%x\n", context_ppc->cr); + printf(" xer = 0x%x\n", context_ppc->xer); + printf(" lr = 0x%x\n", context_ppc->lr); + printf(" ctr = 0x%x\n", context_ppc->ctr); + printf(" mq = 0x%x\n", context_ppc->mq); + printf(" vrsave = 0x%x\n", context_ppc->vrsave); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_ppc->float_save.fpregs[fpr_index]); + } + printf(" float_save.fpscr = 0x%x\n", + context_ppc->float_save.fpscr); + // TODO(mmentovai): print the 128-bit quantities in + // context_ppc->vector_save. This isn't done yet because printf + // doesn't support 128-bit quantities, and printing them using + // PRIx64 as two 64-bit quantities requires knowledge of the CPU's + // byte ordering. + printf(" vector_save.save_vrvalid = 0x%x\n", + context_ppc->vector_save.save_vrvalid); + printf("\n"); + + break; + } + + case MD_CONTEXT_AMD64: { + const MDRawContextAMD64* context_amd64 = GetContextAMD64(); + printf("MDRawContextAMD64\n"); + printf(" p1_home = 0x%" PRIx64 "\n", + context_amd64->p1_home); + printf(" p2_home = 0x%" PRIx64 "\n", + context_amd64->p2_home); + printf(" p3_home = 0x%" PRIx64 "\n", + context_amd64->p3_home); + printf(" p4_home = 0x%" PRIx64 "\n", + context_amd64->p4_home); + printf(" p5_home = 0x%" PRIx64 "\n", + context_amd64->p5_home); + printf(" p6_home = 0x%" PRIx64 "\n", + context_amd64->p6_home); + printf(" context_flags = 0x%x\n", + context_amd64->context_flags); + printf(" mx_csr = 0x%x\n", + context_amd64->mx_csr); + printf(" cs = 0x%x\n", context_amd64->cs); + printf(" ds = 0x%x\n", context_amd64->ds); + printf(" es = 0x%x\n", context_amd64->es); + printf(" fs = 0x%x\n", context_amd64->fs); + printf(" gs = 0x%x\n", context_amd64->gs); + printf(" ss = 0x%x\n", context_amd64->ss); + printf(" eflags = 0x%x\n", context_amd64->eflags); + printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); + printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); + printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); + printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); + printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); + printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); + printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); + printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); + printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); + printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); + printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); + printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); + printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); + printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); + printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); + printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); + printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); + printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); + printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); + printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); + printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14); + printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15); + printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip); + //TODO: print xmm, vector, debug registers + printf("\n"); + break; + } + + case MD_CONTEXT_SPARC: { + const MDRawContextSPARC* context_sparc = GetContextSPARC(); + printf("MDRawContextSPARC\n"); + printf(" context_flags = 0x%x\n", + context_sparc->context_flags); + for (unsigned int g_r_index = 0; + g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; + ++g_r_index) { + printf(" g_r[%2d] = 0x%" PRIx64 "\n", + g_r_index, context_sparc->g_r[g_r_index]); + } + printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); + printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); + printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); + printf(" y = 0x%" PRIx64 "\n", context_sparc->y); + printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); + printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); + + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_sparc->float_save.regs[fpr_index]); + } + printf(" float_save.filler = 0x%" PRIx64 "\n", + context_sparc->float_save.filler); + printf(" float_save.fsr = 0x%" PRIx64 "\n", + context_sparc->float_save.fsr); + break; + } + + default: { + break; + } + } +} + + +// +// MinidumpMemoryRegion +// + + +u_int32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024; // 1MB + + +MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) + : MinidumpObject(minidump), + descriptor_(NULL), + memory_(NULL) { +} + + +MinidumpMemoryRegion::~MinidumpMemoryRegion() { + delete memory_; +} + + +void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { + descriptor_ = descriptor; + valid_ = descriptor && + descriptor_->memory.data_size <= + numeric_limits::max() - + descriptor_->start_of_memory_range; +} + + +const u_int8_t* MinidumpMemoryRegion::GetMemory() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory"; + return NULL; + } + + if (!memory_) { + if (descriptor_->memory.data_size == 0) { + BPLOG(ERROR) << "MinidumpMemoryRegion is empty"; + return NULL; + } + + if (!minidump_->SeekSet(descriptor_->memory.rva)) { + BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region"; + return NULL; + } + + if (descriptor_->memory.data_size > max_bytes_) { + BPLOG(ERROR) << "MinidumpMemoryRegion size " << + descriptor_->memory.data_size << " exceeds maximum " << + max_bytes_; + return NULL; + } + + scoped_ptr< vector > memory( + new vector(descriptor_->memory.data_size)); + + if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) { + BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region"; + return NULL; + } + + memory_ = memory.release(); + } + + return &(*memory_)[0]; +} + + +u_int64_t MinidumpMemoryRegion::GetBase() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase"; + return static_cast(-1); + } + + return descriptor_->start_of_memory_range; +} + + +u_int32_t MinidumpMemoryRegion::GetSize() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize"; + return 0; + } + + return descriptor_->memory.data_size; +} + + +void MinidumpMemoryRegion::FreeMemory() { + delete memory_; + memory_ = NULL; +} + + +template +bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(u_int64_t address, + T* value) { + BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal " + "requires |value|"; + assert(value); + *value = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for " + "GetMemoryAtAddressInternal"; + return false; + } + + if (address < descriptor_->start_of_memory_range || + sizeof(T) > numeric_limits::max() - address || + address + sizeof(T) > descriptor_->start_of_memory_range + + descriptor_->memory.data_size) { + BPLOG(ERROR) << "MinidumpMemoryRegion request out of range: " << + HexString(address) << "+" << sizeof(T) << "/" << + HexString(descriptor_->start_of_memory_range) << "+" << + HexString(descriptor_->memory.data_size); + return false; + } + + const u_int8_t* memory = GetMemory(); + if (!memory) { + // GetMemory already logged a perfectly good message. + return false; + } + + // If the CPU requires memory accesses to be aligned, this can crash. + // x86 and ppc are able to cope, though. + *value = *reinterpret_cast( + &memory[address - descriptor_->start_of_memory_range]); + + if (minidump_->swap()) + Swap(value); + + return true; +} + + +bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t address, + u_int8_t* value) { + return GetMemoryAtAddressInternal(address, value); +} + + +bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t address, + u_int16_t* value) { + return GetMemoryAtAddressInternal(address, value); +} + + +bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t address, + u_int32_t* value) { + return GetMemoryAtAddressInternal(address, value); +} + + +bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t address, + u_int64_t* value) { + return GetMemoryAtAddressInternal(address, value); +} + + +void MinidumpMemoryRegion::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data"; + return; + } + + const u_int8_t* memory = GetMemory(); + if (memory) { + printf("0x"); + for (unsigned int byte_index = 0; + byte_index < descriptor_->memory.data_size; + byte_index++) { + printf("%02x", memory[byte_index]); + } + printf("\n"); + } else { + printf("No memory\n"); + } +} + + +// +// MinidumpThread +// + + +MinidumpThread::MinidumpThread(Minidump* minidump) + : MinidumpObject(minidump), + thread_(), + memory_(NULL), + context_(NULL) { +} + + +MinidumpThread::~MinidumpThread() { + delete memory_; + delete context_; +} + + +bool MinidumpThread::Read() { + // Invalidate cached data. + delete memory_; + memory_ = NULL; + delete context_; + context_ = NULL; + + valid_ = false; + + if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) { + BPLOG(ERROR) << "MinidumpThread cannot read thread"; + return false; + } + + if (minidump_->swap()) { + Swap(&thread_.thread_id); + Swap(&thread_.suspend_count); + Swap(&thread_.priority_class); + Swap(&thread_.priority); + Swap(&thread_.teb); + Swap(&thread_.stack); + Swap(&thread_.thread_context); + } + + // Check for base + size overflow or undersize. + if (thread_.stack.memory.data_size == 0 || + thread_.stack.memory.data_size > numeric_limits::max() - + thread_.stack.start_of_memory_range) { + BPLOG(ERROR) << "MinidumpThread has a memory region problem, " << + HexString(thread_.stack.start_of_memory_range) << "+" << + HexString(thread_.stack.memory.data_size); + return false; + } + + memory_ = new MinidumpMemoryRegion(minidump_); + memory_->SetDescriptor(&thread_.stack); + + valid_ = true; + return true; +} + + +MinidumpMemoryRegion* MinidumpThread::GetMemory() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory"; + return NULL; + } + + return memory_; +} + + +MinidumpContext* MinidumpThread::GetContext() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpThread for GetContext"; + return NULL; + } + + if (!context_) { + if (!minidump_->SeekSet(thread_.thread_context.rva)) { + BPLOG(ERROR) << "MinidumpThread cannot seek to context"; + return NULL; + } + + scoped_ptr context(new MinidumpContext(minidump_)); + + if (!context->Read(thread_.thread_context.data_size)) { + BPLOG(ERROR) << "MinidumpThread cannot read context"; + return NULL; + } + + context_ = context.release(); + } + + return context_; +} + + +bool MinidumpThread::GetThreadID(u_int32_t *thread_id) const { + BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires " + "|thread_id|"; + assert(thread_id); + *thread_id = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID"; + return false; + } + + *thread_id = thread_.thread_id; + return true; +} + + +void MinidumpThread::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpThread cannot print invalid data"; + return; + } + + printf("MDRawThread\n"); + printf(" thread_id = 0x%x\n", thread_.thread_id); + printf(" suspend_count = %d\n", thread_.suspend_count); + printf(" priority_class = 0x%x\n", thread_.priority_class); + printf(" priority = 0x%x\n", thread_.priority); + printf(" teb = 0x%" PRIx64 "\n", thread_.teb); + printf(" stack.start_of_memory_range = 0x%" PRIx64 "\n", + thread_.stack.start_of_memory_range); + printf(" stack.memory.data_size = 0x%x\n", + thread_.stack.memory.data_size); + printf(" stack.memory.rva = 0x%x\n", thread_.stack.memory.rva); + printf(" thread_context.data_size = 0x%x\n", + thread_.thread_context.data_size); + printf(" thread_context.rva = 0x%x\n", + thread_.thread_context.rva); + + MinidumpContext* context = GetContext(); + if (context) { + printf("\n"); + context->Print(); + } else { + printf(" (no context)\n"); + printf("\n"); + } + + MinidumpMemoryRegion* memory = GetMemory(); + if (memory) { + printf("Stack\n"); + memory->Print(); + } else { + printf("No stack\n"); + } + printf("\n"); +} + + +// +// MinidumpThreadList +// + + +u_int32_t MinidumpThreadList::max_threads_ = 256; + + +MinidumpThreadList::MinidumpThreadList(Minidump* minidump) + : MinidumpStream(minidump), + id_to_thread_map_(), + threads_(NULL), + thread_count_(0) { +} + + +MinidumpThreadList::~MinidumpThreadList() { + delete threads_; +} + + +bool MinidumpThreadList::Read(u_int32_t expected_size) { + // Invalidate cached data. + id_to_thread_map_.clear(); + delete threads_; + threads_ = NULL; + thread_count_ = 0; + + valid_ = false; + + u_int32_t thread_count; + if (expected_size < sizeof(thread_count)) { + BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " << + expected_size << " < " << sizeof(thread_count); + return false; + } + if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) { + BPLOG(ERROR) << "MinidumpThreadList cannot read thread count"; + return false; + } + + if (minidump_->swap()) + Swap(&thread_count); + + if (thread_count > numeric_limits::max() / sizeof(MDRawThread)) { + BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count << + " would cause multiplication overflow"; + return false; + } + + if (expected_size != sizeof(thread_count) + + thread_count * sizeof(MDRawThread)) { + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(thread_count) + 4 + + thread_count * sizeof(MDRawThread)) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << + " != " << sizeof(thread_count) + + thread_count * sizeof(MDRawThread); + return false; + } + } + + + if (thread_count > max_threads_) { + BPLOG(ERROR) << "MinidumpThreadList count " << thread_count << + " exceeds maximum " << max_threads_; + return false; + } + + if (thread_count != 0) { + scoped_ptr threads( + new MinidumpThreads(thread_count, MinidumpThread(minidump_))); + + for (unsigned int thread_index = 0; + thread_index < thread_count; + ++thread_index) { + MinidumpThread* thread = &(*threads)[thread_index]; + + // Assume that the file offset is correct after the last read. + if (!thread->Read()) { + BPLOG(ERROR) << "MinidumpThreadList cannot read thread " << + thread_index << "/" << thread_count; + return false; + } + + u_int32_t thread_id; + if (!thread->GetThreadID(&thread_id)) { + BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " << + thread_index << "/" << thread_count; + return false; + } + + if (GetThreadByID(thread_id)) { + // Another thread with this ID is already in the list. Data error. + BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " << + HexString(thread_id) << " at thread " << + thread_index << "/" << thread_count; + return false; + } + id_to_thread_map_[thread_id] = thread; + } + + threads_ = threads.release(); + } + + thread_count_ = thread_count; + + valid_ = true; + return true; +} + + +MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index) + const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex"; + return NULL; + } + + if (index >= thread_count_) { + BPLOG(ERROR) << "MinidumpThreadList index out of range: " << + index << "/" << thread_count_; + return NULL; + } + + return &(*threads_)[index]; +} + + +MinidumpThread* MinidumpThreadList::GetThreadByID(u_int32_t thread_id) { + // Don't check valid_. Read calls this method before everything is + // validated. It is safe to not check valid_ here. + return id_to_thread_map_[thread_id]; +} + + +void MinidumpThreadList::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data"; + return; + } + + printf("MinidumpThreadList\n"); + printf(" thread_count = %d\n", thread_count_); + printf("\n"); + + for (unsigned int thread_index = 0; + thread_index < thread_count_; + ++thread_index) { + printf("thread[%d]\n", thread_index); + + (*threads_)[thread_index].Print(); + } +} + + +// +// MinidumpModule +// + + +u_int32_t MinidumpModule::max_cv_bytes_ = 1024; +u_int32_t MinidumpModule::max_misc_bytes_ = 1024; + + +MinidumpModule::MinidumpModule(Minidump* minidump) + : MinidumpObject(minidump), + module_valid_(false), + has_debug_info_(false), + module_(), + name_(NULL), + cv_record_(NULL), + cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE), + misc_record_(NULL) { +} + + +MinidumpModule::~MinidumpModule() { + delete name_; + delete cv_record_; + delete misc_record_; +} + + +bool MinidumpModule::Read() { + // Invalidate cached data. + delete name_; + name_ = NULL; + delete cv_record_; + cv_record_ = NULL; + cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE; + delete misc_record_; + misc_record_ = NULL; + + module_valid_ = false; + has_debug_info_ = false; + valid_ = false; + + if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) { + BPLOG(ERROR) << "MinidumpModule cannot read module"; + return false; + } + + if (minidump_->swap()) { + Swap(&module_.base_of_image); + Swap(&module_.size_of_image); + Swap(&module_.checksum); + Swap(&module_.time_date_stamp); + Swap(&module_.module_name_rva); + Swap(&module_.version_info.signature); + Swap(&module_.version_info.struct_version); + Swap(&module_.version_info.file_version_hi); + Swap(&module_.version_info.file_version_lo); + Swap(&module_.version_info.product_version_hi); + Swap(&module_.version_info.product_version_lo); + Swap(&module_.version_info.file_flags_mask); + Swap(&module_.version_info.file_flags); + Swap(&module_.version_info.file_os); + Swap(&module_.version_info.file_type); + Swap(&module_.version_info.file_subtype); + Swap(&module_.version_info.file_date_hi); + Swap(&module_.version_info.file_date_lo); + Swap(&module_.cv_record); + Swap(&module_.misc_record); + // Don't swap reserved fields because their contents are unknown (as + // are their proper widths). + } + + // Check for base + size overflow or undersize. + if (module_.size_of_image == 0 || + module_.size_of_image > + numeric_limits::max() - module_.base_of_image) { + BPLOG(ERROR) << "MinidumpModule has a module problem, " << + HexString(module_.base_of_image) << "+" << + HexString(module_.size_of_image); + return false; + } + + module_valid_ = true; + return true; +} + + +bool MinidumpModule::ReadAuxiliaryData() { + if (!module_valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData"; + return false; + } + + // Each module must have a name. + name_ = minidump_->ReadString(module_.module_name_rva); + if (!name_) { + BPLOG(ERROR) << "MinidumpModule could not read name"; + return false; + } + + // At this point, we have enough info for the module to be valid. + valid_ = true; + + // CodeView and miscellaneous debug records are only required if the + // module indicates that they exist. + if (module_.cv_record.data_size && !GetCVRecord(NULL)) { + BPLOG(ERROR) << "MinidumpModule has no CodeView record, " + "but one was expected"; + return false; + } + + if (module_.misc_record.data_size && !GetMiscRecord(NULL)) { + BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, " + "but one was expected"; + return false; + } + + has_debug_info_ = true; + return true; +} + + +string MinidumpModule::code_file() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for code_file"; + return ""; + } + + return *name_; +} + + +string MinidumpModule::code_identifier() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier"; + return ""; + } + + if (!has_debug_info_) + return ""; + + MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo(); + if (!minidump_system_info) { + BPLOG(ERROR) << "MinidumpModule code_identifier requires " + "MinidumpSystemInfo"; + return ""; + } + + const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info(); + if (!raw_system_info) { + BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo"; + return ""; + } + + string identifier; + + switch (raw_system_info->platform_id) { + case MD_OS_WIN32_NT: + case MD_OS_WIN32_WINDOWS: { + // Use the same format that the MS symbol server uses in filesystem + // hierarchies. + char identifier_string[17]; + snprintf(identifier_string, sizeof(identifier_string), "%08X%x", + module_.time_date_stamp, module_.size_of_image); + identifier = identifier_string; + break; + } + + case MD_OS_MAC_OS_X: + case MD_OS_SOLARIS: + case MD_OS_LINUX: { + // TODO(mmentovai): support uuid extension if present, otherwise fall + // back to version (from LC_ID_DYLIB?), otherwise fall back to something + // else. + identifier = "id"; + break; + } + + default: { + // Without knowing what OS generated the dump, we can't generate a good + // identifier. Return an empty string, signalling failure. + BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, " + "found " << HexString(raw_system_info->platform_id); + break; + } + } + + return identifier; +} + + +string MinidumpModule::debug_file() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for debug_file"; + return ""; + } + + if (!has_debug_info_) + return ""; + + string file; + // Prefer the CodeView record if present. + if (cv_record_) { + if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { + // It's actually an MDCVInfoPDB70 structure. + const MDCVInfoPDB70* cv_record_70 = + reinterpret_cast(&(*cv_record_)[0]); + assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); + + // GetCVRecord guarantees pdb_file_name is null-terminated. + file = reinterpret_cast(cv_record_70->pdb_file_name); + } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { + // It's actually an MDCVInfoPDB20 structure. + const MDCVInfoPDB20* cv_record_20 = + reinterpret_cast(&(*cv_record_)[0]); + assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); + + // GetCVRecord guarantees pdb_file_name is null-terminated. + file = reinterpret_cast(cv_record_20->pdb_file_name); + } + + // If there's a CodeView record but it doesn't match a known signature, + // try the miscellaneous record. + } + + if (file.empty()) { + // No usable CodeView record. Try the miscellaneous debug record. + if (misc_record_) { + const MDImageDebugMisc* misc_record = + reinterpret_cast(&(*misc_record_)[0]); + if (!misc_record->unicode) { + // If it's not Unicode, just stuff it into the string. It's unclear + // if misc_record->data is 0-terminated, so use an explicit size. + file = string( + reinterpret_cast(misc_record->data), + module_.misc_record.data_size - MDImageDebugMisc_minsize); + } else { + // There's a misc_record but it encodes the debug filename in UTF-16. + // (Actually, because miscellaneous records are so old, it's probably + // UCS-2.) Convert it to UTF-8 for congruity with the other strings + // that this method (and all other methods in the Minidump family) + // return. + + unsigned int bytes = + module_.misc_record.data_size - MDImageDebugMisc_minsize; + if (bytes % 2 == 0) { + unsigned int utf16_words = bytes / 2; + + // UTF16ToUTF8 expects a vector, so create a temporary one + // and copy the UTF-16 data into it. + vector string_utf16(utf16_words); + if (utf16_words) + memcpy(&string_utf16[0], &misc_record->data, bytes); + + // GetMiscRecord already byte-swapped the data[] field if it contains + // UTF-16, so pass false as the swap argument. + scoped_ptr new_file(UTF16ToUTF8(string_utf16, false)); + file = *new_file; + } + } + } + } + + BPLOG_IF(ERROR, file.empty()) << "MinidumpModule could not determine " + "debug_file for " << *name_; + + return file; +} + + +string MinidumpModule::debug_identifier() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier"; + return ""; + } + + if (!has_debug_info_) + return ""; + + string identifier; + + // Use the CodeView record if present. + if (cv_record_) { + if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { + // It's actually an MDCVInfoPDB70 structure. + const MDCVInfoPDB70* cv_record_70 = + reinterpret_cast(&(*cv_record_)[0]); + assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); + + // Use the same format that the MS symbol server uses in filesystem + // hierarchies. + char identifier_string[41]; + snprintf(identifier_string, sizeof(identifier_string), + "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", + cv_record_70->signature.data1, + cv_record_70->signature.data2, + cv_record_70->signature.data3, + cv_record_70->signature.data4[0], + cv_record_70->signature.data4[1], + cv_record_70->signature.data4[2], + cv_record_70->signature.data4[3], + cv_record_70->signature.data4[4], + cv_record_70->signature.data4[5], + cv_record_70->signature.data4[6], + cv_record_70->signature.data4[7], + cv_record_70->age); + identifier = identifier_string; + } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { + // It's actually an MDCVInfoPDB20 structure. + const MDCVInfoPDB20* cv_record_20 = + reinterpret_cast(&(*cv_record_)[0]); + assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); + + // Use the same format that the MS symbol server uses in filesystem + // hierarchies. + char identifier_string[17]; + snprintf(identifier_string, sizeof(identifier_string), + "%08X%x", cv_record_20->signature, cv_record_20->age); + identifier = identifier_string; + } + } + + // TODO(mmentovai): if there's no usable CodeView record, there might be a + // miscellaneous debug record. It only carries a filename, though, and no + // identifier. I'm not sure what the right thing to do for the identifier + // is in that case, but I don't expect to find many modules without a + // CodeView record (or some other Breakpad extension structure in place of + // a CodeView record). Treat it as an error (empty identifier) for now. + + // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). + + BPLOG_IF(ERROR, identifier.empty()) << "MinidumpModule could not determine " + "debug_identifier for " << *name_; + + return identifier; +} + + +string MinidumpModule::version() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for version"; + return ""; + } + + string version; + + if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE && + module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION && + (module_.version_info.file_version_hi != 0 || module_.version_info.file_version_lo != 0)) { + char version_string[24]; + snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u", + module_.version_info.file_version_hi >> 16, + module_.version_info.file_version_hi & 0xffff, + module_.version_info.file_version_lo >> 16, + module_.version_info.file_version_lo & 0xffff); + version = version_string; + } + + // TODO(mmentovai): possibly support other struct types in place of + // the one used with MD_VSFIXEDFILEINFO_SIGNATURE. We can possibly use + // a different structure that better represents versioning facilities on + // Mac OS X and Linux, instead of forcing them to adhere to the dotted + // quad of 16-bit ints that Windows uses. + + BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine " + "version for " << *name_; + + return version; +} + + +const CodeModule* MinidumpModule::Copy() const { + return new BasicCodeModule(this); +} + + +const u_int8_t* MinidumpModule::GetCVRecord(u_int32_t* size) { + if (!module_valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord"; + return NULL; + } + + if (!cv_record_) { + // This just guards against 0-sized CodeView records; more specific checks + // are used when the signature is checked against various structure types. + if (module_.cv_record.data_size == 0) { + return NULL; + } + + if (!minidump_->SeekSet(module_.cv_record.rva)) { + BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record"; + return NULL; + } + + if (module_.cv_record.data_size > max_cv_bytes_) { + BPLOG(ERROR) << "MinidumpModule CodeView record size " << + module_.cv_record.data_size << " exceeds maximum " << + max_cv_bytes_; + return NULL; + } + + // Allocating something that will be accessed as MDCVInfoPDB70 or + // MDCVInfoPDB20 but is allocated as u_int8_t[] can cause alignment + // problems. x86 and ppc are able to cope, though. This allocation + // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are + // variable-sized due to their pdb_file_name fields; these structures + // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating + // them as such would result in incomplete structures or overruns. + scoped_ptr< vector > cv_record( + new vector(module_.cv_record.data_size)); + + if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) { + BPLOG(ERROR) << "MinidumpModule could not read CodeView record"; + return NULL; + } + + u_int32_t signature = MD_CVINFOUNKNOWN_SIGNATURE; + if (module_.cv_record.data_size > sizeof(signature)) { + MDCVInfoPDB70* cv_record_signature = + reinterpret_cast(&(*cv_record)[0]); + signature = cv_record_signature->cv_signature; + if (minidump_->swap()) + Swap(&signature); + } + + if (signature == MD_CVINFOPDB70_SIGNATURE) { + // Now that the structure type is known, recheck the size. + if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) { + BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " << + MDCVInfoPDB70_minsize << " > " << + module_.cv_record.data_size; + return NULL; + } + + if (minidump_->swap()) { + MDCVInfoPDB70* cv_record_70 = + reinterpret_cast(&(*cv_record)[0]); + Swap(&cv_record_70->cv_signature); + Swap(&cv_record_70->signature); + Swap(&cv_record_70->age); + // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit + // quantities. (It's a path, is it UTF-8?) + } + + // The last field of either structure is null-terminated 8-bit character + // data. Ensure that it's null-terminated. + if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { + BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not " + "0-terminated"; + return NULL; + } + } else if (signature == MD_CVINFOPDB20_SIGNATURE) { + // Now that the structure type is known, recheck the size. + if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) { + BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " << + MDCVInfoPDB20_minsize << " > " << + module_.cv_record.data_size; + return NULL; + } + if (minidump_->swap()) { + MDCVInfoPDB20* cv_record_20 = + reinterpret_cast(&(*cv_record)[0]); + Swap(&cv_record_20->cv_header.signature); + Swap(&cv_record_20->cv_header.offset); + Swap(&cv_record_20->signature); + Swap(&cv_record_20->age); + // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit + // quantities. (It's a path, is it UTF-8?) + } + + // The last field of either structure is null-terminated 8-bit character + // data. Ensure that it's null-terminated. + if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { + BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " + "0-terminated"; + return NULL; + } + } + + // If the signature doesn't match something above, it's not something + // that Breakpad can presently handle directly. Because some modules in + // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, + // don't bail out here - allow the data to be returned to the user, + // although byte-swapping can't be done. + + // Store the vector type because that's how storage was allocated, but + // return it casted to u_int8_t*. + cv_record_ = cv_record.release(); + cv_record_signature_ = signature; + } + + if (size) + *size = module_.cv_record.data_size; + + return &(*cv_record_)[0]; +} + + +const MDImageDebugMisc* MinidumpModule::GetMiscRecord(u_int32_t* size) { + if (!module_valid_) { + BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord"; + return NULL; + } + + if (!misc_record_) { + if (module_.misc_record.data_size == 0) { + return NULL; + } + + if (MDImageDebugMisc_minsize > module_.misc_record.data_size) { + BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record " + "size mismatch, " << MDImageDebugMisc_minsize << " > " << + module_.misc_record.data_size; + return NULL; + } + + if (!minidump_->SeekSet(module_.misc_record.rva)) { + BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous " + "debugging record"; + return NULL; + } + + if (module_.misc_record.data_size > max_misc_bytes_) { + BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " << + module_.misc_record.data_size << " exceeds maximum " << + max_misc_bytes_; + return NULL; + } + + // Allocating something that will be accessed as MDImageDebugMisc but + // is allocated as u_int8_t[] can cause alignment problems. x86 and + // ppc are able to cope, though. This allocation style is needed + // because the MDImageDebugMisc is variable-sized due to its data field; + // this structure is not MDImageDebugMisc_minsize and treating it as such + // would result in an incomplete structure or an overrun. + scoped_ptr< vector > misc_record_mem( + new vector(module_.misc_record.data_size)); + MDImageDebugMisc* misc_record = + reinterpret_cast(&(*misc_record_mem)[0]); + + if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) { + BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging " + "record"; + return NULL; + } + + if (minidump_->swap()) { + Swap(&misc_record->data_type); + Swap(&misc_record->length); + // Don't swap misc_record.unicode because it's an 8-bit quantity. + // Don't swap the reserved fields for the same reason, and because + // they don't contain any valid data. + if (misc_record->unicode) { + // There is a potential alignment problem, but shouldn't be a problem + // in practice due to the layout of MDImageDebugMisc. + u_int16_t* data16 = reinterpret_cast(&(misc_record->data)); + unsigned int dataBytes = module_.misc_record.data_size - + MDImageDebugMisc_minsize; + unsigned int dataLength = dataBytes / 2; + for (unsigned int characterIndex = 0; + characterIndex < dataLength; + ++characterIndex) { + Swap(&data16[characterIndex]); + } + } + } + + if (module_.misc_record.data_size != misc_record->length) { + BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data " + "size mismatch, " << module_.misc_record.data_size << + " != " << misc_record->length; + return NULL; + } + + // Store the vector type because that's how storage was allocated, but + // return it casted to MDImageDebugMisc*. + misc_record_ = misc_record_mem.release(); + } + + if (size) + *size = module_.misc_record.data_size; + + return reinterpret_cast(&(*misc_record_)[0]); +} + + +void MinidumpModule::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpModule cannot print invalid data"; + return; + } + + printf("MDRawModule\n"); + printf(" base_of_image = 0x%" PRIx64 "\n", + module_.base_of_image); + printf(" size_of_image = 0x%x\n", + module_.size_of_image); + printf(" checksum = 0x%x\n", + module_.checksum); + printf(" time_date_stamp = 0x%x\n", + module_.time_date_stamp); + printf(" module_name_rva = 0x%x\n", + module_.module_name_rva); + printf(" version_info.signature = 0x%x\n", + module_.version_info.signature); + printf(" version_info.struct_version = 0x%x\n", + module_.version_info.struct_version); + printf(" version_info.file_version = 0x%x:0x%x\n", + module_.version_info.file_version_hi, + module_.version_info.file_version_lo); + printf(" version_info.product_version = 0x%x:0x%x\n", + module_.version_info.product_version_hi, + module_.version_info.product_version_lo); + printf(" version_info.file_flags_mask = 0x%x\n", + module_.version_info.file_flags_mask); + printf(" version_info.file_flags = 0x%x\n", + module_.version_info.file_flags); + printf(" version_info.file_os = 0x%x\n", + module_.version_info.file_os); + printf(" version_info.file_type = 0x%x\n", + module_.version_info.file_type); + printf(" version_info.file_subtype = 0x%x\n", + module_.version_info.file_subtype); + printf(" version_info.file_date = 0x%x:0x%x\n", + module_.version_info.file_date_hi, + module_.version_info.file_date_lo); + printf(" cv_record.data_size = %d\n", + module_.cv_record.data_size); + printf(" cv_record.rva = 0x%x\n", + module_.cv_record.rva); + printf(" misc_record.data_size = %d\n", + module_.misc_record.data_size); + printf(" misc_record.rva = 0x%x\n", + module_.misc_record.rva); + + printf(" (code_file) = \"%s\"\n", code_file().c_str()); + printf(" (code_identifier) = \"%s\"\n", + code_identifier().c_str()); + + u_int32_t cv_record_size; + const u_int8_t *cv_record = GetCVRecord(&cv_record_size); + if (cv_record) { + if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { + const MDCVInfoPDB70* cv_record_70 = + reinterpret_cast(cv_record); + assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); + + printf(" (cv_record).cv_signature = 0x%x\n", + cv_record_70->cv_signature); + printf(" (cv_record).signature = %08x-%04x-%04x-%02x%02x-", + cv_record_70->signature.data1, + cv_record_70->signature.data2, + cv_record_70->signature.data3, + cv_record_70->signature.data4[0], + cv_record_70->signature.data4[1]); + for (unsigned int guidIndex = 2; + guidIndex < 8; + ++guidIndex) { + printf("%02x", cv_record_70->signature.data4[guidIndex]); + } + printf("\n"); + printf(" (cv_record).age = %d\n", + cv_record_70->age); + printf(" (cv_record).pdb_file_name = \"%s\"\n", + cv_record_70->pdb_file_name); + } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { + const MDCVInfoPDB20* cv_record_20 = + reinterpret_cast(cv_record); + assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); + + printf(" (cv_record).cv_header.signature = 0x%x\n", + cv_record_20->cv_header.signature); + printf(" (cv_record).cv_header.offset = 0x%x\n", + cv_record_20->cv_header.offset); + printf(" (cv_record).signature = 0x%x\n", + cv_record_20->signature); + printf(" (cv_record).age = %d\n", + cv_record_20->age); + printf(" (cv_record).pdb_file_name = \"%s\"\n", + cv_record_20->pdb_file_name); + } else { + printf(" (cv_record) = "); + for (unsigned int cv_byte_index = 0; + cv_byte_index < cv_record_size; + ++cv_byte_index) { + printf("%02x", cv_record[cv_byte_index]); + } + printf("\n"); + } + } else { + printf(" (cv_record) = (null)\n"); + } + + const MDImageDebugMisc* misc_record = GetMiscRecord(NULL); + if (misc_record) { + printf(" (misc_record).data_type = 0x%x\n", + misc_record->data_type); + printf(" (misc_record).length = 0x%x\n", + misc_record->length); + printf(" (misc_record).unicode = %d\n", + misc_record->unicode); + // Don't bother printing the UTF-16, we don't really even expect to ever + // see this misc_record anyway. + if (misc_record->unicode) + printf(" (misc_record).data = \"%s\"\n", + misc_record->data); + else + printf(" (misc_record).data = (UTF-16)\n"); + } else { + printf(" (misc_record) = (null)\n"); + } + + printf(" (debug_file) = \"%s\"\n", debug_file().c_str()); + printf(" (debug_identifier) = \"%s\"\n", + debug_identifier().c_str()); + printf(" (version) = \"%s\"\n", version().c_str()); + printf("\n"); +} + + +// +// MinidumpModuleList +// + + +u_int32_t MinidumpModuleList::max_modules_ = 1024; + + +MinidumpModuleList::MinidumpModuleList(Minidump* minidump) + : MinidumpStream(minidump), + range_map_(new RangeMap()), + modules_(NULL), + module_count_(0) { +} + + +MinidumpModuleList::~MinidumpModuleList() { + delete range_map_; + delete modules_; +} + + +bool MinidumpModuleList::Read(u_int32_t expected_size) { + // Invalidate cached data. + range_map_->Clear(); + delete modules_; + modules_ = NULL; + module_count_ = 0; + + valid_ = false; + + u_int32_t module_count; + if (expected_size < sizeof(module_count)) { + BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " << + expected_size << " < " << sizeof(module_count); + return false; + } + if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) { + BPLOG(ERROR) << "MinidumpModuleList could not read module count"; + return false; + } + + if (minidump_->swap()) + Swap(&module_count); + + if (module_count > numeric_limits::max() / MD_MODULE_SIZE) { + BPLOG(ERROR) << "MinidumpModuleList module count " << module_count << + " would cause multiplication overflow"; + return false; + } + + if (expected_size != sizeof(module_count) + + module_count * MD_MODULE_SIZE) { + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(module_count) + 4 + + module_count * MD_MODULE_SIZE) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << + " != " << sizeof(module_count) + + module_count * MD_MODULE_SIZE; + return false; + } + } + + if (module_count > max_modules_) { + BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ << + " exceeds maximum " << max_modules_; + return false; + } + + if (module_count != 0) { + scoped_ptr modules( + new MinidumpModules(module_count, MinidumpModule(minidump_))); + + for (unsigned int module_index = 0; + module_index < module_count; + ++module_index) { + MinidumpModule* module = &(*modules)[module_index]; + + // Assume that the file offset is correct after the last read. + if (!module->Read()) { + BPLOG(ERROR) << "MinidumpModuleList could not read module " << + module_index << "/" << module_count; + return false; + } + } + + // Loop through the module list once more to read additional data and + // build the range map. This is done in a second pass because + // MinidumpModule::ReadAuxiliaryData seeks around, and if it were + // included in the loop above, additional seeks would be needed where + // none are now to read contiguous data. + for (unsigned int module_index = 0; + module_index < module_count; + ++module_index) { + MinidumpModule* module = &(*modules)[module_index]; + + // ReadAuxiliaryData fails if any data that the module indicates should + // exist is missing, but we treat some such cases as valid anyway. See + // issue #222: if a debugging record is of a format that's too large to + // handle, it shouldn't render the entire dump invalid. Check module + // validity before giving up. + if (!module->ReadAuxiliaryData() && !module->valid()) { + BPLOG(ERROR) << "MinidumpModuleList could not read required module " + "auxiliary data for module " << + module_index << "/" << module_count; + return false; + } + + // It is safe to use module->code_file() after successfully calling + // module->ReadAuxiliaryData or noting that the module is valid. + + u_int64_t base_address = module->base_address(); + u_int64_t module_size = module->size(); + if (base_address == static_cast(-1)) { + BPLOG(ERROR) << "MinidumpModuleList found bad base address " + "for module " << module_index << "/" << module_count << + ", " << module->code_file(); + return false; + } + + if (!range_map_->StoreRange(base_address, module_size, module_index)) { + BPLOG(ERROR) << "MinidumpModuleList could not store module " << + module_index << "/" << module_count << ", " << + module->code_file() << ", " << + HexString(base_address) << "+" << + HexString(module_size); + return false; + } + } + + modules_ = modules.release(); + } + + module_count_ = module_count; + + valid_ = true; + return true; +} + + +const MinidumpModule* MinidumpModuleList::GetModuleForAddress( + u_int64_t address) const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress"; + return NULL; + } + + unsigned int module_index; + if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) { + BPLOG(INFO) << "MinidumpModuleList has no module at " << + HexString(address); + return NULL; + } + + return GetModuleAtIndex(module_index); +} + + +const MinidumpModule* MinidumpModuleList::GetMainModule() const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule"; + return NULL; + } + + // The main code module is the first one present in a minidump file's + // MDRawModuleList. + return GetModuleAtSequence(0); +} + + +const MinidumpModule* MinidumpModuleList::GetModuleAtSequence( + unsigned int sequence) const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence"; + return NULL; + } + + if (sequence >= module_count_) { + BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " << + sequence << "/" << module_count_; + return NULL; + } + + unsigned int module_index; + if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) { + BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence; + return NULL; + } + + return GetModuleAtIndex(module_index); +} + + +const MinidumpModule* MinidumpModuleList::GetModuleAtIndex( + unsigned int index) const { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex"; + return NULL; + } + + if (index >= module_count_) { + BPLOG(ERROR) << "MinidumpModuleList index out of range: " << + index << "/" << module_count_; + return NULL; + } + + return &(*modules_)[index]; +} + + +const CodeModules* MinidumpModuleList::Copy() const { + return new BasicCodeModules(this); +} + + +void MinidumpModuleList::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data"; + return; + } + + printf("MinidumpModuleList\n"); + printf(" module_count = %d\n", module_count_); + printf("\n"); + + for (unsigned int module_index = 0; + module_index < module_count_; + ++module_index) { + printf("module[%d]\n", module_index); + + (*modules_)[module_index].Print(); + } +} + + +// +// MinidumpMemoryList +// + + +u_int32_t MinidumpMemoryList::max_regions_ = 256; + + +MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) + : MinidumpStream(minidump), + range_map_(new RangeMap()), + descriptors_(NULL), + regions_(NULL), + region_count_(0) { +} + + +MinidumpMemoryList::~MinidumpMemoryList() { + delete range_map_; + delete descriptors_; + delete regions_; +} + + +bool MinidumpMemoryList::Read(u_int32_t expected_size) { + // Invalidate cached data. + delete descriptors_; + descriptors_ = NULL; + delete regions_; + regions_ = NULL; + range_map_->Clear(); + region_count_ = 0; + + valid_ = false; + + u_int32_t region_count; + if (expected_size < sizeof(region_count)) { + BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " << + expected_size << " < " << sizeof(region_count); + return false; + } + if (!minidump_->ReadBytes(®ion_count, sizeof(region_count))) { + BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count"; + return false; + } + + if (minidump_->swap()) + Swap(®ion_count); + + if (region_count > + numeric_limits::max() / sizeof(MDMemoryDescriptor)) { + BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count << + " would cause multiplication overflow"; + return false; + } + + if (expected_size != sizeof(region_count) + + region_count * sizeof(MDMemoryDescriptor)) { + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(region_count) + 4 + + region_count * sizeof(MDMemoryDescriptor)) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << + " != " << sizeof(region_count) + + region_count * sizeof(MDMemoryDescriptor); + return false; + } + } + + if (region_count > max_regions_) { + BPLOG(ERROR) << "MinidumpMemoryList count " << region_count << + " exceeds maximum " << max_regions_; + return false; + } + + if (region_count != 0) { + scoped_ptr descriptors( + new MemoryDescriptors(region_count)); + + // Read the entire array in one fell swoop, instead of reading one entry + // at a time in the loop. + if (!minidump_->ReadBytes(&(*descriptors)[0], + sizeof(MDMemoryDescriptor) * region_count)) { + BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list"; + return false; + } + + scoped_ptr regions( + new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); + + for (unsigned int region_index = 0; + region_index < region_count; + ++region_index) { + MDMemoryDescriptor* descriptor = &(*descriptors)[region_index]; + + if (minidump_->swap()) + Swap(descriptor); + + u_int64_t base_address = descriptor->start_of_memory_range; + u_int32_t region_size = descriptor->memory.data_size; + + // Check for base + size overflow or undersize. + if (region_size == 0 || + region_size > numeric_limits::max() - base_address) { + BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " << + " region " << region_index << "/" << region_count << + ", " << HexString(base_address) << "+" << + HexString(region_size); + return false; + } + + if (!range_map_->StoreRange(base_address, region_size, region_index)) { + BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " << + region_index << "/" << region_count << ", " << + HexString(base_address) << "+" << + HexString(region_size); + return false; + } + + (*regions)[region_index].SetDescriptor(descriptor); + } + + descriptors_ = descriptors.release(); + regions_ = regions.release(); + } + + region_count_ = region_count; + + valid_ = true; + return true; +} + + +MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex( + unsigned int index) { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex"; + return NULL; + } + + if (index >= region_count_) { + BPLOG(ERROR) << "MinidumpMemoryList index out of range: " << + index << "/" << region_count_; + return NULL; + } + + return &(*regions_)[index]; +} + + +MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress( + u_int64_t address) { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress"; + return NULL; + } + + unsigned int region_index; + if (!range_map_->RetrieveRange(address, ®ion_index, NULL, NULL)) { + BPLOG(INFO) << "MinidumpMemoryList has no memory region at " << + HexString(address); + return NULL; + } + + return GetMemoryRegionAtIndex(region_index); +} + + +void MinidumpMemoryList::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data"; + return; + } + + printf("MinidumpMemoryList\n"); + printf(" region_count = %d\n", region_count_); + printf("\n"); + + for (unsigned int region_index = 0; + region_index < region_count_; + ++region_index) { + MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index]; + printf("region[%d]\n", region_index); + printf("MDMemoryDescriptor\n"); + printf(" start_of_memory_range = 0x%" PRIx64 "\n", + descriptor->start_of_memory_range); + printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size); + printf(" memory.rva = 0x%x\n", descriptor->memory.rva); + MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index); + if (region) { + printf("Memory\n"); + region->Print(); + } else { + printf("No memory\n"); + } + printf("\n"); + } +} + + +// +// MinidumpException +// + + +MinidumpException::MinidumpException(Minidump* minidump) + : MinidumpStream(minidump), + exception_(), + context_(NULL) { +} + + +MinidumpException::~MinidumpException() { + delete context_; +} + + +bool MinidumpException::Read(u_int32_t expected_size) { + // Invalidate cached data. + delete context_; + context_ = NULL; + + valid_ = false; + + if (expected_size != sizeof(exception_)) { + BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size << + " != " << sizeof(exception_); + return false; + } + + if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) { + BPLOG(ERROR) << "MinidumpException cannot read exception"; + return false; + } + + if (minidump_->swap()) { + Swap(&exception_.thread_id); + // exception_.__align is for alignment only and does not need to be + // swapped. + Swap(&exception_.exception_record.exception_code); + Swap(&exception_.exception_record.exception_flags); + Swap(&exception_.exception_record.exception_record); + Swap(&exception_.exception_record.exception_address); + Swap(&exception_.exception_record.number_parameters); + // exception_.exception_record.__align is for alignment only and does not + // need to be swapped. + for (unsigned int parameter_index = 0; + parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS; + ++parameter_index) { + Swap(&exception_.exception_record.exception_information[parameter_index]); + } + Swap(&exception_.thread_context); + } + + valid_ = true; + return true; +} + + +bool MinidumpException::GetThreadID(u_int32_t *thread_id) const { + BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires " + "|thread_id|"; + assert(thread_id); + *thread_id = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID"; + return false; + } + + *thread_id = exception_.thread_id; + return true; +} + + +MinidumpContext* MinidumpException::GetContext() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpException for GetContext"; + return NULL; + } + + if (!context_) { + if (!minidump_->SeekSet(exception_.thread_context.rva)) { + BPLOG(ERROR) << "MinidumpException cannot seek to context"; + return NULL; + } + + scoped_ptr context(new MinidumpContext(minidump_)); + + if (!context->Read(exception_.thread_context.data_size)) { + BPLOG(ERROR) << "MinidumpException cannot read context"; + return NULL; + } + + context_ = context.release(); + } + + return context_; +} + + +void MinidumpException::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpException cannot print invalid data"; + return; + } + + printf("MDException\n"); + printf(" thread_id = 0x%x\n", + exception_.thread_id); + printf(" exception_record.exception_code = 0x%x\n", + exception_.exception_record.exception_code); + printf(" exception_record.exception_flags = 0x%x\n", + exception_.exception_record.exception_flags); + printf(" exception_record.exception_record = 0x%" PRIx64 "\n", + exception_.exception_record.exception_record); + printf(" exception_record.exception_address = 0x%" PRIx64 "\n", + exception_.exception_record.exception_address); + printf(" exception_record.number_parameters = %d\n", + exception_.exception_record.number_parameters); + for (unsigned int parameterIndex = 0; + parameterIndex < exception_.exception_record.number_parameters; + ++parameterIndex) { + printf(" exception_record.exception_information[%2d] = 0x%" PRIx64 "\n", + parameterIndex, + exception_.exception_record.exception_information[parameterIndex]); + } + printf(" thread_context.data_size = %d\n", + exception_.thread_context.data_size); + printf(" thread_context.rva = 0x%x\n", + exception_.thread_context.rva); + MinidumpContext* context = GetContext(); + if (context) { + printf("\n"); + context->Print(); + } else { + printf(" (no context)\n"); + printf("\n"); + } +} + + +// +// MinidumpSystemInfo +// + + +MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) + : MinidumpStream(minidump), + system_info_(), + csd_version_(NULL), + cpu_vendor_(NULL) { +} + + +MinidumpSystemInfo::~MinidumpSystemInfo() { + delete csd_version_; + delete cpu_vendor_; +} + + +bool MinidumpSystemInfo::Read(u_int32_t expected_size) { + // Invalidate cached data. + delete csd_version_; + csd_version_ = NULL; + delete cpu_vendor_; + cpu_vendor_ = NULL; + + valid_ = false; + + if (expected_size != sizeof(system_info_)) { + BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size << + " != " << sizeof(system_info_); + return false; + } + + if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) { + BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info"; + return false; + } + + if (minidump_->swap()) { + Swap(&system_info_.processor_architecture); + Swap(&system_info_.processor_level); + Swap(&system_info_.processor_revision); + // number_of_processors and product_type are 8-bit quantities and need no + // swapping. + Swap(&system_info_.major_version); + Swap(&system_info_.minor_version); + Swap(&system_info_.build_number); + Swap(&system_info_.platform_id); + Swap(&system_info_.csd_version_rva); + Swap(&system_info_.suite_mask); + // Don't swap the reserved2 field because its contents are unknown. + + if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || + system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { + for (unsigned int i = 0; i < 3; ++i) + Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]); + Swap(&system_info_.cpu.x86_cpu_info.version_information); + Swap(&system_info_.cpu.x86_cpu_info.feature_information); + Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); + } else { + for (unsigned int i = 0; i < 2; ++i) + Swap(&system_info_.cpu.other_cpu_info.processor_features[i]); + } + } + + valid_ = true; + return true; +} + + +string MinidumpSystemInfo::GetOS() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS"; + return NULL; + } + + string os; + + switch (system_info_.platform_id) { + case MD_OS_WIN32_NT: + case MD_OS_WIN32_WINDOWS: + os = "windows"; + break; + + case MD_OS_MAC_OS_X: + os = "mac"; + break; + + case MD_OS_LINUX: + os = "linux"; + break; + + case MD_OS_SOLARIS: + os = "solaris"; + break; + + default: + BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " << + HexString(system_info_.platform_id); + break; + } + + return os; +} + + +string MinidumpSystemInfo::GetCPU() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU"; + return ""; + } + + string cpu; + + switch (system_info_.processor_architecture) { + case MD_CPU_ARCHITECTURE_X86: + case MD_CPU_ARCHITECTURE_X86_WIN64: + cpu = "x86"; + break; + + case MD_CPU_ARCHITECTURE_PPC: + cpu = "ppc"; + break; + + case MD_CPU_ARCHITECTURE_SPARC: + cpu = "sparc"; + break; + + default: + BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " << + HexString(system_info_.processor_architecture); + break; + } + + return cpu; +} + + +const string* MinidumpSystemInfo::GetCSDVersion() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion"; + return NULL; + } + + if (!csd_version_) + csd_version_ = minidump_->ReadString(system_info_.csd_version_rva); + + BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read " + "CSD version"; + + return csd_version_; +} + + +const string* MinidumpSystemInfo::GetCPUVendor() { + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor"; + return NULL; + } + + // CPU vendor information can only be determined from x86 minidumps. + if (!cpu_vendor_ && + (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || + system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) { + char cpu_vendor_string[13]; + snprintf(cpu_vendor_string, sizeof(cpu_vendor_string), + "%c%c%c%c%c%c%c%c%c%c%c%c", + system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff, + system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff, + system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff, + (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff); + cpu_vendor_ = new string(cpu_vendor_string); + } + + return cpu_vendor_; +} + + +void MinidumpSystemInfo::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data"; + return; + } + + printf("MDRawSystemInfo\n"); + printf(" processor_architecture = %d\n", + system_info_.processor_architecture); + printf(" processor_level = %d\n", + system_info_.processor_level); + printf(" processor_revision = 0x%x\n", + system_info_.processor_revision); + printf(" number_of_processors = %d\n", + system_info_.number_of_processors); + printf(" product_type = %d\n", + system_info_.product_type); + printf(" major_version = %d\n", + system_info_.major_version); + printf(" minor_version = %d\n", + system_info_.minor_version); + printf(" build_number = %d\n", + system_info_.build_number); + printf(" platform_id = %d\n", + system_info_.platform_id); + printf(" csd_version_rva = 0x%x\n", + system_info_.csd_version_rva); + printf(" suite_mask = 0x%x\n", + system_info_.suite_mask); + for (unsigned int i = 0; i < 3; ++i) { + printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n", + i, system_info_.cpu.x86_cpu_info.vendor_id[i]); + } + printf(" cpu.x86_cpu_info.version_information = 0x%x\n", + system_info_.cpu.x86_cpu_info.version_information); + printf(" cpu.x86_cpu_info.feature_information = 0x%x\n", + system_info_.cpu.x86_cpu_info.feature_information); + printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n", + system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); + const string* csd_version = GetCSDVersion(); + if (csd_version) { + printf(" (csd_version) = \"%s\"\n", + csd_version->c_str()); + } else { + printf(" (csd_version) = (null)\n"); + } + const string* cpu_vendor = GetCPUVendor(); + if (cpu_vendor) { + printf(" (cpu_vendor) = \"%s\"\n", + cpu_vendor->c_str()); + } else { + printf(" (cpu_vendor) = (null)\n"); + } + printf("\n"); +} + + +// +// MinidumpMiscInfo +// + + +MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump) + : MinidumpStream(minidump), + misc_info_() { +} + + +bool MinidumpMiscInfo::Read(u_int32_t expected_size) { + valid_ = false; + + if (expected_size != MD_MISCINFO_SIZE && + expected_size != MD_MISCINFO2_SIZE) { + BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size << + " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE << + ")"; + return false; + } + + if (!minidump_->ReadBytes(&misc_info_, expected_size)) { + BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info"; + return false; + } + + if (minidump_->swap()) { + Swap(&misc_info_.size_of_info); + Swap(&misc_info_.flags1); + Swap(&misc_info_.process_id); + Swap(&misc_info_.process_create_time); + Swap(&misc_info_.process_user_time); + Swap(&misc_info_.process_kernel_time); + if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { + Swap(&misc_info_.processor_max_mhz); + Swap(&misc_info_.processor_current_mhz); + Swap(&misc_info_.processor_mhz_limit); + Swap(&misc_info_.processor_max_idle_state); + Swap(&misc_info_.processor_current_idle_state); + } + } + + if (expected_size != misc_info_.size_of_info) { + BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << + expected_size << " != " << misc_info_.size_of_info; + return false; + } + + valid_ = true; + return true; +} + + +void MinidumpMiscInfo::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data"; + return; + } + + printf("MDRawMiscInfo\n"); + printf(" size_of_info = %d\n", misc_info_.size_of_info); + printf(" flags1 = 0x%x\n", misc_info_.flags1); + printf(" process_id = 0x%x\n", misc_info_.process_id); + printf(" process_create_time = 0x%x\n", + misc_info_.process_create_time); + printf(" process_user_time = 0x%x\n", + misc_info_.process_user_time); + printf(" process_kernel_time = 0x%x\n", + misc_info_.process_kernel_time); + if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { + printf(" processor_max_mhz = %d\n", + misc_info_.processor_max_mhz); + printf(" processor_current_mhz = %d\n", + misc_info_.processor_current_mhz); + printf(" processor_mhz_limit = %d\n", + misc_info_.processor_mhz_limit); + printf(" processor_max_idle_state = 0x%x\n", + misc_info_.processor_max_idle_state); + printf(" processor_current_idle_state = 0x%x\n", + misc_info_.processor_current_idle_state); + } + printf("\n"); +} + + +// +// MinidumpBreakpadInfo +// + + +MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump) + : MinidumpStream(minidump), + breakpad_info_() { +} + + +bool MinidumpBreakpadInfo::Read(u_int32_t expected_size) { + valid_ = false; + + if (expected_size != sizeof(breakpad_info_)) { + BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size << + " != " << sizeof(breakpad_info_); + return false; + } + + if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) { + BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info"; + return false; + } + + if (minidump_->swap()) { + Swap(&breakpad_info_.validity); + Swap(&breakpad_info_.dump_thread_id); + Swap(&breakpad_info_.requesting_thread_id); + } + + valid_ = true; + return true; +} + + +bool MinidumpBreakpadInfo::GetDumpThreadID(u_int32_t *thread_id) const { + BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID " + "requires |thread_id|"; + assert(thread_id); + *thread_id = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID"; + return false; + } + + if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) { + BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread"; + return false; + } + + *thread_id = breakpad_info_.dump_thread_id; + return true; +} + + +bool MinidumpBreakpadInfo::GetRequestingThreadID(u_int32_t *thread_id) + const { + BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID " + "requires |thread_id|"; + assert(thread_id); + *thread_id = 0; + + if (!thread_id || !valid_) { + BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID"; + return false; + } + + if (!(breakpad_info_.validity & + MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) { + BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread"; + return false; + } + + *thread_id = breakpad_info_.requesting_thread_id; + return true; +} + + +void MinidumpBreakpadInfo::Print() { + if (!valid_) { + BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data"; + return; + } + + printf("MDRawBreakpadInfo\n"); + printf(" validity = 0x%x\n", breakpad_info_.validity); + + if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) { + printf(" dump_thread_id = 0x%x\n", breakpad_info_.dump_thread_id); + } else { + printf(" dump_thread_id = (invalid)\n"); + } + + if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) { + printf(" requesting_thread_id = 0x%x\n", + breakpad_info_.requesting_thread_id); + } else { + printf(" requesting_thread_id = (invalid)\n"); + } + + printf("\n"); +} + + +// +// Minidump +// + + +u_int32_t Minidump::max_streams_ = 128; +unsigned int Minidump::max_string_length_ = 1024; + + +Minidump::Minidump(const string& path) + : header_(), + directory_(NULL), + stream_map_(new MinidumpStreamMap()), + path_(path), + fd_(-1), + swap_(false), + valid_(false) { +} + + +Minidump::~Minidump() { + delete directory_; + delete stream_map_; + if (fd_ != -1) { + BPLOG(INFO) << "Minidump closing minidump on fd " << fd_; + close(fd_); + } +} + + +bool Minidump::Open() { + if (fd_ != -1) { + BPLOG(INFO) << "Minidump reopening minidump " << path_ << " on fd " << fd_; + + // The file is already open. Seek to the beginning, which is the position + // the file would be at if it were opened anew. + return SeekSet(0); + } + + // O_BINARY is useful (and defined) on Windows. On other platforms, it's + // useless, and because it's defined as 0 above, harmless. + fd_ = open(path_.c_str(), O_RDONLY | O_BINARY); + if (fd_ == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Minidump could not open minidump " << path_ << + ", error " << error_code << ": " << error_string; + return false; + } + + BPLOG(INFO) << "Minidump opened minidump " << path_ << " on fd " << fd_; + return true; +} + + +bool Minidump::Read() { + // Invalidate cached data. + delete directory_; + directory_ = NULL; + stream_map_->clear(); + + valid_ = false; + + if (!Open()) { + BPLOG(ERROR) << "Minidump cannot open minidump"; + return false; + } + + if (!ReadBytes(&header_, sizeof(MDRawHeader))) { + BPLOG(ERROR) << "Minidump cannot read header"; + return false; + } + + if (header_.signature != MD_HEADER_SIGNATURE) { + // The file may be byte-swapped. Under the present architecture, these + // classes don't know or need to know what CPU (or endianness) the + // minidump was produced on in order to parse it. Use the signature as + // a byte order marker. + u_int32_t signature_swapped = header_.signature; + Swap(&signature_swapped); + if (signature_swapped != MD_HEADER_SIGNATURE) { + // This isn't a minidump or a byte-swapped minidump. + BPLOG(ERROR) << "Minidump header signature mismatch: (" << + HexString(header_.signature) << ", " << + HexString(signature_swapped) << ") != " << + HexString(MD_HEADER_SIGNATURE); + return false; + } + swap_ = true; + } else { + // The file is not byte-swapped. Set swap_ false (it may have been true + // if the object is being reused?) + swap_ = false; + } + + BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") << + "byte-swapping minidump"; + + if (swap_) { + Swap(&header_.signature); + Swap(&header_.version); + Swap(&header_.stream_count); + Swap(&header_.stream_directory_rva); + Swap(&header_.checksum); + Swap(&header_.time_date_stamp); + Swap(&header_.flags); + } + + // Version check. The high 16 bits of header_.version contain something + // else "implementation specific." + if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) { + BPLOG(ERROR) << "Minidump version mismatch: " << + HexString(header_.version & 0x0000ffff) << " != " << + HexString(MD_HEADER_VERSION); + return false; + } + + if (!SeekSet(header_.stream_directory_rva)) { + BPLOG(ERROR) << "Minidump cannot seek to stream directory"; + return false; + } + + if (header_.stream_count > max_streams_) { + BPLOG(ERROR) << "Minidump stream count " << header_.stream_count << + " exceeds maximum " << max_streams_; + return false; + } + + if (header_.stream_count != 0) { + scoped_ptr directory( + new MinidumpDirectoryEntries(header_.stream_count)); + + // Read the entire array in one fell swoop, instead of reading one entry + // at a time in the loop. + if (!ReadBytes(&(*directory)[0], + sizeof(MDRawDirectory) * header_.stream_count)) { + BPLOG(ERROR) << "Minidump cannot read stream directory"; + return false; + } + + for (unsigned int stream_index = 0; + stream_index < header_.stream_count; + ++stream_index) { + MDRawDirectory* directory_entry = &(*directory)[stream_index]; + + if (swap_) { + Swap(&directory_entry->stream_type); + Swap(&directory_entry->location); + } + + // Initialize the stream_map_ map, which speeds locating a stream by + // type. + unsigned int stream_type = directory_entry->stream_type; + switch (stream_type) { + case MD_THREAD_LIST_STREAM: + case MD_MODULE_LIST_STREAM: + case MD_MEMORY_LIST_STREAM: + case MD_EXCEPTION_STREAM: + case MD_SYSTEM_INFO_STREAM: + case MD_MISC_INFO_STREAM: + case MD_BREAKPAD_INFO_STREAM: { + if (stream_map_->find(stream_type) != stream_map_->end()) { + // Another stream with this type was already found. A minidump + // file should contain at most one of each of these stream types. + BPLOG(ERROR) << "Minidump found multiple streams of type " << + stream_type << ", but can only deal with one"; + return false; + } + // Fall through to default + } + + default: { + // Overwrites for stream types other than those above, but it's + // expected to be the user's burden in that case. + (*stream_map_)[stream_type].stream_index = stream_index; + } + } + } + + directory_ = directory.release(); + } + + valid_ = true; + return true; +} + + +MinidumpThreadList* Minidump::GetThreadList() { + MinidumpThreadList* thread_list; + return GetStream(&thread_list); +} + + +MinidumpModuleList* Minidump::GetModuleList() { + MinidumpModuleList* module_list; + return GetStream(&module_list); +} + + +MinidumpMemoryList* Minidump::GetMemoryList() { + MinidumpMemoryList* memory_list; + return GetStream(&memory_list); +} + + +MinidumpException* Minidump::GetException() { + MinidumpException* exception; + return GetStream(&exception); +} + + +MinidumpSystemInfo* Minidump::GetSystemInfo() { + MinidumpSystemInfo* system_info; + return GetStream(&system_info); +} + + +MinidumpMiscInfo* Minidump::GetMiscInfo() { + MinidumpMiscInfo* misc_info; + return GetStream(&misc_info); +} + + +MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() { + MinidumpBreakpadInfo* breakpad_info; + return GetStream(&breakpad_info); +} + + +void Minidump::Print() { + if (!valid_) { + BPLOG(ERROR) << "Minidump cannot print invalid data"; + return; + } + + printf("MDRawHeader\n"); + printf(" signature = 0x%x\n", header_.signature); + printf(" version = 0x%x\n", header_.version); + printf(" stream_count = %d\n", header_.stream_count); + printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); + printf(" checksum = 0x%x\n", header_.checksum); + struct tm timestruct; + gmtime_r(reinterpret_cast(&header_.time_date_stamp), ×truct); + char timestr[20]; + strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); + printf(" time_date_stamp = 0x%x %s\n", header_.time_date_stamp, + timestr); + printf(" flags = 0x%" PRIx64 "\n", header_.flags); + printf("\n"); + + for (unsigned int stream_index = 0; + stream_index < header_.stream_count; + ++stream_index) { + MDRawDirectory* directory_entry = &(*directory_)[stream_index]; + + printf("mDirectory[%d]\n", stream_index); + printf("MDRawDirectory\n"); + printf(" stream_type = %d\n", directory_entry->stream_type); + printf(" location.data_size = %d\n", + directory_entry->location.data_size); + printf(" location.rva = 0x%x\n", directory_entry->location.rva); + printf("\n"); + } + + printf("Streams:\n"); + for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin(); + iterator != stream_map_->end(); + ++iterator) { + u_int32_t stream_type = iterator->first; + MinidumpStreamInfo info = iterator->second; + printf(" stream type 0x%x at index %d\n", stream_type, info.stream_index); + } + printf("\n"); +} + + +const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index) + const { + if (!valid_) { + BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex"; + return NULL; + } + + if (index >= header_.stream_count) { + BPLOG(ERROR) << "Minidump stream directory index out of range: " << + index << "/" << header_.stream_count; + return NULL; + } + + return &(*directory_)[index]; +} + + +bool Minidump::ReadBytes(void* bytes, size_t count) { + // Can't check valid_ because Read needs to call this method before + // validity can be determined. The only member that this method + // depends on is mFD, and an unset or invalid fd may generate an + // error but should not cause a crash. + ssize_t bytes_read = read(fd_, bytes, count); + if (static_cast(bytes_read) != count) { + if (bytes_read == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string; + } else { + BPLOG(ERROR) << "ReadBytes: read " << bytes_read << "/" << count; + } + return false; + } + return true; +} + + +bool Minidump::SeekSet(off_t offset) { + // Can't check valid_ because Read needs to call this method before + // validity can be determined. The only member that this method + // depends on is mFD, and an unset or invalid fd may generate an + // error but should not cause a crash. + off_t sought = lseek(fd_, offset, SEEK_SET); + if (sought != offset) { + if (sought == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string; + } else { + BPLOG(ERROR) << "SeekSet: sought " << sought << "/" << offset; + } + return false; + } + return true; +} + + +string* Minidump::ReadString(off_t offset) { + if (!valid_) { + BPLOG(ERROR) << "Invalid Minidump for ReadString"; + return NULL; + } + if (!SeekSet(offset)) { + BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; + return NULL; + } + + u_int32_t bytes; + if (!ReadBytes(&bytes, sizeof(bytes))) { + BPLOG(ERROR) << "ReadString could not read string size at offset " << + offset; + return NULL; + } + if (swap_) + Swap(&bytes); + + if (bytes % 2 != 0) { + BPLOG(ERROR) << "ReadString found odd-sized " << bytes << + "-byte string at offset " << offset; + return NULL; + } + unsigned int utf16_words = bytes / 2; + + if (utf16_words > max_string_length_) { + BPLOG(ERROR) << "ReadString string length " << utf16_words << + " exceeds maximum " << max_string_length_ << + " at offset " << offset; + return NULL; + } + + vector string_utf16(utf16_words); + + if (utf16_words) { + if (!ReadBytes(&string_utf16[0], bytes)) { + BPLOG(ERROR) << "ReadString could not read " << bytes << + "-byte string at offset " << offset; + return NULL; + } + } + + return UTF16ToUTF8(string_utf16, swap_); +} + + +bool Minidump::SeekToStreamType(u_int32_t stream_type, + u_int32_t* stream_length) { + BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires " + "|stream_length|"; + assert(stream_length); + *stream_length = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType"; + return false; + } + + MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type); + if (iterator == stream_map_->end()) { + // This stream type didn't exist in the directory. + BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present"; + return false; + } + + MinidumpStreamInfo info = iterator->second; + if (info.stream_index >= header_.stream_count) { + BPLOG(ERROR) << "SeekToStreamType: type " << stream_type << + " out of range: " << + info.stream_index << "/" << header_.stream_count; + return false; + } + + MDRawDirectory* directory_entry = &(*directory_)[info.stream_index]; + if (!SeekSet(directory_entry->location.rva)) { + BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " << + stream_type; + return false; + } + + *stream_length = directory_entry->location.data_size; + + return true; +} + + +template +T* Minidump::GetStream(T** stream) { + // stream is a garbage parameter that's present only to account for C++'s + // inability to overload a method based solely on its return type. + + const u_int32_t stream_type = T::kStreamType; + + BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type << + " requires |stream|"; + assert(stream); + *stream = NULL; + + if (!valid_) { + BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type; + return NULL; + } + + MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type); + if (iterator == stream_map_->end()) { + // This stream type didn't exist in the directory. + BPLOG(INFO) << "GetStream: type " << stream_type << " not present"; + return NULL; + } + + // Get a pointer so that the stored stream field can be altered. + MinidumpStreamInfo* info = &iterator->second; + + if (info->stream) { + // This cast is safe because info.stream is only populated by this + // method, and there is a direct correlation between T and stream_type. + *stream = static_cast(info->stream); + return *stream; + } + + u_int32_t stream_length; + if (!SeekToStreamType(stream_type, &stream_length)) { + BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type; + return NULL; + } + + scoped_ptr new_stream(new T(this)); + + if (!new_stream->Read(stream_length)) { + BPLOG(ERROR) << "GetStream could not read stream type " << stream_type; + return NULL; + } + + *stream = new_stream.release(); + info->stream = *stream; + return *stream; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_dump b/thirdparty/google-breakpad/r318/src/processor/minidump_dump new file mode 100644 index 00000000..579bf6bd Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/processor/minidump_dump differ diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_dump.cc b/thirdparty/google-breakpad/r318/src/processor/minidump_dump.cc new file mode 100644 index 00000000..12a699de --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_dump.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_dump.cc: Print the contents of a minidump file in somewhat +// readable text. +// +// Author: Mark Mentovai + +#include + +#include "google_breakpad/processor/minidump.h" +#include "processor/logging.h" + +namespace { + +using google_breakpad::Minidump; +using google_breakpad::MinidumpThreadList; +using google_breakpad::MinidumpModuleList; +using google_breakpad::MinidumpMemoryList; +using google_breakpad::MinidumpException; +using google_breakpad::MinidumpSystemInfo; +using google_breakpad::MinidumpMiscInfo; +using google_breakpad::MinidumpBreakpadInfo; + +static bool PrintMinidumpDump(const char *minidump_file) { + Minidump minidump(minidump_file); + if (!minidump.Read()) { + BPLOG(ERROR) << "minidump.Read() failed"; + return false; + } + minidump.Print(); + + int errors = 0; + + MinidumpThreadList *thread_list = minidump.GetThreadList(); + if (!thread_list) { + ++errors; + BPLOG(ERROR) << "minidump.GetThreadList() failed"; + } else { + thread_list->Print(); + } + + MinidumpModuleList *module_list = minidump.GetModuleList(); + if (!module_list) { + ++errors; + BPLOG(ERROR) << "minidump.GetModuleList() failed"; + } else { + module_list->Print(); + } + + MinidumpMemoryList *memory_list = minidump.GetMemoryList(); + if (!memory_list) { + ++errors; + BPLOG(ERROR) << "minidump.GetMemoryList() failed"; + } else { + memory_list->Print(); + } + + MinidumpException *exception = minidump.GetException(); + if (!exception) { + BPLOG(INFO) << "minidump.GetException() failed"; + } else { + exception->Print(); + } + + MinidumpSystemInfo *system_info = minidump.GetSystemInfo(); + if (!system_info) { + ++errors; + BPLOG(ERROR) << "minidump.GetSystemInfo() failed"; + } else { + system_info->Print(); + } + + MinidumpMiscInfo *misc_info = minidump.GetMiscInfo(); + if (!misc_info) { + ++errors; + BPLOG(ERROR) << "minidump.GetMiscInfo() failed"; + } else { + misc_info->Print(); + } + + MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo(); + if (!breakpad_info) { + // Breakpad info is optional, so don't treat this as an error. + BPLOG(INFO) << "minidump.GetBreakpadInfo() failed"; + } else { + breakpad_info->Print(); + } + + return errors == 0; +} + +} // namespace + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + + return PrintMinidumpDump(argv[1]) ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_dump_test b/thirdparty/google-breakpad/r318/src/processor/minidump_dump_test new file mode 100644 index 00000000..fb62ace7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_dump_test @@ -0,0 +1,36 @@ +#!/bin/sh + +# Copyright (c) 2006, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +testdata_dir=$srcdir/src/processor/testdata +./src/processor/minidump_dump $testdata_dir/minidump2.dmp | \ + tr -d '\015' | \ + diff -u $testdata_dir/minidump2.dump.out - +exit $? diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_processor.cc b/thirdparty/google-breakpad/r318/src/processor/minidump_processor.cc new file mode 100644 index 00000000..3c609170 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_processor.cc @@ -0,0 +1,992 @@ +// 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 + +#include "google_breakpad/processor/minidump_processor.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/process_state.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" +#include "processor/stackwalker_x86.h" + +namespace google_breakpad { + +MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : supplier_(supplier), resolver_(resolver) { +} + +MinidumpProcessor::~MinidumpProcessor() { +} + +MinidumpProcessor::ProcessResult MinidumpProcessor::Process( + const string &minidump_file, ProcessState *process_state) { + BPLOG(INFO) << "Processing minidump in file " << minidump_file; + + Minidump dump(minidump_file); + if (!dump.Read()) { + BPLOG(ERROR) << "Minidump " << minidump_file << " could not be read"; + return PROCESS_ERROR; + } + + process_state->Clear(); + + const MDRawHeader *header = dump.header(); + BPLOG_IF(ERROR, !header) << "Minidump " << minidump_file << " has no header"; + assert(header); + process_state->time_date_stamp_ = header->time_date_stamp; + + bool has_cpu_info = GetCPUInfo(&dump, &process_state->system_info_); + bool has_os_info = GetOSInfo(&dump, &process_state->system_info_); + + u_int32_t dump_thread_id = 0; + bool has_dump_thread = false; + u_int32_t requesting_thread_id = 0; + bool has_requesting_thread = false; + + MinidumpBreakpadInfo *breakpad_info = dump.GetBreakpadInfo(); + if (breakpad_info) { + has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); + has_requesting_thread = + breakpad_info->GetRequestingThreadID(&requesting_thread_id); + } + + MinidumpException *exception = dump.GetException(); + if (exception) { + process_state->crashed_ = true; + has_requesting_thread = exception->GetThreadID(&requesting_thread_id); + + process_state->crash_reason_ = GetCrashReason( + &dump, &process_state->crash_address_); + } + + MinidumpModuleList *module_list = dump.GetModuleList(); + + // Put a copy of the module list into ProcessState object. This is not + // necessarily a MinidumpModuleList, but it adheres to the CodeModules + // interface, which is all that ProcessState needs to expose. + if (module_list) + process_state->modules_ = module_list->Copy(); + + MinidumpThreadList *threads = dump.GetThreadList(); + if (!threads) { + BPLOG(ERROR) << "Minidump " << minidump_file << " has no thread list"; + return PROCESS_ERROR; + } + + BPLOG(INFO) << "Minidump " << minidump_file << " has " << + (has_cpu_info ? "" : "no ") << "CPU info, " << + (has_os_info ? "" : "no ") << "OS info, " << + (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << + (exception != NULL ? "" : "no ") << "exception, " << + (module_list != NULL ? "" : "no ") << "module list, " << + (threads != NULL ? "" : "no ") << "thread list, " << + (has_dump_thread ? "" : "no ") << "dump thread, and " << + (has_requesting_thread ? "" : "no ") << "requesting thread"; + + bool interrupted = false; + bool found_requesting_thread = false; + unsigned int thread_count = threads->thread_count(); + for (unsigned int thread_index = 0; + thread_index < thread_count; + ++thread_index) { + char thread_string_buffer[64]; + snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", + thread_index, thread_count); + string thread_string = minidump_file + ":" + thread_string_buffer; + + MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); + if (!thread) { + BPLOG(ERROR) << "Could not get thread for " << thread_string; + return PROCESS_ERROR; + } + + u_int32_t thread_id; + if (!thread->GetThreadID(&thread_id)) { + BPLOG(ERROR) << "Could not get thread ID for " << thread_string; + return PROCESS_ERROR; + } + + thread_string += " id " + HexString(thread_id); + BPLOG(INFO) << "Looking at thread " << thread_string; + + // If this thread is the thread that produced the minidump, don't process + // it. Because of the problems associated with a thread producing a + // dump of itself (when both its context and its stack are in flux), + // processing that stack wouldn't provide much useful data. + if (has_dump_thread && thread_id == dump_thread_id) { + continue; + } + + MinidumpContext *context = thread->GetContext(); + + if (has_requesting_thread && thread_id == requesting_thread_id) { + if (found_requesting_thread) { + // There can't be more than one requesting thread. + BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; + return PROCESS_ERROR; + } + + // Use processed_state->threads_.size() instead of thread_index. + // thread_index points to the thread index in the minidump, which + // might be greater than the thread index in the threads vector if + // any of the minidump's threads are skipped and not placed into the + // processed threads vector. The thread vector's current size will + // be the index of the current thread when it's pushed into the + // vector. + process_state->requesting_thread_ = process_state->threads_.size(); + + found_requesting_thread = true; + + if (process_state->crashed_) { + // Use the exception record's context for the crashed thread, instead + // of the thread's own context. For the crashed thread, the thread's + // own context is the state inside the exception handler. Using it + // would not result in the expected stack trace from the time of the + // crash. + context = exception->GetContext(); + } + } + + MinidumpMemoryRegion *thread_memory = thread->GetMemory(); + if (!thread_memory) { + BPLOG(ERROR) << "No memory region for " << thread_string; + return PROCESS_ERROR; + } + + // Use process_state->modules_ instead of module_list, because the + // |modules| argument will be used to populate the |module| fields in + // the returned StackFrame objects, which will be placed into the + // returned ProcessState object. module_list's lifetime is only as + // long as the Minidump object: it will be deleted when this function + // returns. process_state->modules_ is owned by the ProcessState object + // (just like the StackFrame objects), and is much more suitable for this + // task. + scoped_ptr stackwalker( + Stackwalker::StackwalkerForCPU(process_state->system_info(), + context, + thread_memory, + process_state->modules_, + supplier_, + resolver_)); + if (!stackwalker.get()) { + BPLOG(ERROR) << "No stackwalker for " << thread_string; + return PROCESS_ERROR; + } + + scoped_ptr stack(new CallStack()); + if (!stackwalker->Walk(stack.get())) { + BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " << + thread_string; + interrupted = true; + } + process_state->threads_.push_back(stack.release()); + } + + if (interrupted) { + BPLOG(INFO) << "Processing interrupted for " << minidump_file; + return PROCESS_INTERRUPTED; + } + + // If a requesting thread was indicated, it must be present. + if (has_requesting_thread && !found_requesting_thread) { + // Don't mark as an error, but invalidate the requesting thread + BPLOG(ERROR) << "Minidump indicated requesting thread " << + HexString(requesting_thread_id) << ", not found in " << + minidump_file; + process_state->requesting_thread_ = -1; + } + + BPLOG(INFO) << "Processed " << minidump_file; + return PROCESS_OK; +} + +// Returns the MDRawSystemInfo from a minidump, or NULL if system info is +// not available from the minidump. If system_info is non-NULL, it is used +// to pass back the MinidumpSystemInfo object. +static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, + MinidumpSystemInfo **system_info) { + MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); + if (!minidump_system_info) + return NULL; + + if (system_info) + *system_info = minidump_system_info; + + return minidump_system_info->system_info(); +} + +// static +bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { + assert(dump); + assert(info); + + info->cpu.clear(); + info->cpu_info.clear(); + + MinidumpSystemInfo *system_info; + const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); + if (!raw_system_info) + return false; + + switch (raw_system_info->processor_architecture) { + case MD_CPU_ARCHITECTURE_X86: + case MD_CPU_ARCHITECTURE_AMD64: { + if (raw_system_info->processor_architecture == + MD_CPU_ARCHITECTURE_X86) + info->cpu = "x86"; + else + info->cpu = "amd64"; + + const string *cpu_vendor = system_info->GetCPUVendor(); + if (cpu_vendor) { + info->cpu_info = *cpu_vendor; + info->cpu_info.append(" "); + } + + char x86_info[36]; + snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", + raw_system_info->processor_level, + raw_system_info->processor_revision >> 8, + raw_system_info->processor_revision & 0xff); + info->cpu_info.append(x86_info); + break; + } + + case MD_CPU_ARCHITECTURE_PPC: { + info->cpu = "ppc"; + break; + } + + case MD_CPU_ARCHITECTURE_SPARC: { + info->cpu = "sparc"; + break; + } + + default: { + // Assign the numeric architecture ID into the CPU string. + char cpu_string[7]; + snprintf(cpu_string, sizeof(cpu_string), "0x%04x", + raw_system_info->processor_architecture); + info->cpu = cpu_string; + break; + } + } + + info->cpu_count = raw_system_info->number_of_processors; + + return true; +} + +// static +bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { + assert(dump); + assert(info); + + info->os.clear(); + info->os_short.clear(); + info->os_version.clear(); + + MinidumpSystemInfo *system_info; + const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); + if (!raw_system_info) + return false; + + info->os_short = system_info->GetOS(); + + switch (raw_system_info->platform_id) { + case MD_OS_WIN32_NT: { + info->os = "Windows NT"; + break; + } + + case MD_OS_WIN32_WINDOWS: { + info->os = "Windows"; + break; + } + + case MD_OS_MAC_OS_X: { + info->os = "Mac OS X"; + break; + } + + case MD_OS_LINUX: { + info->os = "Linux"; + break; + } + + case MD_OS_SOLARIS: { + info->os = "Solaris"; + break; + } + + default: { + // Assign the numeric platform ID into the OS string. + char os_string[11]; + snprintf(os_string, sizeof(os_string), "0x%08x", + raw_system_info->platform_id); + info->os = os_string; + break; + } + } + + char os_version_string[33]; + snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", + raw_system_info->major_version, + raw_system_info->minor_version, + raw_system_info->build_number); + info->os_version = os_version_string; + + const string *csd_version = system_info->GetCSDVersion(); + if (csd_version) { + info->os_version.append(" "); + info->os_version.append(*csd_version); + } + + return true; +} + +// static +string MinidumpProcessor::GetCrashReason(Minidump *dump, u_int64_t *address) { + MinidumpException *exception = dump->GetException(); + if (!exception) + return ""; + + const MDRawExceptionStream *raw_exception = exception->exception(); + if (!raw_exception) + return ""; + + if (address) + *address = raw_exception->exception_record.exception_address; + + // The reason value is OS-specific and possibly CPU-specific. Set up + // sensible numeric defaults for the reason string in case we can't + // map the codes to a string (because there's no system info, or because + // it's an unrecognized platform, or because it's an unrecognized code.) + char reason_string[24]; + u_int32_t exception_code = raw_exception->exception_record.exception_code; + u_int32_t exception_flags = raw_exception->exception_record.exception_flags; + snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x", + exception_code, exception_flags); + string reason = reason_string; + + const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL); + if (!raw_system_info) + return reason; + + switch (raw_system_info->platform_id) { + case MD_OS_MAC_OS_X: { + char flags_string[11]; + snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags); + switch (exception_code) { + case MD_EXCEPTION_MAC_BAD_ACCESS: + reason = "EXC_BAD_ACCESS / "; + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS: + reason.append("KERN_INVALID_ADDRESS"); + break; + case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE: + reason.append("KERN_PROTECTION_FAILURE"); + break; + case MD_EXCEPTION_CODE_MAC_NO_ACCESS: + reason.append("KERN_NO_ACCESS"); + break; + case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE: + reason.append("KERN_MEMORY_FAILURE"); + break; + case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR: + reason.append("KERN_MEMORY_ERROR"); + break; + // These are ppc only but shouldn't be a problem as they're + // unused on x86 + case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ: + reason.append("EXC_PPC_VM_PROT_READ"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE: + reason.append("EXC_PPC_BADSPACE"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED: + reason.append("EXC_PPC_UNALIGNED"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + case MD_EXCEPTION_MAC_BAD_INSTRUCTION: + reason = "EXC_BAD_INSTRUCTION / "; + switch (raw_system_info->processor_architecture) { + case MD_CPU_ARCHITECTURE_PPC: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL: + reason.append("EXC_PPC_INVALID_SYSCALL"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION: + reason.append("EXC_PPC_UNIPL_INST"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION: + reason.append("EXC_PPC_PRIVINST"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER: + reason.append("EXC_PPC_PRIVREG"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_TRACE: + reason.append("EXC_PPC_TRACE"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR: + reason.append("EXC_PPC_PERFMON"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + case MD_CPU_ARCHITECTURE_X86: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION: + reason.append("EXC_I386_INVOP"); + break; + case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT: + reason.append("EXC_INVTSSFLT"); + break; + case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT: + reason.append("EXC_SEGNPFLT"); + break; + case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT: + reason.append("EXC_STKFLT"); + break; + case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: + reason.append("EXC_GPFLT"); + break; + case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT: + reason.append("EXC_ALIGNFLT"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + case MD_EXCEPTION_MAC_ARITHMETIC: + reason = "EXC_ARITHMETIC / "; + switch (raw_system_info->processor_architecture) { + case MD_CPU_ARCHITECTURE_PPC: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW: + reason.append("EXC_PPC_OVERFLOW"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE: + reason.append("EXC_PPC_ZERO_DIVIDE"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT: + reason.append("EXC_FLT_INEXACT"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE: + reason.append("EXC_PPC_FLT_ZERO_DIVIDE"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW: + reason.append("EXC_PPC_FLT_UNDERFLOW"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW: + reason.append("EXC_PPC_FLT_OVERFLOW"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER: + reason.append("EXC_PPC_FLT_NOT_A_NUMBER"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION: + reason.append("EXC_PPC_NOEMULATION"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST: + reason.append("EXC_PPC_ALTIVECASSIST"); + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + case MD_CPU_ARCHITECTURE_X86: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_X86_DIV: + reason.append("EXC_I386_DIV"); + break; + case MD_EXCEPTION_CODE_MAC_X86_INTO: + reason.append("EXC_I386_INTO"); + break; + case MD_EXCEPTION_CODE_MAC_X86_NOEXT: + reason.append("EXC_I386_NOEXT"); + break; + case MD_EXCEPTION_CODE_MAC_X86_EXTOVR: + reason.append("EXC_I386_EXTOVR"); + break; + case MD_EXCEPTION_CODE_MAC_X86_EXTERR: + reason.append("EXC_I386_EXTERR"); + break; + case MD_EXCEPTION_CODE_MAC_X86_EMERR: + reason.append("EXC_I386_EMERR"); + break; + case MD_EXCEPTION_CODE_MAC_X86_BOUND: + reason.append("EXC_I386_BOUND"); + break; + case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR: + reason.append("EXC_I386_SSEEXTERR"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + case MD_EXCEPTION_MAC_EMULATION: + reason = "EXC_EMULATION / "; + reason.append(flags_string); + break; + case MD_EXCEPTION_MAC_SOFTWARE: + reason = "EXC_SOFTWARE / "; + switch (exception_flags) { + // These are ppc only but shouldn't be a problem as they're + // unused on x86 + case MD_EXCEPTION_CODE_MAC_PPC_TRAP: + reason.append("EXC_PPC_TRAP"); + break; + case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE: + reason.append("EXC_PPC_MIGRATE"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + case MD_EXCEPTION_MAC_BREAKPOINT: + reason = "EXC_BREAKPOINT / "; + switch (raw_system_info->processor_architecture) { + case MD_CPU_ARCHITECTURE_PPC: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT: + reason.append("EXC_PPC_BREAKPOINT"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + case MD_CPU_ARCHITECTURE_X86: { + switch (exception_flags) { + case MD_EXCEPTION_CODE_MAC_X86_SGL: + reason.append("EXC_I386_SGL"); + break; + case MD_EXCEPTION_CODE_MAC_X86_BPT: + reason.append("EXC_I386_BPT"); + break; + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + default: + reason.append(flags_string); + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + case MD_EXCEPTION_MAC_SYSCALL: + reason = "EXC_SYSCALL / "; + reason.append(flags_string); + break; + case MD_EXCEPTION_MAC_MACH_SYSCALL: + reason = "EXC_MACH_SYSCALL / "; + reason.append(flags_string); + break; + case MD_EXCEPTION_MAC_RPC_ALERT: + reason = "EXC_RPC_ALERT / "; + reason.append(flags_string); + break; + } + break; + } + + case MD_OS_WIN32_NT: + case MD_OS_WIN32_WINDOWS: { + switch (exception_code) { + case MD_EXCEPTION_CODE_WIN_CONTROL_C: + reason = "DBG_CONTROL_C"; + break; + case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: + reason = "EXCEPTION_GUARD_PAGE"; + break; + case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT: + reason = "EXCEPTION_DATATYPE_MISALIGNMENT"; + break; + case MD_EXCEPTION_CODE_WIN_BREAKPOINT: + reason = "EXCEPTION_BREAKPOINT"; + break; + case MD_EXCEPTION_CODE_WIN_SINGLE_STEP: + reason = "EXCEPTION_SINGLE_STEP"; + break; + case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: + // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that + // caused the fault in exception_information[1]. + // exception_information[0] is 0 if the violation was caused by + // an attempt to read data and 1 if it was an attempt to write + // data. + // This information is useful in addition to the code address, which + // will be present in the crash thread's instruction field anyway. + reason = "EXCEPTION_ACCESS_VIOLATION"; + if (address && + raw_exception->exception_record.number_parameters >= 2) { + *address = + raw_exception->exception_record.exception_information[1]; + } + break; + case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: + reason = "EXCEPTION_IN_PAGE_ERROR"; + break; + case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE: + reason = "EXCEPTION_INVALID_HANDLE"; + break; + case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: + reason = "EXCEPTION_ILLEGAL_INSTRUCTION"; + break; + case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: + reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + break; + case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: + reason = "EXCEPTION_INVALID_DISPOSITION"; + break; + case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED: + reason = "EXCEPTION_BOUNDS_EXCEEDED"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND: + reason = "EXCEPTION_FLT_DENORMAL_OPERAND"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: + reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: + reason = "EXCEPTION_FLT_INEXACT_RESULT"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: + reason = "EXCEPTION_FLT_INVALID_OPERATION"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: + reason = "EXCEPTION_FLT_OVERFLOW"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK: + reason = "EXCEPTION_FLT_STACK_CHECK"; + break; + case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: + reason = "EXCEPTION_FLT_UNDERFLOW"; + break; + case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: + reason = "EXCEPTION_INT_DIVIDE_BY_ZERO"; + break; + case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: + reason = "EXCEPTION_INT_OVERFLOW"; + break; + case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: + reason = "EXCEPTION_PRIV_INSTRUCTION"; + break; + case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: + reason = "EXCEPTION_STACK_OVERFLOW"; + break; + case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: + reason = "EXCEPTION_POSSIBLE_DEADLOCK"; + break; + default: + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + + case MD_OS_LINUX: { + switch (exception_code) { + case MD_EXCEPTION_CODE_LIN_SIGHUP: + reason = "SIGHUP"; + break; + case MD_EXCEPTION_CODE_LIN_SIGINT: + reason = "SIGINT"; + break; + case MD_EXCEPTION_CODE_LIN_SIGQUIT: + reason = "SIGQUIT"; + break; + case MD_EXCEPTION_CODE_LIN_SIGILL: + reason = "SIGILL"; + break; + case MD_EXCEPTION_CODE_LIN_SIGTRAP: + reason = "SIGTRAP"; + break; + case MD_EXCEPTION_CODE_LIN_SIGABRT: + reason = "SIGABRT"; + break; + case MD_EXCEPTION_CODE_LIN_SIGBUS: + reason = "SIGBUS"; + break; + case MD_EXCEPTION_CODE_LIN_SIGFPE: + reason = "SIGFPE"; + break; + case MD_EXCEPTION_CODE_LIN_SIGKILL: + reason = "SIGKILL"; + break; + case MD_EXCEPTION_CODE_LIN_SIGUSR1: + reason = "SIGUSR1"; + break; + case MD_EXCEPTION_CODE_LIN_SIGSEGV: + reason = "SIGSEGV"; + break; + case MD_EXCEPTION_CODE_LIN_SIGUSR2: + reason = "SIGUSR2"; + break; + case MD_EXCEPTION_CODE_LIN_SIGPIPE: + reason = "SIGPIPE"; + break; + case MD_EXCEPTION_CODE_LIN_SIGALRM: + reason = "SIGALRM"; + break; + case MD_EXCEPTION_CODE_LIN_SIGTERM: + reason = "SIGTERM"; + break; + case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: + reason = "SIGSTKFLT"; + break; + case MD_EXCEPTION_CODE_LIN_SIGCHLD: + reason = "SIGCHLD"; + break; + case MD_EXCEPTION_CODE_LIN_SIGCONT: + reason = "SIGCONT"; + break; + case MD_EXCEPTION_CODE_LIN_SIGSTOP: + reason = "SIGSTOP"; + break; + case MD_EXCEPTION_CODE_LIN_SIGTSTP: + reason = "SIGTSTP"; + break; + case MD_EXCEPTION_CODE_LIN_SIGTTIN: + reason = "SIGTTIN"; + break; + case MD_EXCEPTION_CODE_LIN_SIGTTOU: + reason = "SIGTTOU"; + break; + case MD_EXCEPTION_CODE_LIN_SIGURG: + reason = "SIGURG"; + break; + case MD_EXCEPTION_CODE_LIN_SIGXCPU: + reason = "SIGXCPU"; + break; + case MD_EXCEPTION_CODE_LIN_SIGXFSZ: + reason = "SIGXFSZ"; + break; + case MD_EXCEPTION_CODE_LIN_SIGVTALRM: + reason = "SIGVTALRM"; + break; + case MD_EXCEPTION_CODE_LIN_SIGPROF: + reason = "SIGPROF"; + break; + case MD_EXCEPTION_CODE_LIN_SIGWINCH: + reason = "SIGWINCH"; + break; + case MD_EXCEPTION_CODE_LIN_SIGIO: + reason = "SIGIO"; + break; + case MD_EXCEPTION_CODE_LIN_SIGPWR: + reason = "SIGPWR"; + break; + case MD_EXCEPTION_CODE_LIN_SIGSYS: + reason = "SIGSYS"; + break; + default: + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + + case MD_OS_SOLARIS: { + switch (exception_code) { + case MD_EXCEPTION_CODE_SOL_SIGHUP: + reason = "SIGHUP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGINT: + reason = "SIGINT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGQUIT: + reason = "SIGQUIT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGILL: + reason = "SIGILL"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTRAP: + reason = "SIGTRAP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGIOT: + reason = "SIGIOT | SIGABRT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGEMT: + reason = "SIGEMT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGFPE: + reason = "SIGFPE"; + break; + case MD_EXCEPTION_CODE_SOL_SIGKILL: + reason = "SIGKILL"; + break; + case MD_EXCEPTION_CODE_SOL_SIGBUS: + reason = "SIGBUS"; + break; + case MD_EXCEPTION_CODE_SOL_SIGSEGV: + reason = "SIGSEGV"; + break; + case MD_EXCEPTION_CODE_SOL_SIGSYS: + reason = "SIGSYS"; + break; + case MD_EXCEPTION_CODE_SOL_SIGPIPE: + reason = "SIGPIPE"; + break; + case MD_EXCEPTION_CODE_SOL_SIGALRM: + reason = "SIGALRM"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTERM: + reason = "SIGTERM"; + break; + case MD_EXCEPTION_CODE_SOL_SIGUSR1: + reason = "SIGUSR1"; + break; + case MD_EXCEPTION_CODE_SOL_SIGUSR2: + reason = "SIGUSR2"; + break; + case MD_EXCEPTION_CODE_SOL_SIGCLD: + reason = "SIGCLD | SIGCHLD"; + break; + case MD_EXCEPTION_CODE_SOL_SIGPWR: + reason = "SIGPWR"; + break; + case MD_EXCEPTION_CODE_SOL_SIGWINCH: + reason = "SIGWINCH"; + break; + case MD_EXCEPTION_CODE_SOL_SIGURG: + reason = "SIGURG"; + break; + case MD_EXCEPTION_CODE_SOL_SIGPOLL: + reason = "SIGPOLL | SIGIO"; + break; + case MD_EXCEPTION_CODE_SOL_SIGSTOP: + reason = "SIGSTOP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTSTP: + reason = "SIGTSTP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGCONT: + reason = "SIGCONT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTTIN: + reason = "SIGTTIN"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTTOU: + reason = "SIGTTOU"; + break; + case MD_EXCEPTION_CODE_SOL_SIGVTALRM: + reason = "SIGVTALRM"; + break; + case MD_EXCEPTION_CODE_SOL_SIGPROF: + reason = "SIGPROF"; + break; + case MD_EXCEPTION_CODE_SOL_SIGXCPU: + reason = "SIGXCPU"; + break; + case MD_EXCEPTION_CODE_SOL_SIGXFSZ: + reason = "SIGXFSZ"; + break; + case MD_EXCEPTION_CODE_SOL_SIGWAITING: + reason = "SIGWAITING"; + break; + case MD_EXCEPTION_CODE_SOL_SIGLWP: + reason = "SIGLWP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGFREEZE: + reason = "SIGFREEZE"; + break; + case MD_EXCEPTION_CODE_SOL_SIGTHAW: + reason = "SIGTHAW"; + break; + case MD_EXCEPTION_CODE_SOL_SIGCANCEL: + reason = "SIGCANCEL"; + break; + case MD_EXCEPTION_CODE_SOL_SIGLOST: + reason = "SIGLOST"; + break; + case MD_EXCEPTION_CODE_SOL_SIGXRES: + reason = "SIGXRES"; + break; + case MD_EXCEPTION_CODE_SOL_SIGJVM1: + reason = "SIGJVM1"; + break; + case MD_EXCEPTION_CODE_SOL_SIGJVM2: + reason = "SIGJVM2"; + break; + default: + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + + default: { + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + } + + return reason; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_processor_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/minidump_processor_unittest.cc new file mode 100644 index 00000000..bf8a8989 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_processor_unittest.cc @@ -0,0 +1,239 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Unit test for MinidumpProcessor. Uses a pre-generated minidump and +// corresponding symbol file, and checks the stack frames for correctness. + +#include +#include +#include +#include +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/minidump_processor.h" +#include "google_breakpad/processor/process_state.h" +#include "google_breakpad/processor/stack_frame.h" +#include "google_breakpad/processor/symbol_supplier.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" + +namespace { + +using std::string; +using google_breakpad::BasicSourceLineResolver; +using google_breakpad::CallStack; +using google_breakpad::CodeModule; +using google_breakpad::MinidumpProcessor; +using google_breakpad::ProcessState; +using google_breakpad::scoped_ptr; +using google_breakpad::SymbolSupplier; +using google_breakpad::SystemInfo; + +static const char *kSystemInfoOS = "Windows NT"; +static const char *kSystemInfoOSShort = "windows"; +static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2"; +static const char *kSystemInfoCPU = "x86"; +static const char *kSystemInfoCPUInfo = + "GenuineIntel family 6 model 13 stepping 8"; + +#define ASSERT_TRUE(cond) \ + if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + return false; \ + } + +#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond)) + +#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) + +// Use ASSERT_*_ABORT in functions that can't return a boolean. +#define ASSERT_TRUE_ABORT(cond) \ + if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + abort(); \ + } + +#define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2)) + +class TestSymbolSupplier : public SymbolSupplier { + public: + TestSymbolSupplier() : interrupt_(false) {} + + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data); + + // When set to true, causes the SymbolSupplier to return INTERRUPT + void set_interrupt(bool interrupt) { interrupt_ = interrupt; } + + private: + bool interrupt_; +}; + +SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( + const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) { + ASSERT_TRUE_ABORT(module); + ASSERT_TRUE_ABORT(system_info); + ASSERT_EQ_ABORT(system_info->cpu, kSystemInfoCPU); + ASSERT_EQ_ABORT(system_info->cpu_info, kSystemInfoCPUInfo); + ASSERT_EQ_ABORT(system_info->os, kSystemInfoOS); + ASSERT_EQ_ABORT(system_info->os_short, kSystemInfoOSShort); + ASSERT_EQ_ABORT(system_info->os_version, kSystemInfoOSVersion); + + if (interrupt_) { + return INTERRUPT; + } + + if (module && module->code_file() == "c:\\test_app.exe") { + *symbol_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/processor/testdata/symbols/test_app.pdb/" + + module->debug_identifier() + + "/test_app.sym"; + return FOUND; + } + + return NOT_FOUND; +} + +SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( + const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data) { + SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, + symbol_file); + if (s == FOUND) { + std::ifstream in(symbol_file->c_str()); + std::getline(in, *symbol_data, std::string::traits_type::to_char_type( + std::string::traits_type::eof())); + in.close(); + } + + return s; +} + +static bool RunTests() { + TestSymbolSupplier supplier; + BasicSourceLineResolver resolver; + MinidumpProcessor processor(&supplier, &resolver); + + string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/processor/testdata/minidump2.dmp"; + + ProcessState state; + ASSERT_EQ(processor.Process(minidump_file, &state), + MinidumpProcessor::PROCESS_OK); + ASSERT_EQ(state.system_info()->os, kSystemInfoOS); + ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort); + ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion); + ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU); + ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo); + ASSERT_TRUE(state.crashed()); + ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION"); + ASSERT_EQ(state.crash_address(), 0x45); + ASSERT_EQ(state.threads()->size(), 1); + ASSERT_EQ(state.requesting_thread(), 0); + + CallStack *stack = state.threads()->at(0); + ASSERT_TRUE(stack); + ASSERT_EQ(stack->frames()->size(), 4); + + ASSERT_TRUE(stack->frames()->at(0)->module); + ASSERT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000); + ASSERT_EQ(stack->frames()->at(0)->module->code_file(), "c:\\test_app.exe"); + ASSERT_EQ(stack->frames()->at(0)->function_name, + "`anonymous namespace'::CrashFunction"); + ASSERT_EQ(stack->frames()->at(0)->source_file_name, "c:\\test_app.cc"); + ASSERT_EQ(stack->frames()->at(0)->source_line, 58); + + ASSERT_TRUE(stack->frames()->at(1)->module); + ASSERT_EQ(stack->frames()->at(1)->module->base_address(), 0x400000); + ASSERT_EQ(stack->frames()->at(1)->module->code_file(), "c:\\test_app.exe"); + ASSERT_EQ(stack->frames()->at(1)->function_name, "main"); + ASSERT_EQ(stack->frames()->at(1)->source_file_name, "c:\\test_app.cc"); + ASSERT_EQ(stack->frames()->at(1)->source_line, 65); + + // This comes from the CRT + ASSERT_TRUE(stack->frames()->at(2)->module); + ASSERT_EQ(stack->frames()->at(2)->module->base_address(), 0x400000); + ASSERT_EQ(stack->frames()->at(2)->module->code_file(), "c:\\test_app.exe"); + ASSERT_EQ(stack->frames()->at(2)->function_name, "__tmainCRTStartup"); + ASSERT_EQ(stack->frames()->at(2)->source_file_name, + "f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c"); + ASSERT_EQ(stack->frames()->at(2)->source_line, 327); + + // No debug info available for kernel32.dll + ASSERT_TRUE(stack->frames()->at(3)->module); + ASSERT_EQ(stack->frames()->at(3)->module->base_address(), 0x7c800000); + ASSERT_EQ(stack->frames()->at(3)->module->code_file(), + "C:\\WINDOWS\\system32\\kernel32.dll"); + ASSERT_TRUE(stack->frames()->at(3)->function_name.empty()); + ASSERT_TRUE(stack->frames()->at(3)->source_file_name.empty()); + ASSERT_EQ(stack->frames()->at(3)->source_line, 0); + + ASSERT_EQ(state.modules()->module_count(), 13); + ASSERT_TRUE(state.modules()->GetMainModule()); + ASSERT_EQ(state.modules()->GetMainModule()->code_file(), "c:\\test_app.exe"); + ASSERT_FALSE(state.modules()->GetModuleForAddress(0)); + ASSERT_EQ(state.modules()->GetMainModule(), + state.modules()->GetModuleForAddress(0x400000)); + ASSERT_EQ(state.modules()->GetModuleForAddress(0x7c801234)->debug_file(), + "kernel32.pdb"); + ASSERT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(), + "5.1.2600.2622"); + + // Test that the symbol supplier can interrupt processing + state.Clear(); + supplier.set_interrupt(true); + ASSERT_EQ(processor.Process(minidump_file, &state), + MinidumpProcessor::PROCESS_INTERRUPTED); + + return true; +} + +} // namespace + +int main(int argc, char *argv[]) { + BPLOG_INIT(&argc, &argv); + + if (!RunTests()) { + return 1; + } + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk new file mode 100644 index 00000000..58877867 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk differ diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk.cc b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk.cc new file mode 100644 index 00000000..05d9641f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk.cc @@ -0,0 +1,508 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_stackwalk.cc: Process a minidump with MinidumpProcessor, printing +// the results, including stack traces. +// +// Author: Mark Mentovai + +#include +#include +#include +#include + +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/minidump_processor.h" +#include "google_breakpad/processor/process_state.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/logging.h" +#include "processor/pathname_stripper.h" +#include "processor/scoped_ptr.h" +#include "processor/simple_symbol_supplier.h" + +namespace { + +using std::string; +using std::vector; +using google_breakpad::BasicSourceLineResolver; +using google_breakpad::CallStack; +using google_breakpad::CodeModule; +using google_breakpad::CodeModules; +using google_breakpad::MinidumpModule; +using google_breakpad::MinidumpProcessor; +using google_breakpad::PathnameStripper; +using google_breakpad::ProcessState; +using google_breakpad::scoped_ptr; +using google_breakpad::SimpleSymbolSupplier; +using google_breakpad::StackFrame; +using google_breakpad::StackFramePPC; +using google_breakpad::StackFrameSPARC; +using google_breakpad::StackFrameX86; +using google_breakpad::StackFrameAMD64; + +// Separator character for machine readable output. +static const char kOutputSeparator = '|'; + +// PrintRegister prints a register's name and value to stdout. It will +// print four registers on a line. For the first register in a set, +// pass 0 for |sequence|. For registers in a set, pass the most recent +// return value of PrintRegister. Note that PrintRegister will print a +// newline before the first register (with |sequence| set to 0) is printed. +// The caller is responsible for printing the final newline after a set +// of registers is completely printed, regardless of the number of calls +// to PrintRegister. +static int PrintRegister(const char *name, u_int32_t value, int sequence) { + if (sequence % 4 == 0) { + printf("\n "); + } + printf(" %5s = 0x%08x", name, value); + return ++sequence; +} + +// StripSeparator takes a string |original| and returns a copy +// of the string with all occurences of |kOutputSeparator| removed. +static string StripSeparator(const string &original) { + string result = original; + string::size_type position = 0; + while ((position = result.find(kOutputSeparator, position)) != string::npos) { + result.erase(position, 1); + } + return result; +} + +// PrintStack prints the call stack in |stack| to stdout, in a reasonably +// useful form. Module, function, and source file names are displayed if +// they are available. The code offset to the base code address of the +// source line, function, or module is printed, preferring them in that +// order. If no source line, function, or module information is available, +// an absolute code offset is printed. +// +// If |cpu| is a recognized CPU name, relevant register state for each stack +// frame printed is also output, if available. +static void PrintStack(const CallStack *stack, const string &cpu) { + int frame_count = stack->frames()->size(); + for (int frame_index = 0; frame_index < frame_count; ++frame_index) { + const StackFrame *frame = stack->frames()->at(frame_index); + printf("%2d ", frame_index); + + if (frame->module) { + printf("%s", PathnameStripper::File(frame->module->code_file()).c_str()); + if (!frame->function_name.empty()) { + printf("!%s", frame->function_name.c_str()); + if (!frame->source_file_name.empty()) { + string source_file = PathnameStripper::File(frame->source_file_name); + printf(" [%s : %d + 0x%" PRIx64 "]", + source_file.c_str(), + frame->source_line, + frame->instruction - frame->source_line_base); + } else { + printf(" + 0x%" PRIx64, frame->instruction - frame->function_base); + } + } else { + printf(" + 0x%" PRIx64, + frame->instruction - frame->module->base_address()); + } + } else { + printf("0x%" PRIx64, frame->instruction); + } + + int sequence = 0; + if (cpu == "x86") { + const StackFrameX86 *frame_x86 = + reinterpret_cast(frame); + + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP) + sequence = PrintRegister("eip", frame_x86->context.eip, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) + sequence = PrintRegister("esp", frame_x86->context.esp, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP) + sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX) + sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI) + sequence = PrintRegister("esi", frame_x86->context.esi, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI) + sequence = PrintRegister("edi", frame_x86->context.edi, sequence); + if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) { + sequence = PrintRegister("eax", frame_x86->context.eax, sequence); + sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence); + sequence = PrintRegister("edx", frame_x86->context.edx, sequence); + sequence = PrintRegister("efl", frame_x86->context.eflags, sequence); + } + } else if (cpu == "ppc") { + const StackFramePPC *frame_ppc = + reinterpret_cast(frame); + + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0) + sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence); + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1) + sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence); + } else if (cpu == "amd64") { + const StackFrameAMD64 *frame_amd64 = + reinterpret_cast(frame); + + if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP) + sequence = PrintRegister("rip", frame_amd64->context.rip, sequence); + if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) + sequence = PrintRegister("rsp", frame_amd64->context.rsp, sequence); + if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) + sequence = PrintRegister("rbp", frame_amd64->context.rbp, sequence); + } else if (cpu == "sparc") { + const StackFrameSPARC *frame_sparc = + reinterpret_cast(frame); + + if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP) + sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence); + if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP) + sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence); + if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC) + sequence = PrintRegister("pc", frame_sparc->context.pc, sequence); + } + printf("\n"); + } +} + +// PrintStackMachineReadable prints the call stack in |stack| to stdout, +// in the following machine readable pipe-delimited text format: +// thread number|frame number|module|function|source file|line|offset +// +// Module, function, source file, and source line may all be empty +// depending on availability. The code offset follows the same rules as +// PrintStack above. +static void PrintStackMachineReadable(int thread_num, const CallStack *stack) { + int frame_count = stack->frames()->size(); + for (int frame_index = 0; frame_index < frame_count; ++frame_index) { + const StackFrame *frame = stack->frames()->at(frame_index); + printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index, + kOutputSeparator); + + if (frame->module) { + assert(!frame->module->code_file().empty()); + printf("%s", StripSeparator(PathnameStripper::File( + frame->module->code_file())).c_str()); + if (!frame->function_name.empty()) { + printf("%c%s", kOutputSeparator, + StripSeparator(frame->function_name).c_str()); + if (!frame->source_file_name.empty()) { + printf("%c%s%c%d%c0x%" PRIx64, + kOutputSeparator, + StripSeparator(frame->source_file_name).c_str(), + kOutputSeparator, + frame->source_line, + kOutputSeparator, + frame->instruction - frame->source_line_base); + } else { + printf("%c%c%c0x%" PRIx64, + kOutputSeparator, // empty source file + kOutputSeparator, // empty source line + kOutputSeparator, + frame->instruction - frame->function_base); + } + } else { + printf("%c%c%c%c0x%" PRIx64, + kOutputSeparator, // empty function name + kOutputSeparator, // empty source file + kOutputSeparator, // empty source line + kOutputSeparator, + frame->instruction - frame->module->base_address()); + } + } else { + // the printf before this prints a trailing separator for module name + printf("%c%c%c%c0x%" PRIx64, + kOutputSeparator, // empty function name + kOutputSeparator, // empty source file + kOutputSeparator, // empty source line + kOutputSeparator, + frame->instruction); + } + printf("\n"); + } +} + +static void PrintModules(const CodeModules *modules) { + if (!modules) + return; + + printf("\n"); + printf("Loaded modules:\n"); + + u_int64_t main_address = 0; + const CodeModule *main_module = modules->GetMainModule(); + if (main_module) { + main_address = main_module->base_address(); + } + + unsigned int module_count = modules->module_count(); + for (unsigned int module_sequence = 0; + module_sequence < module_count; + ++module_sequence) { + const CodeModule *module = modules->GetModuleAtSequence(module_sequence); + u_int64_t base_address = module->base_address(); + printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s\n", + base_address, base_address + module->size() - 1, + PathnameStripper::File(module->code_file()).c_str(), + module->version().empty() ? "???" : module->version().c_str(), + main_module != NULL && base_address == main_address ? + " (main)" : ""); + } +} + +// PrintModulesMachineReadable outputs a list of loaded modules, +// one per line, in the following machine-readable pipe-delimited +// text format: +// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}| +// {Base Address}|{Max Address}|{Main} +static void PrintModulesMachineReadable(const CodeModules *modules) { + if (!modules) + return; + + u_int64_t main_address = 0; + const CodeModule *main_module = modules->GetMainModule(); + if (main_module) { + main_address = main_module->base_address(); + } + + unsigned int module_count = modules->module_count(); + for (unsigned int module_sequence = 0; + module_sequence < module_count; + ++module_sequence) { + const CodeModule *module = modules->GetModuleAtSequence(module_sequence); + u_int64_t base_address = module->base_address(); + printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n", + kOutputSeparator, + StripSeparator(PathnameStripper::File(module->code_file())).c_str(), + kOutputSeparator, StripSeparator(module->version()).c_str(), + kOutputSeparator, + StripSeparator(PathnameStripper::File(module->debug_file())).c_str(), + kOutputSeparator, + StripSeparator(module->debug_identifier()).c_str(), + kOutputSeparator, base_address, + kOutputSeparator, base_address + module->size() - 1, + kOutputSeparator, + main_module != NULL && base_address == main_address ? 1 : 0); + } +} + +static void PrintProcessState(const ProcessState& process_state) { + // Print OS and CPU information. + string cpu = process_state.system_info()->cpu; + string cpu_info = process_state.system_info()->cpu_info; + printf("Operating system: %s\n", process_state.system_info()->os.c_str()); + printf(" %s\n", + process_state.system_info()->os_version.c_str()); + printf("CPU: %s\n", cpu.c_str()); + if (!cpu_info.empty()) { + // This field is optional. + printf(" %s\n", cpu_info.c_str()); + } + printf(" %d CPU%s\n", + process_state.system_info()->cpu_count, + process_state.system_info()->cpu_count != 1 ? "s" : ""); + printf("\n"); + + // Print crash information. + if (process_state.crashed()) { + printf("Crash reason: %s\n", process_state.crash_reason().c_str()); + printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address()); + } else { + printf("No crash\n"); + } + + // If the thread that requested the dump is known, print it first. + int requesting_thread = process_state.requesting_thread(); + if (requesting_thread != -1) { + printf("\n"); + printf("Thread %d (%s)\n", + requesting_thread, + process_state.crashed() ? "crashed" : + "requested dump, did not crash"); + PrintStack(process_state.threads()->at(requesting_thread), cpu); + } + + // Print all of the threads in the dump. + int thread_count = process_state.threads()->size(); + for (int thread_index = 0; thread_index < thread_count; ++thread_index) { + if (thread_index != requesting_thread) { + // Don't print the crash thread again, it was already printed. + printf("\n"); + printf("Thread %d\n", thread_index); + PrintStack(process_state.threads()->at(thread_index), cpu); + } + } + + PrintModules(process_state.modules()); +} + +static void PrintProcessStateMachineReadable(const ProcessState& process_state) +{ + // Print OS and CPU information. + // OS|{OS Name}|{OS Version} + // CPU|{CPU Name}|{CPU Info}|{Number of CPUs} + printf("OS%c%s%c%s\n", kOutputSeparator, + StripSeparator(process_state.system_info()->os).c_str(), + kOutputSeparator, + StripSeparator(process_state.system_info()->os_version).c_str()); + printf("CPU%c%s%c%s%c%d\n", kOutputSeparator, + StripSeparator(process_state.system_info()->cpu).c_str(), + kOutputSeparator, + // this may be empty + StripSeparator(process_state.system_info()->cpu_info).c_str(), + kOutputSeparator, + process_state.system_info()->cpu_count); + + int requesting_thread = process_state.requesting_thread(); + + // Print crash information. + // Crash|{Crash Reason}|{Crash Address}|{Crashed Thread} + printf("Crash%c", kOutputSeparator); + if (process_state.crashed()) { + printf("%s%c0x%" PRIx64 "%c", + StripSeparator(process_state.crash_reason()).c_str(), + kOutputSeparator, process_state.crash_address(), kOutputSeparator); + } else { + printf("No crash%c%c", kOutputSeparator, kOutputSeparator); + } + + if (requesting_thread != -1) { + printf("%d\n", requesting_thread); + } else { + printf("\n"); + } + + PrintModulesMachineReadable(process_state.modules()); + + // blank line to indicate start of threads + printf("\n"); + + // If the thread that requested the dump is known, print it first. + if (requesting_thread != -1) { + PrintStackMachineReadable(requesting_thread, + process_state.threads()->at(requesting_thread)); + } + + // Print all of the threads in the dump. + int thread_count = process_state.threads()->size(); + for (int thread_index = 0; thread_index < thread_count; ++thread_index) { + if (thread_index != requesting_thread) { + // Don't print the crash thread again, it was already printed. + PrintStackMachineReadable(thread_index, + process_state.threads()->at(thread_index)); + } + } +} + +// Processes |minidump_file| using MinidumpProcessor. |symbol_path|, if +// non-empty, is the base directory of a symbol storage area, laid out in +// the format required by SimpleSymbolSupplier. If such a storage area +// is specified, it is made available for use by the MinidumpProcessor. +// +// Returns the value of MinidumpProcessor::Process. If processing succeeds, +// prints identifying OS and CPU information from the minidump, crash +// information if the minidump was produced as a result of a crash, and +// call stacks for each thread contained in the minidump. All information +// is printed to stdout. +static bool PrintMinidumpProcess(const string &minidump_file, + const vector &symbol_paths, + bool machine_readable) { + scoped_ptr symbol_supplier; + if (!symbol_paths.empty()) { + // TODO(mmentovai): check existence of symbol_path if specified? + symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths)); + } + + BasicSourceLineResolver resolver; + MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver); + + // Process the minidump. + ProcessState process_state; + if (minidump_processor.Process(minidump_file, &process_state) != + MinidumpProcessor::PROCESS_OK) { + BPLOG(ERROR) << "MinidumpProcessor::Process failed"; + return false; + } + + if (machine_readable) { + PrintProcessStateMachineReadable(process_state); + } else { + PrintProcessState(process_state); + } + + return true; +} + +} // namespace + +static void usage(const char *program_name) { + fprintf(stderr, "usage: %s [-m] [symbol-path ...]\n" + " -m : Output in machine-readable format\n", + program_name); +} + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + if (argc < 2) { + usage(argv[0]); + return 1; + } + + const char *minidump_file; + bool machine_readable; + int symbol_path_arg; + + if (strcmp(argv[1], "-m") == 0) { + if (argc < 3) { + usage(argv[0]); + return 1; + } + + machine_readable = true; + minidump_file = argv[2]; + symbol_path_arg = 3; + } else { + machine_readable = false; + minidump_file = argv[1]; + symbol_path_arg = 2; + } + + // extra arguments are symbol paths + std::vector symbol_paths; + if (argc > symbol_path_arg) { + for (int argi = symbol_path_arg; argi < argc; ++argi) + symbol_paths.push_back(argv[argi]); + } + + return PrintMinidumpProcess(minidump_file, + symbol_paths, + machine_readable) ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_machine_readable_test b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_machine_readable_test new file mode 100644 index 00000000..2aadb241 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_machine_readable_test @@ -0,0 +1,37 @@ +#!/bin/sh + +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +testdata_dir=$srcdir/src/processor/testdata +./src/processor/minidump_stackwalk -m $testdata_dir/minidump2.dmp \ + $testdata_dir/symbols | \ + tr -d '\015' | \ + diff -u $testdata_dir/minidump2.stackwalk.machine_readable.out - +exit $? diff --git a/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_test b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_test new file mode 100644 index 00000000..f9790279 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/minidump_stackwalk_test @@ -0,0 +1,37 @@ +#!/bin/sh + +# Copyright (c) 2006, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +testdata_dir=$srcdir/src/processor/testdata +./src/processor/minidump_stackwalk $testdata_dir/minidump2.dmp \ + $testdata_dir/symbols | \ + tr -d '\015' | \ + diff -u $testdata_dir/minidump2.stackwalk.out - +exit $? diff --git a/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.cc b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.cc new file mode 100644 index 00000000..839287bd --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// pathname_stripper.cc: Manipulates pathnames into their component parts. +// +// See pathname_stripper.h for documentation. +// +// Author: Mark Mentovai + +#include "processor/pathname_stripper.h" + +namespace google_breakpad { + +// static +string PathnameStripper::File(const string &path) { + string::size_type slash = path.rfind('/'); + string::size_type backslash = path.rfind('\\'); + + string::size_type file_start = 0; + if (slash != string::npos && + (backslash == string::npos || slash > backslash)) { + file_start = slash + 1; + } else if (backslash != string::npos) { + file_start = backslash + 1; + } + + return path.substr(file_start); +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.h b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.h new file mode 100644 index 00000000..17db75d6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper.h @@ -0,0 +1,53 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// pathname_stripper.h: Manipulates pathnames into their component parts. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_PATHNAME_STRIPPER_H__ +#define PROCESSOR_PATHNAME_STRIPPER_H__ + +#include + +namespace google_breakpad { + +using std::string; + +class PathnameStripper { + public: + // Given path, a pathname with components separated by slashes (/) or + // backslashes (\), returns the trailing component, without any separator. + // If path ends in a separator character, returns an empty string. + static string File(const string &path); +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_PATHNAME_STRIPPER_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/pathname_stripper_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper_unittest.cc new file mode 100644 index 00000000..957c94f2 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/pathname_stripper_unittest.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "processor/pathname_stripper.h" +#include "processor/logging.h" + +#define ASSERT_TRUE(condition) \ + if (!(condition)) { \ + fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ + return false; \ + } + +#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) + +namespace { + +using google_breakpad::PathnameStripper; + +static bool RunTests() { + ASSERT_EQ(PathnameStripper::File("/dir/file"), "file"); + ASSERT_EQ(PathnameStripper::File("\\dir\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("/dir\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("\\dir/file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir/file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir/\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir\\/file"), "file"); + ASSERT_EQ(PathnameStripper::File("file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir/"), ""); + ASSERT_EQ(PathnameStripper::File("dir\\"), ""); + ASSERT_EQ(PathnameStripper::File("dir/dir/"), ""); + ASSERT_EQ(PathnameStripper::File("dir\\dir\\"), ""); + ASSERT_EQ(PathnameStripper::File("dir1/dir2/file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir1\\dir2\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir1/dir2\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir1\\dir2/file"), "file"); + ASSERT_EQ(PathnameStripper::File(""), ""); + ASSERT_EQ(PathnameStripper::File("1"), "1"); + ASSERT_EQ(PathnameStripper::File("1/2"), "2"); + ASSERT_EQ(PathnameStripper::File("1\\2"), "2"); + ASSERT_EQ(PathnameStripper::File("/1/2"), "2"); + ASSERT_EQ(PathnameStripper::File("\\1\\2"), "2"); + ASSERT_EQ(PathnameStripper::File("dir//file"), "file"); + ASSERT_EQ(PathnameStripper::File("dir\\\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("/dir//file"), "file"); + ASSERT_EQ(PathnameStripper::File("\\dir\\\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("c:\\dir\\file"), "file"); + ASSERT_EQ(PathnameStripper::File("c:\\dir\\file.ext"), "file.ext"); + + return true; +} + +} // namespace + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator-inl.h b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator-inl.h new file mode 100644 index 00000000..aa0851d9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator-inl.h @@ -0,0 +1,282 @@ +// 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. + +// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression +// evaluator. +// +// Documentation in postfix_evaluator.h. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ +#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ + + +#include + +#include "processor/postfix_evaluator.h" +#include "google_breakpad/processor/memory_region.h" +#include "processor/logging.h" + +namespace google_breakpad { + +using std::istringstream; +using std::ostringstream; + + +// A small class used in Evaluate to make sure to clean up the stack +// before returning failure. +class AutoStackClearer { + public: + explicit AutoStackClearer(vector *stack) : stack_(stack) {} + ~AutoStackClearer() { stack_->clear(); } + + private: + vector *stack_; +}; + + +template +bool PostfixEvaluator::Evaluate(const string &expression, + DictionaryValidityType *assigned) { + // Ensure that the stack is cleared before returning. + AutoStackClearer clearer(&stack_); + + // Tokenize, splitting on whitespace. + istringstream stream(expression); + string token; + while (stream >> token) { + // There are enough binary operations that do exactly the same thing + // (other than the specific operation, of course) that it makes sense + // to share as much code as possible. + enum BinaryOperation { + BINARY_OP_NONE = 0, + BINARY_OP_ADD, + BINARY_OP_SUBTRACT, + BINARY_OP_MULTIPLY, + BINARY_OP_DIVIDE_QUOTIENT, + BINARY_OP_DIVIDE_MODULUS + }; + + BinaryOperation operation = BINARY_OP_NONE; + if (token == "+") + operation = BINARY_OP_ADD; + else if (token == "-") + operation = BINARY_OP_SUBTRACT; + else if (token == "*") + operation = BINARY_OP_MULTIPLY; + else if (token == "/") + operation = BINARY_OP_DIVIDE_QUOTIENT; + else if (token == "%") + operation = BINARY_OP_DIVIDE_MODULUS; + + if (operation != BINARY_OP_NONE) { + // Get the operands. + ValueType operand1, operand2; + if (!PopValues(&operand1, &operand2)) { + BPLOG(ERROR) << "Could not PopValues to get two values for binary " + "operation " << token << ": " << expression; + return false; + } + + // Perform the operation. + ValueType result; + switch (operation) { + case BINARY_OP_ADD: + result = operand1 + operand2; + break; + case BINARY_OP_SUBTRACT: + result = operand1 - operand2; + break; + case BINARY_OP_MULTIPLY: + result = operand1 * operand2; + break; + case BINARY_OP_DIVIDE_QUOTIENT: + result = operand1 / operand2; + break; + case BINARY_OP_DIVIDE_MODULUS: + result = operand1 % operand2; + break; + case BINARY_OP_NONE: + // This will not happen, but compilers will want a default or + // BINARY_OP_NONE case. + BPLOG(ERROR) << "Not reached!"; + return false; + break; + } + + // Save the result. + PushValue(result); + } else if (token == "^") { + // ^ for unary dereference. Can't dereference without memory. + if (!memory_) { + BPLOG(ERROR) << "Attempt to dereference without memory: " << + expression; + return false; + } + + ValueType address; + if (!PopValue(&address)) { + BPLOG(ERROR) << "Could not PopValue to get value to derefence: " << + expression; + return false; + } + + ValueType value; + if (!memory_->GetMemoryAtAddress(address, &value)) { + BPLOG(ERROR) << "Could not dereference memory at address " << + HexString(address) << ": " << expression; + return false; + } + + PushValue(value); + } else if (token == "=") { + // = for assignment. + ValueType value; + if (!PopValue(&value)) { + BPLOG(ERROR) << "Could not PopValue to get value to assign: " << + expression; + return false; + } + + // Assignment is only meaningful when assigning into an identifier. + // The identifier must name a variable, not a constant. Variables + // begin with '$'. + string identifier; + if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { + BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " + "identifier is needed to assign " << + HexString(value) << ": " << expression; + return false; + } + if (identifier.empty() || identifier[0] != '$') { + BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << + identifier << ": " << expression; + return false; + } + + (*dictionary_)[identifier] = value; + if (assigned) + (*assigned)[identifier] = true; + } else { + // The token is not an operator, it's a literal value or an identifier. + // Push it onto the stack as-is. Use push_back instead of PushValue + // because PushValue pushes ValueType as a string, but token is already + // a string. + stack_.push_back(token); + } + } + + // If there's anything left on the stack, it indicates incomplete execution. + // This is a failure case. If the stack is empty, evalution was complete + // and successful. + BPLOG_IF(ERROR, !stack_.empty()) << "Incomplete execution: " << expression; + return stack_.empty(); +} + + +template +typename PostfixEvaluator::PopResult +PostfixEvaluator::PopValueOrIdentifier( + ValueType *value, string *identifier) { + // There needs to be at least one element on the stack to pop. + if (!stack_.size()) + return POP_RESULT_FAIL; + + string token = stack_.back(); + stack_.pop_back(); + + // First, try to treat the value as a literal. In order for this to + // succed, the entire string must be parseable as ValueType. If this + // isn't possible, it can't be a literal, so treat it as an identifier + // instead. + istringstream token_stream(token); + ValueType literal; + if (token_stream >> literal && token_stream.peek() == EOF) { + if (value) { + *value = literal; + } + return POP_RESULT_VALUE; + } else { + if (identifier) { + *identifier = token; + } + return POP_RESULT_IDENTIFIER; + } +} + + +template +bool PostfixEvaluator::PopValue(ValueType *value) { + ValueType literal; + string token; + PopResult result; + if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { + return false; + } else if (result == POP_RESULT_VALUE) { + // This is the easy case. + *value = literal; + } else { // result == POP_RESULT_IDENTIFIER + // There was an identifier at the top of the stack. Resolve it to a + // value by looking it up in the dictionary. + typename DictionaryType::const_iterator iterator = + dictionary_->find(token); + if (iterator == dictionary_->end()) { + // The identifier wasn't found in the dictionary. Don't imply any + // default value, just fail. + BPLOG(ERROR) << "Identifier " << token << " not in dictionary"; + return false; + } + + *value = iterator->second; + } + + return true; +} + + +template +bool PostfixEvaluator::PopValues(ValueType *value1, + ValueType *value2) { + return PopValue(value2) && PopValue(value1); +} + + +template +void PostfixEvaluator::PushValue(const ValueType &value) { + ostringstream token_stream; + token_stream << value; + stack_.push_back(token_stream.str()); +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator.h b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator.h new file mode 100644 index 00000000..552ed159 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator.h @@ -0,0 +1,158 @@ +// 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. + +// postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator. +// +// PostfixEvaluator evaluates an expression, using the expression itself +// in postfix (reverse Polish) notation and a dictionary mapping constants +// and variables to their values. The evaluator supports standard +// arithmetic operations, assignment into variables, and when an optional +// MemoryRange is provided, dereferencing. (Any unary key-to-value operation +// may be used with a MemoryRange implementation that returns the appropriate +// values, but PostfixEvaluator was written with dereferencing in mind.) +// +// The expression language is simple. Expressions are supplied as strings, +// with operands and operators delimited by whitespace. Operands may be +// either literal values suitable for ValueType, or constants or variables, +// which reference the dictionary. The supported binary operators are + +// (addition), - (subtraction), * (multiplication), / (quotient of division), +// and % (modulus of division). The unary ^ (dereference) operator is also +// provided. These operators allow any operand to be either a literal +// value, constant, or variable. Assignment (=) of any type of operand into +// a variable is also supported. +// +// The dictionary is provided as a map with string keys. Keys beginning +// with the '$' character are treated as variables. All other keys are +// treated as constants. Any results must be assigned into variables in the +// dictionary. These variables do not need to exist prior to calling +// Evaluate, unless used in an expression prior to being assigned to. The +// internal stack state is not made available after evaluation, and any +// values remaining on the stack are treated as evidence of incomplete +// execution and cause the evaluator to indicate failure. +// +// PostfixEvaluator is intended to support evaluation of "program strings" +// obtained from MSVC frame data debugging information in pdb files as +// returned by the DIA APIs. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_POSTFIX_EVALUATOR_H__ +#define PROCESSOR_POSTFIX_EVALUATOR_H__ + + +#include +#include +#include + +namespace google_breakpad { + +using std::map; +using std::string; +using std::vector; + +class MemoryRegion; + +template +class PostfixEvaluator { + public: + typedef map DictionaryType; + typedef map DictionaryValidityType; + + // Create a PostfixEvaluator object that may be used (with Evaluate) on + // one or more expressions. PostfixEvaluator does not take ownership of + // either argument. |memory| may be NULL, in which case dereferencing + // (^) will not be supported. |dictionary| may be NULL, but evaluation + // will fail in that case unless set_dictionary is used before calling + // Evaluate. + PostfixEvaluator(DictionaryType *dictionary, MemoryRegion *memory) + : dictionary_(dictionary), memory_(memory), stack_() {} + + // Evaluate the expression. The results of execution will be stored + // in one (or more) variables in the dictionary. Returns false if any + // failures occure during execution, leaving variables in the dictionary + // in an indeterminate state. If assigned is non-NULL, any keys set in + // the dictionary as a result of evaluation will also be set to true in + // assigned, providing a way to determine if an expression modifies any + // of its input variables. + bool Evaluate(const string &expression, DictionaryValidityType *assigned); + + DictionaryType* dictionary() const { return dictionary_; } + + // Reset the dictionary. PostfixEvaluator does not take ownership. + void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; } + + private: + // Return values for PopValueOrIdentifier + enum PopResult { + POP_RESULT_FAIL = 0, + POP_RESULT_VALUE, + POP_RESULT_IDENTIFIER + }; + + // Retrieves the topmost literal value, constant, or variable from the + // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal + // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER + // if the topmost entry is a constant or variable identifier, and sets + // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such + // as when the stack is empty. + PopResult PopValueOrIdentifier(ValueType *value, string *identifier); + + // Retrieves the topmost value on the stack. If the topmost entry is + // an identifier, the dictionary is queried for the identifier's value. + // Returns false on failure, such as when the stack is empty or when + // a nonexistent identifier is named. + bool PopValue(ValueType *value); + + // Retrieves the top two values on the stack, in the style of PopValue. + // value2 is popped before value1, so that value1 corresponds to the + // entry that was pushed prior to value2. Returns false on failure. + bool PopValues(ValueType *value1, ValueType *value2); + + // Pushes a new value onto the stack. + void PushValue(const ValueType &value); + + // The dictionary mapping constant and variable identifiers (strings) to + // values. Keys beginning with '$' are treated as variable names, and + // PostfixEvaluator is free to create and modify these keys. Weak pointer. + DictionaryType *dictionary_; + + // If non-NULL, the MemoryRegion used for dereference (^) operations. + // If NULL, dereferencing is unsupported and will fail. Weak pointer. + MemoryRegion *memory_; + + // The stack contains state information as execution progresses. Values + // are pushed on to it as the expression string is read and as operations + // yield values; values are popped when used as operands to operators. + vector stack_; +}; + +} // namespace google_breakpad + + +#endif // PROCESSOR_POSTFIX_EVALUATOR_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator_unittest.cc new file mode 100644 index 00000000..d687cc83 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/postfix_evaluator_unittest.cc @@ -0,0 +1,303 @@ +// 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. + +// postfix_evaluator_unittest.cc: Unit tests for PostfixEvaluator. +// +// Author: Mark Mentovai + +#include +#include +#include + +#include "processor/postfix_evaluator-inl.h" + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/processor/memory_region.h" +#include "processor/logging.h" + + +namespace { + + +using std::map; +using std::string; +using google_breakpad::MemoryRegion; +using google_breakpad::PostfixEvaluator; + + +// FakeMemoryRegion is used to test PostfixEvaluator's dereference (^) +// operator. The result of dereferencing a value is one greater than +// the value. +class FakeMemoryRegion : public MemoryRegion { + public: + virtual u_int64_t GetBase() { return 0; } + virtual u_int32_t GetSize() { return 0; } + virtual bool GetMemoryAtAddress(u_int64_t address, u_int8_t *value) { + *value = address + 1; + return true; + } + virtual bool GetMemoryAtAddress(u_int64_t address, u_int16_t *value) { + *value = address + 1; + return true; + } + virtual bool GetMemoryAtAddress(u_int64_t address, u_int32_t *value) { + *value = address + 1; + return true; + } + virtual bool GetMemoryAtAddress(u_int64_t address, u_int64_t *value) { + *value = address + 1; + return true; + } +}; + + +struct EvaluateTest { + // Expression passed to PostfixEvaluator::Evaluate. + const string expression; + + // True if the expression is expected to be evaluable, false if evaluation + // is expected to fail. + bool evaluable; +}; + + +struct EvaluateTestSet { + // The dictionary used for all tests in the set. + PostfixEvaluator::DictionaryType *dictionary; + + // The list of tests. + const EvaluateTest *evaluate_tests; + + // The number of tests. + unsigned int evaluate_test_count; + + // Identifiers and their expected values upon completion of the Evaluate + // tests in the set. + map *validate_data; +}; + + +static bool RunTests() { + // The first test set checks the basic operations and failure modes. + PostfixEvaluator::DictionaryType dictionary_0; + const EvaluateTest evaluate_tests_0[] = { + { "$rAdd 2 2 + =", true }, // $rAdd = 2 + 2 = 4 + { "$rAdd $rAdd 2 + =", true }, // $rAdd = $rAdd + 2 = 6 + { "$rAdd 2 $rAdd + =", true }, // $rAdd = 2 + $rAdd = 8 + { "99", false }, // put some junk on the stack... + { "$rAdd2 2 2 + =", true }, // ...and make sure things still work + { "$rAdd2\t2\n2 + =", true }, // same but with different whitespace + { "$rAdd2 2 2 + = ", true }, // trailing whitespace + { " $rAdd2 2 2 + =", true }, // leading whitespace + { "$rAdd2 2 2 + =", true }, // extra whitespace + { "$T0 2 = +", false }, // too few operands for add + { "2 + =", false }, // too few operands for add + { "2 +", false }, // too few operands for add + { "+", false }, // too few operands for add + { "^", false }, // too few operands for dereference + { "=", false }, // too few operands for assignment + { "2 =", false }, // too few operands for assignment + { "2 2 + =", false }, // too few operands for assignment + { "2 2 =", false }, // can't assign into a literal + { "k 2 =", false }, // can't assign into a constant + { "2", false }, // leftover data on stack + { "2 2 +", false }, // leftover data on stack + { "$rAdd", false }, // leftover data on stack + { "0 $T1 0 0 + =", false }, // leftover data on stack + { "$T2 $T2 2 + =", false }, // can't operate on an undefined value + { "$rMul 9 6 * =", true }, // $rMul = 9 * 6 = 54 + { "$rSub 9 6 - =", true }, // $rSub = 9 - 6 = 3 + { "$rDivQ 9 6 / =", true }, // $rDivQ = 9 / 6 = 1 + { "$rDivM 9 6 % =", true }, // $rDivM = 9 % 6 = 3 + { "$rDeref 9 ^ =", true } // $rDeref = ^9 = 10 (FakeMemoryRegion) + }; + map validate_data_0; + validate_data_0["$rAdd"] = 8; + validate_data_0["$rAdd2"] = 4; + validate_data_0["$rSub"] = 3; + validate_data_0["$rMul"] = 54; + validate_data_0["$rDivQ"] = 1; + validate_data_0["$rDivM"] = 3; + validate_data_0["$rDeref"] = 10; + + // The second test set simulates a couple of MSVC program strings. + // The data is fudged a little bit because the tests use FakeMemoryRegion + // instead of a real stack snapshot, but the program strings are real and + // the implementation doesn't know or care that the data is not real. + PostfixEvaluator::DictionaryType dictionary_1; + dictionary_1["$ebp"] = 0xbfff0010; + dictionary_1["$eip"] = 0x10000000; + dictionary_1["$esp"] = 0xbfff0000; + dictionary_1[".cbSavedRegs"] = 4; + dictionary_1[".cbParams"] = 4; + dictionary_1[".raSearchStart"] = 0xbfff0020; + const EvaluateTest evaluate_tests_1[] = { + { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " + "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true }, + // Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015, + // $ebp = 0xbfff0011, $esp = 0xbfff0018, + // $L = 0xbfff000c, $P = 0xbfff001c + { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " + "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =", + true }, + // Intermediate state: $T0 = 0xbfff0011, $eip = 0xbfff0016, + // $ebp = 0xbfff0012, $esp = 0xbfff0019, + // $L = 0xbfff000d, $P = 0xbfff001d, + // $ebx = 0xbffefff6 + { "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = " + "$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = " + "$ebx $T0 28 - ^ =", + true } + }; + map validate_data_1; + validate_data_1["$T0"] = 0xbfff0012; + validate_data_1["$T1"] = 0xbfff0020; + validate_data_1["$T2"] = 0xbfff0019; + validate_data_1["$eip"] = 0xbfff0021; + validate_data_1["$ebp"] = 0xbfff0012; + validate_data_1["$esp"] = 0xbfff0024; + validate_data_1["$L"] = 0xbfff000e; + validate_data_1["$P"] = 0xbfff0028; + validate_data_1["$ebx"] = 0xbffefff7; + validate_data_1[".cbSavedRegs"] = 4; + validate_data_1[".cbParams"] = 4; + + EvaluateTestSet evaluate_test_sets[] = { + { &dictionary_0, evaluate_tests_0, + sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 }, + { &dictionary_1, evaluate_tests_1, + sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 }, + }; + + unsigned int evaluate_test_set_count = sizeof(evaluate_test_sets) / + sizeof(EvaluateTestSet); + + FakeMemoryRegion fake_memory; + PostfixEvaluator postfix_evaluator = + PostfixEvaluator(NULL, &fake_memory); + + for (unsigned int evaluate_test_set_index = 0; + evaluate_test_set_index < evaluate_test_set_count; + ++evaluate_test_set_index) { + EvaluateTestSet *evaluate_test_set = + &evaluate_test_sets[evaluate_test_set_index]; + const EvaluateTest *evaluate_tests = evaluate_test_set->evaluate_tests; + unsigned int evaluate_test_count = evaluate_test_set->evaluate_test_count; + + // The same dictionary will be used for each test in the set. Earlier + // tests can affect the state of the dictionary for later tests. + postfix_evaluator.set_dictionary(evaluate_test_set->dictionary); + + // Use a new validity dictionary for each test set. + PostfixEvaluator::DictionaryValidityType assigned; + + for (unsigned int evaluate_test_index = 0; + evaluate_test_index < evaluate_test_count; + ++evaluate_test_index) { + const EvaluateTest *evaluate_test = &evaluate_tests[evaluate_test_index]; + + // Do the test. + bool result = postfix_evaluator.Evaluate(evaluate_test->expression, + &assigned); + if (result != evaluate_test->evaluable) { + fprintf(stderr, "FAIL: evaluate set %d/%d, test %d/%d, " + "expression \"%s\", expected %s, observed %s\n", + evaluate_test_set_index, evaluate_test_set_count, + evaluate_test_index, evaluate_test_count, + evaluate_test->expression.c_str(), + evaluate_test->evaluable ? "evaluable" : "not evaluable", + result ? "evaluted" : "not evaluated"); + return false; + } + } + + // Validate the results. + for (map::const_iterator validate_iterator = + evaluate_test_set->validate_data->begin(); + validate_iterator != evaluate_test_set->validate_data->end(); + ++validate_iterator) { + const string identifier = validate_iterator->first; + unsigned int expected_value = validate_iterator->second; + + map::const_iterator dictionary_iterator = + evaluate_test_set->dictionary->find(identifier); + + // The identifier must exist in the dictionary. + if (dictionary_iterator == evaluate_test_set->dictionary->end()) { + fprintf(stderr, "FAIL: evaluate test set %d/%d, " + "validate identifier \"%s\", " + "expected %d, observed not found\n", + evaluate_test_set_index, evaluate_test_set_count, + identifier.c_str(), expected_value); + return false; + } + + // The value in the dictionary must be the same as the expected value. + unsigned int observed_value = dictionary_iterator->second; + if (expected_value != observed_value) { + fprintf(stderr, "FAIL: evaluate test set %d/%d, " + "validate identifier \"%s\", " + "expected %d, observed %d\n", + evaluate_test_set_index, evaluate_test_set_count, + identifier.c_str(), expected_value, observed_value); + return false; + } + + // The value must be set in the "assigned" dictionary if it was a + // variable. It must not have been assigned if it was a constant. + bool expected_assigned = identifier[0] == '$'; + bool observed_assigned = false; + PostfixEvaluator::DictionaryValidityType::const_iterator + iterator_assigned = assigned.find(identifier); + if (iterator_assigned != assigned.end()) { + observed_assigned = iterator_assigned->second; + } + if (expected_assigned != observed_assigned) { + fprintf(stderr, "FAIL: evaluate test set %d/%d, " + "validate assignment of \"%s\", " + "expected %d, observed %d\n", + evaluate_test_set_index, evaluate_test_set_count, + identifier.c_str(), expected_assigned, observed_assigned); + return false; + } + } + } + + return true; +} + + +} // namespace + + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/process_state.cc b/thirdparty/google-breakpad/r318/src/processor/process_state.cc new file mode 100644 index 00000000..934792b3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/process_state.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// process_state.cc: A snapshot of a process, in a fully-digested state. +// +// See process_state.h for documentation. +// +// Author: Mark Mentovai + +#include "google_breakpad/processor/process_state.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_modules.h" + +namespace google_breakpad { + +ProcessState::~ProcessState() { + Clear(); +} + +void ProcessState::Clear() { + time_date_stamp_ = 0; + crashed_ = false; + crash_reason_.clear(); + crash_address_ = 0; + requesting_thread_ = -1; + for (vector::const_iterator iterator = threads_.begin(); + iterator != threads_.end(); + ++iterator) { + delete *iterator; + } + threads_.clear(); + system_info_.Clear(); + delete modules_; + modules_ = NULL; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/range_map-inl.h b/thirdparty/google-breakpad/r318/src/processor/range_map-inl.h new file mode 100644 index 00000000..77bf7d20 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/range_map-inl.h @@ -0,0 +1,210 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// range_map-inl.h: Range map implementation. +// +// See range_map.h for documentation. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_RANGE_MAP_INL_H__ +#define PROCESSOR_RANGE_MAP_INL_H__ + + +#include + +#include "processor/range_map.h" +#include "processor/logging.h" + + +namespace google_breakpad { + + +template +bool RangeMap::StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry) { + AddressType high = base + size - 1; + + // Check for undersize or overflow. + if (size <= 0 || high < base) { + // The processor will hit this case too frequently with common symbol + // files in the size == 0 case, which is more suited to a DEBUG channel. + // Filter those out since there's no DEBUG channel at the moment. + BPLOG_IF(INFO, size != 0) << "StoreRange failed, " << HexString(base) << + "+" << HexString(size) << ", " << + HexString(high); + return false; + } + + // Ensure that this range does not overlap with another one already in the + // map. + MapConstIterator iterator_base = map_.lower_bound(base); + MapConstIterator iterator_high = map_.lower_bound(high); + + if (iterator_base != iterator_high) { + // Some other range begins in the space used by this range. It may be + // contained within the space used by this range, or it may extend lower. + // Regardless, it is an error. + AddressType other_base = iterator_base->second.base(); + AddressType other_size = iterator_base->first - other_base + 1; + BPLOG(INFO) << "StoreRange failed, an existing range is contained by or " + "extends lower than the new range: new " << + HexString(base) << "+" << HexString(size) << ", existing " << + HexString(other_base) << "+" << HexString(other_size); + return false; + } + + if (iterator_high != map_.end()) { + if (iterator_high->second.base() <= high) { + // The range above this one overlaps with this one. It may fully + // contain this range, or it may begin within this range and extend + // higher. Regardless, it's an error. + AddressType other_base = iterator_high->second.base(); + AddressType other_size = iterator_high->first - other_base + 1; + BPLOG(INFO) << "StoreRange failed, an existing range contains or " + "extends higher than the new range: new " << + HexString(base) << "+" << HexString(size) << + ", existing " << + HexString(other_base) << "+" << HexString(other_size); + return false; + } + } + + // Store the range in the map by its high address, so that lower_bound can + // be used to quickly locate a range by address. + map_.insert(MapValue(high, Range(base, entry))); + return true; +} + + +template +bool RangeMap::RetrieveRange( + const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|"; + assert(entry); + + MapConstIterator iterator = map_.lower_bound(address); + if (iterator == map_.end()) + return false; + + // The map is keyed by the high address of each range, so |address| is + // guaranteed to be lower than the range's high address. If |range| is + // not directly preceded by another range, it's possible for address to + // be below the range's low address, though. When that happens, address + // references something not within any range, so return false. + if (address < iterator->second.base()) + return false; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->second.base(); + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +bool RangeMap::RetrieveNearestRange( + const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|"; + assert(entry); + + // If address is within a range, RetrieveRange can handle it. + if (RetrieveRange(address, entry, entry_base, entry_size)) + return true; + + // upper_bound gives the first element whose key is greater than address, + // but we want the first element whose key is less than or equal to address. + // Decrement the iterator to get there, but not if the upper_bound already + // points to the beginning of the map - in that case, address is lower than + // the lowest stored key, so return false. + MapConstIterator iterator = map_.upper_bound(address); + if (iterator == map_.begin()) + return false; + --iterator; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->first; + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +bool RangeMap::RetrieveRangeAtIndex( + int index, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const { + BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|"; + assert(entry); + + if (index >= GetCount()) { + BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount(); + return false; + } + + // Walk through the map. Although it's ordered, it's not a vector, so it + // can't be addressed directly by index. + MapConstIterator iterator = map_.begin(); + for (int this_index = 0; this_index < index; ++this_index) + ++iterator; + + *entry = iterator->second.entry(); + if (entry_base) + *entry_base = iterator->first; + if (entry_size) + *entry_size = iterator->first - iterator->second.base() + 1; + + return true; +} + + +template +int RangeMap::GetCount() const { + return map_.size(); +} + + +template +void RangeMap::Clear() { + map_.clear(); +} + + +} // namespace google_breakpad + + +#endif // PROCESSOR_RANGE_MAP_INL_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/range_map.h b/thirdparty/google-breakpad/r318/src/processor/range_map.h new file mode 100644 index 00000000..a7b67412 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/range_map.h @@ -0,0 +1,126 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// range_map.h: Range maps. +// +// A range map associates a range of addresses with a specific object. This +// is useful when certain objects of variable size are located within an +// address space. The range map makes it simple to determine which object is +// associated with a specific address, which may be any address within the +// range associated with an object. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_RANGE_MAP_H__ +#define PROCESSOR_RANGE_MAP_H__ + + +#include + + +namespace google_breakpad { + + +template +class RangeMap { + public: + RangeMap() : map_() {} + + // Inserts a range into the map. Returns false for a parameter error, + // or if the location of the range would conflict with a range already + // stored in the map. + bool StoreRange(const AddressType &base, + const AddressType &size, + const EntryType &entry); + + // Locates the range encompassing the supplied address. If there is + // no such range, returns false. entry_base and entry_size, if non-NULL, + // are set to the base and size of the entry's range. + bool RetrieveRange(const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) const; + + // Locates the range encompassing the supplied address, if one exists. + // If no range encompasses the supplied address, locates the nearest range + // to the supplied address that is lower than the address. Returns false + // if no range meets these criteria. entry_base and entry_size, if + // non-NULL, are set to the base and size of the entry's range. + bool RetrieveNearestRange(const AddressType &address, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) + const; + + // Treating all ranges as a list ordered by the address spaces that they + // occupy, locates the range at the index specified by index. Returns + // false if index is larger than the number of ranges stored. entry_base + // and entry_size, if non-NULL, are set to the base and size of the entry's + // range. + // + // RetrieveRangeAtIndex is not optimized for speedy operation. + bool RetrieveRangeAtIndex(int index, EntryType *entry, + AddressType *entry_base, AddressType *entry_size) + const; + + // Returns the number of ranges stored in the RangeMap. + int GetCount() const; + + // Empties the range map, restoring it to the state it was when it was + // initially created. + void Clear(); + + private: + class Range { + public: + Range(const AddressType &base, const EntryType &entry) + : base_(base), entry_(entry) {} + + AddressType base() const { return base_; } + EntryType entry() const { return entry_; } + + private: + // The base address of the range. The high address does not need to + // be stored, because RangeMap uses it as the key to the map. + const AddressType base_; + + // The entry corresponding to a range. + const EntryType entry_; + }; + + // Convenience types. + typedef std::map AddressToRangeMap; + typedef typename AddressToRangeMap::const_iterator MapConstIterator; + typedef typename AddressToRangeMap::value_type MapValue; + + // Maps the high address of each range to a EntryType. + AddressToRangeMap map_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_RANGE_MAP_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/range_map_unittest.cc b/thirdparty/google-breakpad/r318/src/processor/range_map_unittest.cc new file mode 100644 index 00000000..5b5ce573 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/range_map_unittest.cc @@ -0,0 +1,494 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// range_map_unittest.cc: Unit tests for RangeMap +// +// Author: Mark Mentovai + + +#include +#include + +#include "processor/range_map-inl.h" + +#include "processor/linked_ptr.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" + + +namespace { + + +using google_breakpad::linked_ptr; +using google_breakpad::scoped_ptr; +using google_breakpad::RangeMap; + + +// A CountedObject holds an int. A global (not thread safe!) count of +// allocated CountedObjects is maintained to help test memory management. +class CountedObject { + public: + explicit CountedObject(int id) : id_(id) { ++count_; } + ~CountedObject() { --count_; } + + static int count() { return count_; } + int id() const { return id_; } + + private: + static int count_; + int id_; +}; + +int CountedObject::count_; + + +typedef int AddressType; +typedef RangeMap< AddressType, linked_ptr > TestMap; + + +// RangeTest contains data to use for store and retrieve tests. See +// RunTests for descriptions of the tests. +struct RangeTest { + // Base address to use for test + AddressType address; + + // Size of range to use for test + AddressType size; + + // Unique ID of range - unstorable ranges must have unique IDs too + int id; + + // Whether this range is expected to be stored successfully or not + bool expect_storable; +}; + + +// A RangeTestSet encompasses multiple RangeTests, which are run in +// sequence on the same RangeMap. +struct RangeTestSet { + // An array of RangeTests + const RangeTest *range_tests; + + // The number of tests in the set + unsigned int range_test_count; +}; + + +// StoreTest uses the data in a RangeTest and calls StoreRange on the +// test RangeMap. It returns true if the expected result occurred, and +// false if something else happened. +static bool StoreTest(TestMap *range_map, const RangeTest *range_test) { + linked_ptr object(new CountedObject(range_test->id)); + bool stored = range_map->StoreRange(range_test->address, + range_test->size, + object); + + if (stored != range_test->expect_storable) { + fprintf(stderr, "FAILED: " + "StoreRange id %d, expected %s, observed %s\n", + range_test->id, + range_test->expect_storable ? "storable" : "not storable", + stored ? "stored" : "not stored"); + return false; + } + + return true; +} + + +// RetrieveTest uses the data in RangeTest and calls RetrieveRange on the +// test RangeMap. If it retrieves the expected value (which can be no +// map entry at the specified range,) it returns true, otherwise, it returns +// false. RetrieveTest will check the values around the base address and +// the high address of a range to guard against off-by-one errors. +static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) { + for (unsigned int side = 0; side <= 1; ++side) { + // When side == 0, check the low side (base address) of each range. + // When side == 1, check the high side (base + size) of each range. + + // Check one-less and one-greater than the target address in addition + // to the target address itself. + + // If the size of the range is only 1, don't check one greater than + // the base or one less than the high - for a successfully stored + // range, these tests would erroneously fail because the range is too + // small. + AddressType low_offset = -1; + AddressType high_offset = 1; + if (range_test->size == 1) { + if (!side) // When checking the low side, + high_offset = 0; // don't check one over the target. + else // When checking the high side, + low_offset = 0; // don't check one under the target. + } + + for (AddressType offset = low_offset; offset <= high_offset; ++offset) { + AddressType address = + offset + + (!side ? range_test->address : + range_test->address + range_test->size - 1); + + bool expected_result = false; // This is correct for tests not stored. + if (range_test->expect_storable) { + if (offset == 0) // When checking the target address, + expected_result = true; // test should always succeed. + else if (offset == -1) // When checking one below the target, + expected_result = side; // should fail low and succeed high. + else // When checking one above the target, + expected_result = !side; // should succeed low and fail high. + } + + linked_ptr object; + AddressType retrieved_base; + AddressType retrieved_size; + bool retrieved = range_map->RetrieveRange(address, &object, + &retrieved_base, + &retrieved_size); + + bool observed_result = retrieved && object->id() == range_test->id; + + if (observed_result != expected_result) { + fprintf(stderr, "FAILED: " + "RetrieveRange id %d, side %d, offset %d, " + "expected %s, observed %s\n", + range_test->id, + side, + offset, + expected_result ? "true" : "false", + observed_result ? "true" : "false"); + return false; + } + + // If a range was successfully retrieved, check that the returned + // bounds match the range as stored. + if (observed_result == true && + (retrieved_base != range_test->address || + retrieved_size != range_test->size)) { + fprintf(stderr, "FAILED: " + "RetrieveRange id %d, side %d, offset %d, " + "expected base/size %d/%d, observed %d/%d\n", + range_test->id, + side, + offset, + range_test->address, range_test->size, + retrieved_base, retrieved_size); + return false; + } + + // Now, check RetrieveNearestRange. The nearest range is always + // expected to be different from the test range when checking one + // less than the low side. + bool expected_nearest = range_test->expect_storable; + if (!side && offset < 0) + expected_nearest = false; + + linked_ptr nearest_object; + AddressType nearest_base; + bool retrieved_nearest = range_map->RetrieveNearestRange(address, + &nearest_object, + &nearest_base, + NULL); + + // When checking one greater than the high side, RetrieveNearestRange + // should usually return the test range. When a different range begins + // at that address, though, then RetrieveNearestRange should return the + // range at the address instead of the test range. + if (side && offset > 0 && nearest_base == address) { + expected_nearest = false; + } + + bool observed_nearest = retrieved_nearest && + nearest_object->id() == range_test->id; + + if (observed_nearest != expected_nearest) { + fprintf(stderr, "FAILED: " + "RetrieveNearestRange id %d, side %d, offset %d, " + "expected %s, observed %s\n", + range_test->id, + side, + offset, + expected_nearest ? "true" : "false", + observed_nearest ? "true" : "false"); + return false; + } + } + } + + return true; +} + + +// Test RetrieveRangeAtIndex, which is supposed to return objects in order +// according to their addresses. This test is performed by looping through +// the map, calling RetrieveRangeAtIndex for all possible indices in sequence, +// and verifying that each call returns a different object than the previous +// call, and that ranges are returned with increasing base addresses. Returns +// false if the test fails. +static bool RetrieveIndexTest(TestMap *range_map, int set) { + linked_ptr object; + CountedObject *last_object = NULL; + AddressType last_base = 0; + + int object_count = range_map->GetCount(); + for (int object_index = 0; object_index < object_count; ++object_index) { + AddressType base; + if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, NULL)) { + fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " + "expected success, observed failure\n", + set, object_index); + return false; + } + + if (!object.get()) { + fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " + "expected object, observed NULL\n", + set, object_index); + return false; + } + + // It's impossible to do these comparisons unless there's a previous + // object to compare against. + if (last_object) { + // The object must be different from the last one. + if (object->id() == last_object->id()) { + fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " + "expected different objects, observed same objects (%d)\n", + set, object_index, object->id()); + return false; + } + + // Each object must have a base greater than the previous object's base. + if (base <= last_base) { + fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " + "expected different bases, observed same bases (%d)\n", + set, object_index, base); + return false; + } + } + + last_object = object.get(); + last_base = base; + } + + // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that + // are too high. + if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL, NULL)) { + fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), " + "expected failure, observed success\n", + set, object_count); + return false; + } + + return true; +} + + +// RunTests runs a series of test sets. +static bool RunTests() { + // These tests will be run sequentially. The first set of tests exercises + // most functions of RangeTest, and verifies all of the bounds-checking. + const RangeTest range_tests_0[] = { + { INT_MIN, 16, 1, true }, // lowest possible range + { -2, 5, 2, true }, // a range through zero + { INT_MAX - 9, 11, 3, false }, // tests anti-overflow + { INT_MAX - 9, 10, 4, true }, // highest possible range + { 5, 0, 5, false }, // tests anti-zero-size + { 5, 1, 6, true }, // smallest possible range + { -20, 15, 7, true }, // entirely negative + + { 10, 10, 10, true }, // causes the following tests to fail + { 9, 10, 11, false }, // one-less base, one-less high + { 9, 11, 12, false }, // one-less base, identical high + { 9, 12, 13, false }, // completely contains existing + { 10, 9, 14, false }, // identical base, one-less high + { 10, 10, 15, false }, // exactly identical to existing range + { 10, 11, 16, false }, // identical base, one-greater high + { 11, 8, 17, false }, // contained completely within + { 11, 9, 18, false }, // one-greater base, identical high + { 11, 10, 19, false }, // one-greater base, one-greater high + { 9, 2, 20, false }, // overlaps bottom by one + { 10, 1, 21, false }, // overlaps bottom by one, contained + { 19, 1, 22, false }, // overlaps top by one, contained + { 19, 2, 23, false }, // overlaps top by one + + { 9, 1, 24, true }, // directly below without overlap + { 20, 1, 25, true }, // directly above without overlap + + { 6, 3, 26, true }, // exactly between two ranges, gapless + { 7, 3, 27, false }, // tries to span two ranges + { 7, 5, 28, false }, // tries to span three ranges + { 4, 20, 29, false }, // tries to contain several ranges + + { 30, 50, 30, true }, + { 90, 25, 31, true }, + { 35, 65, 32, false }, // tries to span two noncontiguous + { 120, 10000, 33, true }, // > 8-bit + { 20000, 20000, 34, true }, // > 8-bit + { 0x10001, 0x10001, 35, true }, // > 16-bit + + { 27, -1, 36, false } // tests high < base + }; + + // Attempt to fill the entire space. The entire space must be filled with + // three stores because AddressType is signed for these tests, so RangeMap + // treats the size as signed and rejects sizes that appear to be negative. + // Even if these tests were run as unsigned, two stores would be needed + // to fill the space because the entire size of the space could only be + // described by using one more bit than would be present in AddressType. + const RangeTest range_tests_1[] = { + { INT_MIN, INT_MAX, 50, true }, // From INT_MIN to -2, inclusive + { -1, 2, 51, true }, // From -1 to 0, inclusive + { 1, INT_MAX, 52, true }, // From 1 to INT_MAX, inclusive + { INT_MIN, INT_MAX, 53, false }, // Can't fill the space twice + { -1, 2, 54, false }, + { 1, INT_MAX, 55, false }, + { -3, 6, 56, false }, // -3 to 2, inclusive - spans 3 ranges + }; + + // A light round of testing to verify that RetrieveRange does the right + // the right thing at the extremities of the range when nothing is stored + // there. Checks are forced without storing anything at the extremities + // by setting size = 0. + const RangeTest range_tests_2[] = { + { INT_MIN, 0, 100, false }, // makes RetrieveRange check low end + { -1, 3, 101, true }, + { INT_MAX, 0, 102, false }, // makes RetrieveRange check high end + }; + + // Similar to the previous test set, but with a couple of ranges closer + // to the extremities. + const RangeTest range_tests_3[] = { + { INT_MIN + 1, 1, 110, true }, + { INT_MAX - 1, 1, 111, true }, + { INT_MIN, 0, 112, false }, // makes RetrieveRange check low end + { INT_MAX, 0, 113, false } // makes RetrieveRange check high end + }; + + // The range map is cleared between sets of tests listed here. + const RangeTestSet range_test_sets[] = { + { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) }, + { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) }, + { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) }, + { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) }, + { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again + }; + + // Maintain the range map in a pointer so that deletion can be meaningfully + // tested. + scoped_ptr range_map(new TestMap()); + + // Run all of the test sets in sequence. + unsigned int range_test_set_count = sizeof(range_test_sets) / + sizeof(RangeTestSet); + for (unsigned int range_test_set_index = 0; + range_test_set_index < range_test_set_count; + ++range_test_set_index) { + const RangeTest *range_tests = + range_test_sets[range_test_set_index].range_tests; + unsigned int range_test_count = + range_test_sets[range_test_set_index].range_test_count; + + // Run the StoreRange test, which validates StoreRange and initializes + // the RangeMap with data for the RetrieveRange test. + int stored_count = 0; // The number of ranges successfully stored + for (unsigned int range_test_index = 0; + range_test_index < range_test_count; + ++range_test_index) { + const RangeTest *range_test = &range_tests[range_test_index]; + if (!StoreTest(range_map.get(), range_test)) + return false; + + if (range_test->expect_storable) + ++stored_count; + } + + // There should be exactly one CountedObject for everything successfully + // stored in the RangeMap. + if (CountedObject::count() != stored_count) { + fprintf(stderr, "FAILED: " + "stored object counts don't match, expected %d, observed %d\n", + stored_count, + CountedObject::count()); + + return false; + } + + // The RangeMap's own count of objects should also match. + if (range_map->GetCount() != stored_count) { + fprintf(stderr, "FAILED: stored object count doesn't match GetCount, " + "expected %d, observed %d\n", + stored_count, range_map->GetCount()); + + return false; + } + + // Run the RetrieveRange test + for (unsigned int range_test_index = 0; + range_test_index < range_test_count; + ++range_test_index) { + const RangeTest *range_test = &range_tests[range_test_index]; + if (!RetrieveTest(range_map.get(), range_test)) + return false; + } + + if (!RetrieveIndexTest(range_map.get(), range_test_set_index)) + return false; + + // Clear the map between test sets. If this is the final test set, + // delete the map instead to test destruction. + if (range_test_set_index < range_test_set_count - 1) + range_map->Clear(); + else + range_map.reset(); + + // Test that all stored objects are freed when the RangeMap is cleared + // or deleted. + if (CountedObject::count() != 0) { + fprintf(stderr, "FAILED: " + "did not free all objects after %s, %d still allocated\n", + range_test_set_index < range_test_set_count - 1 ? "clear" + : "delete", + CountedObject::count()); + + return false; + } + } + + return true; +} + + +} // namespace + + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + return RunTests() ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/processor/scoped_ptr.h b/thirdparty/google-breakpad/r318/src/processor/scoped_ptr.h new file mode 100644 index 00000000..0d4f7fd3 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/scoped_ptr.h @@ -0,0 +1,335 @@ +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +// *** NOTE *** +// If your scoped_ptr is a class member of class FOO pointing to a +// forward declared type BAR (as shown below), then you MUST use a non-inlined +// version of the destructor. The destructor of a scoped_ptr (called from +// FOO's destructor) must have a complete definition of BAR in order to +// destroy it. Example: +// +// -- foo.h -- +// class BAR; +// +// class FOO { +// public: +// FOO(); +// ~FOO(); // Required for sources that instantiate class FOO to compile! +// +// private: +// scoped_ptr bar_; +// }; +// +// -- foo.cc -- +// #include "foo.h" +// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. + +// scoped_ptr_malloc added by Google +// When one of these goes out of scope, instead of doing a delete or +// delete[], it calls free(). scoped_ptr_malloc is likely to see +// much more use than any other specializations. + +// release() added by Google +// Use this to conditionally transfer ownership of a heap-allocated object +// to the caller, usually on method success. + +#ifndef PROCESSOR_SCOPED_PTR_H__ +#define PROCESSOR_SCOPED_PTR_H__ + +#include // for std::ptrdiff_t +#include // for assert +#include // for free() decl + +namespace google_breakpad { + +template +class scoped_ptr { + private: + + T* ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + public: + + typedef T element_type; + + explicit scoped_ptr(T* p = 0): ptr(p) {} + + ~scoped_ptr() { + typedef char type_must_be_complete[sizeof(T)]; + delete ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete ptr; + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr should have its own object + template bool operator==(scoped_ptr const& p) const; + template bool operator!=(scoped_ptr const& p) const; +}; + +template inline +void swap(scoped_ptr& a, scoped_ptr& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr& b) { + return p != b.get(); +} + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template +class scoped_array { + private: + + T* ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + public: + + typedef T element_type; + + explicit scoped_array(T* p = 0) : ptr(p) {} + + ~scoped_array() { + typedef char type_must_be_complete[sizeof(T)]; + delete[] ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete [] ptr; + ptr = p; + } + } + + T& operator[](std::ptrdiff_t i) const { + assert(ptr != 0); + assert(i >= 0); + return ptr[i]; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_array & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_array should have its own object + template bool operator==(scoped_array const& p) const; + template bool operator!=(scoped_array const& p) const; +}; + +template inline +void swap(scoped_array& a, scoped_array& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_array& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_array& b) { + return p != b.get(); +} + + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a +// second template argument, the functor used to free the object. + +template +class scoped_ptr_malloc { + private: + + T* ptr; + + scoped_ptr_malloc(scoped_ptr_malloc const &); + scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); + + public: + + typedef T element_type; + + explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} + + ~scoped_ptr_malloc() { + typedef char type_must_be_complete[sizeof(T)]; + free_((void*) ptr); + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + free_((void*) ptr); + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr_malloc & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr_malloc should have its own object + template + bool operator==(scoped_ptr_malloc const& p) const; + template + bool operator!=(scoped_ptr_malloc const& p) const; + + static FreeProc const free_; +}; + +template +FP const scoped_ptr_malloc::free_ = FP(); + +template inline +void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr_malloc& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr_malloc& b) { + return p != b.get(); +} + +} // namespace google_breakpad + +#endif // PROCESSOR_SCOPED_PTR_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.cc b/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.cc new file mode 100644 index 00000000..c593e955 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// simple_symbol_supplier.cc: A simple SymbolSupplier implementation +// +// See simple_symbol_supplier.h for documentation. +// +// Author: Mark Mentovai + +#include +#include + +#include +#include +#include +#include + +#include "processor/simple_symbol_supplier.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/system_info.h" +#include "processor/logging.h" +#include "processor/pathname_stripper.h" + +namespace google_breakpad { + +static bool file_exists(const string &file_name) { + struct stat sb; + return stat(file_name.c_str(), &sb) == 0; +} + +SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( + const CodeModule *module, const SystemInfo *system_info, + string *symbol_file) { + BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFile " + "requires |symbol_file|"; + assert(symbol_file); + symbol_file->clear(); + + for (unsigned int path_index = 0; path_index < paths_.size(); ++path_index) { + SymbolResult result; + if ((result = GetSymbolFileAtPathFromRoot(module, system_info, + paths_[path_index], + symbol_file)) != NOT_FOUND) { + return result; + } + } + return NOT_FOUND; +} + +SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( + const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data) { + assert(symbol_data); + symbol_data->clear(); + + SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, symbol_file); + + if (s == FOUND) { + std::ifstream in(symbol_file->c_str()); + std::getline(in, *symbol_data, std::string::traits_type::to_char_type( + std::string::traits_type::eof())); + in.close(); + } + return s; +} + +SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot( + const CodeModule *module, const SystemInfo *system_info, + const string &root_path, string *symbol_file) { + BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFileAtPath " + "requires |symbol_file|"; + assert(symbol_file); + symbol_file->clear(); + + if (!module) + return NOT_FOUND; + + // Start with the base path. + string path = root_path; + + // Append the debug (pdb) file name as a directory name. + path.append("/"); + string debug_file_name = PathnameStripper::File(module->debug_file()); + if (debug_file_name.empty()) { + BPLOG(ERROR) << "Can't construct symbol file path without debug_file " + "(code_file = " << + PathnameStripper::File(module->code_file()) << ")"; + return NOT_FOUND; + } + path.append(debug_file_name); + + // Append the identifier as a directory name. + path.append("/"); + string identifier = module->debug_identifier(); + if (identifier.empty()) { + BPLOG(ERROR) << "Can't construct symbol file path without debug_identifier " + "(code_file = " << + PathnameStripper::File(module->code_file()) << + ", debug_file = " << debug_file_name << ")"; + return NOT_FOUND; + } + path.append(identifier); + + // Transform the debug file name into one ending in .sym. If the existing + // name ends in .pdb, strip the .pdb. Otherwise, add .sym to the non-.pdb + // name. + path.append("/"); + string debug_file_extension; + if (debug_file_name.size() > 4) + debug_file_extension = debug_file_name.substr(debug_file_name.size() - 4); + std::transform(debug_file_extension.begin(), debug_file_extension.end(), + debug_file_extension.begin(), tolower); + if (debug_file_extension == ".pdb") { + path.append(debug_file_name.substr(0, debug_file_name.size() - 4)); + } else { + path.append(debug_file_name); + } + path.append(".sym"); + + if (!file_exists(path)) { + BPLOG(INFO) << "No symbol file at " << path; + return NOT_FOUND; + } + + *symbol_file = path; + return FOUND; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.h b/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.h new file mode 100644 index 00000000..dff6a512 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/simple_symbol_supplier.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// simple_symbol_supplier.h: A simple SymbolSupplier implementation +// +// SimpleSymbolSupplier is a straightforward implementation of SymbolSupplier +// that stores symbol files in a filesystem tree. A SimpleSymbolSupplier is +// created with one or more base directories, which are the root paths for all +// symbol files. Each symbol file contained therein has a directory entry in +// the base directory with a name identical to the corresponding debugging +// file (pdb). Within each of these directories, there are subdirectories +// named for the debugging file's identifier. For recent pdb files, this is +// a concatenation of the pdb's uuid and age, presented in hexadecimal form, +// without any dashes or separators. The uuid is in uppercase hexadecimal +// and the age is in lowercase hexadecimal. Within that subdirectory, +// SimpleSymbolSupplier expects to find the symbol file, which is named +// identically to the debug file, but with a .sym extension. If the original +// debug file had a name ending in .pdb, the .pdb extension will be replaced +// with .sym. This sample hierarchy is rooted at the "symbols" base +// directory: +// +// symbols +// symbols/test_app.pdb +// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1 +// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1/test_app.sym +// symbols/kernel32.pdb +// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542 +// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym +// +// In this case, the uuid of test_app.pdb is +// 63fe4780-728d-4937-9b9d-7bb6460cb42a and its age is 1. +// +// This scheme was chosen to be roughly analogous to the way that +// symbol files may be accessed from Microsoft Symbol Server. A hierarchy +// used for Microsoft Symbol Server storage is usable as a hierarchy for +// SimpleSymbolServer, provided that the pdb files are transformed to dumped +// format using a tool such as dump_syms, and given a .sym extension. +// +// SimpleSymbolSupplier will iterate over all root paths searching for +// a symbol file existing in that path. +// +// SimpleSymbolSupplier supports any debugging file which can be identified +// by a CodeModule object's debug_file and debug_identifier accessors. The +// expected ultimate source of these CodeModule objects are MinidumpModule +// objects; it is this class that is responsible for assigning appropriate +// values for debug_file and debug_identifier. +// +// Author: Mark Mentovai + +#ifndef PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ +#define PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ + +#include +#include + +#include "google_breakpad/processor/symbol_supplier.h" + +namespace google_breakpad { + +using std::string; +using std::vector; + +class CodeModule; + +class SimpleSymbolSupplier : public SymbolSupplier { + public: + // Creates a new SimpleSymbolSupplier, using path as the root path where + // symbols are stored. + explicit SimpleSymbolSupplier(const string &path) : paths_(1, path) {} + + // Creates a new SimpleSymbolSupplier, using paths as a list of root + // paths where symbols may be stored. + explicit SimpleSymbolSupplier(const vector &paths) : paths_(paths) {} + + virtual ~SimpleSymbolSupplier() {} + + // Returns the path to the symbol file for the given module. See the + // description above. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data); + protected: + SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module, + const SystemInfo *system_info, + const string &root_path, + string *symbol_file); + + private: + vector paths_; +}; + +} // namespace google_breakpad + +#endif // PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/stack_frame_info.h b/thirdparty/google-breakpad/r318/src/processor/stack_frame_info.h new file mode 100644 index 00000000..052a9338 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stack_frame_info.h @@ -0,0 +1,126 @@ +// 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. + +// stack_frame_info.h: Holds debugging information about a stack frame. +// +// This structure is specific to Windows debugging information obtained +// from pdb files using the DIA API. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACK_FRAME_INFO_H__ +#define PROCESSOR_STACK_FRAME_INFO_H__ + +#include + +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +struct StackFrameInfo { + public: + enum Validity { + VALID_NONE = 0, + VALID_PARAMETER_SIZE = 1, + VALID_ALL = -1 + }; + + StackFrameInfo() : valid(VALID_NONE), + prolog_size(0), + epilog_size(0), + parameter_size(0), + saved_register_size(0), + local_size(0), + max_stack_size(0), + allocates_base_pointer(0), + program_string() {} + + StackFrameInfo(u_int32_t set_prolog_size, + u_int32_t set_epilog_size, + u_int32_t set_parameter_size, + u_int32_t set_saved_register_size, + u_int32_t set_local_size, + u_int32_t set_max_stack_size, + int set_allocates_base_pointer, + const std::string set_program_string) + : valid(VALID_ALL), + prolog_size(set_prolog_size), + epilog_size(set_epilog_size), + parameter_size(set_parameter_size), + saved_register_size(set_saved_register_size), + local_size(set_local_size), + max_stack_size(set_max_stack_size), + allocates_base_pointer(set_allocates_base_pointer), + program_string(set_program_string) {} + + // CopyFrom makes "this" StackFrameInfo object identical to "that". + void CopyFrom(const StackFrameInfo &that) { + valid = that.valid; + prolog_size = that.prolog_size; + epilog_size = that.epilog_size; + parameter_size = that.parameter_size; + saved_register_size = that.saved_register_size; + local_size = that.local_size; + max_stack_size = that.max_stack_size; + allocates_base_pointer = that.allocates_base_pointer; + program_string = that.program_string; + } + + // Clears the StackFrameInfo object so that users will see it as though + // it contains no information. + void Clear() { + valid = VALID_NONE; + program_string.erase(); + } + + // Identifies which fields in the structure are valid. This is of + // type Validity, but it is defined as an int because it's not + // possible to OR values into an enumerated type. Users must check + // this field before using any other. + int valid; + + // These values come from IDiaFrameData. + u_int32_t prolog_size; + u_int32_t epilog_size; + u_int32_t parameter_size; + u_int32_t saved_register_size; + u_int32_t local_size; + u_int32_t max_stack_size; + + // Only one of allocates_base_pointer or program_string will be valid. + // If program_string is empty, use allocates_base_pointer. + bool allocates_base_pointer; + std::string program_string; +}; + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACK_FRAME_INFO_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker.cc new file mode 100644 index 00000000..de67bdaa --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker.cc @@ -0,0 +1,193 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker.cc: Generic stackwalker. +// +// See stackwalker.h for documentation. +// +// Author: Mark Mentovai + + +#include + +#include "google_breakpad/processor/stackwalker.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/source_line_resolver_interface.h" +#include "google_breakpad/processor/stack_frame.h" +#include "google_breakpad/processor/symbol_supplier.h" +#include "processor/linked_ptr.h" +#include "processor/logging.h" +#include "processor/scoped_ptr.h" +#include "processor/stack_frame_info.h" +#include "processor/stackwalker_ppc.h" +#include "processor/stackwalker_sparc.h" +#include "processor/stackwalker_x86.h" +#include "processor/stackwalker_amd64.h" + +namespace google_breakpad { + + +Stackwalker::Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : system_info_(system_info), + memory_(memory), + modules_(modules), + supplier_(supplier), + resolver_(resolver) { +} + + +bool Stackwalker::Walk(CallStack *stack) { + BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|"; + assert(stack); + stack->Clear(); + + // stack_frame_info parallels the CallStack. The vector is passed to the + // GetCallerFrame function. It contains information that may be helpful + // for stackwalking. + vector< linked_ptr > stack_frame_info; + + // Begin with the context frame, and keep getting callers until there are + // no more. + + // Take ownership of the pointer returned by GetContextFrame. + scoped_ptr frame(GetContextFrame()); + + while (frame.get()) { + // frame already contains a good frame with properly set instruction and + // frame_pointer fields. The frame structure comes from either the + // context frame (above) or a caller frame (below). + + linked_ptr frame_info; + + // Resolve the module information, if a module map was provided. + if (modules_) { + const CodeModule *module = + modules_->GetModuleForAddress(frame->instruction); + if (module) { + frame->module = module; + if (resolver_ && + !resolver_->HasModule(frame->module->code_file()) && + supplier_) { + string symbol_data, symbol_file; + SymbolSupplier::SymbolResult symbol_result = + supplier_->GetSymbolFile(module, system_info_, + &symbol_file, &symbol_data); + + switch (symbol_result) { + case SymbolSupplier::FOUND: + resolver_->LoadModuleUsingMapBuffer(frame->module->code_file(), + symbol_data); + break; + case SymbolSupplier::NOT_FOUND: + break; // nothing to do + case SymbolSupplier::INTERRUPT: + return false; + } + } + frame_info.reset(resolver_->FillSourceLineInfo(frame.get())); + } + } + + // Add the frame to the call stack. Relinquish the ownership claim + // over the frame, because the stack now owns it. + stack->frames_.push_back(frame.release()); + + // Add the frame info to the parallel stack. + stack_frame_info.push_back(frame_info); + frame_info.reset(NULL); + + // Get the next frame and take ownership. + frame.reset(GetCallerFrame(stack, stack_frame_info)); + } + + return true; +} + + +// static +Stackwalker* Stackwalker::StackwalkerForCPU( + const SystemInfo *system_info, + MinidumpContext *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) { + if (!context) { + BPLOG(ERROR) << "Can't choose a stackwalker implementation without context"; + return NULL; + } + + Stackwalker *cpu_stackwalker = NULL; + + u_int32_t cpu = context->GetContextCPU(); + switch (cpu) { + case MD_CONTEXT_X86: + cpu_stackwalker = new StackwalkerX86(system_info, + context->GetContextX86(), + memory, modules, supplier, + resolver); + break; + + case MD_CONTEXT_PPC: + cpu_stackwalker = new StackwalkerPPC(system_info, + context->GetContextPPC(), + memory, modules, supplier, + resolver); + break; + + case MD_CONTEXT_AMD64: + cpu_stackwalker = new StackwalkerAMD64(system_info, + context->GetContextAMD64(), + memory, modules, supplier, + resolver); + break; + + case MD_CONTEXT_SPARC: + cpu_stackwalker = new StackwalkerSPARC(system_info, + context->GetContextSPARC(), + memory, modules, supplier, + resolver); + break; + } + + BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) << + ", can't choose a stackwalker " + "implementation"; + return cpu_stackwalker; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.cc new file mode 100644 index 00000000..7a413963 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.cc @@ -0,0 +1,131 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_amd64.cc: amd64-specific stackwalker. +// +// See stackwalker_amd64.h for documentation. +// +// Author: Mark Mentovai, Ted Mielczarek + + +#include "processor/stackwalker_amd64.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/logging.h" + +namespace google_breakpad { + + +StackwalkerAMD64::StackwalkerAMD64(const SystemInfo *system_info, + const MDRawContextAMD64 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : Stackwalker(system_info, memory, modules, supplier, resolver), + context_(context) { +} + + +StackFrame* StackwalkerAMD64::GetContextFrame() { + if (!context_ || !memory_) { + BPLOG(ERROR) << "Can't get context frame without context or memory"; + return NULL; + } + + StackFrameAMD64 *frame = new StackFrameAMD64(); + + // The instruction pointer is stored directly in a register, so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL; + frame->instruction = frame->context.rip; + + return frame; +} + + +StackFrame* StackwalkerAMD64::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } + + StackFrameAMD64 *last_frame = static_cast( + stack->frames()->back()); + + //FIXME: this pretty much doesn't work at all due to FPO + // being enabled by default. + // Brain-dead stackwalking: + // %rip_new = *(%rbp_old + 8) + // %rsp_new = %rbp_old + 16 + // %rbp_new = *(%rbp_old) + + // A caller frame must reside higher in memory than its callee frames. + // Anything else is an error, or an indication that we've reached the + // end of the stack. + u_int64_t stack_pointer = last_frame->context.rbp + 16; + if (stack_pointer <= last_frame->context.rsp) { + return NULL; + } + + u_int64_t instruction; + if (!memory_->GetMemoryAtAddress(last_frame->context.rbp + 8, + &instruction) || + instruction <= 1) { + return NULL; + } + + u_int64_t stack_base; + if (!memory_->GetMemoryAtAddress(last_frame->context.rbp, + &stack_base) || + stack_base <= 1) { + return NULL; + } + + StackFrameAMD64 *frame = new StackFrameAMD64(); + + frame->context = last_frame->context; + frame->context.rip = instruction; + frame->context.rsp = stack_pointer; + frame->context.rbp = stack_base; + frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP | + StackFrameAMD64::CONTEXT_VALID_RSP | + StackFrameAMD64::CONTEXT_VALID_RBP; + + frame->instruction = frame->context.rip - 1; + + return frame; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.h b/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.h new file mode 100644 index 00000000..a3e11358 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_amd64.h @@ -0,0 +1,80 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_amd64.h: amd64-specific stackwalker. +// +// Provides stack frames given amd64 register context and a memory region +// corresponding to a amd64 stack. +// +// Author: Mark Mentovai, Ted Mielczarek + + +#ifndef PROCESSOR_STACKWALKER_AMD64_H__ +#define PROCESSOR_STACKWALKER_AMD64_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerAMD64 : public Stackwalker { + public: + // context is a amd64 context object that gives access to amd64-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerAMD64(const SystemInfo *system_info, + const MDRawContextAMD64 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp, + // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp)) + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextAMD64 *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_AMD64_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.cc new file mode 100644 index 00000000..02a49b21 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.cc @@ -0,0 +1,146 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_ppc.cc: ppc-specific stackwalker. +// +// See stackwalker_ppc.h for documentation. +// +// Author: Mark Mentovai + + +#include "processor/stackwalker_ppc.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/logging.h" + +namespace google_breakpad { + + +StackwalkerPPC::StackwalkerPPC(const SystemInfo *system_info, + const MDRawContextPPC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : Stackwalker(system_info, memory, modules, supplier, resolver), + context_(context) { + if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { + // This implementation only covers 32-bit ppc CPUs. The limits of the + // supplied stack are invalid. Mark memory_ = NULL, which will cause + // stackwalking to fail. + BPLOG(ERROR) << "Memory out of range for stackwalking: " << + HexString(memory_->GetBase()) << "+" << + HexString(memory_->GetSize()); + memory_ = NULL; + } +} + + +StackFrame* StackwalkerPPC::GetContextFrame() { + if (!context_ || !memory_) { + BPLOG(ERROR) << "Can't get context frame without context or memory"; + return NULL; + } + + StackFramePPC *frame = new StackFramePPC(); + + // The instruction pointer is stored directly in a register, so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL; + frame->instruction = frame->context.srr0; + + return frame; +} + + +StackFrame* StackwalkerPPC::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } + + // The instruction pointers for previous frames are saved on the stack. + // The typical ppc calling convention is for the called procedure to store + // its return address in the calling procedure's stack frame at 8(%r1), + // and to allocate its own stack frame by decrementing %r1 (the stack + // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc has + // no hardware stack, there is no distinction between the stack pointer and + // frame pointer, and what is typically thought of as the frame pointer on + // an x86 is usually referred to as the stack pointer on a ppc. + + StackFramePPC *last_frame = static_cast( + stack->frames()->back()); + + // A caller frame must reside higher in memory than its callee frames. + // Anything else is an error, or an indication that we've reached the + // end of the stack. + u_int32_t stack_pointer; + if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], + &stack_pointer) || + stack_pointer <= last_frame->context.gpr[1]) { + return NULL; + } + + // Mac OS X/Darwin gives 1 as the return address from the bottom-most + // frame in a stack (a thread's entry point). I haven't found any + // documentation on this, but 0 or 1 would be bogus return addresses, + // so check for them here and return false (end of stack) when they're + // hit to avoid having a phantom frame. + u_int32_t instruction; + if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) || + instruction <= 1) { + return NULL; + } + + StackFramePPC *frame = new StackFramePPC(); + + frame->context = last_frame->context; + frame->context.srr0 = instruction; + frame->context.gpr[1] = stack_pointer; + frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 | + StackFramePPC::CONTEXT_VALID_GPR1; + + // frame->context.srr0 is the return address, which is one instruction + // past the branch that caused us to arrive at the callee. Set + // frame_ppc->instruction to four less than that. Since all ppc + // instructions are 4 bytes wide, this is the address of the branch + // instruction. This allows source line information to match up with the + // line that contains a function call. Callers that require the exact + // return address value may access the context.srr0 field of StackFramePPC. + frame->instruction = frame->context.srr0 - 4; + + return frame; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.h b/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.h new file mode 100644 index 00000000..3d312419 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_ppc.h @@ -0,0 +1,81 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_ppc.h: ppc-specific stackwalker. +// +// Provides stack frames given ppc register context and a memory region +// corresponding to a ppc stack. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACKWALKER_PPC_H__ +#define PROCESSOR_STACKWALKER_PPC_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerPPC : public Stackwalker { + public: + // context is a ppc context object that gives access to ppc-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerPPC(const SystemInfo *system_info, + const MDRawContextPPC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using ppc context (stack pointer in %r1, + // saved program counter in %srr0) and stack conventions (saved stack + // pointer at 0(%r1), return address at 8(0(%r1)). + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextPPC *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_PPC_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest.cc new file mode 100644 index 00000000..6b71a6a8 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest.cc @@ -0,0 +1,425 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_selftest.cc: Tests StackwalkerX86 or StackwalkerPPC using the +// running process' stack as test data, if running on an x86 or ppc and +// compiled with gcc. This test is not enabled in the "make check" suite +// by default, because certain optimizations interfere with its proper +// operation. To turn it on, configure with --enable-selftest. +// +// Optimizations that cause problems: +// - stack frame reuse. The Recursor function here calls itself with +// |return Recursor|. When the caller's frame is reused, it will cause +// CountCallerFrames to correctly return the same number of frames +// in both the caller and callee. This is considered an unexpected +// condition in the test, which expects a callee to have one more +// caller frame in the stack than its caller. +// - frame pointer omission. Even with a stackwalker that understands +// this optimization, the code to harness debug information currently +// only exists to retrieve it from minidumps, not the current process. +// +// This test can also serve as a developmental and debugging aid if +// PRINT_STACKS is defined. +// +// Author: Mark Mentovai + +#include "processor/logging.h" + +#if defined(__i386) && !defined(__i386__) +#define __i386__ +#endif +#if defined(__sparc) && !defined(__sparc__) +#define __sparc__ +#endif + +#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \ + (defined(__i386__) || defined(__ppc__) || defined(__sparc__)) + + +#include + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/scoped_ptr.h" + +using google_breakpad::BasicSourceLineResolver; +using google_breakpad::CallStack; +using google_breakpad::MemoryRegion; +using google_breakpad::scoped_ptr; +using google_breakpad::StackFrame; +using google_breakpad::StackFramePPC; +using google_breakpad::StackFrameX86; +using google_breakpad::StackFrameSPARC; + +#if defined(__i386__) +#include "processor/stackwalker_x86.h" +using google_breakpad::StackwalkerX86; +#elif defined(__ppc__) +#include "processor/stackwalker_ppc.h" +using google_breakpad::StackwalkerPPC; +#elif defined(__sparc__) +#include "processor/stackwalker_sparc.h" +using google_breakpad::StackwalkerSPARC; +#endif // __i386__ || __ppc__ || __sparc__ + +#define RECURSION_DEPTH 100 + + +// A simple MemoryRegion subclass that provides direct access to this +// process' memory space by pointer. +class SelfMemoryRegion : public MemoryRegion { + public: + virtual u_int64_t GetBase() { return 0; } + virtual u_int32_t GetSize() { return 0xffffffff; } + + bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value) { + return GetMemoryAtAddressInternal(address, value); } + bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value) { + return GetMemoryAtAddressInternal(address, value); } + bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value) { + return GetMemoryAtAddressInternal(address, value); } + bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value) { + return GetMemoryAtAddressInternal(address, value); } + + private: + template bool GetMemoryAtAddressInternal(u_int64_t address, + T* value) { + // Without knowing what addresses are actually mapped, just assume that + // everything low is not mapped. This helps the stackwalker catch the + // end of a stack when it tries to dereference a null or low pointer + // in an attempt to find the caller frame. Other unmapped accesses will + // cause the program to crash, but that would properly be a test failure. + if (address < 0x100) + return false; + + u_int8_t* memory = 0; + *value = *reinterpret_cast(&memory[address]); + return true; + } +}; + + +#if defined(__GNUC__) + + +#if defined(__i386__) + +// GetEBP returns the current value of the %ebp register. Because it's +// implemented as a function, %ebp itself contains GetEBP's frame pointer +// and not the caller's frame pointer. Dereference %ebp to obtain the +// caller's frame pointer, which the compiler-generated preamble stored +// on the stack (provided frame pointers are not being omitted.) Because +// this function depends on the compiler-generated preamble, inlining is +// disabled. +static u_int32_t GetEBP() __attribute__((noinline)); +static u_int32_t GetEBP() { + u_int32_t ebp; + __asm__ __volatile__( + "movl (%%ebp), %0" + : "=a" (ebp) + ); + return ebp; +} + + +// The caller's %esp is 8 higher than the value of %ebp in this function, +// assuming that it's not inlined and that the standard prolog is used. +// The CALL instruction places a 4-byte return address on the stack above +// the caller's %esp, and this function's prolog will save the caller's %ebp +// on the stack as well, for another 4 bytes, before storing %esp in %ebp. +static u_int32_t GetESP() __attribute__((noinline)); +static u_int32_t GetESP() { + u_int32_t ebp; + __asm__ __volatile__( + "movl %%ebp, %0" + : "=a" (ebp) + ); + return ebp + 8; +} + + +// GetEIP returns the instruction pointer identifying the next instruction +// to execute after GetEIP returns. It obtains this information from the +// stack, where it was placed by the call instruction that called GetEIP. +// This function depends on frame pointers not being omitted. It is possible +// to write a pure asm version of this routine that has no compiler-generated +// preamble and uses %esp instead of %ebp; that would function in the +// absence of frame pointers. However, the simpler approach is used here +// because GetEBP and stackwalking necessarily depends on access to frame +// pointers. Because this function depends on a call instruction and the +// compiler-generated preamble, inlining is disabled. +static u_int32_t GetEIP() __attribute__((noinline)); +static u_int32_t GetEIP() { + u_int32_t eip; + __asm__ __volatile__( + "movl 4(%%ebp), %0" + : "=a" (eip) + ); + return eip; +} + + +#elif defined(__ppc__) + + +// GetSP returns the current value of the %r1 register, which by convention, +// is the stack pointer on ppc. Because it's implemented as a function, +// %r1 itself contains GetSP's own stack pointer and not the caller's stack +// pointer. Dereference %r1 to obtain the caller's stack pointer, which the +// compiler-generated prolog stored on the stack. Because this function +// depends on the compiler-generated prolog, inlining is disabled. +static u_int32_t GetSP() __attribute__((noinline)); +static u_int32_t GetSP() { + u_int32_t sp; + __asm__ __volatile__( + "lwz %0, 0(r1)" + : "=r" (sp) + ); + return sp; +} + + +// GetPC returns the program counter identifying the next instruction to +// execute after GetPC returns. It obtains this information from the +// link register, where it was placed by the branch instruction that called +// GetPC. Because this function depends on the caller's use of a branch +// instruction, inlining is disabled. +static u_int32_t GetPC() __attribute__((noinline)); +static u_int32_t GetPC() { + u_int32_t lr; + __asm__ __volatile__( + "mflr %0" + : "=r" (lr) + ); + return lr; +} + + +#elif defined(__sparc__) + + +// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which +// by convention, is the stack pointer on sparc. Because it's implemented +// as a function, %sp itself contains GetSP's own stack pointer and not +// the caller's stack pointer. Dereference to obtain the caller's stack +// pointer, which the compiler-generated prolog stored on the stack. +// Because this function depends on the compiler-generated prolog, inlining +// is disabled. +static u_int32_t GetSP() __attribute__((noinline)); +static u_int32_t GetSP() { + u_int32_t sp; + __asm__ __volatile__( + "mov %%fp, %0" + : "=r" (sp) + ); + return sp; +} + +// GetFP returns the current value of the %fp register. Because it's +// implemented as a function, %fp itself contains GetFP's frame pointer +// and not the caller's frame pointer. Dereference %fp to obtain the +// caller's frame pointer, which the compiler-generated preamble stored +// on the stack (provided frame pointers are not being omitted.) Because +// this function depends on the compiler-generated preamble, inlining is +// disabled. +static u_int32_t GetFP() __attribute__((noinline)); +static u_int32_t GetFP() { + u_int32_t fp; + __asm__ __volatile__( + "ld [%%fp+56], %0" + : "=r" (fp) + ); + return fp; +} + +// GetPC returns the program counter identifying the next instruction to +// execute after GetPC returns. It obtains this information from the +// link register, where it was placed by the branch instruction that called +// GetPC. Because this function depends on the caller's use of a branch +// instruction, inlining is disabled. +static u_int32_t GetPC() __attribute__((noinline)); +static u_int32_t GetPC() { + u_int32_t pc; + __asm__ __volatile__( + "mov %%i7, %0" + : "=r" (pc) + ); + return pc + 8; +} + +#endif // __i386__ || __ppc__ || __sparc__ + +#elif defined(__SUNPRO_CC) + +#if defined(__i386__) +extern "C" { +extern u_int32_t GetEIP(); +extern u_int32_t GetEBP(); +extern u_int32_t GetESP(); +} +#elif defined(__sparc__) +extern "C" { +extern u_int32_t GetPC(); +extern u_int32_t GetFP(); +extern u_int32_t GetSP(); +} +#endif // __i386__ || __sparc__ + +#endif // __GNUC__ || __SUNPRO_CC + +// CountCallerFrames returns the number of stack frames beneath the function +// that called CountCallerFrames. Because this function's return value +// is dependent on the size of the stack beneath it, inlining is disabled, +// and any function that calls this should not be inlined either. +#if defined(__GNUC__) +static unsigned int CountCallerFrames() __attribute__((noinline)); +#elif defined(__SUNPRO_CC) +static unsigned int CountCallerFrames(); +#endif +static unsigned int CountCallerFrames() { + SelfMemoryRegion memory; + BasicSourceLineResolver resolver; + +#if defined(__i386__) + MDRawContextX86 context = MDRawContextX86(); + context.eip = GetEIP(); + context.ebp = GetEBP(); + context.esp = GetESP(); + + StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL, + NULL, &resolver); +#elif defined(__ppc__) + MDRawContextPPC context = MDRawContextPPC(); + context.srr0 = GetPC(); + context.gpr[1] = GetSP(); + + StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL, + NULL, &resolver); +#elif defined(__sparc__) + MDRawContextSPARC context = MDRawContextSPARC(); + context.pc = GetPC(); + context.g_r[14] = GetSP(); + context.g_r[30] = GetFP(); + + StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory, + NULL, NULL, &resolver); +#endif // __i386__ || __ppc__ || __sparc__ + + CallStack stack; + stackwalker.Walk(&stack); + +#ifdef PRINT_STACKS + printf("\n"); + for (unsigned int frame_index = 0; + frame_index < stack.frames()->size(); + ++frame_index) { + StackFrame *frame = stack.frames()->at(frame_index); + printf("frame %-3d instruction = 0x%08" PRIx64, + frame_index, frame->instruction); +#if defined(__i386__) + StackFrameX86 *frame_x86 = reinterpret_cast(frame); + printf(" esp = 0x%08x ebp = 0x%08x\n", + frame_x86->context.esp, frame_x86->context.ebp); +#elif defined(__ppc__) + StackFramePPC *frame_ppc = reinterpret_cast(frame); + printf(" gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]); +#elif defined(__sparc__) + StackFrameSPARC *frame_sparc = reinterpret_cast(frame); + printf(" sp = 0x%08x fp = 0x%08x\n", + frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]); +#endif // __i386__ || __ppc__ || __sparc__ + } +#endif // PRINT_STACKS + + // Subtract 1 because the caller wants the number of frames beneath + // itself. Because the caller called us, subract two for our frame and its + // frame, which are included in stack.size(). + return stack.frames()->size() - 2; +} + + +// Recursor verifies that the number stack frames beneath itself is one more +// than the number of stack frames beneath its parent. When depth frames +// have been reached, Recursor stops checking and returns success. If the +// frame count check fails at any depth, Recursor will stop and return false. +// Because this calls CountCallerFrames, inlining is disabled. +#if defined(__GNUC__) +static bool Recursor(unsigned int depth, unsigned int parent_callers) + __attribute__((noinline)); +#elif defined(__SUNPRO_CC) +static bool Recursor(unsigned int depth, unsigned int parent_callers); +#endif +static bool Recursor(unsigned int depth, unsigned int parent_callers) { + unsigned int callers = CountCallerFrames(); + if (callers != parent_callers + 1) + return false; + + if (depth) + return Recursor(depth - 1, callers); + + // depth == 0 + return true; +} + + +// Because this calls CountCallerFrames, inlining is disabled - but because +// it's main (and nobody calls it other than the entry point), it wouldn't +// be inlined anyway. +#if defined(__GNUC__) +int main(int argc, char** argv) __attribute__((noinline)); +#elif defined(__SUNPRO_CC) +int main(int argc, char** argv); +#endif +int main(int argc, char** argv) { + BPLOG_INIT(&argc, &argv); + + return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1; +} + + +#else +// Not i386 or ppc or sparc? We can only test stacks we know how to walk. + + +int main(int argc, char **argv) { + BPLOG_INIT(&argc, &argv); + + // "make check" interprets an exit status of 77 to mean that the test is + // not supported. + BPLOG(ERROR) << "Selftest not supported here"; + return 77; +} + + +#endif // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__) diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest_sol.s b/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest_sol.s new file mode 100644 index 00000000..648b0499 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_selftest_sol.s @@ -0,0 +1,111 @@ +/* Copyright (c) 2007, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* stackwalker_selftest_sol.s + * On Solaris, the recommeded compiler is CC, so we can not use gcc inline + * asm, use this method instead. + * + * How to compile: as -P -L -D_ASM -D_STDC -K PIC -o \ + * src/processor/stackwalker_selftest_sol.o \ + * src/processor/stackwalker_selftest_sol.s + * + * Author: Michael Shang + */ + +#include + +#if defined(__i386) + + +ENTRY(GetEBP) + pushl %ebp + movl %esp,%ebp + subl $0x00000004,%esp + movl 0x00000000(%ebp),%eax + movl %eax,0xfffffffc(%ebp) + movl 0xfffffffc(%ebp),%eax + leave + ret +SET_SIZE(GetEBP) + +ENTRY(GetEIP) + pushl %ebp + movl %esp,%ebp + subl $0x00000004,%esp + movl 0x00000004(%ebp),%eax + movl %eax,0xfffffffc(%ebp) + movl 0xfffffffc(%ebp),%eax + leave + ret +SET_SIZE(GetEIP) + +ENTRY(GetESP) + pushl %ebp + movl %esp,%ebp + subl $0x00000004,%esp + movl %ebp,%eax + movl %eax,0xfffffffc(%ebp) + movl 0xfffffffc(%ebp),%eax + addl $0x00000008,%eax + leave + ret +SET_SIZE(GetESP) + + +#elif defined(__sparc) + + +ENTRY(GetPC) + save %sp, -120, %sp + mov %i7, %i4 + inccc 8, %i4 + mov %i4, %i0 + ret + restore +SET_SIZE(GetPC) + +ENTRY(GetSP) + save %sp, -120, %sp + mov %fp, %i4 + mov %i4, %i0 + ret + restore +SET_SIZE(GetSP) + +ENTRY(GetFP) + save %sp, -120, %sp + ld [%fp + 56], %g1 + mov %g1, %i0 + ret + restore +SET_SIZE(GetFP) + + +#endif // __i386 || __sparc diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.cc new file mode 100644 index 00000000..b7b6f005 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.cc @@ -0,0 +1,139 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_sparc.cc: sparc-specific stackwalker. +// +// See stackwalker_sparc.h for documentation. +// +// Author: Michael Shang + + +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/logging.h" +#include "processor/stackwalker_sparc.h" + +namespace google_breakpad { + + +StackwalkerSPARC::StackwalkerSPARC(const SystemInfo *system_info, + const MDRawContextSPARC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : Stackwalker(system_info, memory, modules, supplier, resolver), + context_(context) { +} + + +StackFrame* StackwalkerSPARC::GetContextFrame() { + if (!context_ || !memory_) { + BPLOG(ERROR) << "Can't get context frame without context or memory"; + return NULL; + } + + StackFrameSPARC *frame = new StackFrameSPARC(); + + // The instruction pointer is stored directly in a register, so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFrameSPARC::CONTEXT_VALID_ALL; + frame->instruction = frame->context.pc; + + return frame; +} + + +StackFrame* StackwalkerSPARC::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } + + StackFrameSPARC *last_frame = static_cast( + stack->frames()->back()); + + // new: caller + // old: callee + // %fp, %i6 and g_r[30] is the same, see minidump_format.h + // %sp, %o6 and g_r[14] is the same, see minidump_format.h + // %sp_new = %fp_old + // %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6 + // %pc_new = *(%fp_old + 32 + 32 - 4) + 8 + // which is callee's %i7 plus 8 + + // A caller frame must reside higher in memory than its callee frames. + // Anything else is an error, or an indication that we've reached the + // end of the stack. + u_int32_t stack_pointer = last_frame->context.g_r[30]; + if (stack_pointer <= last_frame->context.g_r[14]) { + return NULL; + } + + u_int32_t instruction; + if (!memory_->GetMemoryAtAddress(stack_pointer + 60, + &instruction) || instruction <= 1) { + return NULL; + } + + u_int32_t stack_base; + if (!memory_->GetMemoryAtAddress(stack_pointer + 56, + &stack_base) || stack_base <= 1) { + return NULL; + } + + StackFrameSPARC *frame = new StackFrameSPARC(); + + frame->context = last_frame->context; + frame->context.g_r[14] = stack_pointer; + frame->context.g_r[30] = stack_base; + + // frame->context.pc is the return address, which is 2 instruction + // past the branch that caused us to arrive at the callee, which are + // a CALL instruction then a NOP instruction. + // frame_ppc->instruction to 8 less than that. Since all sparc + // instructions are 4 bytes wide, this is the address of the branch + // instruction. This allows source line information to match up with the + // line that contains a function call. Callers that require the exact + // return address value may access the %i7/g_r[31] field of StackFrameSPARC. + frame->context.pc = instruction + 8; + frame->instruction = instruction; + frame->context_validity = StackFrameSPARC::CONTEXT_VALID_PC | + StackFrameSPARC::CONTEXT_VALID_SP | + StackFrameSPARC::CONTEXT_VALID_FP; + + return frame; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.h b/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.h new file mode 100644 index 00000000..f051e5bb --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_sparc.h @@ -0,0 +1,86 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_sparc.h: sparc-specific stackwalker. +// +// Provides stack frames given sparc register context and a memory region +// corresponding to an sparc stack. +// +// Author: Michael Shang + + +#ifndef PROCESSOR_STACKWALKER_SPARC_H__ +#define PROCESSOR_STACKWALKER_SPARC_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerSPARC : public Stackwalker { + public: + // context is a sparc context object that gives access to sparc-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerSPARC(const SystemInfo *system_info, + const MDRawContextSPARC *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and + // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or + // alternate conventions as guided by stack_frame_info_). + // Implementation of Stackwalker, using ppc context (stack pointer in %r1, + // saved program counter in %srr0) and stack conventions (saved stack + // pointer at 0(%r1), return address at 8(0(%r1)). + // Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and + // stack conventions (saved %sp at) + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextSPARC *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_SPARC_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.cc b/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.cc new file mode 100644 index 00000000..e39df17f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.cc @@ -0,0 +1,432 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_x86.cc: x86-specific stackwalker. +// +// See stackwalker_x86.h for documentation. +// +// Author: Mark Mentovai + + +#include "processor/postfix_evaluator-inl.h" + +#include "processor/stackwalker_x86.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/linked_ptr.h" +#include "processor/logging.h" +#include "processor/stack_frame_info.h" + +namespace google_breakpad { + + +StackwalkerX86::StackwalkerX86(const SystemInfo *system_info, + const MDRawContextX86 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : Stackwalker(system_info, memory, modules, supplier, resolver), + context_(context) { + if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { + // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid. + // Mark memory_ = NULL, which will cause stackwalking to fail. + BPLOG(ERROR) << "Memory out of range for stackwalking: " << + HexString(memory_->GetBase()) << "+" << + HexString(memory_->GetSize()); + memory_ = NULL; + } +} + + +StackFrame* StackwalkerX86::GetContextFrame() { + if (!context_ || !memory_) { + BPLOG(ERROR) << "Can't get context frame without context or memory"; + return NULL; + } + + StackFrameX86 *frame = new StackFrameX86(); + + // The instruction pointer is stored directly in a register, so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL; + frame->instruction = frame->context.eip; + + return frame; +} + + +StackFrame* StackwalkerX86::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } + + StackFrameX86 *last_frame = static_cast( + stack->frames()->back()); + StackFrameInfo *last_frame_info = stack_frame_info.back().get(); + + // This stackwalker sets each frame's %esp to its value immediately prior + // to the CALL into the callee. This means that %esp points to the last + // callee argument pushed onto the stack, which may not be where %esp points + // after the callee returns. Specifically, the value is correct for the + // cdecl calling convention, but not other conventions. The cdecl + // convention requires a caller to pop its callee's arguments from the + // stack after the callee returns. This is usually accomplished by adding + // the known size of the arguments to %esp. Other calling conventions, + // including stdcall, thiscall, and fastcall, require the callee to pop any + // parameters stored on the stack before returning. This is usually + // accomplished by using the RET n instruction, which pops n bytes off + // the stack after popping the return address. + // + // Because each frame's %esp will point to a location on the stack after + // callee arguments have been PUSHed, when locating things in a stack frame + // relative to %esp, the size of the arguments to the callee need to be + // taken into account. This seems a little bit unclean, but it's better + // than the alternative, which would need to take these same things into + // account, but only for cdecl functions. With this implementation, we get + // to be agnostic about each function's calling convention. Furthermore, + // this is how Windows debugging tools work, so it means that the %esp + // values produced by this stackwalker directly correspond to the %esp + // values you'll see there. + // + // If the last frame has no callee (because it's the context frame), just + // set the callee parameter size to 0: the stack pointer can't point to + // callee arguments because there's no callee. This is correct as long + // as the context wasn't captured while arguments were being pushed for + // a function call. Note that there may be functions whose parameter sizes + // are unknown, 0 is also used in that case. When that happens, it should + // be possible to walk to the next frame without reference to %esp. + + int frames_already_walked = stack_frame_info.size(); + u_int32_t last_frame_callee_parameter_size = 0; + if (frames_already_walked >= 2) { + StackFrameInfo *last_frame_callee_info = + stack_frame_info[frames_already_walked - 2].get(); + if (last_frame_callee_info && + last_frame_callee_info->valid & StackFrameInfo::VALID_PARAMETER_SIZE) { + last_frame_callee_parameter_size = + last_frame_callee_info->parameter_size; + } + } + + // Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used + // in each program string, and their previous values are known, so set them + // here. .cbCalleeParams is a Breakpad extension that allows us to use + // the PostfixEvaluator engine when certain types of debugging information + // are present without having to write the constants into the program string + // as literals. + PostfixEvaluator::DictionaryType dictionary; + dictionary["$ebp"] = last_frame->context.ebp; + dictionary["$esp"] = last_frame->context.esp; + dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size; + + if (last_frame_info && last_frame_info->valid == StackFrameInfo::VALID_ALL) { + // FPO debugging data is available. Initialize constants. + dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size; + dictionary[".cbLocals"] = last_frame_info->local_size; + dictionary[".raSearchStart"] = last_frame->context.esp + + last_frame_callee_parameter_size + + last_frame_info->local_size + + last_frame_info->saved_register_size; + } + if (last_frame_info && + last_frame_info->valid & StackFrameInfo::VALID_PARAMETER_SIZE) { + // This is treated separately because it can either come from FPO data or + // from other debugging data. + dictionary[".cbParams"] = last_frame_info->parameter_size; + } + + // Decide what type of program string to use. The program string is in + // postfix notation and will be passed to PostfixEvaluator::Evaluate. + // Given the dictionary and the program string, it is possible to compute + // the return address and the values of other registers in the calling + // function. When encountering a nontraditional frame (one which takes + // advantage of FPO), the stack may need to be scanned for these values. + // For traditional frames, simple deterministic dereferencing suffices + // without any need for scanning. The results of program string evaluation + // will be used to determine whether to scan for better values. + string program_string; + bool traditional_frame = true; + bool recover_ebp = true; + if (last_frame_info && last_frame_info->valid == StackFrameInfo::VALID_ALL) { + // FPO data available. + traditional_frame = false; + if (!last_frame_info->program_string.empty()) { + // The FPO data has its own program string, which will tell us how to + // get to the caller frame, and may even fill in the values of + // nonvolatile registers and provide pointers to local variables and + // parameters. In some cases, particularly with program strings that use + // .raSearchStart, the stack may need to be scanned afterward. + program_string = last_frame_info->program_string; + } else if (last_frame_info->allocates_base_pointer) { + // The function corresponding to the last frame doesn't use the frame + // pointer for conventional purposes, but it does allocate a new + // frame pointer and use it for its own purposes. Its callee's + // information is still accessed relative to %esp, and the previous + // value of %ebp can be recovered from a location in its stack frame, + // within the saved-register area. + // + // Functions that fall into this category use the %ebp register for + // a purpose other than the frame pointer. They restore the caller's + // %ebp before returning. These functions create their stack frame + // after a CALL by decrementing the stack pointer in an amount + // sufficient to store local variables, and then PUSHing saved + // registers onto the stack. Arguments to a callee function, if any, + // are PUSHed after that. Walking up to the caller, therefore, + // can be done solely with calculations relative to the stack pointer + // (%esp). The return address is recovered from the memory location + // above the known sizes of the callee's parameters, saved registers, + // and locals. The caller's stack pointer (the value of %esp when + // the caller executed CALL) is the location immediately above the + // saved return address. The saved value of %ebp to be restored for + // the caller is at a known location in the saved-register area of + // the stack frame. + // + // For this type of frame, MSVC 14 (from Visual Studio 8/2005) in + // link-time code generation mode (/LTCG and /GL) can generate erroneous + // debugging data. The reported size of saved registers can be 0, + // which is clearly an error because these frames must, at the very + // least, save %ebp. For this reason, in addition to those given above + // about the use of .raSearchStart, the stack may need to be scanned + // for a better return address and a better frame pointer after the + // program string is evaluated. + // + // %eip_new = *(%esp_old + callee_params + saved_regs + locals) + // %ebp_new = *(%esp_old + callee_params + saved_regs - 8) + // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 + program_string = "$eip .raSearchStart ^ = " + "$ebp $esp .cbCalleeParams + .cbSavedRegs + 8 - ^ = " + "$esp .raSearchStart 4 + ="; + } else { + // The function corresponding to the last frame doesn't use %ebp at + // all. The callee frame is located relative to %esp. + // + // The called procedure's instruction pointer and stack pointer are + // recovered in the same way as the case above, except that no + // frame pointer (%ebp) is used at all, so it is not saved anywhere + // in the callee's stack frame and does not need to be recovered. + // Because %ebp wasn't used in the callee, whatever value it has + // is the value that it had in the caller, so it can be carried + // straight through without bringing its validity into question. + // + // Because of the use of .raSearchStart, the stack will possibly be + // examined to locate a better return address after program string + // evaluation. The stack will not be examined to locate a saved + // %ebp value, because these frames do not save (or use) %ebp. + // + // %eip_new = *(%esp_old + callee_params + saved_regs + locals) + // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 + // %ebp_new = %ebp_old + program_string = "$eip .raSearchStart ^ = " + "$esp .raSearchStart 4 + ="; + recover_ebp = false; + } + } else { + // No FPO information is available for the last frame. Assume that the + // standard %ebp-using x86 calling convention is in use. + // + // The typical x86 calling convention, when frame pointers are present, + // is for the calling procedure to use CALL, which pushes the return + // address onto the stack and sets the instruction pointer (%eip) to + // the entry point of the called routine. The called routine then + // PUSHes the calling routine's frame pointer (%ebp) onto the stack + // before copying the stack pointer (%esp) to the frame pointer (%ebp). + // Therefore, the calling procedure's frame pointer is always available + // by dereferencing the called procedure's frame pointer, and the return + // address is always available at the memory location immediately above + // the address pointed to by the called procedure's frame pointer. The + // calling procedure's stack pointer (%esp) is 8 higher than the value + // of the called procedure's frame pointer at the time the calling + // procedure made the CALL: 4 bytes for the return address pushed by the + // CALL itself, and 4 bytes for the callee's PUSH of the caller's frame + // pointer. + // + // Instruction and frame pointer recovery for these traditional frames is + // entirely deterministic, and the stack will not be scanned after + // recovering these values. + // + // %eip_new = *(%ebp_old + 4) + // %esp_new = %ebp_old + 8 + // %ebp_new = *(%ebp_old) + program_string = "$eip $ebp 4 + ^ = " + "$esp $ebp 8 + = " + "$ebp $ebp ^ ="; + } + + // Now crank it out, making sure that the program string set at least the + // two required variables. + PostfixEvaluator evaluator = + PostfixEvaluator(&dictionary, memory_); + PostfixEvaluator::DictionaryValidityType dictionary_validity; + if (!evaluator.Evaluate(program_string, &dictionary_validity) || + dictionary_validity.find("$eip") == dictionary_validity.end() || + dictionary_validity.find("$esp") == dictionary_validity.end()) { + return NULL; + } + + // If this stack frame did not use %ebp in a traditional way, locating the + // return address isn't entirely deterministic. In that case, the stack + // can be scanned to locate the return address. + // + // Even in nontraditional frames, if program string evaluation resulted in + // both %eip and %ebp values of 0, trust that the end of the stack has been + // reached and don't scan for anything else. + if (!traditional_frame && + (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0)) { + int offset = 0; + + // This scan can only be done if a CodeModules object is available, to + // check that candidate return addresses are in fact inside a module. + // + // TODO(mmentovai): This ignores dynamically-generated code. One possible + // solution is to check the minidump's memory map to see if the candidate + // %eip value comes from a mapped executable page, although this would + // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad + // client doesn't currently write (it would need to call MiniDumpWriteDump + // with the MiniDumpWithFullMemoryInfo type bit set). Even given this + // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce + // an independent execute privilege on memory pages. + + u_int32_t eip = dictionary["$eip"]; + if (modules_ && !modules_->GetModuleForAddress(eip)) { + const int kRASearchWords = 15; + + // The instruction pointer at .raSearchStart was invalid, so start + // looking one 32-bit word above that location. + u_int32_t location_start = dictionary[".raSearchStart"] + 4; + + for (u_int32_t location = location_start; + location <= location_start + kRASearchWords * 4; + location += 4) { + if (!memory_->GetMemoryAtAddress(location, &eip)) + break; + + if (modules_->GetModuleForAddress(eip)) { + // This is a better return address that what program string + // evaluation found. Use it, and set %esp to the location above the + // one where the return address was found. + // + // TODO(mmentovai): The return-address check can be made even + // stronger in modules for which debugging data is available. In + // that case, it's possible to check that the candidate return + // address is inside a known function. + + dictionary["$eip"] = eip; + dictionary["$esp"] = location + 4; + offset = location - location_start; + break; + } + } + } + + // When trying to recover the previous value of the frame pointer (%ebp), + // start looking at the lowest possible address in the saved-register + // area, and look at the entire saved register area, increased by the + // size of |offset| to account for additional data that may be on the + // stack. The scan is performed from the highest possible address to + // the lowest, because we expect that the function's prolog would have + // saved %ebp early. + u_int32_t ebp = dictionary["$ebp"]; + u_int32_t value; // throwaway variable to check pointer validity + if (recover_ebp && !memory_->GetMemoryAtAddress(ebp, &value)) { + int fp_search_bytes = last_frame_info->saved_register_size + offset; + u_int32_t location_end = last_frame->context.esp + + last_frame_callee_parameter_size; + + for (u_int32_t location = location_end + fp_search_bytes; + location >= location_end; + location -= 4) { + if (!memory_->GetMemoryAtAddress(location, &ebp)) + break; + + if (memory_->GetMemoryAtAddress(ebp, &value)) { + // The candidate value is a pointer to the same memory region + // (the stack). Prefer it as a recovered %ebp result. + dictionary["$ebp"] = ebp; + break; + } + } + } + } + + // Treat an instruction address of 0 as end-of-stack. Treat incorrect stack + // direction as end-of-stack to enforce progress and avoid infinite loops. + if (dictionary["$eip"] == 0 || + dictionary["$esp"] <= last_frame->context.esp) { + return NULL; + } + + // Create a new stack frame (ownership will be transferred to the caller) + // and fill it in. + StackFrameX86 *frame = new StackFrameX86(); + + frame->context = last_frame->context; + frame->context.eip = dictionary["$eip"]; + frame->context.esp = dictionary["$esp"]; + frame->context.ebp = dictionary["$ebp"]; + frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | + StackFrameX86::CONTEXT_VALID_ESP | + StackFrameX86::CONTEXT_VALID_EBP; + + // These are nonvolatile (callee-save) registers, and the program string + // may have filled them in. + if (dictionary_validity.find("$ebx") != dictionary_validity.end()) { + frame->context.ebx = dictionary["$ebx"]; + frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX; + } + if (dictionary_validity.find("$esi") != dictionary_validity.end()) { + frame->context.esi = dictionary["$esi"]; + frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI; + } + if (dictionary_validity.find("$edi") != dictionary_validity.end()) { + frame->context.edi = dictionary["$edi"]; + frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI; + } + + // frame->context.eip is the return address, which is one instruction + // past the CALL that caused us to arrive at the callee. Set + // frame->instruction to one less than that. This won't reference the + // beginning of the CALL instruction, but it's guaranteed to be within the + // CALL, which is sufficient to get the source line information to match up + // with the line that contains a function call. Callers that require the + // exact return address value may access the context.eip field of + // StackFrameX86. + frame->instruction = frame->context.eip - 1; + + return frame; +} + + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.h b/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.h new file mode 100644 index 00000000..14b9e8b9 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/stackwalker_x86.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// stackwalker_x86.h: x86-specific stackwalker. +// +// Provides stack frames given x86 register context and a memory region +// corresponding to an x86 stack. +// +// Author: Mark Mentovai + + +#ifndef PROCESSOR_STACKWALKER_X86_H__ +#define PROCESSOR_STACKWALKER_X86_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + + +class StackwalkerX86 : public Stackwalker { + public: + // context is an x86 context object that gives access to x86-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerX86(const SystemInfo *system_info, + const MDRawContextX86 *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and + // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or + // alternate conventions as guided by stack_frame_info_). + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextX86 *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_X86_H__ diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dmp b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dmp new file mode 100644 index 00000000..1a6feee7 Binary files /dev/null and b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dmp differ diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dump.out b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dump.out new file mode 100644 index 00000000..d8816e5d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.dump.out @@ -0,0 +1,705 @@ +MDRawHeader + signature = 0x504d444d + version = 0x5128a793 + stream_count = 9 + stream_directory_rva = 0x20 + checksum = 0x0 + time_date_stamp = 0x45d35f73 2007-02-14 19:13:55 + flags = 0x0 + +mDirectory[0] +MDRawDirectory + stream_type = 3 + location.data_size = 100 + location.rva = 0x184 + +mDirectory[1] +MDRawDirectory + stream_type = 4 + location.data_size = 1408 + location.rva = 0x1e8 + +mDirectory[2] +MDRawDirectory + stream_type = 5 + location.data_size = 52 + location.rva = 0x1505 + +mDirectory[3] +MDRawDirectory + stream_type = 6 + location.data_size = 168 + location.rva = 0xdc + +mDirectory[4] +MDRawDirectory + stream_type = 7 + location.data_size = 56 + location.rva = 0x8c + +mDirectory[5] +MDRawDirectory + stream_type = 15 + location.data_size = 24 + location.rva = 0xc4 + +mDirectory[6] +MDRawDirectory + stream_type = 1197932545 + location.data_size = 12 + location.rva = 0x14f9 + +mDirectory[7] +MDRawDirectory + stream_type = 0 + location.data_size = 0 + location.rva = 0x0 + +mDirectory[8] +MDRawDirectory + stream_type = 0 + location.data_size = 0 + location.rva = 0x0 + +Streams: + stream type 0x0 at index 8 + stream type 0x3 at index 0 + stream type 0x4 at index 1 + stream type 0x5 at index 2 + stream type 0x6 at index 3 + stream type 0x7 at index 4 + stream type 0xf at index 5 + stream type 0x47670001 at index 6 + +MinidumpThreadList + thread_count = 2 + +thread[0] +MDRawThread + thread_id = 0xbf4 + suspend_count = 0 + priority_class = 0x0 + priority = 0x0 + teb = 0x7ffdf000 + stack.start_of_memory_range = 0x12f31c + stack.memory.data_size = 0xce4 + stack.memory.rva = 0x1639 + thread_context.data_size = 0x2cc + thread_context.rva = 0xd94 + +MDRawContextX86 + context_flags = 0x1003f + dr0 = 0x0 + dr1 = 0x0 + dr2 = 0x0 + dr3 = 0x0 + dr6 = 0x0 + dr7 = 0x0 + float_save.control_word = 0xffff027f + float_save.status_word = 0xffff0000 + float_save.tag_word = 0xffffffff + float_save.error_offset = 0x0 + float_save.error_selector = 0x220000 + float_save.data_offset = 0x0 + float_save.data_selector = 0xffff0000 + float_save.register_area[80] = 0x0000000018b72200000118b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + float_save.cr0_npx_state = 0x0 + gs = 0x0 + fs = 0x3b + es = 0x23 + ds = 0x23 + edi = 0x0 + esi = 0x7b8 + ebx = 0x7c883780 + edx = 0x7c97c0d8 + ecx = 0x7c80b46e + eax = 0x400000 + ebp = 0x12f384 + eip = 0x7c90eb94 + cs = 0x1b + eflags = 0x246 + esp = 0x12f320 + ss = 0x23 + extended_registers[512] = 0x7f0200000000220000000000000000000000000000000000801f0000ffff00000000000018b72200000100000000000018b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509917c4e09917c38b622002400020024b42200020000009041917c0070fd7f0510907cccb22200000000009cb3220018ee907c7009917cc0e4977c6f3e917c623e917c08020000dcb62200b4b622001e000000000000000000000000000000000000002eb42200000000000f000000020000001e00200000fcfd7f2f63796764726976652f632f444f43554d457e312f4d4d454e544f7e312f4c4f43414c537e312f54656d7000000000000000000130b422000000004300000000000000001efcfd7f4509917c4e09917c5ad9000008b32200b4b62200 + +Stack +0x00000000c0e9907ccb25807cb8070000000000000000000034ff1200b0fe12008037887c140000000100000000000000000000001000000027e0907c2e39917c0050fd7f00f0fd7f000000000400000034f312006947c788d4f31200a89a837cf825807c0000000098f312003225807cb8070000ffffffff00000000e4f31200ff1d4000b8070000ffffffffa8fa12008037887c0e1c4000a8fa120000000000ff792a0f64f91200b01b400000004000b0fe12000040020070fa1200084042000000000080fa120080fa12004e30867ca8fa12000000000000000000000000000018000002100000e3ef907c0000000079d900000000000048f41200000014003207917c0500000078071400000014000000000020f412003207917ca05f140018ee907cfa00000074f61200000000009615917ceb06917cf00298000100000000000000384f14009615917ceb06917c7801140008000000404f14000000a659985f1400080000000000000018ee907c90fea700400698003815917c184f1400eb06917c00000000800000000000a65988f69f0090f51200a569917cf8f41200d95c878880f5120043ef907c480485000500000090f5120088fea700a8212400000000000000000080f512002469917cf8fbfd7fa821240008000000f500000000000000384d850078019800a8fa120004000000a05f140096d4917c00000000b0d4917c0000000008069800184f140000000000104f140000000000184f140000004000000000010040020063003a005c0074006500730074005f006100700070002e006500780065000000000000002f00000028000000184f1400780185007801140028000000000000000000140084f3120010000000d8f5120018ee907cf006917cffffffffeb06917ce619917c88e6a7003003000001030000ff1b917c0000980080e6a70080069800400698000000980080e6a70000000000000000000000000080e6a7000818000088e6a700d759927c78019800081800000210000000009800f8f31200280a0000dcf6120018ee907cf006917cffffffffeb06917c0859927c00009800080000005859927c00000000000001000000a659000000005a6202000010000068fe030001000000dffe03000000010000000100fffffe7f0100000001c0c27700008500000000002dc0c27700000000684aaf590000a659241a917c80c0977c0000000000000000cd5c927c0050fd7f0000a65900000100080000004550fd7f0000000000000000000000000050fd7fcd5c927c05000000d4f61200f45c927c80e4977c05000000010000000050fd7f18f712007009917cc0e4977c172e817cff2d817c000000000000a6590000a6590210000000f0fd7f05000000e8f612000806980064f81200a89a837c002e817cffffffffff2d817cc8242400dd8ea75901000000000000004cf712003608a9590000a65901000000000000000100000060f71200e407a9596cf7120000004000000000010040020063003a005c0074006500730074005f006100700070002e0065007800650000006d05917c905f140000000000440d020000000000604f14000c0000007801140000000000a04e1400d84d8700400687004509917c0800000000000000000000004000000078011400a8038700404f14000510907c000000000000000078011400980387000800000008000000c0e4977cd04d8700f835887c7801140010000000a0e7ae591600000030fd1200d39b917c44000000620000000000a65950e9ae59d8eaae59a80387000100000014040000000000000100000002000000f800a659c003870001000000780114009508917c0000a659091b917c020000000900000040000000a2fd12009cfd1200404f1400a2fd1200d04d8700640187000000000000000000d04d870010000000d84d8700384f1400a803870010000000c00300000000870074fb1200404f14006cfe120018ee907cf006917cffffffffeb06917ca09d400000008700000000000400000000000000ffffff3fc04d8700ccfd12009c4d400004000000fa19917cb84d870064018700c04d8700063440000400000018000000c04d870079d90000c0038700fa31400000000000c04d8700c04d87000000000001000000b0fe120082294000c04d87000000000000000000c04d870048fe12008cfe120000000000e224400040fe12008cfe1200c04d8700d84d8700b0fe12008600817c54fa1200d8f9120000000000160018005479420079d90000000000000757917c00000200a4f91200a4f91200a4f91200020000000200000000000000c4f912000000000079d9000014fb12004cfa120014fb1200005a917c00fa1200a0fb120001000000655a917ca405817c74c1977ce705817c00000000f4fd120098fb120000000000a0fb12000000000090fb12000000800070fa120000000000000000000000000016001800547942000000000001000000000000000000000000000000000000003308917ca89a837c0000807c0000807ce800807c2cfa12001fe2907c11fa877cffffffffe06f817c000000006cfa12001c0000000f000000e06f817c8fc60000f0f312000060817cc8fa1200a89a837c7039867cfffffffff0ff1200da36847ca8fa1200099b837cb0fa120000000000b0fa12000000000000000000000000009cfb1200b8fb1200d4fa1200bf37907c9cfb1200e0ff1200b8fb120070fb1200b0ff1200d837907ce0ff120084fb12008b37907c9cfb1200e0ff1200b8fb120070fb1200a89a837c010000009cfb1200e0ff12006078937c9cfb1200e0ff1200b8fb120070fb1200a89a837c280a00009cfb12000200000018ee907c9032917cffffffff8832917c3364917c68fb1200000087003207917c02000000dc31917c1232917c8132917c8832917c1e000000c01e2400080200003807917c54fb12003207917cc4fb120018ee907c9032917c0000130000d01200beb4800088fe1200faea907c00000000b8fb12009cfb1200b8fb1200050000c000000000000000009e4240000200000001000000450000003f0001000000000000000000000000000000000000000000000000007f02ffff0000ffffffffffff0000000000002200000000000000ffff0000000018b72200000118b7220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b0000002300000023000000280a000002000000c1ab807c58bc420094fe12004500000088fe12009e4240001b0000004602010084fe1200230000007f0200000000220000000000000000000000000000000000801f0000ffff00000000000018b72200000100000000000018b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509917c4e09917c38b622002400020024b42200020000009041917c0070fd7f0510907cccb22200000000009cb3220018ee907c7009917cc0e4977c6f3e917c623e917c08020000dcb62200b4b622001e000000000000000000000000000000000000002eb42200000000000f000000020000001e00200000fcfd7f2f63796764726976652f632f444f43554d457e312f4d4d454e544f7e312f4c4f43414c537e312f54656d7000000000000000000130b422000000004300000000000000001efcfd7f4509917c4e09917c5ad9000008b32200b4b622004500000070ff120000424000b8278700dc31917c00000000004c870000000020040000000000000007000000000000004042400000000000000000002e000000000000000cff12007b434100010000000700000084434100004d87002e39917cffffffff24000000240000002700000000000000584d870004000000b1944000244c87002a0000002f000000c0fe1200004d8700584d87000000a659b0b9a859015d400015aa400000000000b4070000784e14000000000001000000f40b00000000000000000000bc070000b8070000f40b0000a8fa120000000000009c4000599c400094b240004f752a0fc0ff1200ec534000010000003039870050398700ff752a0f00002400a02024000050fd7f050000c00100000005000000000000000000240084ff1200acfa1200e0ff1200d06f4000a70b7a0f00000000f0ff1200d76f817c00002400a02024000050fd7f050000c0c8ff1200a8fa1200ffffffffa89a837ce06f817c0000000000000000000000004354400000000000 + +thread[1] +MDRawThread + thread_id = 0x11c0 + suspend_count = 0 + priority_class = 0x0 + priority = 0x0 + teb = 0x7ffde000 + stack.start_of_memory_range = 0x97f6e8 + stack.memory.data_size = 0x918 + stack.memory.rva = 0x231d + thread_context.data_size = 0x2cc + thread_context.rva = 0x1060 + +MDRawContextX86 + context_flags = 0x1003f + dr0 = 0x0 + dr1 = 0x0 + dr2 = 0x0 + dr3 = 0x0 + dr6 = 0x0 + dr7 = 0x0 + float_save.control_word = 0xffff027f + float_save.status_word = 0xffff0000 + float_save.tag_word = 0xffffffff + float_save.error_offset = 0x0 + float_save.error_selector = 0x870000 + float_save.data_offset = 0x0 + float_save.data_selector = 0xffff0000 + float_save.register_area[80] = 0x84fb120000001400320778071400000014000000f4fe1200a0fd120018eeb0fd12003815917c961534ff120034ff12000000e7712a0f2a0000005400ccfb120068514000584d540000002a000000f4fe + float_save.cr0_npx_state = 0x0 + gs = 0x0 + fs = 0x3b + es = 0x23 + ds = 0x23 + edi = 0x145b00 + esi = 0x145aa8 + ebx = 0x145ad0 + edx = 0x7c90eb94 + ecx = 0x7 + eax = 0xa80000 + ebp = 0x97f6fc + eip = 0x7c90eb94 + cs = 0x1b + eflags = 0x246 + esp = 0x97f6ec + ss = 0x23 + extended_registers[512] = 0x7f0200000000870000000000000000000000000000000000801f0000ccfb120084fb1200000014003207917c050000007807140000001400000000005cfb1200f4fe1200a0fd120018ee907c2d020000b0fd12003815917c9615917ceb06917c34ff120034ff12000000000060000000e7712a0f2a0000005400000000000000ccfb120068514000584d870034fc1200540000002a000000f4fe1200f8fe12002c2f4000584d87005e00000034fc12005400000000000000b0fe1200f4fe1200c0fe12005f21400034fc12002a0000003b762a0f91214000303132330000870038393a3b3c3d3e3f4041424300000000070000003bd11e2340061400b858101e5e03e0652e005c00320033003100650064003100780114002d0066003300380034002d0000000000390034002d0062003800350038002d0031003000984e1400350065003000330065003000360035002e0064006d0070000000907c08000000ffffffff8832917cbeb4807c780114001d00f40b784e14000401000044fd120050fd1200c01e240078011400bdb9807ca04e14007c80c2770000000008fd120078011400ecfc1200f0fc1200e6b9807cffffffff7c80c27708fd12001c00000024fd1200e92a867c7c80c277b45a887c8037887c2d0200000080c2770000c17780000000005003000010000020000000780114005cff12001648847c091b917c + +Stack +0x8000108020fa97009fd7907c0000000048f7970005000f0040061400000000004cf7970037b9807c00000000000000003103917c780114000000000061dc907cf1b8807c00000000ffffffff70f79700000000000000000054f797003082140001000000000000000200000000000000000000007cf7970020b9807c0e00000004000000006000000000a80078011400000000000882140092d5907c8b9b807c9c070000d0f89700780114009c07000038821400807f140020dea85910fa9700780114009807000088fb9700e07f14009c0700000000000078011400000000000882140000000000000000000000000078011400ba0300000000000000000000000000000000000000000000000000007801140000000000000000000000000000000000c0030000000000000000000000000000088214005c0057000600000078011400000000005c00730079007300740065006d0033000082140068011400000000000000000000821400d47f1400807f140070f8970061eea859e000a8000000a8001c4e000084f89700bdeea859e000a8000000a8001c4e0000a4f897005fefa8590000a8000000000006000000c4f89700e000a80060fe9700c8f897005abfa8590000a80000000000060000001c000000d47f1400807f1400380000006ce9907c88b9807cffffffff0000a80000000000807f140030fa97007fc3a859a0c4a859b0fb970060fe9700684f1400504500004c010400ca9610410000000000000000e0000e210b01070a00400000003a000000000000f1100000001000000000bf760000000000100000000200000500010005000100040000000000000000b00000000400009ba2000000001400285214000000000034fa97007801140034fa9700910e917c080614006d05917cc84d85005c4e8500684f140000000000b04800002852140078011400e00300003052140000000000000000000000000078011400c403000030821400380000000000000000000000000000000000000000000000000000003882140048050000780200003800000000100000ec000000b8470000400000000000000000000000000000000000140000000000807f140000000000000000000000000000000101a900000060fe9700dcff9700dcff97000050fd7f78fa970054fa9700ad9d917c8cfa9700c2066f7f0e000000000000001c01000078fa9700c84d850068fa970085ae807c78fc970024fc970083dba85978fc97008cfa9700800000008edba85914010000050000000100000096020000b8fc97003815917c9615917ceb06917c60fe970060fe9700c4fd9700d8fa9700000014003207917c21000000b80c14000000140030521400b0fa9700fffffffff4fc970018ee907c3807917cffffffff3207917cab06917ceb06917ccc4f140060fe9700684f1400e0004000e4fa9700a863917c74fb970018ee907c3808917cffffffff3308917c5b2c817c872c817c00000000f4fb9700000000000000000054fd970018ee907c4006140064fd97003815917c00e0fd7feb06917c684f140038821400780114000050fd7facfb970000000000000004000000000090fe97000000000018fb970050531400508b1400a89a837cffe9907cf60d817ca807000000000000ffe9907cf60d817c08000000000000000000000000000000585314003cfc97003882140000000000160e817cc4fd970060fe970058531400208f1400588b1400460f917c50531400208f1400780114003082140000000000b8fc970078011400b8fc9700910e917c080614006d05917c3882140060fe97000000000000000000960200003082140078011400ffe9907c38821400a807000000000000780114005853140058fc9700505314001000000000000000160e817c784e8500c4fd9700388214000000000024010000f00c00001000000044fc970000000000c7e2907ce721807cffffffffe8f69700388214001809000098fc9700acfc9700d2e2a859ffffffffe8f697003882140018090000c4fc97003882140060fe9700c4fd9700ccfc97004ee3a859ffffffffe8f69700000000003882140018090000e0fc9700f4fc970093b2a859ffffffffe8f69700000000003882140018090000c4fd970060fe9700a85a140078fd9700a5b3a85960fe9700c4fd9700684f1400e8f697000000000018090000000000000200000080fd9700c4fd970060fe970000000000f40b000000000000000000000000000000f0fd7f000000001cf3120000000000e40c000039160000cc020000940d00000000000000000000000000000000000002000000ac4f14006010000098fd97005eb7a8593916000000000000684f1400784e85000000000084ff9700d4fe97007bb9a85960fe9700c4fd9700684f14003849140084ff9700010000000000000008ff9700f40b0000090000000000000020000000200000006c0000008c000000380000001e000000c4000000dc000000a80000008401000064000000b801000030000000e801000080050000e8010000680700000000000068070000680700000000000005150000340000002915000039150000fc1600001d23000068070000600300008a070000c80a0000310a00002c130000f91400000c000000352c000000000000ffffffff5c0f0000c84d8500784e8500884e85000000000000000000000000004c010000fc39a6590000000002000000050000000100000000008500280a000001000001cc0200009c0000000b00000050000000040000000010000000000000000000000001000000000000000000000000000034ff970078baa859384914005c0f0000c84d850001000000884e8500684f140008ff970064ff970000000000a8070000b0fe1200f40b00009cfb120000000000b8fb12000000000000000000ae20140000000000884e8500784e8500c84d8500a8fa120011204000ffffffff5c0f0000a80700000000000078ff970064ff970000000000adbf807c2025807cecff97000100000084ff970003000000c0110000f40b0000f40b0000a8fa120000000000010067470c0000006cff9700bc070000ffffffff000000006c1a4000f40b000000fa12000000000000004000a09d4000b0fe120083b6807cb0fe120000004000a09d4000b0fe120000e0fd7f00069c86c0ff9700d8863f86ffffffffa89a837c90b6807c000000000000000000000000301a4000b0fe120000000000 + +MinidumpModuleList + module_count = 13 + +module[0] +MDRawModule + base_of_image = 0x400000 + size_of_image = 0x2d000 + checksum = 0x0 + time_date_stamp = 0x45d35f6c + module_name_rva = 0x78a + version_info.signature = 0x0 + version_info.struct_version = 0x0 + version_info.file_version = 0x0:0x0 + version_info.product_version = 0x0:0x0 + version_info.file_flags_mask = 0x0 + version_info.file_flags = 0x0 + version_info.file_os = 0x0 + version_info.file_type = 0x0 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 40 + cv_record.rva = 0x132c + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "c:\test_app.exe" + (code_identifier) = "45D35F6C2d000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 5a9832e5-2872-41c1-838e-d98914e9b7ff + (cv_record).age = 1 + (cv_record).pdb_file_name = "c:\test_app.pdb" + (misc_record) = (null) + (debug_file) = "c:\test_app.pdb" + (debug_identifier) = "5A9832E5287241C1838ED98914E9B7FF1" + (version) = "" + +module[1] +MDRawModule + base_of_image = 0x7c900000 + size_of_image = 0xb0000 + checksum = 0xaf2f7 + time_date_stamp = 0x411096b4 + module_name_rva = 0x7ae + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 34 + cv_record.rva = 0x1354 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\ntdll.dll" + (code_identifier) = "411096B4b0000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 36515fb5-d043-45e4-91f6-72fa2e2878c0 + (cv_record).age = 2 + (cv_record).pdb_file_name = "ntdll.pdb" + (misc_record) = (null) + (debug_file) = "ntdll.pdb" + (debug_identifier) = "36515FB5D04345E491F672FA2E2878C02" + (version) = "5.1.2600.2180" + +module[2] +MDRawModule + base_of_image = 0x7c800000 + size_of_image = 0xf4000 + checksum = 0xf724d + time_date_stamp = 0x44ab9a84 + module_name_rva = 0x7ee + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280b81 + version_info.product_version = 0x50001:0xa280b81 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 37 + cv_record.rva = 0x1376 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\kernel32.dll" + (code_identifier) = "44AB9A84f4000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = bce8785c-57b4-4245-a669-896b6a19b954 + (cv_record).age = 2 + (cv_record).pdb_file_name = "kernel32.pdb" + (misc_record) = (null) + (debug_file) = "kernel32.pdb" + (debug_identifier) = "BCE8785C57B44245A669896B6A19B9542" + (version) = "5.1.2600.2945" + +module[3] +MDRawModule + base_of_image = 0x774e0000 + size_of_image = 0x13d000 + checksum = 0x13dc6b + time_date_stamp = 0x42e5be93 + module_name_rva = 0x834 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280aa6 + version_info.product_version = 0x50001:0xa280aa6 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 34 + cv_record.rva = 0x139b + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\ole32.dll" + (code_identifier) = "42E5BE9313d000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 683b65b2-46f4-4187-96d2-ee6d4c55eb11 + (cv_record).age = 2 + (cv_record).pdb_file_name = "ole32.pdb" + (misc_record) = (null) + (debug_file) = "ole32.pdb" + (debug_identifier) = "683B65B246F4418796D2EE6D4C55EB112" + (version) = "5.1.2600.2726" + +module[4] +MDRawModule + base_of_image = 0x77dd0000 + size_of_image = 0x9b000 + checksum = 0xa0de4 + time_date_stamp = 0x411096a7 + module_name_rva = 0x874 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 37 + cv_record.rva = 0x13bd + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\advapi32.dll" + (code_identifier) = "411096A79b000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 455d6c5f-184d-45bb-b5c5-f30f82975114 + (cv_record).age = 2 + (cv_record).pdb_file_name = "advapi32.pdb" + (misc_record) = (null) + (debug_file) = "advapi32.pdb" + (debug_identifier) = "455D6C5F184D45BBB5C5F30F829751142" + (version) = "5.1.2600.2180" + +module[5] +MDRawModule + base_of_image = 0x77e70000 + size_of_image = 0x91000 + checksum = 0x9c482 + time_date_stamp = 0x411096ae + module_name_rva = 0x8ba + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 35 + cv_record.rva = 0x13e2 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\rpcrt4.dll" + (code_identifier) = "411096AE91000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = bea45a72-1da1-41da-a3ba-86b3a2031153 + (cv_record).age = 2 + (cv_record).pdb_file_name = "rpcrt4.pdb" + (misc_record) = (null) + (debug_file) = "rpcrt4.pdb" + (debug_identifier) = "BEA45A721DA141DAA3BA86B3A20311532" + (version) = "5.1.2600.2180" + +module[6] +MDRawModule + base_of_image = 0x77f10000 + size_of_image = 0x47000 + checksum = 0x4d0d0 + time_date_stamp = 0x43b34feb + module_name_rva = 0x8fc + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280b02 + version_info.product_version = 0x50001:0xa280b02 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 34 + cv_record.rva = 0x1405 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\gdi32.dll" + (code_identifier) = "43B34FEB47000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = c0ea66be-00a6-4bd7-aef7-9e443a91869c + (cv_record).age = 2 + (cv_record).pdb_file_name = "gdi32.pdb" + (misc_record) = (null) + (debug_file) = "gdi32.pdb" + (debug_identifier) = "C0EA66BE00A64BD7AEF79E443A91869C2" + (version) = "5.1.2600.2818" + +module[7] +MDRawModule + base_of_image = 0x77d40000 + size_of_image = 0x90000 + checksum = 0x9505c + time_date_stamp = 0x42260159 + module_name_rva = 0x93c + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280a3e + version_info.product_version = 0x50001:0xa280a3e + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 35 + cv_record.rva = 0x1427 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\user32.dll" + (code_identifier) = "4226015990000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = ee2b714d-83a3-4c9d-8802-7621272f8326 + (cv_record).age = 2 + (cv_record).pdb_file_name = "user32.pdb" + (misc_record) = (null) + (debug_file) = "user32.pdb" + (debug_identifier) = "EE2B714D83A34C9D88027621272F83262" + (version) = "5.1.2600.2622" + +module[8] +MDRawModule + base_of_image = 0x77c10000 + size_of_image = 0x58000 + checksum = 0x57cd3 + time_date_stamp = 0x41109752 + module_name_rva = 0x97e + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x70000:0xa280884 + version_info.product_version = 0x60001:0x21be0884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x1 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 35 + cv_record.rva = 0x144a + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\msvcrt.dll" + (code_identifier) = "4110975258000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = a678f3c3-0ded-426b-8390-32b996987e38 + (cv_record).age = 1 + (cv_record).pdb_file_name = "msvcrt.pdb" + (misc_record) = (null) + (debug_file) = "msvcrt.pdb" + (debug_identifier) = "A678F3C30DED426B839032B996987E381" + (version) = "7.0.2600.2180" + +module[9] +MDRawModule + base_of_image = 0x76390000 + size_of_image = 0x1d000 + checksum = 0x2a024 + time_date_stamp = 0x411096ae + module_name_rva = 0x9c0 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 34 + cv_record.rva = 0x146d + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\imm32.dll" + (code_identifier) = "411096AE1d000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 2c17a49c-251b-4c8e-b9e2-ad13d7d9ea16 + (cv_record).age = 2 + (cv_record).pdb_file_name = "imm32.pdb" + (misc_record) = (null) + (debug_file) = "imm32.pdb" + (debug_identifier) = "2C17A49C251B4C8EB9E2AD13D7D9EA162" + (version) = "5.1.2600.2180" + +module[10] +MDRawModule + base_of_image = 0x59a60000 + size_of_image = 0xa1000 + checksum = 0xa8824 + time_date_stamp = 0x4110969a + module_name_rva = 0xa00 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 36 + cv_record.rva = 0x148f + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\dbghelp.dll" + (code_identifier) = "4110969Aa1000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 39559573-e21b-46f2-8e28-6923be9e6a76 + (cv_record).age = 1 + (cv_record).pdb_file_name = "dbghelp.pdb" + (misc_record) = (null) + (debug_file) = "dbghelp.pdb" + (debug_identifier) = "39559573E21B46F28E286923BE9E6A761" + (version) = "5.1.2600.2180" + +module[11] +MDRawModule + base_of_image = 0x77c00000 + size_of_image = 0x8000 + checksum = 0x11d78 + time_date_stamp = 0x411096b7 + module_name_rva = 0xa44 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 36 + cv_record.rva = 0x14b3 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\version.dll" + (code_identifier) = "411096B78000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = 180a90c4-0384-463e-82dd-c45b2c8ab76e + (cv_record).age = 2 + (cv_record).pdb_file_name = "version.pdb" + (misc_record) = (null) + (debug_file) = "version.pdb" + (debug_identifier) = "180A90C40384463E82DDC45B2C8AB76E2" + (version) = "5.1.2600.2180" + +module[12] +MDRawModule + base_of_image = 0x76bf0000 + size_of_image = 0xb000 + checksum = 0xa29b + time_date_stamp = 0x411096ca + module_name_rva = 0xa88 + version_info.signature = 0xfeef04bd + version_info.struct_version = 0x10000 + version_info.file_version = 0x50001:0xa280884 + version_info.product_version = 0x50001:0xa280884 + version_info.file_flags_mask = 0x3f + version_info.file_flags = 0x0 + version_info.file_os = 0x40004 + version_info.file_type = 0x2 + version_info.file_subtype = 0x0 + version_info.file_date = 0x0:0x0 + cv_record.data_size = 34 + cv_record.rva = 0x14d7 + misc_record.data_size = 0 + misc_record.rva = 0x0 + (code_file) = "C:\WINDOWS\system32\psapi.dll" + (code_identifier) = "411096CAb000" + (cv_record).cv_signature = 0x53445352 + (cv_record).signature = a5c3a1f9-689f-43d8-ad22-8a0929388970 + (cv_record).age = 2 + (cv_record).pdb_file_name = "psapi.pdb" + (misc_record) = (null) + (debug_file) = "psapi.pdb" + (debug_identifier) = "A5C3A1F9689F43D8AD228A09293889702" + (version) = "5.1.2600.2180" + +MinidumpMemoryList + region_count = 3 + +region[0] +MDMemoryDescriptor + start_of_memory_range = 0x7c90eb14 + memory.data_size = 0x100 + memory.rva = 0x1539 +Memory +0xff83c4ec890424c744240401000000895c2408c74424100000000054e877000000c208009090909090558bec83ec508944240c64a1180000008b80a4010000890424c744240400000000c744240800000000c74424100000000054e8380000008b04248be55dc3908da424000000008d490090909090908bd40f349090909090c38da424000000008d64240090909090908d542408cd2ec3558bec9c81ecd00200008985dcfdffff898dd8fdffff8b45088b4d0489480c8d852cfdffff8988b80000008998a40000008990a800000089b0a000000089b89c0000008d4d0c8988c40000008b4d008988b40000008b4dfc8988c00000008c88bc0000008c989800 + +region[1] +MDMemoryDescriptor + start_of_memory_range = 0x12f31c + memory.data_size = 0xce4 + memory.rva = 0x1639 +Memory +0x00000000c0e9907ccb25807cb8070000000000000000000034ff1200b0fe12008037887c140000000100000000000000000000001000000027e0907c2e39917c0050fd7f00f0fd7f000000000400000034f312006947c788d4f31200a89a837cf825807c0000000098f312003225807cb8070000ffffffff00000000e4f31200ff1d4000b8070000ffffffffa8fa12008037887c0e1c4000a8fa120000000000ff792a0f64f91200b01b400000004000b0fe12000040020070fa1200084042000000000080fa120080fa12004e30867ca8fa12000000000000000000000000000018000002100000e3ef907c0000000079d900000000000048f41200000014003207917c0500000078071400000014000000000020f412003207917ca05f140018ee907cfa00000074f61200000000009615917ceb06917cf00298000100000000000000384f14009615917ceb06917c7801140008000000404f14000000a659985f1400080000000000000018ee907c90fea700400698003815917c184f1400eb06917c00000000800000000000a65988f69f0090f51200a569917cf8f41200d95c878880f5120043ef907c480485000500000090f5120088fea700a8212400000000000000000080f512002469917cf8fbfd7fa821240008000000f500000000000000384d850078019800a8fa120004000000a05f140096d4917c00000000b0d4917c0000000008069800184f140000000000104f140000000000184f140000004000000000010040020063003a005c0074006500730074005f006100700070002e006500780065000000000000002f00000028000000184f1400780185007801140028000000000000000000140084f3120010000000d8f5120018ee907cf006917cffffffffeb06917ce619917c88e6a7003003000001030000ff1b917c0000980080e6a70080069800400698000000980080e6a70000000000000000000000000080e6a7000818000088e6a700d759927c78019800081800000210000000009800f8f31200280a0000dcf6120018ee907cf006917cffffffffeb06917c0859927c00009800080000005859927c00000000000001000000a659000000005a6202000010000068fe030001000000dffe03000000010000000100fffffe7f0100000001c0c27700008500000000002dc0c27700000000684aaf590000a659241a917c80c0977c0000000000000000cd5c927c0050fd7f0000a65900000100080000004550fd7f0000000000000000000000000050fd7fcd5c927c05000000d4f61200f45c927c80e4977c05000000010000000050fd7f18f712007009917cc0e4977c172e817cff2d817c000000000000a6590000a6590210000000f0fd7f05000000e8f612000806980064f81200a89a837c002e817cffffffffff2d817cc8242400dd8ea75901000000000000004cf712003608a9590000a65901000000000000000100000060f71200e407a9596cf7120000004000000000010040020063003a005c0074006500730074005f006100700070002e0065007800650000006d05917c905f140000000000440d020000000000604f14000c0000007801140000000000a04e1400d84d8700400687004509917c0800000000000000000000004000000078011400a8038700404f14000510907c000000000000000078011400980387000800000008000000c0e4977cd04d8700f835887c7801140010000000a0e7ae591600000030fd1200d39b917c44000000620000000000a65950e9ae59d8eaae59a80387000100000014040000000000000100000002000000f800a659c003870001000000780114009508917c0000a659091b917c020000000900000040000000a2fd12009cfd1200404f1400a2fd1200d04d8700640187000000000000000000d04d870010000000d84d8700384f1400a803870010000000c00300000000870074fb1200404f14006cfe120018ee907cf006917cffffffffeb06917ca09d400000008700000000000400000000000000ffffff3fc04d8700ccfd12009c4d400004000000fa19917cb84d870064018700c04d8700063440000400000018000000c04d870079d90000c0038700fa31400000000000c04d8700c04d87000000000001000000b0fe120082294000c04d87000000000000000000c04d870048fe12008cfe120000000000e224400040fe12008cfe1200c04d8700d84d8700b0fe12008600817c54fa1200d8f9120000000000160018005479420079d90000000000000757917c00000200a4f91200a4f91200a4f91200020000000200000000000000c4f912000000000079d9000014fb12004cfa120014fb1200005a917c00fa1200a0fb120001000000655a917ca405817c74c1977ce705817c00000000f4fd120098fb120000000000a0fb12000000000090fb12000000800070fa120000000000000000000000000016001800547942000000000001000000000000000000000000000000000000003308917ca89a837c0000807c0000807ce800807c2cfa12001fe2907c11fa877cffffffffe06f817c000000006cfa12001c0000000f000000e06f817c8fc60000f0f312000060817cc8fa1200a89a837c7039867cfffffffff0ff1200da36847ca8fa1200099b837cb0fa120000000000b0fa12000000000000000000000000009cfb1200b8fb1200d4fa1200bf37907c9cfb1200e0ff1200b8fb120070fb1200b0ff1200d837907ce0ff120084fb12008b37907c9cfb1200e0ff1200b8fb120070fb1200a89a837c010000009cfb1200e0ff12006078937c9cfb1200e0ff1200b8fb120070fb1200a89a837c280a00009cfb12000200000018ee907c9032917cffffffff8832917c3364917c68fb1200000087003207917c02000000dc31917c1232917c8132917c8832917c1e000000c01e2400080200003807917c54fb12003207917cc4fb120018ee907c9032917c0000130000d01200beb4800088fe1200faea907c00000000b8fb12009cfb1200b8fb1200050000c000000000000000009e4240000200000001000000450000003f0001000000000000000000000000000000000000000000000000007f02ffff0000ffffffffffff0000000000002200000000000000ffff0000000018b72200000118b7220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b0000002300000023000000280a000002000000c1ab807c58bc420094fe12004500000088fe12009e4240001b0000004602010084fe1200230000007f0200000000220000000000000000000000000000000000801f0000ffff00000000000018b72200000100000000000018b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509917c4e09917c38b622002400020024b42200020000009041917c0070fd7f0510907cccb22200000000009cb3220018ee907c7009917cc0e4977c6f3e917c623e917c08020000dcb62200b4b622001e000000000000000000000000000000000000002eb42200000000000f000000020000001e00200000fcfd7f2f63796764726976652f632f444f43554d457e312f4d4d454e544f7e312f4c4f43414c537e312f54656d7000000000000000000130b422000000004300000000000000001efcfd7f4509917c4e09917c5ad9000008b32200b4b622004500000070ff120000424000b8278700dc31917c00000000004c870000000020040000000000000007000000000000004042400000000000000000002e000000000000000cff12007b434100010000000700000084434100004d87002e39917cffffffff24000000240000002700000000000000584d870004000000b1944000244c87002a0000002f000000c0fe1200004d8700584d87000000a659b0b9a859015d400015aa400000000000b4070000784e14000000000001000000f40b00000000000000000000bc070000b8070000f40b0000a8fa120000000000009c4000599c400094b240004f752a0fc0ff1200ec534000010000003039870050398700ff752a0f00002400a02024000050fd7f050000c00100000005000000000000000000240084ff1200acfa1200e0ff1200d06f4000a70b7a0f00000000f0ff1200d76f817c00002400a02024000050fd7f050000c0c8ff1200a8fa1200ffffffffa89a837ce06f817c0000000000000000000000004354400000000000 + +region[2] +MDMemoryDescriptor + start_of_memory_range = 0x97f6e8 + memory.data_size = 0x918 + memory.rva = 0x231d +Memory +0x8000108020fa97009fd7907c0000000048f7970005000f0040061400000000004cf7970037b9807c00000000000000003103917c780114000000000061dc907cf1b8807c00000000ffffffff70f79700000000000000000054f797003082140001000000000000000200000000000000000000007cf7970020b9807c0e00000004000000006000000000a80078011400000000000882140092d5907c8b9b807c9c070000d0f89700780114009c07000038821400807f140020dea85910fa9700780114009807000088fb9700e07f14009c0700000000000078011400000000000882140000000000000000000000000078011400ba0300000000000000000000000000000000000000000000000000007801140000000000000000000000000000000000c0030000000000000000000000000000088214005c0057000600000078011400000000005c00730079007300740065006d0033000082140068011400000000000000000000821400d47f1400807f140070f8970061eea859e000a8000000a8001c4e000084f89700bdeea859e000a8000000a8001c4e0000a4f897005fefa8590000a8000000000006000000c4f89700e000a80060fe9700c8f897005abfa8590000a80000000000060000001c000000d47f1400807f1400380000006ce9907c88b9807cffffffff0000a80000000000807f140030fa97007fc3a859a0c4a859b0fb970060fe9700684f1400504500004c010400ca9610410000000000000000e0000e210b01070a00400000003a000000000000f1100000001000000000bf760000000000100000000200000500010005000100040000000000000000b00000000400009ba2000000001400285214000000000034fa97007801140034fa9700910e917c080614006d05917cc84d85005c4e8500684f140000000000b04800002852140078011400e00300003052140000000000000000000000000078011400c403000030821400380000000000000000000000000000000000000000000000000000003882140048050000780200003800000000100000ec000000b8470000400000000000000000000000000000000000140000000000807f140000000000000000000000000000000101a900000060fe9700dcff9700dcff97000050fd7f78fa970054fa9700ad9d917c8cfa9700c2066f7f0e000000000000001c01000078fa9700c84d850068fa970085ae807c78fc970024fc970083dba85978fc97008cfa9700800000008edba85914010000050000000100000096020000b8fc97003815917c9615917ceb06917c60fe970060fe9700c4fd9700d8fa9700000014003207917c21000000b80c14000000140030521400b0fa9700fffffffff4fc970018ee907c3807917cffffffff3207917cab06917ceb06917ccc4f140060fe9700684f1400e0004000e4fa9700a863917c74fb970018ee907c3808917cffffffff3308917c5b2c817c872c817c00000000f4fb9700000000000000000054fd970018ee907c4006140064fd97003815917c00e0fd7feb06917c684f140038821400780114000050fd7facfb970000000000000004000000000090fe97000000000018fb970050531400508b1400a89a837cffe9907cf60d817ca807000000000000ffe9907cf60d817c08000000000000000000000000000000585314003cfc97003882140000000000160e817cc4fd970060fe970058531400208f1400588b1400460f917c50531400208f1400780114003082140000000000b8fc970078011400b8fc9700910e917c080614006d05917c3882140060fe97000000000000000000960200003082140078011400ffe9907c38821400a807000000000000780114005853140058fc9700505314001000000000000000160e817c784e8500c4fd9700388214000000000024010000f00c00001000000044fc970000000000c7e2907ce721807cffffffffe8f69700388214001809000098fc9700acfc9700d2e2a859ffffffffe8f697003882140018090000c4fc97003882140060fe9700c4fd9700ccfc97004ee3a859ffffffffe8f69700000000003882140018090000e0fc9700f4fc970093b2a859ffffffffe8f69700000000003882140018090000c4fd970060fe9700a85a140078fd9700a5b3a85960fe9700c4fd9700684f1400e8f697000000000018090000000000000200000080fd9700c4fd970060fe970000000000f40b000000000000000000000000000000f0fd7f000000001cf3120000000000e40c000039160000cc020000940d00000000000000000000000000000000000002000000ac4f14006010000098fd97005eb7a8593916000000000000684f1400784e85000000000084ff9700d4fe97007bb9a85960fe9700c4fd9700684f14003849140084ff9700010000000000000008ff9700f40b0000090000000000000020000000200000006c0000008c000000380000001e000000c4000000dc000000a80000008401000064000000b801000030000000e801000080050000e8010000680700000000000068070000680700000000000005150000340000002915000039150000fc1600001d23000068070000600300008a070000c80a0000310a00002c130000f91400000c000000352c000000000000ffffffff5c0f0000c84d8500784e8500884e85000000000000000000000000004c010000fc39a6590000000002000000050000000100000000008500280a000001000001cc0200009c0000000b00000050000000040000000010000000000000000000000001000000000000000000000000000034ff970078baa859384914005c0f0000c84d850001000000884e8500684f140008ff970064ff970000000000a8070000b0fe1200f40b00009cfb120000000000b8fb12000000000000000000ae20140000000000884e8500784e8500c84d8500a8fa120011204000ffffffff5c0f0000a80700000000000078ff970064ff970000000000adbf807c2025807cecff97000100000084ff970003000000c0110000f40b0000f40b0000a8fa120000000000010067470c0000006cff9700bc070000ffffffff000000006c1a4000f40b000000fa12000000000000004000a09d4000b0fe120083b6807cb0fe120000004000a09d4000b0fe120000e0fd7f00069c86c0ff9700d8863f86ffffffffa89a837c90b6807c000000000000000000000000301a4000b0fe120000000000 + +MDException + thread_id = 0xbf4 + exception_record.exception_code = 0xc0000005 + exception_record.exception_flags = 0x0 + exception_record.exception_record = 0x0 + exception_record.exception_address = 0x40429e + exception_record.number_parameters = 2 + exception_record.exception_information[ 0] = 0x1 + exception_record.exception_information[ 1] = 0x45 + thread_context.data_size = 716 + thread_context.rva = 0xac8 + +MDRawContextX86 + context_flags = 0x1003f + dr0 = 0x0 + dr1 = 0x0 + dr2 = 0x0 + dr3 = 0x0 + dr6 = 0x0 + dr7 = 0x0 + float_save.control_word = 0xffff027f + float_save.status_word = 0xffff0000 + float_save.tag_word = 0xffffffff + float_save.error_offset = 0x0 + float_save.error_selector = 0x220000 + float_save.data_offset = 0x0 + float_save.data_selector = 0xffff0000 + float_save.register_area[80] = 0x0000000018b72200000118b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + float_save.cr0_npx_state = 0x0 + gs = 0x0 + fs = 0x3b + es = 0x23 + ds = 0x23 + edi = 0xa28 + esi = 0x2 + ebx = 0x7c80abc1 + edx = 0x42bc58 + ecx = 0x12fe94 + eax = 0x45 + ebp = 0x12fe88 + eip = 0x40429e + cs = 0x1b + eflags = 0x10246 + esp = 0x12fe84 + ss = 0x23 + extended_registers[512] = 0x7f0200000000220000000000000000000000000000000000801f0000ffff00000000000018b72200000100000000000018b72200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509917c4e09917c38b622002400020024b42200020000009041917c0070fd7f0510907cccb22200000000009cb3220018ee907c7009917cc0e4977c6f3e917c623e917c08020000dcb62200b4b622001e000000000000000000000000000000000000002eb42200000000000f000000020000001e00200000fcfd7f2f63796764726976652f632f444f43554d457e312f4d4d454e544f7e312f4c4f43414c537e312f54656d7000000000000000000130b422000000004300000000000000001efcfd7f4509917c4e09917c5ad9000008b32200b4b62200 + +MDRawSystemInfo + processor_architecture = 0 + processor_level = 6 + processor_revision = 0xd08 + number_of_processors = 1 + product_type = 1 + major_version = 5 + minor_version = 1 + build_number = 2600 + platform_id = 2 + csd_version_rva = 0x768 + suite_mask = 0x100 + cpu.x86_cpu_info.vendor_id[0] = 0x756e6547 + cpu.x86_cpu_info.vendor_id[1] = 0x49656e69 + cpu.x86_cpu_info.vendor_id[2] = 0x6c65746e + cpu.x86_cpu_info.version_information = 0x6d8 + cpu.x86_cpu_info.feature_information = 0xafe9fbff + cpu.x86_cpu_info.amd_extended_cpu_features = 0xffffffff + (csd_version) = "Service Pack 2" + (cpu_vendor) = "GenuineIntel" + +MDRawMiscInfo + size_of_info = 24 + flags1 = 0x3 + process_id = 0xf5c + process_create_time = 0x45d35f73 + process_user_time = 0x0 + process_kernel_time = 0x0 + +MDRawBreakpadInfo + validity = 0x3 + dump_thread_id = 0x11c0 + requesting_thread_id = 0xbf4 + diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.machine_readable.out b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.machine_readable.out new file mode 100644 index 00000000..e1589534 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.machine_readable.out @@ -0,0 +1,21 @@ +OS|Windows NT|5.1.2600 Service Pack 2 +CPU|x86|GenuineIntel family 6 model 13 stepping 8|1 +Crash|EXCEPTION_ACCESS_VIOLATION|0x45|0 +Module|test_app.exe||test_app.pdb|5A9832E5287241C1838ED98914E9B7FF1|0x00400000|0x0042cfff|1 +Module|dbghelp.dll|5.1.2600.2180|dbghelp.pdb|39559573E21B46F28E286923BE9E6A761|0x59a60000|0x59b00fff|0 +Module|imm32.dll|5.1.2600.2180|imm32.pdb|2C17A49C251B4C8EB9E2AD13D7D9EA162|0x76390000|0x763acfff|0 +Module|psapi.dll|5.1.2600.2180|psapi.pdb|A5C3A1F9689F43D8AD228A09293889702|0x76bf0000|0x76bfafff|0 +Module|ole32.dll|5.1.2600.2726|ole32.pdb|683B65B246F4418796D2EE6D4C55EB112|0x774e0000|0x7761cfff|0 +Module|version.dll|5.1.2600.2180|version.pdb|180A90C40384463E82DDC45B2C8AB76E2|0x77c00000|0x77c07fff|0 +Module|msvcrt.dll|7.0.2600.2180|msvcrt.pdb|A678F3C30DED426B839032B996987E381|0x77c10000|0x77c67fff|0 +Module|user32.dll|5.1.2600.2622|user32.pdb|EE2B714D83A34C9D88027621272F83262|0x77d40000|0x77dcffff|0 +Module|advapi32.dll|5.1.2600.2180|advapi32.pdb|455D6C5F184D45BBB5C5F30F829751142|0x77dd0000|0x77e6afff|0 +Module|rpcrt4.dll|5.1.2600.2180|rpcrt4.pdb|BEA45A721DA141DAA3BA86B3A20311532|0x77e70000|0x77f00fff|0 +Module|gdi32.dll|5.1.2600.2818|gdi32.pdb|C0EA66BE00A64BD7AEF79E443A91869C2|0x77f10000|0x77f56fff|0 +Module|kernel32.dll|5.1.2600.2945|kernel32.pdb|BCE8785C57B44245A669896B6A19B9542|0x7c800000|0x7c8f3fff|0 +Module|ntdll.dll|5.1.2600.2180|ntdll.pdb|36515FB5D04345E491F672FA2E2878C02|0x7c900000|0x7c9affff|0 + +0|0|test_app.exe|`anonymous namespace'::CrashFunction|c:\test_app.cc|58|0x3 +0|1|test_app.exe|main|c:\test_app.cc|65|0x4 +0|2|test_app.exe|__tmainCRTStartup|f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c|327|0x11 +0|3|kernel32.dll|BaseProcessStart|||0x22 diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.out b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.out new file mode 100644 index 00000000..21b425de --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/minidump2.stackwalk.out @@ -0,0 +1,35 @@ +Operating system: Windows NT + 5.1.2600 Service Pack 2 +CPU: x86 + GenuineIntel family 6 model 13 stepping 8 + 1 CPU + +Crash reason: EXCEPTION_ACCESS_VIOLATION +Crash address: 0x45 + +Thread 0 (crashed) + 0 test_app.exe!`anonymous namespace'::CrashFunction [test_app.cc : 58 + 0x3] + eip = 0x0040429e esp = 0x0012fe84 ebp = 0x0012fe88 ebx = 0x7c80abc1 + esi = 0x00000002 edi = 0x00000a28 eax = 0x00000045 ecx = 0x0012fe94 + edx = 0x0042bc58 efl = 0x00010246 + 1 test_app.exe!main [test_app.cc : 65 + 0x4] + eip = 0x00404200 esp = 0x0012fe90 ebp = 0x0012ff70 + 2 test_app.exe!__tmainCRTStartup [crt0.c : 327 + 0x11] + eip = 0x004053ec esp = 0x0012ff78 ebp = 0x0012ffc0 + 3 kernel32.dll!BaseProcessStart + 0x22 + eip = 0x7c816fd7 esp = 0x0012ffc8 ebp = 0x0012fff0 + +Loaded modules: +0x00400000 - 0x0042cfff test_app.exe ??? (main) +0x59a60000 - 0x59b00fff dbghelp.dll 5.1.2600.2180 +0x76390000 - 0x763acfff imm32.dll 5.1.2600.2180 +0x76bf0000 - 0x76bfafff psapi.dll 5.1.2600.2180 +0x774e0000 - 0x7761cfff ole32.dll 5.1.2600.2726 +0x77c00000 - 0x77c07fff version.dll 5.1.2600.2180 +0x77c10000 - 0x77c67fff msvcrt.dll 7.0.2600.2180 +0x77d40000 - 0x77dcffff user32.dll 5.1.2600.2622 +0x77dd0000 - 0x77e6afff advapi32.dll 5.1.2600.2180 +0x77e70000 - 0x77f00fff rpcrt4.dll 5.1.2600.2180 +0x77f10000 - 0x77f56fff gdi32.dll 5.1.2600.2818 +0x7c800000 - 0x7c8f3fff kernel32.dll 5.1.2600.2945 +0x7c900000 - 0x7c9affff ntdll.dll 5.1.2600.2180 diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/module1.out b/thirdparty/google-breakpad/r318/src/processor/testdata/module1.out new file mode 100644 index 00000000..85687828 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/module1.out @@ -0,0 +1,19 @@ +MODULE windows x86 111111111111111111111111111111111 module1.pdb +FILE 1 file1_1.cc +FILE 2 file1_2.cc +FILE 3 file1_3.cc +FUNC 1000 c 0 Function1_1 +1000 4 44 1 +1004 4 45 1 +1008 4 46 1 +FUNC 1100 8 4 Function1_2 +1100 4 65 2 +1104 4 66 2 +FUNC 1200 100 8 Function1_3 +FUNC 1300 100 c Function1_4 +FUNC 2000 0 0 Test_Zero_Size_Function_Is_Ignored +2000 4 88 2 +STACK WIN 4 1000 c 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = +STACK WIN 4 1100 8 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = +STACK WIN 4 1100 100 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = +STACK WIN 4 1300 100 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/module2.out b/thirdparty/google-breakpad/r318/src/processor/testdata/module2.out new file mode 100644 index 00000000..265401c1 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/module2.out @@ -0,0 +1,17 @@ +MODULE windows x86 222222222 module2.pdb +FILE 1 file2_1.cc +FILE 2 file2_2.cc +FILE 3 file2_3.cc +FUNC 2000 c 4 Function2_1 +1000 4 54 1 +1004 4 55 1 +1008 4 56 1 +PUBLIC 2160 0 Public2_1 +FUNC 2170 14 4 Function2_2 +2170 6 10 2 +2176 4 12 2 +217a 6 13 2 +2180 4 21 2 +PUBLIC 21a0 0 Public2_2 +STACK WIN 4 2000 c 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = +STACK WIN 4 2170 14 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ = diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/module3_bad.out b/thirdparty/google-breakpad/r318/src/processor/testdata/module3_bad.out new file mode 100644 index 00000000..bb772486 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/module3_bad.out @@ -0,0 +1,3 @@ +MODULE windows x86 333333333333333333333333333333333 module3.pdb +FILE 1 file1.cc +FUNC 1000 diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/module4_bad.out b/thirdparty/google-breakpad/r318/src/processor/testdata/module4_bad.out new file mode 100644 index 00000000..d01fb2cc --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/module4_bad.out @@ -0,0 +1,5 @@ +MODULE windows x86 444444444444444444444444444444444 module4.pdb +FILE 1 file4_1.cc +FILE 2 file4_2.cc +1000 4 44 1 +1004 4 45 1 diff --git a/thirdparty/google-breakpad/r318/src/processor/testdata/test_app.cc b/thirdparty/google-breakpad/r318/src/processor/testdata/test_app.cc new file mode 100644 index 00000000..f230ef3f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/processor/testdata/test_app.cc @@ -0,0 +1,69 @@ +// 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. + +// This file is used to generate minidump2.dmp and minidump2.sym. +// cl /Zi test_app.cc /Fetest_app.exe /I google_breakpad/src \ +// google_breakpad/src/client/windows/releasestaticcrt/exception_handler.lib +// Then run test_app to generate a dump, and dump_syms to create the .sym file. + +#include + +#include "client/windows/handler/exception_handler.h" + +namespace { + +static bool callback(const wchar_t *dump_path, const wchar_t *id, + void *context, EXCEPTION_POINTERS *exinfo, + MDRawAssertionInfo *assertion, + bool succeeded) { + if (succeeded) { + printf("dump guid is %ws\n", id); + } else { + printf("dump failed\n"); + } + fflush(stdout); + + return succeeded; +} + +static void CrashFunction() { + int *i = reinterpret_cast(0x45); + *i = 5; // crash! +} + +} // namespace + +int main(int argc, char **argv) { + google_breakpad::ExceptionHandler eh( + L".", NULL, callback, NULL, + google_breakpad::ExceptionHandler::HANDLER_ALL); + CrashFunction(); + printf("did not crash?\n"); + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/stamp-h1 b/thirdparty/google-breakpad/r318/src/stamp-h1 new file mode 100644 index 00000000..57ea58e4 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/stamp-h1 @@ -0,0 +1 @@ +timestamp for src/config.h diff --git a/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/Makefile b/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/Makefile new file mode 100644 index 00000000..7d74abad --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/Makefile @@ -0,0 +1,30 @@ +CXX=g++ +CC=gcc + +CXXFLAGS=-gstabs -I../../.. -DNDEBUG -Wall -D_REENTRANT + +.PHONY:all clean + +BIN=dump_syms + +all:$(BIN) + +DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o + +dump_syms:$(DUMP_OBJ) + $(CXX) $(CXXFLAGS) -o $@ $^ + +dump_symbols.o:../../../common/linux/dump_symbols.cc + $(CXX) $(CXXFLAGS) -c $^ + +guid_creator.o:../../../common/linux/guid_creator.cc + $(CXX) $(CXXFLAGS) -c $^ + +file_id.o:../../../common/linux/file_id.cc + $(CXX) $(CXXFLAGS) -c $^ + +md5.o:../../../common/md5.c + $(CC) $(CXXFLAGS) -c $^ + +clean: + rm -f $(BIN) $(DUMP_OBJ) diff --git a/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/dump_syms.cc b/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/dump_syms.cc new file mode 100644 index 00000000..e7eb0a2d --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/linux/dump_syms/dump_syms.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + +#include "common/linux/dump_symbols.h" + +using namespace google_breakpad; + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + const char *binary = argv[1]; + + DumpSymbols dumper; + if (!dumper.WriteSymbolFile(binary, fileno(stdout))) { + fprintf(stderr, "Failed to write symbol file.\n"); + return 1; + } + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/linux/symupload/Makefile b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/Makefile new file mode 100644 index 00000000..c0c49eed --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/Makefile @@ -0,0 +1,24 @@ +CXX=g++ + +CXXFLAGS=-gstabs -I../../.. -Wall -D_REENTRANT + +.PHONY:all clean + +BIN=minidump_upload sym_upload + +all:$(BIN) + +DUMP_UPLOAD_OBJ=minidump_upload.o http_upload.o +SYM_UPLOAD_OBJ=sym_upload.o http_upload.o + +minidump_upload:$(DUMP_UPLOAD_OBJ) + $(CXX) $(CXXFLAGS) -ldl -o $@ $^ + +sym_upload:$(SYM_UPLOAD_OBJ) + $(CXX) $(CXXFLAGS) -ldl -o $@ $^ + +http_upload.o:../../../common/linux/http_upload.cc + $(CXX) $(CXXFLAGS) `curl-config --cflags` -c $^ + +clean: + rm *.o $(BIN) diff --git a/thirdparty/google-breakpad/r318/src/tools/linux/symupload/minidump_upload.cc b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/minidump_upload.cc new file mode 100644 index 00000000..cab6ad43 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/minidump_upload.cc @@ -0,0 +1,144 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_upload.m: Upload a minidump to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// prod: the product name +// ver: the product version +// symbol_file: the breakpad format symbol file + +#include + +#include + +#include "common/linux/http_upload.h" + +using google_breakpad::HTTPUpload; + +struct Options { + std::string minidumpPath; + std::string uploadURLStr; + std::string product; + std::string version; + std::string proxy; + std::string proxy_user_pwd; + bool success; +}; + +//============================================================================= +static void Start(Options *options) { + std::map parameters; + // Add parameters + parameters["prod"] = options->product; + parameters["ver"] = options->version; + + // Send it + std::string response, error; + bool success = HTTPUpload::SendRequest(options->uploadURLStr, + parameters, + options->minidumpPath, + "upload_file_minidump", + options->proxy, + options->proxy_user_pwd, + &response, + &error); + + if (success) { + printf("Successfully sent the minidump file.\n"); + } else { + printf("Failed to send minidump: %s\n", error.c_str()); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } + options->success = success; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit minidump information.\n"); + fprintf(stderr, "Usage: %s [options...] -p -v " + "\n", argv[0]); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " should be a minidump.\n"); + fprintf(stderr, " is the destination for the upload\n"); + + fprintf(stderr, "-p:\t Product name\n"); + fprintf(stderr, "-v:\t Product version\n"); + fprintf(stderr, "-x:\t Use HTTP proxy on given port\n"); + fprintf(stderr, "-u:\t Set proxy user and password\n"); + fprintf(stderr, "-h:\t Usage\n"); + fprintf(stderr, "-?:\t Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "p:u:v:x:h?")) != -1) { + switch (ch) { + case 'p': + options->product = optarg; + break; + case 'u': + options->proxy_user_pwd = optarg; + break; + case 'v': + options->version = optarg; + break; + case 'x': + options->proxy = optarg; + break; + + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->minidumpPath = argv[optind]; + options->uploadURLStr = argv[optind + 1]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + Options options; + SetupOptions(argc, argv, &options); + Start(&options); + return options.success ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/linux/symupload/sym_upload.cc b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/sym_upload.cc new file mode 100644 index 00000000..4e4da065 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/linux/symupload/sym_upload.cc @@ -0,0 +1,216 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// code_file: the basename of the module, e.g. "app" +// debug_file: the basename of the debugging file, e.g. "app" +// debug_identifier: the debug file's identifier, usually consisting of +// the guid and age embedded in the pdb, e.g. +// "11111111BBBB3333DDDD555555555555F" +// version: the file version of the module, e.g. "1.2.3.4" +// os: the operating system that the module was built for +// cpu: the CPU that the module was built for +// symbol_file: the contents of the breakpad-format symbol file + +#include + +#include +#include +#include +#include +#include +#include + +#include "common/linux/http_upload.h" + +using google_breakpad::HTTPUpload; + +typedef struct { + std::string symbolsPath; + std::string uploadURLStr; + std::string proxy; + std::string proxy_user_pwd; + std::string version; + bool success; +} Options; + +static void TokenizeByChar(const std::string &source_string, + int c, std::vector *results) { + assert(results); + std::string::size_type cur_pos = 0, next_pos = 0; + while ((next_pos = source_string.find(c, cur_pos)) != std::string::npos) { + if (next_pos != cur_pos) + results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); + cur_pos = next_pos + 1; + } + if (cur_pos < source_string.size() && next_pos != cur_pos) + results->push_back(source_string.substr(cur_pos)); +} + +//============================================================================= +// Parse out the module line which have 5 parts. +// MODULE +static bool ModuleDataForSymbolFile(const std::string &file, + std::vector *module_parts) { + assert(module_parts); + const size_t kModulePartNumber = 5; + FILE *fp = fopen(file.c_str(), "r"); + if (fp) { + char buffer[1024]; + if (fgets(buffer, sizeof(buffer), fp)) { + std::string line(buffer); + std::string::size_type line_break_pos = line.find_first_of('\n'); + if (line_break_pos == std::string::npos) { + assert(!"The file is invalid!"); + fclose(fp); + return false; + } + line.resize(line_break_pos); + const char kDelimiter = ' '; + TokenizeByChar(line, kDelimiter, module_parts); + if (module_parts->size() != kModulePartNumber) + module_parts->clear(); + } + fclose(fp); + } + + return module_parts->size() == kModulePartNumber; +} + +//============================================================================= +static std::string CompactIdentifier(const std::string &uuid) { + std::vector components; + TokenizeByChar(uuid, '-', &components); + std::string result; + for (size_t i = 0; i < components.size(); ++i) + result += components[i]; + return result; +} + +//============================================================================= +static void Start(Options *options) { + std::map parameters; + options->success = false; + std::vector module_parts; + if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { + fprintf(stderr, "Failed to parse symbol file!\n"); + return; + } + + std::string compacted_id = CompactIdentifier(module_parts[3]); + + // Add parameters + if (!options->version.empty()) + parameters["version"] = options->version; + + // MODULE + // 0 1 2 3 4 + parameters["os"] = module_parts[1]; + parameters["cpu"] = module_parts[2]; + parameters["debug_file"] = module_parts[4]; + parameters["code_file"] = module_parts[4]; + parameters["debug_identifier"] = compacted_id; + std::string response, error; + bool success = HTTPUpload::SendRequest(options->uploadURLStr, + parameters, + options->symbolsPath, + "symbol_file", + options->proxy, + options->proxy_user_pwd, + &response, + &error); + + if (success) { + printf("Successfully sent the symbol file.\n"); + } else { + printf("Failed to send symbol file: %s\n", error.c_str()); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } + options->success = success; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit symbol information.\n"); + fprintf(stderr, "Usage: %s [options...] \n", argv[0]); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " should be created by using the dump_syms tool.\n"); + fprintf(stderr, " is the destination for the upload\n"); + fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); + fprintf(stderr, "-x:\t Use HTTP proxy on given port\n"); + fprintf(stderr, "-u:\t Set proxy user and password\n"); + fprintf(stderr, "-h:\t Usage\n"); + fprintf(stderr, "-?:\t Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "u:v:x:h?")) != -1) { + switch (ch) { + case 'u': + options->proxy_user_pwd = optarg; + break; + case 'v': + options->version = optarg; + break; + case 'x': + options->proxy = optarg; + break; + + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->symbolsPath = argv[optind]; + options->uploadURLStr = argv[optind + 1]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + Options options; + SetupOptions(argc, argv, &options); + Start(&options); + return options.success ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/crash_report.mm b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/crash_report.mm new file mode 100644 index 00000000..f90ee42f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/crash_report.mm @@ -0,0 +1,362 @@ +// 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. + +// crash_report.mm: Convert the contents of a minidump into a format that +// looks more like Apple's CrashReporter format + +#include + +#include +#include + +#include + +#include + +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/minidump_processor.h" +#include "google_breakpad/processor/process_state.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "google_breakpad/processor/system_info.h" +#include "processor/pathname_stripper.h" +#include "processor/scoped_ptr.h" +#include "processor/simple_symbol_supplier.h" + +#include "on_demand_symbol_supplier.h" + +using std::string; + +using google_breakpad::BasicSourceLineResolver; +using google_breakpad::CallStack; +using google_breakpad::CodeModule; +using google_breakpad::CodeModules; +using google_breakpad::MinidumpProcessor; +using google_breakpad::OnDemandSymbolSupplier; +using google_breakpad::PathnameStripper; +using google_breakpad::ProcessState; +using google_breakpad::scoped_ptr; +using google_breakpad::StackFrame; +using google_breakpad::StackFramePPC; +using google_breakpad::StackFrameX86; +using google_breakpad::SystemInfo; + +typedef struct { + NSString *minidumpPath; + NSString *searchDir; + NSString *symbolSearchDir; +} Options; + +//============================================================================= +static int PrintRegister(const char *name, u_int32_t value, int sequence) { + if (sequence % 4 == 0) { + printf("\n"); + } + printf("%6s = 0x%08x ", name, value); + return ++sequence; +} + +//============================================================================= +static void PrintStack(const CallStack *stack, const string &cpu) { + int frame_count = stack->frames()->size(); + char buffer[1024]; + for (int frame_index = 0; frame_index < frame_count; ++frame_index) { + const StackFrame *frame = stack->frames()->at(frame_index); + const CodeModule *module = frame->module; + printf("%2d ", frame_index); + + if (module) { + // Module name (20 chars max) + strcpy(buffer, PathnameStripper::File(module->code_file()).c_str()); + int maxStr = 20; + buffer[maxStr] = 0; + printf("%-*s", maxStr, buffer); + + strcpy(buffer, module->version().c_str()); + buffer[maxStr] = 0; + + printf("%-*s",maxStr, buffer); + + u_int64_t instruction = frame->instruction; + + // PPC only: Adjust the instruction to match that of Crash reporter. The + // instruction listed is actually the return address. See the detailed + // comments in stackwalker_ppc.cc for more information. + if (cpu == "ppc" && frame_index) + instruction += 4; + + printf(" 0x%08llx ", instruction); + + // Function name + if (!frame->function_name.empty()) { + printf("%s", frame->function_name.c_str()); + if (!frame->source_file_name.empty()) { + string source_file = PathnameStripper::File(frame->source_file_name); + printf(" + 0x%llx (%s:%d)", + instruction - frame->source_line_base, + source_file.c_str(), frame->source_line); + } else { + printf(" + 0x%llx", instruction - frame->function_base); + } + } + } + printf("\n"); + } +} + +//============================================================================= +static void PrintRegisters(const CallStack *stack, const string &cpu) { + int sequence = 0; + const StackFrame *frame = stack->frames()->at(0); + if (cpu == "x86") { + const StackFrameX86 *frame_x86 = + reinterpret_cast(frame); + + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP) + sequence = PrintRegister("eip", frame_x86->context.eip, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) + sequence = PrintRegister("esp", frame_x86->context.esp, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP) + sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX) + sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI) + sequence = PrintRegister("esi", frame_x86->context.esi, sequence); + if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI) + sequence = PrintRegister("edi", frame_x86->context.edi, sequence); + if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) { + sequence = PrintRegister("eax", frame_x86->context.eax, sequence); + sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence); + sequence = PrintRegister("edx", frame_x86->context.edx, sequence); + sequence = PrintRegister("efl", frame_x86->context.eflags, sequence); + } + } else if (cpu == "ppc") { + const StackFramePPC *frame_ppc = + reinterpret_cast(frame); + + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_ALL == + StackFramePPC::CONTEXT_VALID_ALL) { + sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence); + sequence = PrintRegister("srr1", frame_ppc->context.srr1, sequence); + sequence = PrintRegister("cr", frame_ppc->context.cr, sequence); + sequence = PrintRegister("xer", frame_ppc->context.xer, sequence); + sequence = PrintRegister("lr", frame_ppc->context.lr, sequence); + sequence = PrintRegister("ctr", frame_ppc->context.ctr, sequence); + sequence = PrintRegister("mq", frame_ppc->context.mq, sequence); + sequence = PrintRegister("vrsave", frame_ppc->context.vrsave, sequence); + + sequence = 0; + char buffer[5]; + for (int i = 0; i < MD_CONTEXT_PPC_GPR_COUNT; ++i) { + sprintf(buffer, "r%d", i); + sequence = PrintRegister(buffer, frame_ppc->context.gpr[i], sequence); + } + } else { + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0) + sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence); + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1) + sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence); + } + } + + printf("\n"); +} + +static void PrintModules(const CodeModules *modules) { + if (!modules) + return; + + printf("\n"); + printf("Loaded modules:\n"); + + u_int64_t main_address = 0; + const CodeModule *main_module = modules->GetMainModule(); + if (main_module) { + main_address = main_module->base_address(); + } + + unsigned int module_count = modules->module_count(); + for (unsigned int module_sequence = 0; + module_sequence < module_count; + ++module_sequence) { + const CodeModule *module = modules->GetModuleAtSequence(module_sequence); + assert(module); + u_int64_t base_address = module->base_address(); + printf("0x%08llx - 0x%08llx %s %s%s %s\n", + base_address, base_address + module->size() - 1, + PathnameStripper::File(module->code_file()).c_str(), + module->version().empty() ? "???" : module->version().c_str(), + main_module != NULL && base_address == main_address ? + " (main)" : "", + module->code_file().c_str()); + } +} + +//============================================================================= +static void Start(Options *options) { + string minidump_file([options->minidumpPath fileSystemRepresentation]); + + BasicSourceLineResolver resolver; + string search_dir = options->searchDir ? + [options->searchDir fileSystemRepresentation] : ""; + string symbol_search_dir = options->symbolSearchDir ? + [options->symbolSearchDir fileSystemRepresentation] : ""; + scoped_ptr symbol_supplier( + new OnDemandSymbolSupplier(search_dir, symbol_search_dir)); + scoped_ptr + minidump_processor(new MinidumpProcessor(symbol_supplier.get(), &resolver)); + ProcessState process_state; + if (minidump_processor->Process(minidump_file, &process_state) != + MinidumpProcessor::PROCESS_OK) { + fprintf(stderr, "MinidumpProcessor::Process failed\n"); + return; + } + + const SystemInfo *system_info = process_state.system_info(); + string cpu = system_info->cpu; + + // Convert the time to a string + u_int32_t time_date_stamp = process_state.time_date_stamp(); + struct tm timestruct; + gmtime_r(reinterpret_cast(&time_date_stamp), ×truct); + char timestr[20]; + strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); + printf("Date: %s GMT\n", timestr); + + printf("Operating system: %s (%s)\n", system_info->os.c_str(), + system_info->os_version.c_str()); + printf("Architecture: %s\n", cpu.c_str()); + + if (process_state.crashed()) { + printf("Crash reason: %s\n", process_state.crash_reason().c_str()); + printf("Crash address: 0x%llx\n", process_state.crash_address()); + } else { + printf("No crash\n"); + } + + int requesting_thread = process_state.requesting_thread(); + if (requesting_thread != -1) { + printf("\n"); + printf("Thread %d (%s)\n", + requesting_thread, + process_state.crashed() ? "crashed" : + "requested dump, did not crash"); + PrintStack(process_state.threads()->at(requesting_thread), cpu); + } + + // Print all of the threads in the dump. + int thread_count = process_state.threads()->size(); + for (int thread_index = 0; thread_index < thread_count; ++thread_index) { + if (thread_index != requesting_thread) { + // Don't print the crash thread again, it was already printed. + printf("\n"); + printf("Thread %d\n", thread_index); + PrintStack(process_state.threads()->at(thread_index), cpu); + } + } + + // Print the crashed registers + if (requesting_thread != -1) { + printf("\nThread %d:", requesting_thread); + PrintRegisters(process_state.threads()->at(requesting_thread), cpu); + } + + // Print information about modules + PrintModules(process_state.modules()); +} + +//============================================================================= +static void Usage(int argc, const char *argv[]) { + fprintf(stderr, "Convert a minidump to a crash report. Breakpad symbol " + "files will be used (or created if missing) in /tmp.\n" + "If a symbol-file-search-dir is specified, any symbol " + "files in it will be used instead of being loaded from " + "modules on disk.\n" + "If modules cannot be found at the paths stored in the " + "minidump file, they will be searched for at " + "/.\n"); + fprintf(stderr, "Usage: %s [-s module-search-dir] [-S symbol-file-search-dir] minidump-file\n", argv[0]); + fprintf(stderr, "\t-s: Specify a search directory to use for missing modules\n" + "\t-S: Specify a search directory to use for symbol files\n" + "\t-h: Usage\n" + "\t-?: Usage\n"); +} + +//============================================================================= +static void SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "S:s:h?")) != -1) { + switch (ch) { + case 's': + options->searchDir = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:optarg + length:strlen(optarg)]; + break; + + case 'S': + options->symbolSearchDir = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:optarg + length:strlen(optarg)]; + break; + + case 'h': + case '?': + Usage(argc, argv); + exit(1); + break; + } + } + + if ((argc - optind) != 1) { + fprintf(stderr, "%s: Missing minidump file\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->minidumpPath = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:argv[optind] + length:strlen(argv[optind])]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + Options options; + + bzero(&options, sizeof(Options)); + SetupOptions(argc, argv, &options); + Start(&options); + [pool release]; + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.h b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.h new file mode 100644 index 00000000..9c0e8b78 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.h @@ -0,0 +1,97 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// on_demand_symbol_supplier.h: Provides a Symbol Supplier that will create +// a breakpad symbol file on demand. + +#ifndef TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__ +#define TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__ + +#include +#include +#include "google_breakpad/processor/symbol_supplier.h" + +namespace google_breakpad { + +using std::map; +using std::string; +class MinidumpModule; + +class OnDemandSymbolSupplier : public SymbolSupplier { + public: + // |search_dir| is the directory to search for alternative symbols with + // the same name as the module in the minidump + OnDemandSymbolSupplier(const string &search_dir, + const string &symbol_search_dir); + virtual ~OnDemandSymbolSupplier() {} + + // Returns the path to the symbol file for the given module. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + + // Returns the path to the symbol file for the given module. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data); + protected: + // Search directory + string search_dir_; + string symbol_search_dir_; + + // When we create a symbol file for a module, save the name of the module + // and the path to that module's symbol file. + map module_file_map_; + + // Return the name for |module| This will be the value used as the key + // to the |module_file_map_|. + string GetNameForModule(const CodeModule *module); + + // Find the module on local system. If the module resides in a different + // location than the full path in the minidump, this will be the location + // used. + string GetLocalModulePath(const CodeModule *module); + + // Return the full path for |module|. + string GetModulePath(const CodeModule *module); + + // Return the path to the symbol file for |module|. If an empty string is + // returned, then |module| doesn't have a symbol file. + string GetModuleSymbolFile(const CodeModule *module); + + // Generate the breakpad symbol file for |module|. Return true if successful. + // File is generated in /tmp. + bool GenerateSymbolFile(const CodeModule *module, + const SystemInfo *system_info); +}; + +} // namespace google_breakpad + +#endif // TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__ diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.mm b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.mm new file mode 100644 index 00000000..4123a27c --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/crash_report/on_demand_symbol_supplier.mm @@ -0,0 +1,267 @@ +// 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 +#include +#include +#include +#include + +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/system_info.h" +#include "processor/pathname_stripper.h" + +#include "on_demand_symbol_supplier.h" +#include "dump_syms.h" + +using std::map; +using std::string; + +using google_breakpad::OnDemandSymbolSupplier; +using google_breakpad::PathnameStripper; +using google_breakpad::SymbolSupplier; +using google_breakpad::SystemInfo; + +OnDemandSymbolSupplier::OnDemandSymbolSupplier(const string &search_dir, + const string &symbol_search_dir) + : search_dir_(search_dir) { + NSFileManager *mgr = [NSFileManager defaultManager]; + int length = symbol_search_dir.length(); + if (length) { + // Load all sym files in symbol_search_dir into our module_file_map + // A symbol file always starts with a line like this: + // MODULE mac x86 BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon + // or + // MODULE mac ppc BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon + const char *symbolSearchStr = symbol_search_dir.c_str(); + NSString *symbolSearchPath = + [mgr stringWithFileSystemRepresentation:symbolSearchStr + length:strlen(symbolSearchStr)]; + NSDirectoryEnumerator *dirEnum = [mgr enumeratorAtPath:symbolSearchPath]; + NSString *fileName; + NSCharacterSet *hexSet = + [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"]; + NSCharacterSet *newlineSet = + [NSCharacterSet characterSetWithCharactersInString:@"\r\n"]; + while ((fileName = [dirEnum nextObject])) { + // Check to see what type of file we have + NSDictionary *attrib = [dirEnum fileAttributes]; + NSString *fileType = [attrib objectForKey:NSFileType]; + if ([fileType isEqualToString:NSFileTypeDirectory]) { + // Skip subdirectories + [dirEnum skipDescendents]; + } else { + NSString *filePath = [symbolSearchPath stringByAppendingPathComponent:fileName]; + NSString *dataStr = [[[NSString alloc] initWithContentsOfFile:filePath] autorelease]; + if (dataStr) { + // Check file to see if it is of appropriate type, and grab module + // name. + NSScanner *scanner = [NSScanner scannerWithString:dataStr]; + BOOL goodScan = [scanner scanString:@"MODULE mac " intoString:nil]; + if (goodScan) { + goodScan = ([scanner scanString:@"x86 " intoString:nil] || + [scanner scanString:@"ppc " intoString:nil]); + if (goodScan) { + NSString *moduleID; + goodScan = [scanner scanCharactersFromSet:hexSet + intoString:&moduleID]; + if (goodScan) { + // Module IDs are always 33 chars long + goodScan = [moduleID length] == 33; + if (goodScan) { + NSString *moduleName; + goodScan = [scanner scanUpToCharactersFromSet:newlineSet + intoString:&moduleName]; + if (goodScan) { + goodScan = [moduleName length] > 0; + if (goodScan) { + const char *moduleNameStr = [moduleName UTF8String]; + const char *filePathStr = [filePath fileSystemRepresentation]; + // Map our file + module_file_map_[moduleNameStr] = filePathStr; + } + } + } + } + } + } + } + } + } + } +} + +SymbolSupplier::SymbolResult +OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) { + string path(GetModuleSymbolFile(module)); + + if (path.empty()) { + if (!GenerateSymbolFile(module, system_info)) + return NOT_FOUND; + + path = GetModuleSymbolFile(module); + } + + if (path.empty()) + return NOT_FOUND; + + *symbol_file = path; + return FOUND; +} + +SymbolSupplier::SymbolResult +OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data) { + SymbolSupplier::SymbolResult s = GetSymbolFile(module, + system_info, + symbol_file); + + + if (s == FOUND) { + ifstream in(symbol_file->c_str()); + getline(in, *symbol_data, std::string::traits_type::to_char_type( + std::string::traits_type::eof())); + in.close(); + } + + return s; +} + +string OnDemandSymbolSupplier::GetLocalModulePath(const CodeModule *module) { + NSFileManager *mgr = [NSFileManager defaultManager]; + const char *moduleStr = module->code_file().c_str(); + NSString *modulePath = + [mgr stringWithFileSystemRepresentation:moduleStr length:strlen(moduleStr)]; + const char *searchStr = search_dir_.c_str(); + NSString *searchDir = + [mgr stringWithFileSystemRepresentation:searchStr length:strlen(searchStr)]; + + if ([mgr fileExistsAtPath:modulePath]) + return module->code_file(); + + // If the module is not found, try to start appending the components to the + // search string and stop if a file (not dir) is found or all components + // have been appended + NSArray *pathComponents = [modulePath componentsSeparatedByString:@"/"]; + int count = [pathComponents count]; + NSMutableString *path = [NSMutableString string]; + + for (int i = 0; i < count; ++i) { + [path setString:searchDir]; + + for (int j = 0; j < i + 1; ++j) { + int idx = count - 1 - i + j; + [path appendFormat:@"/%@", [pathComponents objectAtIndex:idx]]; + } + + BOOL isDir; + if ([mgr fileExistsAtPath:path isDirectory:&isDir] && (!isDir)) { + return [path fileSystemRepresentation]; + } + } + + return ""; +} + +string OnDemandSymbolSupplier::GetModulePath(const CodeModule *module) { + return module->code_file(); +} + +string OnDemandSymbolSupplier::GetNameForModule(const CodeModule *module) { + return PathnameStripper::File(module->code_file()); +} + +string OnDemandSymbolSupplier::GetModuleSymbolFile(const CodeModule *module) { + string name(GetNameForModule(module)); + map::iterator result = module_file_map_.find(name); + + return (result == module_file_map_.end()) ? "" : (*result).second; +} + +static float GetFileModificationTime(const char *path) { + float result = 0; + struct stat file_stat; + if (stat(path, &file_stat) == 0) + result = (float)file_stat.st_mtimespec.tv_sec + + (float)file_stat.st_mtimespec.tv_nsec / 1.0e9; + + return result; +} + +bool OnDemandSymbolSupplier::GenerateSymbolFile(const CodeModule *module, + const SystemInfo *system_info) { + bool result = true; + string name = GetNameForModule(module); + string module_path = GetLocalModulePath(module); + NSString *symbol_path = [NSString stringWithFormat:@"/tmp/%s.%s.sym", + name.c_str(), system_info->cpu.c_str()]; + + if (module_path.empty()) + return false; + + // Check if there's already a symbol file cached. Ensure that the file is + // newer than the module. Otherwise, generate a new one. + BOOL generate_file = YES; + if ([[NSFileManager defaultManager] fileExistsAtPath:symbol_path]) { + // Check if the module file is newer than the saved symbols + float cache_time = + GetFileModificationTime([symbol_path fileSystemRepresentation]); + float module_time = + GetFileModificationTime(module_path.c_str()); + + if (cache_time > module_time) + generate_file = NO; + } + + if (generate_file) { + NSString *module_str = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:module_path.c_str() + length:module_path.length()]; + DumpSymbols *dump = [[DumpSymbols alloc] initWithContentsOfFile:module_str]; + const char *archStr = system_info->cpu.c_str(); + if ([dump setArchitecture:[NSString stringWithUTF8String:archStr]]) { + [dump writeSymbolFile:symbol_path]; + } else { + printf("Architecture %s not available for %s\n", archStr, name.c_str()); + result = false; + } + [dump release]; + } + + // Add the mapping + if (result) + module_file_map_[name] = [symbol_path fileSystemRepresentation]; + + return result; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.m b/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.m new file mode 100644 index 00000000..3729a8d5 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.m @@ -0,0 +1,142 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dump_syms_tool.m: Command line tool that uses the DumpSymbols class. +// TODO(waylonis): accept stdin + +#include +#include + +#include "dump_syms.h" +#include "common/mac/macho_utilities.h" + +typedef struct { + NSString *srcPath; + NSString *arch; + NSString *uuidStr; + BOOL result; +} Options; + +//============================================================================= +static void Start(Options *options) { + DumpSymbols *dump = [[DumpSymbols alloc] + initWithContentsOfFile:options->srcPath]; + + if (!dump) { + fprintf(stderr, "%s is not a valid Mach-o file\n", + [options->srcPath fileSystemRepresentation]); + options->result = NO; + return; + } + + if (![dump setArchitecture:options->arch]) { + fprintf(stderr, "Architecture: %s not available in %s\n", + [options->arch UTF8String], + [options->srcPath fileSystemRepresentation]); + options->result = NO; + return; + } + + options->result = [dump writeSymbolFile:@"-"]; +} + +//============================================================================= +static void Usage(int argc, const char *argv[]) { + fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n"); + fprintf(stderr, "Usage: %s [-a ppc|i386|x86] \n", + argv[0]); + fprintf(stderr, "\t-a: Architecture type [default: native]\n"); + fprintf(stderr, "\t-h: Usage\n"); + fprintf(stderr, "\t-?: Usage\n"); +} + +//============================================================================= +static void SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + const NXArchInfo *localArchInfo = NXGetLocalArchInfo(); + char ch; + + if (localArchInfo) { + if (localArchInfo->cputype & CPU_ARCH_ABI64) + options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC64) ? @"ppc64": + @"x86_64"; + else + options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC) ? @"ppc" : + @"x86"; + } + + while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) { + switch (ch) { + case 'a': + if (strcmp("ppc", optarg) == 0) + options->arch = @"ppc"; + else if (strcmp("x86", optarg) == 0 || strcmp("i386", optarg) == 0) + options->arch = @"x86"; + else if (strcmp("ppc64", optarg) == 0) + options->arch = @"ppc64"; + else if (strcmp("x86_64", optarg) == 0) + options->arch = @"x86_64"; + else { + fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg); + Usage(argc, argv); + exit(1); + } + break; + case '?': + case 'h': + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 1) { + fprintf(stderr, "Must specify Mach-o file\n"); + Usage(argc, argv); + exit(1); + } + + options->srcPath = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:argv[optind] + length:strlen(argv[optind])]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + Options options; + + bzero(&options, sizeof(Options)); + SetupOptions(argc, argv, &options); + Start(&options); + + [pool release]; + + return !options.result; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.mm b/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.mm new file mode 100644 index 00000000..827cea41 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/dump_syms/dump_syms_tool.mm @@ -0,0 +1,142 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dump_syms_tool.m: Command line tool that uses the DumpSymbols class. +// TODO(waylonis): accept stdin + +#include +#include + +#include "dump_syms.h" +#include "common/mac/macho_utilities.h" + +typedef struct { + NSString *srcPath; + NSString *arch; + NSString *uuidStr; + BOOL result; +} Options; + +//============================================================================= +static void Start(Options *options) { + DumpSymbols *dump = [[DumpSymbols alloc] + initWithContentsOfFile:options->srcPath]; + + if (!dump) { + fprintf(stderr, "%s is not a valid Mach-o file\n", + [options->srcPath fileSystemRepresentation]); + options->result = NO; + return; + } + + if (![dump setArchitecture:options->arch]) { + fprintf(stderr, "Architecture: %s not available in %s\n", + [options->arch UTF8String], + [options->srcPath fileSystemRepresentation]); + options->result = NO; + return; + } + + options->result = [dump writeSymbolFile:@"-"]; +} + +//============================================================================= +static void Usage(int argc, const char *argv[]) { + fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n"); + fprintf(stderr, "Usage: %s [-a ppc|i386|x86] \n", + argv[0]); + fprintf(stderr, "\t-a: Architecture type [default: native]\n"); + fprintf(stderr, "\t-h: Usage\n"); + fprintf(stderr, "\t-?: Usage\n"); +} + +//============================================================================= +static void SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + const NXArchInfo *localArchInfo = NXGetLocalArchInfo(); + signed char ch; + + if (localArchInfo) { + if (localArchInfo->cputype & CPU_ARCH_ABI64) + options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC64) ? @"ppc64": + @"x86_64"; + else + options->arch = (localArchInfo->cputype == CPU_TYPE_POWERPC) ? @"ppc" : + @"x86"; + } + + while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) { + switch (ch) { + case 'a': + if (strcmp("ppc", optarg) == 0) + options->arch = @"ppc"; + else if (strcmp("x86", optarg) == 0 || strcmp("i386", optarg) == 0) + options->arch = @"x86"; + else if (strcmp("ppc64", optarg) == 0) + options->arch = @"ppc64"; + else if (strcmp("x86_64", optarg) == 0) + options->arch = @"x86_64"; + else { + fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg); + Usage(argc, argv); + exit(1); + } + break; + case '?': + case 'h': + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 1) { + fprintf(stderr, "Must specify Mach-o file\n"); + Usage(argc, argv); + exit(1); + } + + options->srcPath = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:argv[optind] + length:strlen(argv[optind])]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + Options options; + + bzero(&options, sizeof(Options)); + SetupOptions(argc, argv, &options); + Start(&options); + + [pool release]; + + return !options.result; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/symupload/minidump_upload.m b/thirdparty/google-breakpad/r318/src/tools/mac/symupload/minidump_upload.m new file mode 100644 index 00000000..4f9d8c7a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/symupload/minidump_upload.m @@ -0,0 +1,135 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_upload.m: Upload a minidump to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// prod: the product name +// ver: the product version +// symbol_file: the breakpad format symbol file + +#import + +#import + +#import "common/mac/HTTPMultipartUpload.h" + +typedef struct { + NSString *minidumpPath; + NSString *uploadURLStr; + NSString *product; + NSString *version; + BOOL success; +} Options; + +//============================================================================= +static void Start(Options *options) { + NSURL *url = [NSURL URLWithString:options->uploadURLStr]; + HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url]; + NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; + + // Add parameters + [parameters setObject:options->product forKey:@"prod"]; + [parameters setObject:options->version forKey:@"ver"]; + [ul setParameters:parameters]; + + // Add file + [ul addFileAtPath:options->minidumpPath name:@"upload_file_minidump"]; + + // Send it + NSError *error = nil; + NSData *data = [ul send:&error]; + NSString *result = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + + NSLog(@"Send: %@", error ? [error description] : @"No Error"); + NSLog(@"Response: %d", [[ul response] statusCode]); + NSLog(@"Result: %d bytes\n%@", [data length], result); + + [result release]; + [ul release]; + options->success = !error; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit minidump information.\n"); + fprintf(stderr, "Usage: %s -p -v " + "\n", argv[0]); + fprintf(stderr, " should be a minidump.\n"); + fprintf(stderr, " is the destination for the upload\n"); + + fprintf(stderr, "\t-h: Usage\n"); + fprintf(stderr, "\t-?: Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "p:v:h?")) != -1) { + switch (ch) { + case 'p': + options->product = [NSString stringWithCString:optarg]; + break; + case 'v': + options->version = [NSString stringWithCString:optarg]; + break; + + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->minidumpPath = [NSString stringWithCString:argv[optind]]; + options->uploadURLStr = [NSString stringWithCString:argv[optind + 1]]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + Options options; + + bzero(&options, sizeof(Options)); + SetupOptions(argc, argv, &options); + Start(&options); + + [pool release]; + return options.success ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/mac/symupload/symupload.m b/thirdparty/google-breakpad/r318/src/tools/mac/symupload/symupload.m new file mode 100644 index 00000000..d4a30150 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/mac/symupload/symupload.m @@ -0,0 +1,190 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// symupload.m: Upload a symbol file to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// code_file: the basename of the module, e.g. "app" +// debug_file: the basename of the debugging file, e.g. "app" +// debug_identifier: the debug file's identifier, usually consisting of +// the guid and age embedded in the pdb, e.g. +// "11111111BBBB3333DDDD555555555555F" +// os: the operating system that the module was built for +// cpu: the CPU that the module was built for (x86 or ppc) +// symbol_file: the contents of the breakpad-format symbol file + +#include + +#include +#include "HTTPMultipartUpload.h" + +typedef struct { + NSString *symbolsPath; + NSString *uploadURLStr; + BOOL success; +} Options; + +//============================================================================= +static NSArray *ModuleDataForSymbolFile(NSString *file) { + NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:file]; + NSData *data = [fh readDataOfLength:1024]; + NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSScanner *scanner = [NSScanner scannerWithString:str]; + NSString *line; + NSMutableArray *parts = nil; + const int MODULE_ID_INDEX = 3; + + if ([scanner scanUpToString:@"\n" intoString:&line]) { + parts = [[NSMutableArray alloc] init]; + NSScanner *moduleInfoScanner = [NSScanner scannerWithString:line]; + NSString *moduleInfo; + // Get everything BEFORE the module name. None of these properties + // can have spaces. + for (int i = 0; i <= MODULE_ID_INDEX; i++) { + [moduleInfoScanner scanUpToString:@" " intoString:&moduleInfo]; + [parts addObject:moduleInfo]; + } + + // Now get the module name. This can have a space so we scan to + // the end of the line. + [moduleInfoScanner scanUpToString:@"\n" intoString:&moduleInfo]; + [parts addObject:moduleInfo]; + } + + [str release]; + + return parts; +} + +//============================================================================= +static NSString *CompactIdentifier(NSString *uuid) { + NSMutableString *str = [NSMutableString stringWithString:uuid]; + [str replaceOccurrencesOfString:@"-" withString:@"" options:0 + range:NSMakeRange(0, [str length])]; + + return str; +} + +//============================================================================= +static void Start(Options *options) { + NSURL *url = [NSURL URLWithString:options->uploadURLStr]; + HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url]; + NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; + NSArray *moduleParts = ModuleDataForSymbolFile(options->symbolsPath); + NSMutableString *compactedID = + [NSMutableString stringWithString:[moduleParts objectAtIndex:3]]; + [compactedID replaceOccurrencesOfString:@"-" withString:@"" options:0 + range:NSMakeRange(0, [compactedID length])]; + + // Add parameters + [parameters setObject:compactedID forKey:@"debug_identifier"]; + + // MODULE + // 0 1 2 3 4 + [parameters setObject:[moduleParts objectAtIndex:1] forKey:@"os"]; + [parameters setObject:[moduleParts objectAtIndex:2] forKey:@"cpu"]; + [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"debug_file"]; + [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"code_file"]; + [ul setParameters:parameters]; + + NSArray *keys = [parameters allKeys]; + int count = [keys count]; + for (int i = 0; i < count; ++i) { + NSString *key = [keys objectAtIndex:i]; + NSString *value = [parameters objectForKey:key]; + fprintf(stdout, "'%s' = '%s'\n", [key UTF8String], + [value UTF8String]); + } + + // Add file + [ul addFileAtPath:options->symbolsPath name:@"symbol_file"]; + + // Send it + NSError *error = nil; + NSData *data = [ul send:&error]; + NSString *result = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + + fprintf(stdout, "Send: %s\n", error ? [[error description] UTF8String] : + "No Error"); + fprintf(stdout, "Response: %d\n", [[ul response] statusCode]); + fprintf(stdout, "Result: %d bytes\n%s\n", [data length], [result UTF8String]); + + [result release]; + [ul release]; + options->success = !error; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit symbol information.\n"); + fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, " should be created by using the dump_syms tool.\n"); + fprintf(stderr, " is the destination for the upload\n"); + fprintf(stderr, "\t-h: Usage\n"); + fprintf(stderr, "\t-?: Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "h?")) != -1) { + switch (ch) { + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->symbolsPath = [NSString stringWithCString:argv[optind]]; + options->uploadURLStr = [NSString stringWithCString:argv[optind + 1]]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + Options options; + + bzero(&options, sizeof(Options)); + SetupOptions(argc, argv, &options); + Start(&options); + + [pool release]; + return options.success ? 0 : 1; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/Makefile b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/Makefile new file mode 100644 index 00000000..f0a4c11a --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/Makefile @@ -0,0 +1,64 @@ +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Author: Alfred Peng + +CXX=CC +CC=cc + +CXXFLAGS=-g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -lelf -ldemangle -D_REENTRANT + +.PHONY:all clean + +BIN=dump_syms + +all:$(BIN) + +DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o + +dump_syms:$(DUMP_OBJ) + $(CXX) $(CXXFLAGS) -o $@ $^ + +dump_symbols.o:../../../common/solaris/dump_symbols.cc + $(CXX) $(CXXFLAGS) -c $^ + +guid_creator.o:../../../common/solaris/guid_creator.cc + $(CXX) $(CXXFLAGS) -c $^ + +file_id.o:../../../common/solaris/file_id.cc + $(CXX) $(CXXFLAGS) -c $^ + +md5.o:../../../common/md5.c + $(CC) $(CXXFLAGS) -c $^ + +test:all + ./run_regtest.sh + +clean: + rm -f $(BIN) $(DUMP_OBJ) diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/dump_syms.cc b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/dump_syms.cc new file mode 100644 index 00000000..54cea57e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/dump_syms.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include + +#include "common/solaris/dump_symbols.h" + +using namespace google_breakpad; + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + const char *binary = argv[1]; + + DumpSymbols dumper; + if (!dumper.WriteSymbolFile(binary, fileno(stdout))) { + fprintf(stderr, "Failed to write symbol file.\n"); + return 1; + } + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/run_regtest.sh b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/run_regtest.sh new file mode 100644 index 00000000..ffb34330 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/run_regtest.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +./dump_syms testdata/dump_syms_regtest.o > testdata/dump_syms_regtest.new +status=$? + +if [ $status -ne 0 ] ; then + echo "FAIL, dump_syms failed" + exit $status +fi + +diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \ + testdata/dump_syms_regtest.diff +status=$? + +if [ $status -eq 0 ] ; then + rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new + echo "PASS" +else + echo "FAIL, see testdata/dump_syms_regtest.[new|diff]" +fi + +exit $status diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc new file mode 100644 index 00000000..e617a23b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ./dump_syms dump_syms_regtest.pdb > dump_syms_regtest.sym + +namespace google_breakpad { + +class C { + public: + C() : member_(1) {} + virtual ~C() {} + + void set_member(int value) { member_ = value; } + int member() const { return member_; } + + void f() { member_ = g(); } + virtual int g() { return 2; } + static char* h(const C &that) { return 0; } + + private: + int member_; +}; + +static int i() { + return 3; +} + +} // namespace google_breakpad + +int main(int argc, char **argv) { + google_breakpad::C object; + object.set_member(google_breakpad::i()); + object.f(); + int value = object.g(); + char *nothing = object.h(object); + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs new file mode 100644 index 00000000..c5f93ef7 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs @@ -0,0 +1,129 @@ + + +Debugging Stab table -- 104 entries + + 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x67,0x71c + 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0 + 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0 + 3: .stabs "",N_OBJ,0x0,0x0,0x0 + 4: .stabs "",N_OBJ,0x0,0x0,0x0 + 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e + 6: .stabs "dump_syms_regtest.cc",N_SOL,0x0,0x0,0x0 + 7: .stabs "char:t(0,1)=bsc1;0;8",N_ISYM,0x0,0x0,0x0 + 8: .stabs "short:t(0,2)=bs2;0;16",N_ISYM,0x0,0x0,0x0 + 9: .stabs "int:t(0,3)=bs4;0;32",N_ISYM,0x0,0x0,0x0 + 10: .stabs "long:t(0,4)=bs4;0;32",N_ISYM,0x0,0x0,0x0 + 11: .stabs "long long:t(0,5)=bs8;0;64",N_ISYM,0x0,0x0,0x0 + 12: .stabs "unsigned char:t(0,6)=buc1;0;8",N_ISYM,0x0,0x0,0x0 + 13: .stabs "unsigned short:t(0,7)=bu2;0;16",N_ISYM,0x0,0x0,0x0 + 14: .stabs "unsigned:t(0,8)=bu4;0;32",N_ISYM,0x0,0x0,0x0 + 15: .stabs "unsigned long:t(0,9)=bu4;0;32",N_ISYM,0x0,0x0,0x0 + 16: .stabs "unsigned long long:t(0,10)=bu8;0;64",N_ISYM,0x0,0x0,0x0 + 17: .stabs "signed char:t(0,11)=bsc1;0;8",N_ISYM,0x0,0x0,0x0 + 18: .stabs "wchar_t:t(0,12)=buc4;0;32",N_ISYM,0x0,0x0,0x0 + 19: .stabs "void:t(0,13)=bs0;0;0",N_ISYM,0x0,0x0,0x0 + 20: .stabs "float:t(0,14)=R1;4",N_ISYM,0x0,0x0,0x0 + 21: .stabs "double:t(0,15)=R2;8",N_ISYM,0x0,0x0,0x0 + 22: .stabs "long double:t(0,16)=R6;12",N_ISYM,0x0,0x0,0x0 + 23: .stabs "...:t(0,17)=buv4;0;32",N_ISYM,0x0,0x0,0x0 + 24: .stabs "bool:t(0,18)=bub1;0;8",N_ISYM,0x0,0x0,0x0 + 25: .stabs "__1nPgoogle_breakpad_:T(0,19)=Yn0google_breakpad;",N_ISYM,0x0,0x0,0x0 + 26: .stabs "nBC(0,19):U(0,20)",N_ESYM,0x0,0x0,0x0 + 27: .stabs "nBC(0,19):T(0,20)=Yc8C;;AcHmember_:(0,3),32,32;;Cc2t6M_v K2c2T6M_v CcKset_member6Mi_v CcGmember6kM_i CcBf6M_v K3cBg6M_i GcBh6Frk1_pc;;;2 0;;;;110;",N_ESYM,0x0,0x8,0x0 + 28: .stabs "main:F(0,3);(0,3);(0,21)=*(0,22)=*(0,1)",N_FUN,0x0,0x38,0x0 + 29: .stabs "main",N_MAIN,0x0,0x0,0x0 + 30: .stabs "argc:p(0,3)",N_PSYM,0x0,0x4,0x8 + 31: .stabs "argv:p(0,21)",N_PSYM,0x0,0x4,0xc + 32: .stabn N_LBRAC,0x0,0x1,0x12 + 33: .stabs "object:(0,20)",N_LSYM,0x0,0x8,0xfffffff4 + 34: .stabs "value:(0,3)",N_LSYM,0x0,0x4,0xfffffff0 + 35: .stabs "nothing:(0,22)",N_LSYM,0x0,0x4,0xffffffec + 36: .stabn N_SLINE,0x0,0x39,0x12 + 37: .stabs "object:2",N_CONSTRUCT,0x0,0xc,0x12 + 38: .stabn N_SLINE,0x2,0x3a,0x1e + 39: .stabn N_SLINE,0x0,0x3b,0x36 + 40: .stabn N_SLINE,0x0,0x3c,0x42 + 41: .stabn N_SLINE,0x0,0x3d,0x57 + 42: .stabn N_SLINE,0x0,0x3f,0x6c + 43: .stabs "2:0",N_DESTRUCT,0x0,0xc,0x73 + 44: .stabn N_SLINE,0xfffffffe,0x40,0x9c + 45: .stabn N_RBRAC,0x0,0x1,0x9c + 46: .stabs "__1cPgoogle_breakpadBi6F_i_:f(0,3)",N_FUN,0x0,0x32,0x0 + 47: .stabn N_LBRAC,0x0,0x1,0x6 + 48: .stabn N_SLINE,0x0,0x33,0x6 + 49: .stabn N_SLINE,0x0,0x34,0x10 + 50: .stabn N_RBRAC,0x0,0x1,0x10 + 51: .stabs "__1cPgoogle_breakpadBC2t6M_v_:F(0,13);(0,23)=*(0,20)",N_FUN,0x0,0x24,0x0 + 52: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 53: .stabn N_LBRAC,0x0,0x1,0x3 + 54: .stabn N_SLINE,0x0,0x24,0x25 + 55: .stabn N_RBRAC,0x0,0x1,0x25 + 56: .stabs "__1cPgoogle_breakpadBC2T6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0 + 57: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 58: .stabn N_LBRAC,0x0,0x1,0x3 + 59: .stabn N_SLINE,0x0,0x25,0x3 + 60: .stabn N_RBRAC,0x0,0x1,0x3 + 61: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_:F(0,13);(0,23);(0,3)",N_FUN,0x0,0x27,0x0 + 62: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 63: .stabs "value:p(0,3)",N_PSYM,0x0,0x4,0xc + 64: .stabn N_LBRAC,0x0,0x1,0x3 + 65: .stabn N_SLINE,0x0,0x27,0x3 + 66: .stabn N_SLINE,0x0,0x27,0xc + 67: .stabn N_RBRAC,0x0,0x1,0xc + 68: .stabs "__1cPgoogle_breakpadBCBf6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x2a,0x0 + 69: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 70: .stabn N_LBRAC,0x0,0x1,0x3 + 71: .stabn N_SLINE,0x0,0x2a,0x3 + 72: .stabn N_SLINE,0x0,0x2a,0x1d + 73: .stabn N_RBRAC,0x0,0x1,0x1d + 74: .stabs "__1cPgoogle_breakpadBCBg6M_i_:F(0,3);(0,23)",N_FUN,0x0,0x2b,0x0 + 75: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 76: .stabn N_LBRAC,0x0,0x1,0x6 + 77: .stabn N_SLINE,0x0,0x2b,0x6 + 78: .stabn N_SLINE,0x0,0x2b,0x10 + 79: .stabn N_RBRAC,0x0,0x1,0x10 + 80: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_:F(0,22);(0,24)=&(0,25)=k(0,20)",N_FUN,0x0,0x2c,0x0 + 81: .stabs "that:p(0,24)",N_PSYM,0x0,0x4,0x8 + 82: .stabn N_LBRAC,0x0,0x1,0x6 + 83: .stabn N_SLINE,0x0,0x2c,0x6 + 84: .stabn N_SLINE,0x0,0x2c,0x10 + 85: .stabn N_RBRAC,0x0,0x1,0x10 + 86: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0 + 87: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 88: .stabn N_LBRAC,0x0,0x1,0x3 + 89: .stabn N_SLINE,0x0,0x25,0xf + 90: .stabn N_RBRAC,0x0,0x1,0xf + 91: .stabs "__SLIP.DELETER__A:f(0,13);(0,23);(0,3)",N_FUN,0x0,0x25,0x0 + 92: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 93: .stabs "delete:p(0,3)",N_PSYM,0x0,0x4,0xc + 94: .stabn N_LBRAC,0x0,0x1,0x3 + 95: .stabn N_LBRAC,0x0,0x2,0x3 + 96: .stabn N_RBRAC,0x0,0x2,0x28 + 97: .stabn N_RBRAC,0x0,0x1,0x28 + 98: .stabs "true:l(0,18);1",N_LSYM,0x0,0x4,0x0 + 99: .stabs "false:l(0,18);0",N_LSYM,0x0,0x4,0x0 + 100: .stabs "__1c2k6Fpv_v_:P(0,13);(0,26)=*(0,13)",N_FUN,0x0,0x0,0x0 + 101: .stabs "__1cPgoogle_breakpadBC2t5B6M_v_:F__1cPgoogle_breakpadBC2t6M_v_",N_ALIAS,0x0,0x0,0x0 + 102: .stabs "cbD__RTTI__1nPgoogle_breakpadBC_(0,19):YR(0,20)",N_LSYM,0x0,0x0,0x0 + 103: .stabn N_ENDM,0x0,0x0,0x0 + + +Index Stab table -- 17 entries + + 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x10,0x3b1 + 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0 + 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0 + 3: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata",N_OBJ,0x0,0x0,0x0 + 4: .stabs "dump_syms_regtest.o",N_OBJ,0x0,0x0,0x0 + 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e + 6: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/; /ws/on10-tools-prc/SUNWspro/SS11/prod/bin/CC -g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -D_REENTRANT -xs dump_syms_regtest.cc -Qoption ccfe -prefix -Qoption ccfe .XAB6Z2hOiL\$Gl1b.",N_CMDLINE,0x0,0x0,0x0 + 7: .stabs "__1nPgoogle_breakpadBC_:U",N_ESYM,0x0,0x0,0x0 + 8: .stabs "main",N_MAIN,0x0,0x0,0x0 + 9: .stabs "main",N_FUN,0x0,0x0,0x0 + 10: .stabs "__1cPgoogle_breakpadBC2t6M_v_",N_FUN,0x0,0x0,0x0 + 11: .stabs "__1cPgoogle_breakpadBC2T6M_v_",N_FUN,0x0,0x0,0x0 + 12: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_",N_FUN,0x0,0x0,0x0 + 13: .stabs "__1cPgoogle_breakpadBCBf6M_v_",N_FUN,0x0,0x0,0x0 + 14: .stabs "__1cPgoogle_breakpadBCBg6M_i_",N_FUN,0x0,0x0,0x0 + 15: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_",N_FUN,0x0,0x0,0x0 + 16: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_",N_FUN,0x0,0x0,0x0 diff --git a/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym new file mode 100644 index 00000000..44d3c539 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym @@ -0,0 +1,33 @@ +MODULE solaris x86 3DC8191474338D8587339B5FB3E2C62A0 dump_syms_regtest.o +FILE 0 dump_syms_regtest.cc +FUNC 0 156 0 main +12 18 57 0 +1e 12 58 0 +36 24 59 0 +42 12 60 0 +57 21 61 0 +6c 21 63 0 +9c 48 64 0 +FUNC 0 16 0 int google_breakpad::i() +6 6 51 0 +10 10 52 0 +FUNC 0 37 0 google_breakpad::C::C() +25 37 36 0 +FUNC 0 3 0 google_breakpad::C::~C() +3 3 37 0 +FUNC 0 12 0 void google_breakpad::C::set_member(int) +3 3 39 0 +c 9 39 0 +FUNC 0 29 0 void google_breakpad::C::f() +3 3 42 0 +1d 26 42 0 +FUNC 0 16 0 int google_breakpad::C::g() +6 6 43 0 +10 10 43 0 +FUNC 0 16 0 char*google_breakpad::C::h(const google_breakpad::C&) +6 6 44 0 +10 10 44 0 +FUNC 0 15 0 google_breakpad::C::~C #Nvariant 1() +f 15 37 0 +FUNC 0 0 0 __SLIP.DELETER__A +FUNC 0 0 0 void operator delete(void*) diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.cc b/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.cc new file mode 100644 index 00000000..2b6278ba --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.cc @@ -0,0 +1,522 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ms_symbol_server_converter.cc: Obtain symbol files from a Microsoft +// symbol server, and convert them to Breakpad's dumped format. +// +// See ms_symbol_server_converter.h for documentation. +// +// Author: Mark Mentovai + +#include +#include + +#include +#include + +#include "tools/windows/converter/ms_symbol_server_converter.h" +#include "common/windows/pdb_source_line_writer.h" +#include "common/windows/string_utils-inl.h" + +// SYMOPT_NO_PROMPTS is not defined in earlier platform SDKs. Define it +// in that case, in the event that this code is used with a newer version +// of DbgHelp at runtime that recognizes the option. The presence of this +// bit in the symbol options should not harm earlier versions of DbgHelp. +#ifndef SYMOPT_NO_PROMPTS +#define SYMOPT_NO_PROMPTS 0x00080000 +#endif // SYMOPT_NO_PROMPTS + +namespace google_breakpad { + +// Use sscanf_s if it is available, to quench the warning about scanf being +// deprecated. Use scanf where sscanf_is not available. Note that the +// parameters passed to sscanf and sscanf_s are only compatible as long as +// fields of type c, C, s, S, and [ are not used. +#if _MSC_VER >= 1400 // MSVC 2005/8 +#define SSCANF sscanf_s +#else // _MSC_VER >= 1400 +#define SSCANF sscanf +#endif // _MSC_VER >= 1400 + +bool GUIDOrSignatureIdentifier::InitializeFromString( + const string &identifier) { + type_ = TYPE_NONE; + + size_t length = identifier.length(); + + if (length > 32 && length <= 40) { + // GUID + if (SSCANF(identifier.c_str(), + "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X", + &guid_.Data1, &guid_.Data2, &guid_.Data3, + &guid_.Data4[0], &guid_.Data4[1], + &guid_.Data4[2], &guid_.Data4[3], + &guid_.Data4[4], &guid_.Data4[5], + &guid_.Data4[6], &guid_.Data4[7], + &age_) != 12) { + return false; + } + + type_ = TYPE_GUID; + } else if (length > 8 && length <= 15) { + // Signature + if (SSCANF(identifier.c_str(), "%08X%x", &signature_, &age_) != 2) { + return false; + } + + type_ = TYPE_SIGNATURE; + } else { + return false; + } + + return true; +} + +#undef SSCANF + +MSSymbolServerConverter::MSSymbolServerConverter( + const string &local_cache, const vector &symbol_servers) + : symbol_path_(), + fail_dns_(false), + fail_timeout_(false), + fail_not_found_(false) { + // Setting local_cache can be done without verifying that it exists because + // SymSrv will create it if it is missing - any creation failures will occur + // at that time, so there's nothing to check here, making it safe to + // assign this in the constructor. + + assert(symbol_servers.size() > 0); + + // These are characters that are interpreted as having special meanings in + // symbol_path_. + const char *kInvalidCharacters = "*;"; + assert(local_cache.find_first_of(kInvalidCharacters) == string::npos); + + for (vector::const_iterator symbol_server = symbol_servers.begin(); + symbol_server != symbol_servers.end(); + ++symbol_server) { + // The symbol path format is explained by + // http://msdn.microsoft.com/library/en-us/debug/base/using_symsrv.asp . + // "srv*" is the same as "symsrv*symsrv.dll*", which means that + // symsrv.dll is to be responsible for locating symbols. symsrv.dll + // interprets the rest of the string as a series of symbol stores separated + // by '*'. "srv*local_cache*symbol_server" means to check local_cache + // first for the symbol file, and if it is not found there, to check + // symbol_server. Symbol files found on the symbol server will be placed + // in the local cache, decompressed. + // + // Multiple specifications in this format may be presented, separated by + // semicolons. + + assert((*symbol_server).find_first_of(kInvalidCharacters) == string::npos); + symbol_path_ += "srv*" + local_cache + "*" + *symbol_server + ";"; + } + + // Strip the trailing semicolon. + symbol_path_.erase(symbol_path_.length() - 1); +} + +// A stack-based class that manages SymInitialize and SymCleanup calls. +class AutoSymSrv { + public: + AutoSymSrv() : initialized_(false) {} + + ~AutoSymSrv() { + if (!Cleanup()) { + // Print the error message here, because destructors have no return + // value. + fprintf(stderr, "~AutoSymSrv: SymCleanup: error %d\n", GetLastError()); + } + } + + bool Initialize(HANDLE process, char *path, bool invade_process) { + process_ = process; + initialized_ = SymInitialize(process, path, invade_process) == TRUE; + return initialized_; + } + + bool Cleanup() { + if (initialized_) { + if (SymCleanup(process_)) { + initialized_ = false; + return true; + } + return false; + } + + return true; + } + + private: + HANDLE process_; + bool initialized_; +}; + +// A stack-based class that "owns" a pathname and deletes it when destroyed, +// unless told not to by having its Release() method called. Early deletions +// are supported by calling Delete(). +class AutoDeleter { + public: + AutoDeleter(const string &path) : path_(path) {} + + ~AutoDeleter() { + int error; + if ((error = Delete()) != 0) { + // Print the error message here, because destructors have no return + // value. + fprintf(stderr, "~AutoDeleter: Delete: error %d for %s\n", + error, path_.c_str()); + } + } + + int Delete() { + if (path_.empty()) + return 0; + + int error = remove(path_.c_str()); + Release(); + return error; + } + + void Release() { + path_.clear(); + } + + private: + string path_; +}; + +MSSymbolServerConverter::LocateResult +MSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo &missing, + string *symbol_file) { + assert(symbol_file); + symbol_file->clear(); + + GUIDOrSignatureIdentifier identifier; + if (!identifier.InitializeFromString(missing.debug_identifier)) { + fprintf(stderr, + "LocateSymbolFile: Unparseable debug_identifier for %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_FAILURE; + } + + HANDLE process = GetCurrentProcess(); // CloseHandle is not needed. + AutoSymSrv symsrv; + if (!symsrv.Initialize(process, + const_cast(symbol_path_.c_str()), + false)) { + fprintf(stderr, "LocateSymbolFile: SymInitialize: error %d for %s %s %s\n", + GetLastError(), + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_FAILURE; + } + + if (!SymRegisterCallback64(process, SymCallback, + reinterpret_cast(this))) { + fprintf(stderr, + "LocateSymbolFile: SymRegisterCallback64: error %d for %s %s %s\n", + GetLastError(), + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_FAILURE; + } + + // SYMOPT_DEBUG arranges for SymCallback to be called with additional + // debugging information. This is used to determine the nature of failures. + DWORD options = SymGetOptions() | SYMOPT_DEBUG | SYMOPT_NO_PROMPTS | + SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_SECURE; + SymSetOptions(options); + + // SymCallback will set these as needed inisde the SymFindFileInPath call. + fail_dns_ = false; + fail_timeout_ = false; + fail_not_found_ = false; + + // Do the lookup. + char path[MAX_PATH]; + if (!SymFindFileInPath( + process, NULL, + const_cast(missing.debug_file.c_str()), + const_cast(identifier.guid_or_signature_pointer()), + identifier.age(), 0, + identifier.type() == GUIDOrSignatureIdentifier::TYPE_GUID ? + SSRVOPT_GUIDPTR : SSRVOPT_DWORDPTR, + path, SymFindFileInPathCallback, this)) { + DWORD error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) { + // This can be returned for a number of reasons. Use the crumbs + // collected by SymCallback to determine which one is relevant. + + // These errors are possibly transient. + if (fail_dns_ || fail_timeout_) { + return LOCATE_RETRY; + } + + // This is an authoritiative file-not-found message. + if (fail_not_found_) { + fprintf(stderr, + "LocateSymbolFile: SymFindFileInPath: LOCATE_NOT_FOUND error " + "for %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_NOT_FOUND; + } + + // If the error is FILE_NOT_FOUND but none of the known error + // conditions are matched, fall through to LOCATE_FAILURE. + } + + fprintf(stderr, + "LocateSymbolFile: SymFindFileInPath: error %d for %s %s %s\n", + error, + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_FAILURE; + } + + // The AutoDeleter ensures that the file is only kept when returning + // LOCATE_SUCCESS. + AutoDeleter deleter(path); + + // Do the cleanup here even though it will happen when symsrv goes out of + // scope, to allow it to influence the return value. + if (!symsrv.Cleanup()) { + fprintf(stderr, "LocateSymbolFile: SymCleanup: error %d for %s %s %s\n", + GetLastError(), + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str()); + return LOCATE_FAILURE; + } + + deleter.Release(); + + *symbol_file = path; + return LOCATE_SUCCESS; +} + +// static +BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process, + ULONG action, + ULONG64 data, + ULONG64 context) { + MSSymbolServerConverter *self = + reinterpret_cast(context); + + switch (action) { + case CBA_EVENT: { + IMAGEHLP_CBA_EVENT *cba_event = + reinterpret_cast(data); + + // Put the string into a string object to be able to use string::find + // for substring matching. This is important because the not-found + // message does not use the entire string but is appended to the URL + // that SymSrv attempted to retrieve. + string desc(cba_event->desc); + + // desc_action maps strings (in desc) to boolean pointers that are to + // be set to true if the string matches. + struct desc_action { + const char *desc; // The substring to match. + bool *action; // On match, this pointer will be set to true. + }; + + static const desc_action desc_actions[] = { + // When a DNS error occurs, it could be indiciative of network + // problems. + { "SYMSRV: The server name or address could not be resolved\n", + &self->fail_dns_ }, + + // This message is produced if no connection is opened. + { "SYMSRV: A connection with the server could not be established\n", + &self->fail_timeout_ }, + + // This message is produced if a connection is established but the + // server fails to respond to the HTTP request. + { "SYMSRV: The operation timed out\n", + &self->fail_timeout_ }, + + // This message is produced when the requested file is not found, + // even if one or more of the above messages are also produced. + // It's trapped to distinguish between not-found and unknown-failure + // conditions. Note that this message will not be produced if a + // connection is established and the server begins to respond to the + // HTTP request but does not finish transmitting the file. + { " not found\n", + &self->fail_not_found_ } + }; + + for (int desc_action_index = 0; + desc_action_index < sizeof(desc_actions) / sizeof(desc_action); + ++desc_action_index) { + if (desc.find(desc_actions[desc_action_index].desc) != string::npos) { + *(desc_actions[desc_action_index].action) = true; + break; + } + } + + break; + } + } + + // This function is a mere fly on the wall. Treat everything as unhandled. + return FALSE; +} + +// static +BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback( + char *filename, void *context) { + // FALSE ends the search, indicating that the located symbol file is + // satisfactory. + return FALSE; +} + +MSSymbolServerConverter::LocateResult +MSSymbolServerConverter::LocateAndConvertSymbolFile( + const MissingSymbolInfo &missing, + bool keep_symbol_file, + string *converted_symbol_file, + string *symbol_file) { + assert(converted_symbol_file); + converted_symbol_file->clear(); + if (symbol_file) { + symbol_file->clear(); + } + + string pdb_file; + LocateResult result = LocateSymbolFile(missing, &pdb_file); + if (result != LOCATE_SUCCESS) { + return result; + } + + if (symbol_file && keep_symbol_file) { + *symbol_file = pdb_file; + } + + // Conversion may fail because the file is corrupt. If a broken file is + // kept in the local cache, LocateSymbolFile will not hit the network again + // to attempt to locate it. To guard against problems like this, the + // symbol file in the local cache will be removed if conversion fails. + AutoDeleter pdb_deleter(pdb_file); + + // Be sure that it's a .pdb file, since we'll be replacing .pdb with .sym + // for the converted file's name. + string pdb_extension = pdb_file.substr(pdb_file.length() - 4); + // strcasecmp is called _stricmp here. + if (_stricmp(pdb_extension.c_str(), ".pdb") != 0) { + fprintf(stderr, "LocateAndConvertSymbolFile: " + "LocateSymbolFile: no .pdb extension for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pdb_file.c_str()); + return LOCATE_FAILURE; + } + + // PDBSourceLineWriter wants the filename as a wstring, so convert it. + wstring pdb_file_w; + if (!WindowsStringUtils::safe_mbstowcs(pdb_file, &pdb_file_w)) { + fprintf(stderr, "LocateAndConvertSymbolFile: " + "WindowsStringUtils::safe_mbstowcs failed for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pdb_file.c_str()); + return LOCATE_FAILURE; + } + + PDBSourceLineWriter writer; + if (!writer.Open(pdb_file_w, PDBSourceLineWriter::PDB_FILE)) { + fprintf(stderr, "LocateAndConvertSymbolFile: " + "PDBSourceLineWriter::Open failed for %s %s %s %ws\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pdb_file_w.c_str()); + return LOCATE_FAILURE; + } + + *converted_symbol_file = pdb_file.substr(0, pdb_file.length() - 4) + ".sym"; + + FILE *converted_output = NULL; +#if _MSC_VER >= 1400 // MSVC 2005/8 + errno_t err; + if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) + != 0) { +#else // _MSC_VER >= 1400 + // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier + // environments. Don't use fopen with MSVC8 and later, because it's + // deprecated. fopen does not provide reliable error codes, so just use + // -1 in the event of a failure. + int err; + if (!(converted_output = fopen(converted_symbol_file->c_str(), "w"))) { + err = -1; +#endif // _MSC_VER >= 1400 + fprintf(stderr, "LocateAndConvertSymbolFile: " + "fopen_s: error %d for %s %s %s %s\n", + err, + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + converted_symbol_file->c_str()); + return LOCATE_FAILURE; + } + + AutoDeleter sym_deleter(*converted_symbol_file); + + bool success = writer.WriteMap(converted_output); + fclose(converted_output); + + if (!success) { + fprintf(stderr, "LocateAndConvertSymbolFile: " + "PDBSourceLineWriter::WriteMap failed for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pdb_file.c_str()); + return LOCATE_FAILURE; + } + + if (keep_symbol_file) { + pdb_deleter.Release(); + } + + sym_deleter.Release(); + + return LOCATE_SUCCESS; +} + +} // namespace google_breakpad diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.h b/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.h new file mode 100644 index 00000000..fffb7b8b --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/converter/ms_symbol_server_converter.h @@ -0,0 +1,201 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ms_symbol_server_converter.h: Obtain symbol files from a Microsoft +// symbol server, and convert them to Breakpad's dumped format. +// +// At runtime, MSSymbolServerConverter and code that it calls depend on being +// able to locate suitable versions of dbghelp.dll and symsrv.dll. For best +// results, place these files in the same directory as the executable. +// dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are +// both redistributable, as indicated by the package's redist.txt file. +// +// When connecting to Microsoft's symbol server at +// http://msdl.microsoft.com/download/symbols/, which provides access to +// symbols for the operating system itself, symsrv.dll requires agreement to +// Microsoft's "Terms of Use for Microsoft Symbols and Binaries." Because this +// library places the symbol engine into a promptless mode, the dialog with the +// terms will not appear, and use of Microsoft's symbol server will not be +// possible. To indicate agreement to the terms, create a file called +// symsrv.yes in the same directory as symsrv.dll. (Note that symsrv.dll will +// also recognize a symsrv.no file as indicating that you do not accept the +// terms; the .yes file takes priority over the .no file.) The terms of use +// are contained within symsrv.dll; they were formerly available online at +// http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but +// do not appear to be available online any longer as of January, 2007. It is +// possible to view the terms from within WinDbg (Debugging Tools for Windows) +// by removing any symsrv.yes and symsrv.no files from WinDbg's directory, +// setting the symbol path to include Microsoft's symbol server (.sympath), and +// attempting to load symbols from their server (.reload). +// +// This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8, +// included with Microsoft Visual Studio 8 in Common7/IDE. This has also +// been tested with dbghelp.dll and symsrv.dll 6.6.7.5, included with that +// version of Debugging Tools for Windows, available at +// http://www.microsoft.com/whdc/devtools/debugging/ . +// +// Author: Mark Mentovai + + +#ifndef MS_SYMBOL_SERVER_CONVERTER_H__ +#define MS_SYMBOL_SERVER_CONVERTER_H__ + +#include + +#include +#include + +namespace google_breakpad { + +using std::string; +using std::vector; + +// MissingSymbolInfo contains the subset of the information in the processor's +// CodeModule structure relevant to obtaining a missing symbol file. Only +// debug_file and debug_identifier are relevant in actually obtaining the +// missing file; the other fields are for convenience. +struct MissingSymbolInfo { + string code_file; + string code_identifier; + string debug_file; + string debug_identifier; + string version; +}; + +class GUIDOrSignatureIdentifier { + public: + enum GUIDOrSignatureType { + TYPE_NONE = 0, + TYPE_GUID, + TYPE_SIGNATURE + }; + + GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {} + + // Converts |identifier|, a debug_identifier-formatted string, into its + // component fields: either a GUID and age, or signature and age. If + // successful, sets the relevant fields in the object, including the type + // field, and returns true. On error, returns false. + bool InitializeFromString(const string &identifier); + + GUIDOrSignatureType type() const { return type_; } + GUID guid() const { return guid_; } + DWORD signature() const { return signature_; } + int age() const { return age_; } + const void *guid_or_signature_pointer() const { return &guid_; } + + private: + GUIDOrSignatureType type_; + + // An identifier contains either a 128-bit uuid or a 32-bit signature. + union { + GUID guid_; + DWORD signature_; + }; + + // All identifiers used here have age fields, which indicate a specific + // revision given a uuid or signature. + int age_; +}; + +class MSSymbolServerConverter { + public: + enum LocateResult { + LOCATE_FAILURE = 0, + LOCATE_NOT_FOUND, // Authoritative: the file is not present. + LOCATE_RETRY, // Transient (network?) error, try again later. + LOCATE_SUCCESS + }; + + // Create a new object. local_cache is the location (pathname) of a local + // symbol store used to hold downloaded and converted symbol files. This + // directory will be created by LocateSymbolFile when it successfully + // retrieves a symbol file. symbol_servers contains a list of locations (URLs + // or pathnames) of the upstream symbol server stores, given in order of + // preference, with the first string in the vector identifying the first + // store to try. The vector must contain at least one string. None of the + // strings passed to this constructor may contain asterisk ('*') or semicolon + // (';') characters, as the symbol engine uses these characters as separators. + MSSymbolServerConverter(const string &local_cache, + const vector &symbol_servers); + + // Locates the symbol file specified by the identifying information in + // |missing|, by checking the symbol stores identified when the object + // was created. When returning LOCATE_SUCCESS, symbol_file is set to + // the pathname of the decompressed symbol file as it is stored in the + // local cache. + LocateResult LocateSymbolFile(const MissingSymbolInfo &missing, + string *symbol_file); + + // Calls LocateSymbolFile and converts the returned symbol file to the + // dumped-symbol format, storing it adjacent to the symbol file. The + // only conversion supported is from pdb files. Returns the return + // value of LocateSymbolFile, or if LocateSymbolFile succeeds but + // conversion fails, returns LOCATE_FAILURE. The pathname to the + // pdb file and to the converted symbol file are returned in + // converted_symbol_file and symbol_file. symbol_file is optional and + // may be NULL. If only the converted symbol file is desired, set + // keep_symbol_file to false to indicate that the original symbol file + // (pdb) should be deleted after conversion. + LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing, + bool keep_symbol_file, + string *converted_symbol_file, + string *symbol_file); + + private: + // Called by various SymSrv functions to report status as progress is made + // and to allow the callback to influence processing. Messages sent to this + // callback can be used to distinguish between the various failure modes + // that SymFindFileInPath might encounter. + static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data, + ULONG64 context); + + // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate + // symbol file is located, when it's present in the local cache. + // SymFindFileInPath actually seems to accept NULL for a callback function + // and behave properly for our needs in that case, but the documentation + // doesn't mention it, so this little callback is provided. + static BOOL CALLBACK SymFindFileInPathCallback(char *filename, + void *context); + + // The search path used by SymSrv, built based on the arguments to the + // constructor. + string symbol_path_; + + // SymCallback will set at least one of these failure variables if + // SymFindFileInPath fails for an expected reason. + bool fail_dns_; // DNS failures (fail_not_found_ will also be set). + bool fail_timeout_; // Timeouts (fail_not_found_ will also be set). + bool fail_not_found_; // The file could not be found. If this is the only + // fail_* member set, then it is authoritative. +}; + +} // namespace google_breakpad + +#endif // MS_SYMBOL_SERVER_CONVERTER_H__ diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/dump_syms.cc b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/dump_syms.cc new file mode 100644 index 00000000..3e8827b6 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/dump_syms.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Windows utility to dump the line number data from a pdb file to +// a text-based format that we can use from the minidump processor. + +#include + +#include + +#include "common/windows/pdb_source_line_writer.h" + +using std::wstring; +using google_breakpad::PDBSourceLineWriter; + +int wmain(int argc, wchar_t **argv) { + if (argc < 2) { + fprintf(stderr, "Usage: %ws \n", argv[0]); + return 1; + } + + PDBSourceLineWriter writer; + if (!writer.Open(wstring(argv[1]), PDBSourceLineWriter::ANY_FILE)) { + fprintf(stderr, "Open failed\n"); + return 1; + } + + if (!writer.WriteMap(stdout)) { + fprintf(stderr, "WriteMap failed\n"); + return 1; + } + + writer.Close(); + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/run_regtest.sh b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/run_regtest.sh new file mode 100644 index 00000000..1f20f64f --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/run_regtest.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# Copyright (c) 2006, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Release/dump_syms.exe testdata/dump_syms_regtest.pdb | \ + tr -d '\015' > \ + testdata/dump_syms_regtest.new +status=$? + +if [ $status -ne 0 ] ; then + echo "FAIL, dump_syms.exe failed" + exit $status +fi + +diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \ + testdata/dump_syms_regtest.diff +status=$? + +if [ $status -eq 0 ] ; then + rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new + echo "PASS" +else + echo "FAIL, see testdata/dump_syms_regtest.[new|diff]" +fi + +exit $status diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc new file mode 100644 index 00000000..ce53f582 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc @@ -0,0 +1,65 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// cl /Zi dump_syms_regtest.cc +// dump_syms dump_syms_regtest.pdb | tr -d '\015' > dump_syms_regtest.sym + +namespace google_breakpad { + +class C { + public: + C() : member_(1) {} + virtual ~C() {} + + void set_member(int value) { member_ = value; } + int member() const { return member_; } + + void f() { member_ = g(); } + virtual int g() { return 2; } + static char* h(const C &that) { return 0; } + + private: + int member_; +}; + +static int i() { + return 3; +} + +} // namespace google_breakpad + +int main(int argc, char **argv) { + google_breakpad::C object; + object.set_member(google_breakpad::i()); + object.f(); + int value = object.g(); + char *nothing = object.h(object); + + return 0; +} diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym new file mode 100644 index 00000000..8e5ce026 --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym @@ -0,0 +1,14097 @@ +MODULE windows x86 3EB931A9CE0242ABB14FFDF4ECAA97FC1 dump_syms_regtest.pdb +FILE 1 c:\breakpad\trunk\src\tools\windows\dump_syms\testdata\dump_syms_regtest.cc +FILE 2 f:\sp\public\sdk\inc\reason.h +FILE 3 f:\sp\public\sdk\inc\wincon.h +FILE 4 f:\sp\public\sdk\inc\pshpack2.h +FILE 5 f:\sp\public\sdk\inc\mcx.h +FILE 6 f:\sp\public\sdk\inc\winuser.h +FILE 7 f:\sp\public\sdk\inc\winnls.h +FILE 8 f:\sp\public\sdk\inc\guiddef.h +FILE 9 f:\sp\public\sdk\inc\specstrings.h +FILE 10 f:\sp\public\sdk\inc\basetsd.h +FILE 11 f:\sp\public\sdk\inc\stralign.h +FILE 12 f:\sp\public\sdk\inc\tvout.h +FILE 13 f:\sp\public\sdk\inc\winsvc.h +FILE 14 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 15 f:\sp\public\sdk\inc\wingdi.h +FILE 16 f:\sp\public\sdk\inc\pshpack4.h +FILE 17 f:\sp\public\sdk\inc\poppack.h +FILE 18 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sect_attribs.h +FILE 19 f:\sp\public\sdk\inc\winnetwk.h +FILE 20 f:\sp\public\sdk\inc\imm.h +FILE 21 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 22 f:\sp\public\sdk\inc\windef.h +FILE 23 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 24 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\tran\i386\cpu_disp.c +FILE 25 f:\sp\public\sdk\inc\pshpack1.h +FILE 26 f:\sp\public\sdk\inc\winver.h +FILE 27 f:\sp\public\sdk\inc\windows.h +FILE 28 f:\sp\public\sdk\inc\winnt.h +FILE 29 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 30 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 31 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 32 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 33 f:\sp\public\sdk\inc\ddbanned.h +FILE 34 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 35 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 36 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 37 f:\sp\public\sdk\inc\winreg.h +FILE 38 f:\sp\public\sdk\inc\winbase.h +FILE 39 f:\sp\public\sdk\inc\winerror.h +FILE 40 f:\sp\public\sdk\inc\pshpack8.h +FILE 41 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 42 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 43 f:\sp\public\sdk\inc\reason.h +FILE 44 f:\sp\public\sdk\inc\wincon.h +FILE 45 f:\sp\public\sdk\inc\pshpack2.h +FILE 46 f:\sp\public\sdk\inc\mcx.h +FILE 47 f:\sp\public\sdk\inc\winuser.h +FILE 48 f:\sp\public\sdk\inc\winnls.h +FILE 49 f:\sp\public\sdk\inc\guiddef.h +FILE 50 f:\sp\public\sdk\inc\specstrings.h +FILE 51 f:\sp\public\sdk\inc\basetsd.h +FILE 52 f:\sp\public\sdk\inc\stralign.h +FILE 53 f:\sp\public\sdk\inc\tvout.h +FILE 54 f:\sp\public\sdk\inc\winsvc.h +FILE 55 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 56 f:\sp\public\sdk\inc\wingdi.h +FILE 57 f:\sp\public\sdk\inc\pshpack4.h +FILE 58 f:\sp\public\sdk\inc\poppack.h +FILE 59 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sect_attribs.h +FILE 60 f:\sp\public\sdk\inc\winnetwk.h +FILE 61 f:\sp\public\sdk\inc\imm.h +FILE 62 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 63 f:\sp\public\sdk\inc\windef.h +FILE 64 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 65 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\tran\i386\mathfcns.c +FILE 66 f:\sp\public\sdk\inc\pshpack1.h +FILE 67 f:\sp\public\sdk\inc\winver.h +FILE 68 f:\sp\public\sdk\inc\windows.h +FILE 69 f:\sp\public\sdk\inc\winnt.h +FILE 70 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 71 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 72 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 73 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 74 f:\sp\public\sdk\inc\ddbanned.h +FILE 75 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 76 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 77 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 78 f:\sp\public\sdk\inc\winreg.h +FILE 79 f:\sp\public\sdk\inc\winbase.h +FILE 80 f:\sp\public\sdk\inc\winerror.h +FILE 81 f:\sp\public\sdk\inc\pshpack8.h +FILE 82 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 83 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 84 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 85 f:\sp\public\sdk\inc\winreg.h +FILE 86 f:\sp\public\sdk\inc\winbase.h +FILE 87 f:\sp\public\sdk\inc\winerror.h +FILE 88 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 89 f:\sp\public\sdk\inc\windef.h +FILE 90 f:\sp\vctools\crt_bld\self_x86\crt\src\ctime.h +FILE 91 f:\sp\vctools\crt_bld\self_x86\crt\src\wtime.inl +FILE 92 f:\sp\vctools\crt_bld\self_x86\crt\src\time.h +FILE 93 f:\sp\public\sdk\inc\pshpack8.h +FILE 94 f:\sp\public\sdk\inc\reason.h +FILE 95 f:\sp\public\sdk\inc\wincon.h +FILE 96 f:\sp\vctools\crt_bld\self_x86\crt\src\time.inl +FILE 97 f:\sp\public\sdk\inc\pshpack2.h +FILE 98 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 99 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 100 f:\sp\public\sdk\inc\mcx.h +FILE 101 f:\sp\public\sdk\inc\winuser.h +FILE 102 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 103 f:\sp\public\sdk\inc\winnls.h +FILE 104 f:\sp\public\sdk\inc\guiddef.h +FILE 105 f:\sp\public\sdk\inc\stralign.h +FILE 106 f:\sp\public\sdk\inc\winnt.h +FILE 107 f:\sp\public\sdk\inc\specstrings.h +FILE 108 f:\sp\public\sdk\inc\basetsd.h +FILE 109 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 110 f:\sp\public\sdk\inc\tvout.h +FILE 111 f:\sp\public\sdk\inc\winsvc.h +FILE 112 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 113 f:\sp\public\sdk\inc\wingdi.h +FILE 114 f:\sp\vctools\crt_bld\self_x86\crt\src\tzset.c +FILE 115 f:\sp\public\sdk\inc\pshpack4.h +FILE 116 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 117 f:\sp\public\sdk\inc\poppack.h +FILE 118 f:\sp\public\sdk\inc\winnetwk.h +FILE 119 f:\sp\public\sdk\inc\imm.h +FILE 120 f:\sp\public\sdk\inc\ddbanned.h +FILE 121 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 122 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 123 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 124 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 125 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 126 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 127 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 128 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 129 f:\sp\public\sdk\inc\windows.h +FILE 130 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 131 f:\sp\public\sdk\inc\pshpack1.h +FILE 132 f:\sp\public\sdk\inc\winver.h +FILE 133 f:\sp\vctools\crt_bld\self_x86\crt\src\time.inl +FILE 134 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 135 f:\sp\public\sdk\inc\winnt.h +FILE 136 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 137 f:\sp\public\sdk\inc\winreg.h +FILE 138 f:\sp\public\sdk\inc\winbase.h +FILE 139 f:\sp\public\sdk\inc\winerror.h +FILE 140 f:\sp\public\sdk\inc\pshpack8.h +FILE 141 f:\sp\public\sdk\inc\reason.h +FILE 142 f:\sp\public\sdk\inc\wincon.h +FILE 143 f:\sp\public\sdk\inc\pshpack2.h +FILE 144 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 145 f:\sp\public\sdk\inc\mcx.h +FILE 146 f:\sp\public\sdk\inc\winuser.h +FILE 147 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 148 f:\sp\public\sdk\inc\winnls.h +FILE 149 f:\sp\public\sdk\inc\guiddef.h +FILE 150 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 151 f:\sp\public\sdk\inc\stralign.h +FILE 152 f:\sp\public\sdk\inc\specstrings.h +FILE 153 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 154 f:\sp\public\sdk\inc\basetsd.h +FILE 155 f:\sp\public\sdk\inc\windows.h +FILE 156 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 157 f:\sp\public\sdk\inc\tvout.h +FILE 158 f:\sp\public\sdk\inc\winsvc.h +FILE 159 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 160 f:\sp\public\sdk\inc\wingdi.h +FILE 161 f:\sp\vctools\crt_bld\self_x86\crt\src\timeset.c +FILE 162 f:\sp\public\sdk\inc\pshpack4.h +FILE 163 f:\sp\public\sdk\inc\poppack.h +FILE 164 f:\sp\public\sdk\inc\winnetwk.h +FILE 165 f:\sp\public\sdk\inc\imm.h +FILE 166 f:\sp\public\sdk\inc\ddbanned.h +FILE 167 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 168 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 169 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 170 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 171 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 172 f:\sp\public\sdk\inc\windef.h +FILE 173 f:\sp\public\sdk\inc\pshpack1.h +FILE 174 f:\sp\vctools\crt_bld\self_x86\crt\src\wtime.inl +FILE 175 f:\sp\vctools\crt_bld\self_x86\crt\src\time.h +FILE 176 f:\sp\public\sdk\inc\winver.h +FILE 177 f:\sp\public\sdk\inc\wincon.h +FILE 178 f:\sp\vctools\crt_bld\self_x86\crt\src\time.h +FILE 179 f:\sp\public\sdk\inc\imm.h +FILE 180 f:\sp\public\sdk\inc\winbase.h +FILE 181 f:\sp\public\sdk\inc\wingdi.h +FILE 182 f:\sp\public\sdk\inc\winver.h +FILE 183 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 184 f:\sp\public\sdk\inc\windows.h +FILE 185 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 186 f:\sp\public\sdk\inc\pshpack2.h +FILE 187 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 188 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 189 f:\sp\public\sdk\inc\reason.h +FILE 190 f:\sp\vctools\crt_bld\self_x86\crt\src\strftime.c +FILE 191 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 192 f:\sp\public\sdk\inc\specstrings.h +FILE 193 f:\sp\public\sdk\inc\basetsd.h +FILE 194 f:\sp\public\sdk\inc\pshpack4.h +FILE 195 f:\sp\vctools\crt_bld\self_x86\crt\src\wtime.inl +FILE 196 f:\sp\public\sdk\inc\winnetwk.h +FILE 197 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 198 f:\sp\public\sdk\inc\stralign.h +FILE 199 f:\sp\vctools\crt_bld\self_x86\crt\src\time.inl +FILE 200 f:\sp\public\sdk\inc\poppack.h +FILE 201 f:\sp\public\sdk\inc\winsvc.h +FILE 202 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 203 f:\sp\public\sdk\inc\windef.h +FILE 204 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 205 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 206 f:\sp\public\sdk\inc\winuser.h +FILE 207 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 208 f:\sp\public\sdk\inc\mcx.h +FILE 209 f:\sp\public\sdk\inc\pshpack8.h +FILE 210 f:\sp\public\sdk\inc\guiddef.h +FILE 211 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 212 f:\sp\public\sdk\inc\winnt.h +FILE 213 f:\sp\public\sdk\inc\winnls.h +FILE 214 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 215 f:\sp\public\sdk\inc\pshpack1.h +FILE 216 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 217 f:\sp\public\sdk\inc\winerror.h +FILE 218 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 219 f:\sp\public\sdk\inc\winreg.h +FILE 220 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 221 f:\sp\public\sdk\inc\ddbanned.h +FILE 222 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 223 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 224 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 225 f:\sp\public\sdk\inc\tvout.h +FILE 226 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 227 f:\sp\public\sdk\inc\poppack.h +FILE 228 f:\sp\public\sdk\inc\winnetwk.h +FILE 229 f:\sp\public\sdk\inc\imm.h +FILE 230 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 231 f:\sp\public\sdk\inc\windef.h +FILE 232 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 233 f:\sp\public\sdk\inc\pshpack1.h +FILE 234 f:\sp\public\sdk\inc\winver.h +FILE 235 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 236 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 237 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 238 f:\sp\public\sdk\inc\winnt.h +FILE 239 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 240 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 241 f:\sp\public\sdk\inc\winreg.h +FILE 242 f:\sp\vctools\crt_bld\self_x86\crt\src\days.c +FILE 243 f:\sp\public\sdk\inc\winbase.h +FILE 244 f:\sp\public\sdk\inc\winerror.h +FILE 245 f:\sp\public\sdk\inc\pshpack8.h +FILE 246 f:\sp\public\sdk\inc\reason.h +FILE 247 f:\sp\public\sdk\inc\wincon.h +FILE 248 f:\sp\public\sdk\inc\ddbanned.h +FILE 249 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 250 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 251 f:\sp\public\sdk\inc\pshpack2.h +FILE 252 f:\sp\public\sdk\inc\mcx.h +FILE 253 f:\sp\public\sdk\inc\winuser.h +FILE 254 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 255 f:\sp\public\sdk\inc\winnls.h +FILE 256 f:\sp\public\sdk\inc\guiddef.h +FILE 257 f:\sp\public\sdk\inc\windows.h +FILE 258 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 259 f:\sp\public\sdk\inc\specstrings.h +FILE 260 f:\sp\public\sdk\inc\basetsd.h +FILE 261 f:\sp\public\sdk\inc\stralign.h +FILE 262 f:\sp\public\sdk\inc\tvout.h +FILE 263 f:\sp\public\sdk\inc\winsvc.h +FILE 264 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 265 f:\sp\public\sdk\inc\wingdi.h +FILE 266 f:\sp\public\sdk\inc\pshpack4.h +FILE 267 f:\sp\public\sdk\inc\wincon.h +FILE 268 f:\sp\public\sdk\inc\imm.h +FILE 269 f:\sp\public\sdk\inc\winbase.h +FILE 270 f:\sp\public\sdk\inc\wingdi.h +FILE 271 f:\sp\public\sdk\inc\winver.h +FILE 272 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 273 f:\sp\public\sdk\inc\windows.h +FILE 274 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 275 f:\sp\public\sdk\inc\pshpack2.h +FILE 276 f:\sp\public\sdk\inc\reason.h +FILE 277 f:\sp\vctools\crt_bld\self_x86\crt\src\strnicol.c +FILE 278 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 279 f:\sp\public\sdk\inc\specstrings.h +FILE 280 f:\sp\public\sdk\inc\basetsd.h +FILE 281 f:\sp\public\sdk\inc\pshpack4.h +FILE 282 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 283 f:\sp\public\sdk\inc\winnetwk.h +FILE 284 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 285 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 286 f:\sp\public\sdk\inc\stralign.h +FILE 287 f:\sp\public\sdk\inc\poppack.h +FILE 288 f:\sp\public\sdk\inc\winsvc.h +FILE 289 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 290 f:\sp\public\sdk\inc\windef.h +FILE 291 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 292 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 293 f:\sp\public\sdk\inc\winuser.h +FILE 294 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 295 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 296 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 297 f:\sp\public\sdk\inc\mcx.h +FILE 298 f:\sp\public\sdk\inc\pshpack8.h +FILE 299 f:\sp\public\sdk\inc\guiddef.h +FILE 300 f:\sp\public\sdk\inc\winnt.h +FILE 301 f:\sp\public\sdk\inc\winnls.h +FILE 302 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 303 f:\sp\public\sdk\inc\pshpack1.h +FILE 304 f:\sp\public\sdk\inc\winerror.h +FILE 305 f:\sp\public\sdk\inc\winreg.h +FILE 306 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 307 f:\sp\public\sdk\inc\ddbanned.h +FILE 308 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 309 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 310 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 311 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 312 f:\sp\public\sdk\inc\tvout.h +FILE 313 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 314 f:\sp\public\sdk\inc\mcx.h +FILE 315 f:\sp\public\sdk\inc\pshpack8.h +FILE 316 f:\sp\public\sdk\inc\winnt.h +FILE 317 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 318 f:\sp\public\sdk\inc\specstrings.h +FILE 319 f:\sp\public\sdk\inc\basetsd.h +FILE 320 f:\sp\public\sdk\inc\winnls.h +FILE 321 f:\sp\public\sdk\inc\pshpack1.h +FILE 322 f:\sp\public\sdk\inc\winerror.h +FILE 323 f:\sp\public\sdk\inc\winreg.h +FILE 324 f:\sp\vctools\crt_bld\self_x86\crt\src\strnicmp.c +FILE 325 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 326 f:\sp\public\sdk\inc\tvout.h +FILE 327 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 328 f:\sp\public\sdk\inc\wincon.h +FILE 329 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 330 f:\sp\public\sdk\inc\imm.h +FILE 331 f:\sp\public\sdk\inc\guiddef.h +FILE 332 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 333 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 334 f:\sp\public\sdk\inc\winbase.h +FILE 335 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 336 f:\sp\public\sdk\inc\wingdi.h +FILE 337 f:\sp\public\sdk\inc\windows.h +FILE 338 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 339 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 340 f:\sp\public\sdk\inc\winver.h +FILE 341 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 342 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 343 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 344 f:\sp\public\sdk\inc\pshpack2.h +FILE 345 f:\sp\public\sdk\inc\reason.h +FILE 346 f:\sp\public\sdk\inc\pshpack4.h +FILE 347 f:\sp\public\sdk\inc\winnetwk.h +FILE 348 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 349 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 350 f:\sp\public\sdk\inc\stralign.h +FILE 351 f:\sp\public\sdk\inc\windef.h +FILE 352 f:\sp\public\sdk\inc\poppack.h +FILE 353 f:\sp\public\sdk\inc\winsvc.h +FILE 354 f:\sp\public\sdk\inc\ddbanned.h +FILE 355 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 356 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 357 f:\sp\public\sdk\inc\winuser.h +FILE 358 f:\sp\public\sdk\inc\mcx.h +FILE 359 f:\sp\public\sdk\inc\pshpack8.h +FILE 360 f:\sp\public\sdk\inc\winnt.h +FILE 361 f:\sp\public\sdk\inc\specstrings.h +FILE 362 f:\sp\public\sdk\inc\basetsd.h +FILE 363 f:\sp\public\sdk\inc\winnls.h +FILE 364 f:\sp\public\sdk\inc\pshpack1.h +FILE 365 f:\sp\public\sdk\inc\winerror.h +FILE 366 f:\sp\public\sdk\inc\winreg.h +FILE 367 f:\sp\vctools\crt_bld\self_x86\crt\src\stricmp.c +FILE 368 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 369 f:\sp\public\sdk\inc\tvout.h +FILE 370 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 371 f:\sp\public\sdk\inc\wincon.h +FILE 372 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 373 f:\sp\public\sdk\inc\imm.h +FILE 374 f:\sp\public\sdk\inc\guiddef.h +FILE 375 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 376 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 377 f:\sp\public\sdk\inc\winbase.h +FILE 378 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 379 f:\sp\public\sdk\inc\wingdi.h +FILE 380 f:\sp\public\sdk\inc\windows.h +FILE 381 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 382 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 383 f:\sp\public\sdk\inc\winver.h +FILE 384 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 385 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 386 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 387 f:\sp\public\sdk\inc\pshpack2.h +FILE 388 f:\sp\public\sdk\inc\reason.h +FILE 389 f:\sp\public\sdk\inc\pshpack4.h +FILE 390 f:\sp\public\sdk\inc\winnetwk.h +FILE 391 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 392 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 393 f:\sp\public\sdk\inc\stralign.h +FILE 394 f:\sp\public\sdk\inc\windef.h +FILE 395 f:\sp\public\sdk\inc\poppack.h +FILE 396 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 397 f:\sp\public\sdk\inc\winsvc.h +FILE 398 f:\sp\public\sdk\inc\ddbanned.h +FILE 399 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 400 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 401 f:\sp\public\sdk\inc\winuser.h +FILE 402 f:\sp\public\sdk\inc\winnt.h +FILE 403 f:\sp\public\sdk\inc\pshpack4.h +FILE 404 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 405 f:\sp\public\sdk\inc\poppack.h +FILE 406 f:\sp\vctools\crt_bld\self_x86\crt\src\tcsncpy_s.inl +FILE 407 f:\sp\public\sdk\inc\winnetwk.h +FILE 408 f:\sp\public\sdk\inc\imm.h +FILE 409 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 410 f:\sp\public\sdk\inc\pshpack1.h +FILE 411 f:\sp\public\sdk\inc\winver.h +FILE 412 f:\sp\vctools\crt_bld\self_x86\crt\src\internal_securecrt.h +FILE 413 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 414 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 415 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 416 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 417 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 418 f:\sp\public\sdk\inc\guiddef.h +FILE 419 f:\sp\public\sdk\inc\windows.h +FILE 420 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 421 f:\sp\public\sdk\inc\specstrings.h +FILE 422 f:\sp\public\sdk\inc\basetsd.h +FILE 423 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 424 f:\sp\public\sdk\inc\winreg.h +FILE 425 f:\sp\vctools\crt_bld\self_x86\crt\src\strncpy_s.c +FILE 426 f:\sp\public\sdk\inc\winbase.h +FILE 427 f:\sp\public\sdk\inc\winerror.h +FILE 428 f:\sp\public\sdk\inc\pshpack8.h +FILE 429 f:\sp\public\sdk\inc\reason.h +FILE 430 f:\sp\public\sdk\inc\wincon.h +FILE 431 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 432 f:\sp\public\sdk\inc\ddbanned.h +FILE 433 f:\sp\public\sdk\inc\windef.h +FILE 434 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 435 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 436 f:\sp\public\sdk\inc\pshpack2.h +FILE 437 f:\sp\public\sdk\inc\mcx.h +FILE 438 f:\sp\public\sdk\inc\winuser.h +FILE 439 f:\sp\public\sdk\inc\winnls.h +FILE 440 f:\sp\public\sdk\inc\stralign.h +FILE 441 f:\sp\public\sdk\inc\tvout.h +FILE 442 f:\sp\public\sdk\inc\winsvc.h +FILE 443 f:\sp\public\sdk\inc\wingdi.h +FILE 444 f:\sp\public\sdk\inc\winnt.h +FILE 445 f:\sp\public\sdk\inc\pshpack4.h +FILE 446 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 447 f:\sp\public\sdk\inc\poppack.h +FILE 448 f:\sp\vctools\crt_bld\self_x86\crt\src\tcscpy_s.inl +FILE 449 f:\sp\public\sdk\inc\winnetwk.h +FILE 450 f:\sp\public\sdk\inc\imm.h +FILE 451 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 452 f:\sp\public\sdk\inc\pshpack1.h +FILE 453 f:\sp\public\sdk\inc\winver.h +FILE 454 f:\sp\vctools\crt_bld\self_x86\crt\src\internal_securecrt.h +FILE 455 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 456 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 457 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 458 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 459 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 460 f:\sp\public\sdk\inc\guiddef.h +FILE 461 f:\sp\public\sdk\inc\windows.h +FILE 462 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 463 f:\sp\public\sdk\inc\specstrings.h +FILE 464 f:\sp\public\sdk\inc\basetsd.h +FILE 465 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 466 f:\sp\public\sdk\inc\winreg.h +FILE 467 f:\sp\vctools\crt_bld\self_x86\crt\src\strcpy_s.c +FILE 468 f:\sp\public\sdk\inc\winbase.h +FILE 469 f:\sp\public\sdk\inc\winerror.h +FILE 470 f:\sp\public\sdk\inc\pshpack8.h +FILE 471 f:\sp\public\sdk\inc\reason.h +FILE 472 f:\sp\public\sdk\inc\wincon.h +FILE 473 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 474 f:\sp\public\sdk\inc\ddbanned.h +FILE 475 f:\sp\public\sdk\inc\windef.h +FILE 476 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 477 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 478 f:\sp\public\sdk\inc\pshpack2.h +FILE 479 f:\sp\public\sdk\inc\mcx.h +FILE 480 f:\sp\public\sdk\inc\winuser.h +FILE 481 f:\sp\public\sdk\inc\winnls.h +FILE 482 f:\sp\public\sdk\inc\stralign.h +FILE 483 f:\sp\public\sdk\inc\tvout.h +FILE 484 f:\sp\public\sdk\inc\winsvc.h +FILE 485 f:\sp\public\sdk\inc\wingdi.h +FILE 486 f:\sp\public\sdk\inc\winnt.h +FILE 487 f:\sp\public\sdk\inc\pshpack4.h +FILE 488 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 489 f:\sp\public\sdk\inc\poppack.h +FILE 490 f:\sp\vctools\crt_bld\self_x86\crt\src\tcscat_s.inl +FILE 491 f:\sp\public\sdk\inc\winnetwk.h +FILE 492 f:\sp\public\sdk\inc\imm.h +FILE 493 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 494 f:\sp\public\sdk\inc\pshpack1.h +FILE 495 f:\sp\public\sdk\inc\winver.h +FILE 496 f:\sp\vctools\crt_bld\self_x86\crt\src\internal_securecrt.h +FILE 497 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 498 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 499 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 500 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 501 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 502 f:\sp\public\sdk\inc\guiddef.h +FILE 503 f:\sp\public\sdk\inc\windows.h +FILE 504 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 505 f:\sp\public\sdk\inc\specstrings.h +FILE 506 f:\sp\public\sdk\inc\basetsd.h +FILE 507 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 508 f:\sp\public\sdk\inc\winreg.h +FILE 509 f:\sp\vctools\crt_bld\self_x86\crt\src\strcat_s.c +FILE 510 f:\sp\public\sdk\inc\winbase.h +FILE 511 f:\sp\public\sdk\inc\winerror.h +FILE 512 f:\sp\public\sdk\inc\pshpack8.h +FILE 513 f:\sp\public\sdk\inc\reason.h +FILE 514 f:\sp\public\sdk\inc\wincon.h +FILE 515 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 516 f:\sp\public\sdk\inc\ddbanned.h +FILE 517 f:\sp\public\sdk\inc\windef.h +FILE 518 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 519 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 520 f:\sp\public\sdk\inc\pshpack2.h +FILE 521 f:\sp\public\sdk\inc\mcx.h +FILE 522 f:\sp\public\sdk\inc\winuser.h +FILE 523 f:\sp\public\sdk\inc\winnls.h +FILE 524 f:\sp\public\sdk\inc\stralign.h +FILE 525 f:\sp\public\sdk\inc\tvout.h +FILE 526 f:\sp\public\sdk\inc\winsvc.h +FILE 527 f:\sp\public\sdk\inc\wingdi.h +FILE 528 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 529 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 530 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 531 f:\sp\vctools\crt_bld\self_x86\crt\src\strlen_s.c +FILE 532 f:\sp\public\sdk\inc\ddbanned.h +FILE 533 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 534 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 535 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\strpbrk.asm +FILE 536 F:\SP\vctools\crt_bld\SELF_X86\crt\src\Intel\STRSPN.ASM +FILE 537 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 538 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\_strnicm.asm +FILE 539 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 540 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 541 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 542 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 543 f:\sp\vctools\crt_bld\self_x86\crt\src\intel\strncmp.c +FILE 544 f:\sp\public\sdk\inc\ddbanned.h +FILE 545 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 546 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 547 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\strlen.asm +FILE 548 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 549 f:\sp\public\sdk\inc\pshpack2.h +FILE 550 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 551 f:\sp\public\sdk\inc\mcx.h +FILE 552 f:\sp\public\sdk\inc\winuser.h +FILE 553 f:\sp\public\sdk\inc\winnls.h +FILE 554 f:\sp\public\sdk\inc\stralign.h +FILE 555 f:\sp\public\sdk\inc\tvout.h +FILE 556 f:\sp\public\sdk\inc\winsvc.h +FILE 557 f:\sp\public\sdk\inc\wingdi.h +FILE 558 f:\sp\public\sdk\inc\winnt.h +FILE 559 f:\sp\public\sdk\inc\pshpack4.h +FILE 560 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 561 f:\sp\public\sdk\inc\poppack.h +FILE 562 f:\sp\public\sdk\inc\winnetwk.h +FILE 563 f:\sp\public\sdk\inc\imm.h +FILE 564 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 565 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 566 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 567 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 568 f:\sp\vctools\crt_bld\self_x86\crt\src\strdup.c +FILE 569 f:\sp\public\sdk\inc\pshpack1.h +FILE 570 f:\sp\public\sdk\inc\winver.h +FILE 571 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 572 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 573 f:\sp\public\sdk\inc\guiddef.h +FILE 574 f:\sp\public\sdk\inc\windows.h +FILE 575 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 576 f:\sp\public\sdk\inc\specstrings.h +FILE 577 f:\sp\public\sdk\inc\basetsd.h +FILE 578 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 579 f:\sp\public\sdk\inc\winreg.h +FILE 580 f:\sp\public\sdk\inc\ddbanned.h +FILE 581 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 582 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 583 f:\sp\public\sdk\inc\winbase.h +FILE 584 f:\sp\public\sdk\inc\winerror.h +FILE 585 f:\sp\public\sdk\inc\pshpack8.h +FILE 586 f:\sp\public\sdk\inc\reason.h +FILE 587 f:\sp\public\sdk\inc\wincon.h +FILE 588 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 589 f:\sp\public\sdk\inc\windef.h +FILE 590 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\strcspn.asm +FILE 591 F:\SP\vctools\crt_bld\SELF_X86\crt\src\Intel\STRSPN.ASM +FILE 592 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 593 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\strcmp.asm +FILE 594 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 595 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\strchr.asm +FILE 596 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 597 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\string\i386\p4_memset.c +FILE 598 f:\sp\public\sdk\inc\ddbanned.h +FILE 599 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 600 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 601 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\memset.asm +FILE 602 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 603 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\memmove.asm +FILE 604 F:\SP\vctools\crt_bld\SELF_X86\crt\src\Intel\MEMCPY.ASM +FILE 605 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 606 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\string\i386\memcmp.c +FILE 607 f:\sp\public\sdk\inc\ddbanned.h +FILE 608 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 609 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 610 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\string\i386\p4_memcpy.c +FILE 611 f:\sp\public\sdk\inc\ddbanned.h +FILE 612 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 613 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 614 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\memcpy.asm +FILE 615 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 616 f:\sp\public\sdk\inc\pshpack2.h +FILE 617 f:\sp\public\sdk\inc\winreg.h +FILE 618 f:\sp\public\sdk\inc\guiddef.h +FILE 619 f:\sp\public\sdk\inc\windows.h +FILE 620 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 621 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 622 f:\sp\public\sdk\inc\specstrings.h +FILE 623 f:\sp\public\sdk\inc\basetsd.h +FILE 624 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 625 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 626 f:\sp\public\sdk\inc\pshpack4.h +FILE 627 f:\sp\public\sdk\inc\reason.h +FILE 628 f:\sp\public\sdk\inc\wincon.h +FILE 629 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 630 f:\sp\public\sdk\inc\poppack.h +FILE 631 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 632 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 633 f:\sp\public\sdk\inc\mcx.h +FILE 634 f:\sp\public\sdk\inc\winuser.h +FILE 635 f:\sp\public\sdk\inc\winnls.h +FILE 636 f:\sp\public\sdk\inc\stralign.h +FILE 637 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 638 f:\sp\public\sdk\inc\windef.h +FILE 639 f:\sp\public\sdk\inc\tvout.h +FILE 640 f:\sp\public\sdk\inc\winsvc.h +FILE 641 f:\sp\vctools\crt_bld\self_x86\crt\src\tidtable.c +FILE 642 f:\sp\public\sdk\inc\wingdi.h +FILE 643 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 644 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 645 f:\sp\public\sdk\inc\winnt.h +FILE 646 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 647 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 648 f:\sp\public\sdk\inc\winnetwk.h +FILE 649 f:\sp\public\sdk\inc\imm.h +FILE 650 f:\sp\public\sdk\inc\ddbanned.h +FILE 651 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 652 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 653 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 654 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 655 f:\sp\public\sdk\inc\winbase.h +FILE 656 f:\sp\public\sdk\inc\winerror.h +FILE 657 f:\sp\public\sdk\inc\pshpack1.h +FILE 658 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 659 f:\sp\vctools\crt_bld\self_x86\crt\src\memory.h +FILE 660 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 661 f:\sp\vctools\crt_bld\self_x86\crt\src\msdos.h +FILE 662 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 663 f:\sp\public\sdk\inc\pshpack8.h +FILE 664 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 665 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 666 f:\sp\public\sdk\inc\winver.h +FILE 667 f:\sp\public\sdk\inc\pshpack4.h +FILE 668 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 669 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 670 f:\sp\public\sdk\inc\poppack.h +FILE 671 f:\sp\public\sdk\inc\winnt.h +FILE 672 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 673 f:\sp\public\sdk\inc\winnetwk.h +FILE 674 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 675 f:\sp\public\sdk\inc\imm.h +FILE 676 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 677 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 678 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 679 f:\sp\public\sdk\inc\pshpack1.h +FILE 680 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 681 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 682 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 683 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 684 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 685 f:\sp\public\sdk\inc\winver.h +FILE 686 f:\sp\public\sdk\inc\guiddef.h +FILE 687 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 688 f:\sp\public\sdk\inc\specstrings.h +FILE 689 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 690 f:\sp\public\sdk\inc\basetsd.h +FILE 691 f:\sp\public\sdk\inc\windows.h +FILE 692 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 693 f:\sp\public\sdk\inc\winreg.h +FILE 694 f:\sp\vctools\crt_bld\self_x86\crt\src\stdenvp.c +FILE 695 f:\sp\public\sdk\inc\winbase.h +FILE 696 f:\sp\public\sdk\inc\winerror.h +FILE 697 f:\sp\public\sdk\inc\pshpack8.h +FILE 698 f:\sp\public\sdk\inc\reason.h +FILE 699 f:\sp\public\sdk\inc\ddbanned.h +FILE 700 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 701 f:\sp\public\sdk\inc\wincon.h +FILE 702 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 703 f:\sp\public\sdk\inc\pshpack2.h +FILE 704 f:\sp\public\sdk\inc\mcx.h +FILE 705 f:\sp\public\sdk\inc\winuser.h +FILE 706 f:\sp\public\sdk\inc\winnls.h +FILE 707 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 708 f:\sp\public\sdk\inc\windef.h +FILE 709 f:\sp\public\sdk\inc\stralign.h +FILE 710 f:\sp\public\sdk\inc\tvout.h +FILE 711 f:\sp\public\sdk\inc\winsvc.h +FILE 712 f:\sp\public\sdk\inc\wingdi.h +FILE 713 f:\sp\public\sdk\inc\poppack.h +FILE 714 f:\sp\vctools\crt_bld\self_x86\crt\src\dos.h +FILE 715 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 716 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 717 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 718 f:\sp\public\sdk\inc\winnetwk.h +FILE 719 f:\sp\public\sdk\inc\imm.h +FILE 720 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 721 f:\sp\public\sdk\inc\windef.h +FILE 722 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 723 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 724 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 725 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 726 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 727 f:\sp\public\sdk\inc\pshpack1.h +FILE 728 f:\sp\public\sdk\inc\winver.h +FILE 729 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 730 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 731 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 732 f:\sp\public\sdk\inc\winnt.h +FILE 733 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 734 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 735 f:\sp\public\sdk\inc\winreg.h +FILE 736 f:\sp\vctools\crt_bld\self_x86\crt\src\stdargv.c +FILE 737 f:\sp\public\sdk\inc\winbase.h +FILE 738 f:\sp\public\sdk\inc\winerror.h +FILE 739 f:\sp\public\sdk\inc\pshpack8.h +FILE 740 f:\sp\public\sdk\inc\reason.h +FILE 741 f:\sp\public\sdk\inc\wincon.h +FILE 742 f:\sp\public\sdk\inc\ddbanned.h +FILE 743 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 744 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 745 f:\sp\public\sdk\inc\pshpack2.h +FILE 746 f:\sp\public\sdk\inc\mcx.h +FILE 747 f:\sp\public\sdk\inc\winuser.h +FILE 748 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 749 f:\sp\public\sdk\inc\winnls.h +FILE 750 f:\sp\public\sdk\inc\guiddef.h +FILE 751 f:\sp\public\sdk\inc\windows.h +FILE 752 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 753 f:\sp\public\sdk\inc\specstrings.h +FILE 754 f:\sp\public\sdk\inc\basetsd.h +FILE 755 f:\sp\public\sdk\inc\stralign.h +FILE 756 f:\sp\public\sdk\inc\tvout.h +FILE 757 f:\sp\public\sdk\inc\winsvc.h +FILE 758 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 759 f:\sp\public\sdk\inc\wingdi.h +FILE 760 f:\sp\public\sdk\inc\pshpack4.h +FILE 761 f:\sp\public\sdk\inc\reason.h +FILE 762 f:\sp\public\sdk\inc\wincon.h +FILE 763 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 764 f:\sp\public\sdk\inc\poppack.h +FILE 765 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 766 f:\sp\public\sdk\inc\mcx.h +FILE 767 f:\sp\public\sdk\inc\winuser.h +FILE 768 f:\sp\public\sdk\inc\winnls.h +FILE 769 f:\sp\public\sdk\inc\stralign.h +FILE 770 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 771 f:\sp\public\sdk\inc\windef.h +FILE 772 f:\sp\public\sdk\inc\tvout.h +FILE 773 f:\sp\public\sdk\inc\winsvc.h +FILE 774 f:\sp\public\sdk\inc\wingdi.h +FILE 775 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 776 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 777 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 778 f:\sp\public\sdk\inc\winnt.h +FILE 779 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 780 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 781 f:\sp\public\sdk\inc\winnetwk.h +FILE 782 f:\sp\public\sdk\inc\imm.h +FILE 783 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 784 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 785 f:\sp\vctools\crt_bld\self_x86\crt\src\mlock.c +FILE 786 f:\sp\public\sdk\inc\winbase.h +FILE 787 f:\sp\public\sdk\inc\winerror.h +FILE 788 f:\sp\public\sdk\inc\pshpack1.h +FILE 789 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 790 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 791 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 792 f:\sp\public\sdk\inc\pshpack8.h +FILE 793 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 794 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 795 f:\sp\public\sdk\inc\winver.h +FILE 796 f:\sp\public\sdk\inc\ddbanned.h +FILE 797 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 798 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 799 f:\sp\public\sdk\inc\pshpack2.h +FILE 800 f:\sp\public\sdk\inc\winreg.h +FILE 801 f:\sp\public\sdk\inc\guiddef.h +FILE 802 f:\sp\public\sdk\inc\windows.h +FILE 803 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 804 f:\sp\public\sdk\inc\specstrings.h +FILE 805 f:\sp\public\sdk\inc\basetsd.h +FILE 806 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 807 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 808 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 809 f:\sp\public\sdk\inc\pshpack4.h +FILE 810 f:\sp\public\sdk\inc\poppack.h +FILE 811 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 812 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 813 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 814 f:\sp\public\sdk\inc\winnetwk.h +FILE 815 f:\sp\public\sdk\inc\imm.h +FILE 816 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 817 f:\sp\public\sdk\inc\windef.h +FILE 818 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 819 f:\sp\public\sdk\inc\pshpack1.h +FILE 820 f:\sp\public\sdk\inc\winver.h +FILE 821 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 822 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 823 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 824 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 825 f:\sp\public\sdk\inc\winnt.h +FILE 826 f:\sp\vctools\crt_bld\self_x86\crt\src\cmsgs.h +FILE 827 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 828 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 829 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 830 f:\sp\public\sdk\inc\winreg.h +FILE 831 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 832 f:\sp\vctools\crt_bld\self_x86\crt\src\crt0msg.c +FILE 833 f:\sp\public\sdk\inc\winbase.h +FILE 834 f:\sp\public\sdk\inc\winerror.h +FILE 835 f:\sp\public\sdk\inc\pshpack8.h +FILE 836 f:\sp\public\sdk\inc\reason.h +FILE 837 f:\sp\public\sdk\inc\wincon.h +FILE 838 f:\sp\public\sdk\inc\ddbanned.h +FILE 839 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 840 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 841 f:\sp\public\sdk\inc\pshpack2.h +FILE 842 f:\sp\public\sdk\inc\mcx.h +FILE 843 f:\sp\public\sdk\inc\winuser.h +FILE 844 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 845 f:\sp\public\sdk\inc\winnls.h +FILE 846 f:\sp\public\sdk\inc\guiddef.h +FILE 847 f:\sp\public\sdk\inc\windows.h +FILE 848 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 849 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 850 f:\sp\public\sdk\inc\specstrings.h +FILE 851 f:\sp\public\sdk\inc\basetsd.h +FILE 852 f:\sp\public\sdk\inc\stralign.h +FILE 853 f:\sp\public\sdk\inc\tvout.h +FILE 854 f:\sp\public\sdk\inc\winsvc.h +FILE 855 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 856 f:\sp\public\sdk\inc\wingdi.h +FILE 857 f:\sp\public\sdk\inc\pshpack4.h +FILE 858 f:\sp\public\sdk\inc\pshpack1.h +FILE 859 f:\sp\public\sdk\inc\winver.h +FILE 860 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 861 f:\sp\public\sdk\inc\winnt.h +FILE 862 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 863 f:\sp\public\sdk\inc\winreg.h +FILE 864 f:\sp\public\sdk\inc\winbase.h +FILE 865 f:\sp\public\sdk\inc\winerror.h +FILE 866 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 867 f:\sp\public\sdk\inc\pshpack8.h +FILE 868 f:\sp\public\sdk\inc\reason.h +FILE 869 f:\sp\public\sdk\inc\wincon.h +FILE 870 f:\sp\public\sdk\inc\pshpack2.h +FILE 871 f:\sp\vctools\crt_bld\self_x86\crt\src\crt0init.c +FILE 872 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 873 f:\sp\public\sdk\inc\mcx.h +FILE 874 f:\sp\public\sdk\inc\winuser.h +FILE 875 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 876 f:\sp\public\sdk\inc\winnls.h +FILE 877 f:\sp\public\sdk\inc\guiddef.h +FILE 878 f:\sp\public\sdk\inc\windows.h +FILE 879 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 880 f:\sp\public\sdk\inc\specstrings.h +FILE 881 f:\sp\public\sdk\inc\basetsd.h +FILE 882 f:\sp\public\sdk\inc\stralign.h +FILE 883 f:\sp\public\sdk\inc\tvout.h +FILE 884 f:\sp\public\sdk\inc\winsvc.h +FILE 885 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 886 f:\sp\public\sdk\inc\wingdi.h +FILE 887 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 888 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 889 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 890 f:\sp\public\sdk\inc\pshpack4.h +FILE 891 f:\sp\public\sdk\inc\ddbanned.h +FILE 892 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 893 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 894 f:\sp\public\sdk\inc\poppack.h +FILE 895 f:\sp\public\sdk\inc\winnetwk.h +FILE 896 f:\sp\public\sdk\inc\imm.h +FILE 897 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 898 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 899 f:\sp\public\sdk\inc\windef.h +FILE 900 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 901 f:\sp\public\sdk\inc\poppack.h +FILE 902 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 903 f:\sp\public\sdk\inc\winnetwk.h +FILE 904 f:\sp\public\sdk\inc\imm.h +FILE 905 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 906 f:\sp\public\sdk\inc\windef.h +FILE 907 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 908 f:\sp\public\sdk\inc\pshpack1.h +FILE 909 f:\sp\public\sdk\inc\winver.h +FILE 910 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 911 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 912 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 913 f:\sp\public\sdk\inc\winnt.h +FILE 914 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 915 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 916 f:\sp\public\sdk\inc\winreg.h +FILE 917 f:\sp\vctools\crt_bld\self_x86\crt\src\crt0fp.c +FILE 918 f:\sp\public\sdk\inc\winbase.h +FILE 919 f:\sp\public\sdk\inc\winerror.h +FILE 920 f:\sp\public\sdk\inc\pshpack8.h +FILE 921 f:\sp\public\sdk\inc\reason.h +FILE 922 f:\sp\public\sdk\inc\wincon.h +FILE 923 f:\sp\public\sdk\inc\ddbanned.h +FILE 924 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 925 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 926 f:\sp\public\sdk\inc\pshpack2.h +FILE 927 f:\sp\public\sdk\inc\mcx.h +FILE 928 f:\sp\public\sdk\inc\winuser.h +FILE 929 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 930 f:\sp\public\sdk\inc\winnls.h +FILE 931 f:\sp\public\sdk\inc\guiddef.h +FILE 932 f:\sp\public\sdk\inc\windows.h +FILE 933 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 934 f:\sp\public\sdk\inc\specstrings.h +FILE 935 f:\sp\public\sdk\inc\basetsd.h +FILE 936 f:\sp\public\sdk\inc\stralign.h +FILE 937 f:\sp\public\sdk\inc\tvout.h +FILE 938 f:\sp\public\sdk\inc\winsvc.h +FILE 939 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 940 f:\sp\public\sdk\inc\wingdi.h +FILE 941 f:\sp\public\sdk\inc\pshpack4.h +FILE 942 f:\sp\vctools\crt_bld\self_x86\crt\src\process.h +FILE 943 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 944 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 945 f:\sp\public\sdk\inc\pshpack4.h +FILE 946 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 947 f:\sp\public\sdk\inc\reason.h +FILE 948 f:\sp\public\sdk\inc\wincon.h +FILE 949 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 950 f:\sp\public\sdk\inc\poppack.h +FILE 951 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 952 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 953 f:\sp\public\sdk\inc\mcx.h +FILE 954 f:\sp\public\sdk\inc\winuser.h +FILE 955 f:\sp\public\sdk\inc\winnls.h +FILE 956 f:\sp\public\sdk\inc\stralign.h +FILE 957 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 958 f:\sp\public\sdk\inc\windef.h +FILE 959 f:\sp\public\sdk\inc\tvout.h +FILE 960 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 961 f:\sp\public\sdk\inc\winsvc.h +FILE 962 f:\sp\public\sdk\inc\wingdi.h +FILE 963 f:\sp\vctools\crt_bld\self_x86\crt\src\msdos.h +FILE 964 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 965 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 966 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 967 f:\sp\vctools\crt_bld\self_x86\crt\src\mbdata.h +FILE 968 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 969 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 970 f:\sp\public\sdk\inc\winnt.h +FILE 971 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 972 f:\sp\public\sdk\inc\winnetwk.h +FILE 973 f:\sp\public\sdk\inc\imm.h +FILE 974 f:\sp\vctools\crt_bld\self_x86\crt\src\crt0dat.c +FILE 975 f:\sp\public\sdk\inc\winbase.h +FILE 976 f:\sp\public\sdk\inc\winerror.h +FILE 977 f:\sp\public\sdk\inc\pshpack1.h +FILE 978 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 979 f:\sp\public\sdk\inc\pshpack8.h +FILE 980 f:\sp\public\sdk\inc\winver.h +FILE 981 f:\sp\public\sdk\inc\ddbanned.h +FILE 982 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 983 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 984 f:\sp\vctools\crt_bld\self_x86\crt\src\dos.h +FILE 985 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 986 f:\sp\public\sdk\inc\pshpack2.h +FILE 987 f:\sp\public\sdk\inc\winreg.h +FILE 988 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 989 f:\sp\public\sdk\inc\guiddef.h +FILE 990 f:\sp\public\sdk\inc\windows.h +FILE 991 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 992 f:\sp\public\sdk\inc\specstrings.h +FILE 993 f:\sp\public\sdk\inc\basetsd.h +FILE 994 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 995 f:\sp\public\sdk\inc\tvout.h +FILE 996 f:\sp\public\sdk\inc\winsvc.h +FILE 997 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 998 f:\sp\public\sdk\inc\wingdi.h +FILE 999 f:\sp\public\sdk\inc\pshpack4.h +FILE 1000 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1001 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1002 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 1003 f:\sp\public\sdk\inc\poppack.h +FILE 1004 f:\sp\vctools\crt_bld\self_x86\crt\src\process.h +FILE 1005 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 1006 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 1007 f:\sp\public\sdk\inc\winnetwk.h +FILE 1008 f:\sp\public\sdk\inc\imm.h +FILE 1009 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1010 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1011 f:\sp\public\sdk\inc\windef.h +FILE 1012 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1013 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1014 f:\sp\vctools\crt_bld\self_x86\crt\src\dos.h +FILE 1015 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1016 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1017 f:\sp\public\sdk\inc\pshpack1.h +FILE 1018 f:\sp\public\sdk\inc\winver.h +FILE 1019 f:\sp\public\sdk\inc\winnt.h +FILE 1020 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1021 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1022 f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c +FILE 1023 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1024 f:\sp\public\sdk\inc\winreg.h +FILE 1025 f:\sp\public\sdk\inc\winbase.h +FILE 1026 f:\sp\public\sdk\inc\winerror.h +FILE 1027 f:\sp\public\sdk\inc\ddbanned.h +FILE 1028 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1029 f:\sp\public\sdk\inc\pshpack8.h +FILE 1030 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1031 f:\sp\public\sdk\inc\reason.h +FILE 1032 f:\sp\public\sdk\inc\wincon.h +FILE 1033 f:\sp\public\sdk\inc\pshpack2.h +FILE 1034 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1035 f:\sp\public\sdk\inc\mcx.h +FILE 1036 f:\sp\public\sdk\inc\winuser.h +FILE 1037 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1038 f:\sp\public\sdk\inc\winnls.h +FILE 1039 f:\sp\public\sdk\inc\guiddef.h +FILE 1040 f:\sp\public\sdk\inc\windows.h +FILE 1041 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1042 f:\sp\public\sdk\inc\specstrings.h +FILE 1043 f:\sp\public\sdk\inc\basetsd.h +FILE 1044 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 1045 f:\sp\public\sdk\inc\stralign.h +FILE 1046 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\alloca16.asm +FILE 1047 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 1048 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\chkstk.asm +FILE 1049 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 1050 f:\sp\public\sdk\inc\wincon.h +FILE 1051 f:\sp\public\sdk\inc\imm.h +FILE 1052 f:\sp\public\sdk\inc\winbase.h +FILE 1053 f:\sp\public\sdk\inc\wingdi.h +FILE 1054 f:\sp\public\sdk\inc\winver.h +FILE 1055 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 1056 f:\sp\public\sdk\inc\windows.h +FILE 1057 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 1058 f:\sp\public\sdk\inc\pshpack2.h +FILE 1059 f:\sp\public\sdk\inc\reason.h +FILE 1060 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\rtc\initsect.cpp +FILE 1061 f:\sp\public\sdk\inc\specstrings.h +FILE 1062 f:\sp\public\sdk\inc\basetsd.h +FILE 1063 f:\sp\public\sdk\inc\pshpack4.h +FILE 1064 f:\sp\public\sdk\inc\winnetwk.h +FILE 1065 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 1066 f:\sp\public\sdk\inc\stralign.h +FILE 1067 f:\sp\public\sdk\inc\poppack.h +FILE 1068 f:\sp\public\sdk\inc\winsvc.h +FILE 1069 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 1070 f:\sp\public\sdk\inc\windef.h +FILE 1071 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 1072 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 1073 f:\sp\public\sdk\inc\winuser.h +FILE 1074 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 1075 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sect_attribs.h +FILE 1076 f:\sp\public\sdk\inc\mcx.h +FILE 1077 f:\sp\public\sdk\inc\pshpack8.h +FILE 1078 f:\sp\public\sdk\inc\guiddef.h +FILE 1079 f:\sp\public\sdk\inc\winnt.h +FILE 1080 f:\sp\public\sdk\inc\winnls.h +FILE 1081 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 1082 f:\sp\public\sdk\inc\pshpack1.h +FILE 1083 f:\sp\public\sdk\inc\winerror.h +FILE 1084 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\rtcapi.h +FILE 1085 f:\sp\public\sdk\inc\winreg.h +FILE 1086 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 1087 f:\sp\public\sdk\inc\ddbanned.h +FILE 1088 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 1089 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 1090 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\rtcpriv.h +FILE 1091 f:\sp\public\sdk\inc\tvout.h +FILE 1092 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\malloc.h +FILE 1093 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 1094 f:\sp\public\sdk\inc\poppack.h +FILE 1095 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1096 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1097 f:\sp\public\sdk\inc\winnetwk.h +FILE 1098 f:\sp\public\sdk\inc\imm.h +FILE 1099 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1100 f:\sp\public\sdk\inc\windef.h +FILE 1101 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1102 f:\sp\public\sdk\inc\pshpack1.h +FILE 1103 f:\sp\public\sdk\inc\winver.h +FILE 1104 f:\sp\public\sdk\inc\windows.h +FILE 1105 f:\sp\public\sdk\inc\winnt.h +FILE 1106 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1107 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1108 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1109 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1110 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1111 f:\sp\public\sdk\inc\winreg.h +FILE 1112 f:\sp\public\sdk\inc\winbase.h +FILE 1113 f:\sp\vctools\crt_bld\self_x86\crt\src\wtombenv.c +FILE 1114 f:\sp\public\sdk\inc\winerror.h +FILE 1115 f:\sp\public\sdk\inc\pshpack8.h +FILE 1116 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1117 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1118 f:\sp\public\sdk\inc\reason.h +FILE 1119 f:\sp\public\sdk\inc\wincon.h +FILE 1120 f:\sp\public\sdk\inc\ddbanned.h +FILE 1121 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1122 f:\sp\public\sdk\inc\pshpack2.h +FILE 1123 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1124 f:\sp\public\sdk\inc\mcx.h +FILE 1125 f:\sp\public\sdk\inc\winuser.h +FILE 1126 f:\sp\public\sdk\inc\winnls.h +FILE 1127 f:\sp\public\sdk\inc\guiddef.h +FILE 1128 f:\sp\public\sdk\inc\specstrings.h +FILE 1129 f:\sp\public\sdk\inc\basetsd.h +FILE 1130 f:\sp\public\sdk\inc\stralign.h +FILE 1131 f:\sp\public\sdk\inc\tvout.h +FILE 1132 f:\sp\public\sdk\inc\winsvc.h +FILE 1133 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1134 f:\sp\public\sdk\inc\wingdi.h +FILE 1135 f:\sp\public\sdk\inc\pshpack4.h +FILE 1136 f:\sp\public\sdk\inc\winnt.h +FILE 1137 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1138 f:\sp\public\sdk\inc\winreg.h +FILE 1139 f:\sp\public\sdk\inc\winbase.h +FILE 1140 f:\sp\public\sdk\inc\winerror.h +FILE 1141 f:\sp\public\sdk\inc\pshpack8.h +FILE 1142 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1143 f:\sp\public\sdk\inc\reason.h +FILE 1144 f:\sp\public\sdk\inc\wincon.h +FILE 1145 f:\sp\vctools\crt_bld\self_x86\crt\src\float.h +FILE 1146 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1147 f:\sp\public\sdk\inc\pshpack2.h +FILE 1148 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1149 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1150 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1151 f:\sp\public\sdk\inc\mcx.h +FILE 1152 f:\sp\public\sdk\inc\winuser.h +FILE 1153 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1154 f:\sp\public\sdk\inc\winnls.h +FILE 1155 f:\sp\public\sdk\inc\guiddef.h +FILE 1156 f:\sp\public\sdk\inc\windows.h +FILE 1157 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1158 f:\sp\public\sdk\inc\specstrings.h +FILE 1159 f:\sp\public\sdk\inc\basetsd.h +FILE 1160 f:\sp\public\sdk\inc\stralign.h +FILE 1161 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1162 f:\sp\vctools\crt_bld\self_x86\crt\src\signal.h +FILE 1163 f:\sp\public\sdk\inc\tvout.h +FILE 1164 f:\sp\public\sdk\inc\winsvc.h +FILE 1165 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1166 f:\sp\vctools\crt_bld\self_x86\crt\src\winxfltr.c +FILE 1167 f:\sp\public\sdk\inc\wingdi.h +FILE 1168 f:\sp\public\sdk\inc\pshpack4.h +FILE 1169 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 1170 f:\sp\public\sdk\inc\poppack.h +FILE 1171 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1172 f:\sp\public\sdk\inc\winnetwk.h +FILE 1173 f:\sp\public\sdk\inc\imm.h +FILE 1174 f:\sp\public\sdk\inc\ddbanned.h +FILE 1175 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1176 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1177 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1178 f:\sp\public\sdk\inc\windef.h +FILE 1179 f:\sp\vctools\crt_bld\self_x86\crt\src\crtwrn.h +FILE 1180 f:\sp\public\sdk\inc\pshpack1.h +FILE 1181 f:\sp\public\sdk\inc\winver.h +FILE 1182 f:\sp\public\sdk\inc\winnetwk.h +FILE 1183 f:\sp\public\sdk\inc\imm.h +FILE 1184 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1185 f:\sp\public\sdk\inc\windef.h +FILE 1186 f:\sp\public\sdk\inc\pshpack1.h +FILE 1187 f:\sp\public\sdk\inc\winver.h +FILE 1188 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1189 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1190 f:\sp\public\sdk\inc\winnt.h +FILE 1191 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1192 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1193 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1194 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1195 f:\sp\public\sdk\inc\winreg.h +FILE 1196 f:\sp\public\sdk\inc\winbase.h +FILE 1197 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1198 f:\sp\public\sdk\inc\winerror.h +FILE 1199 f:\sp\vctools\crt_bld\self_x86\crt\src\winsig.c +FILE 1200 f:\sp\public\sdk\inc\pshpack8.h +FILE 1201 f:\sp\public\sdk\inc\reason.h +FILE 1202 f:\sp\public\sdk\inc\wincon.h +FILE 1203 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1204 f:\sp\public\sdk\inc\pshpack2.h +FILE 1205 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1206 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1207 f:\sp\public\sdk\inc\mcx.h +FILE 1208 f:\sp\public\sdk\inc\winuser.h +FILE 1209 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1210 f:\sp\public\sdk\inc\winnls.h +FILE 1211 f:\sp\public\sdk\inc\guiddef.h +FILE 1212 f:\sp\public\sdk\inc\windows.h +FILE 1213 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1214 f:\sp\public\sdk\inc\specstrings.h +FILE 1215 f:\sp\public\sdk\inc\ddbanned.h +FILE 1216 f:\sp\public\sdk\inc\basetsd.h +FILE 1217 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1218 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1219 f:\sp\public\sdk\inc\stralign.h +FILE 1220 f:\sp\vctools\crt_bld\self_x86\crt\src\signal.h +FILE 1221 f:\sp\public\sdk\inc\tvout.h +FILE 1222 f:\sp\public\sdk\inc\winsvc.h +FILE 1223 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1224 f:\sp\public\sdk\inc\wingdi.h +FILE 1225 f:\sp\vctools\crt_bld\self_x86\crt\src\float.h +FILE 1226 f:\sp\vctools\crt_bld\self_x86\crt\src\crtwrn.h +FILE 1227 f:\sp\public\sdk\inc\pshpack4.h +FILE 1228 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 1229 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1230 f:\sp\public\sdk\inc\poppack.h +FILE 1231 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1232 f:\sp\public\sdk\inc\wincon.h +FILE 1233 f:\sp\public\sdk\inc\imm.h +FILE 1234 f:\sp\public\sdk\inc\winbase.h +FILE 1235 f:\sp\public\sdk\inc\wingdi.h +FILE 1236 f:\sp\public\sdk\inc\winver.h +FILE 1237 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1238 f:\sp\public\sdk\inc\windows.h +FILE 1239 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1240 f:\sp\public\sdk\inc\pshpack2.h +FILE 1241 f:\sp\public\sdk\inc\reason.h +FILE 1242 f:\sp\vctools\crt_bld\self_x86\crt\src\w_str.c +FILE 1243 f:\sp\public\sdk\inc\specstrings.h +FILE 1244 f:\sp\public\sdk\inc\basetsd.h +FILE 1245 f:\sp\public\sdk\inc\pshpack4.h +FILE 1246 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1247 f:\sp\public\sdk\inc\winnetwk.h +FILE 1248 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1249 f:\sp\public\sdk\inc\stralign.h +FILE 1250 f:\sp\public\sdk\inc\poppack.h +FILE 1251 f:\sp\public\sdk\inc\winsvc.h +FILE 1252 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1253 f:\sp\public\sdk\inc\windef.h +FILE 1254 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1255 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1256 f:\sp\public\sdk\inc\winuser.h +FILE 1257 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1258 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1259 f:\sp\public\sdk\inc\mcx.h +FILE 1260 f:\sp\public\sdk\inc\pshpack8.h +FILE 1261 f:\sp\public\sdk\inc\guiddef.h +FILE 1262 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1263 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1264 f:\sp\public\sdk\inc\winnt.h +FILE 1265 f:\sp\public\sdk\inc\winnls.h +FILE 1266 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1267 f:\sp\public\sdk\inc\pshpack1.h +FILE 1268 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1269 f:\sp\public\sdk\inc\winerror.h +FILE 1270 f:\sp\public\sdk\inc\winreg.h +FILE 1271 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1272 f:\sp\public\sdk\inc\ddbanned.h +FILE 1273 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1274 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1275 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1276 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1277 f:\sp\public\sdk\inc\tvout.h +FILE 1278 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1279 f:\sp\public\sdk\inc\wincon.h +FILE 1280 f:\sp\public\sdk\inc\imm.h +FILE 1281 f:\sp\public\sdk\inc\winbase.h +FILE 1282 f:\sp\public\sdk\inc\wingdi.h +FILE 1283 f:\sp\public\sdk\inc\winver.h +FILE 1284 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1285 f:\sp\public\sdk\inc\windows.h +FILE 1286 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1287 f:\sp\public\sdk\inc\pshpack2.h +FILE 1288 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1289 f:\sp\public\sdk\inc\reason.h +FILE 1290 f:\sp\vctools\crt_bld\self_x86\crt\src\w_loc.c +FILE 1291 f:\sp\public\sdk\inc\specstrings.h +FILE 1292 f:\sp\public\sdk\inc\basetsd.h +FILE 1293 f:\sp\public\sdk\inc\pshpack4.h +FILE 1294 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1295 f:\sp\public\sdk\inc\winnetwk.h +FILE 1296 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1297 f:\sp\public\sdk\inc\stralign.h +FILE 1298 f:\sp\public\sdk\inc\poppack.h +FILE 1299 f:\sp\public\sdk\inc\winsvc.h +FILE 1300 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1301 f:\sp\public\sdk\inc\windef.h +FILE 1302 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1303 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1304 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1305 f:\sp\public\sdk\inc\winuser.h +FILE 1306 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1307 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1308 f:\sp\public\sdk\inc\mcx.h +FILE 1309 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1310 f:\sp\public\sdk\inc\pshpack8.h +FILE 1311 f:\sp\public\sdk\inc\guiddef.h +FILE 1312 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1313 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1314 f:\sp\public\sdk\inc\winnt.h +FILE 1315 f:\sp\public\sdk\inc\winnls.h +FILE 1316 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1317 f:\sp\public\sdk\inc\pshpack1.h +FILE 1318 f:\sp\public\sdk\inc\winerror.h +FILE 1319 f:\sp\public\sdk\inc\winreg.h +FILE 1320 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1321 f:\sp\public\sdk\inc\ddbanned.h +FILE 1322 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1323 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1324 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1325 f:\sp\public\sdk\inc\tvout.h +FILE 1326 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1327 f:\sp\public\sdk\inc\poppack.h +FILE 1328 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1329 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1330 f:\sp\public\sdk\inc\winnetwk.h +FILE 1331 f:\sp\public\sdk\inc\imm.h +FILE 1332 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1333 f:\sp\public\sdk\inc\windef.h +FILE 1334 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1335 f:\sp\vctools\crt_bld\self_x86\crt\src\wchar.h +FILE 1336 f:\sp\public\sdk\inc\pshpack1.h +FILE 1337 f:\sp\public\sdk\inc\winver.h +FILE 1338 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1339 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1340 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1341 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1342 f:\sp\public\sdk\inc\winnt.h +FILE 1343 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 1344 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1345 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1346 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1347 f:\sp\public\sdk\inc\winreg.h +FILE 1348 f:\sp\vctools\crt_bld\self_x86\crt\src\convrtcp.c +FILE 1349 f:\sp\public\sdk\inc\winbase.h +FILE 1350 f:\sp\public\sdk\inc\winerror.h +FILE 1351 f:\sp\public\sdk\inc\pshpack8.h +FILE 1352 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1353 f:\sp\public\sdk\inc\reason.h +FILE 1354 f:\sp\public\sdk\inc\wincon.h +FILE 1355 f:\sp\public\sdk\inc\ddbanned.h +FILE 1356 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1357 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1358 f:\sp\public\sdk\inc\pshpack2.h +FILE 1359 f:\sp\public\sdk\inc\mcx.h +FILE 1360 f:\sp\public\sdk\inc\winuser.h +FILE 1361 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1362 f:\sp\vctools\crt_bld\self_x86\crt\src\wtime.inl +FILE 1363 f:\sp\public\sdk\inc\winnls.h +FILE 1364 f:\sp\public\sdk\inc\guiddef.h +FILE 1365 f:\sp\public\sdk\inc\windows.h +FILE 1366 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1367 f:\sp\public\sdk\inc\specstrings.h +FILE 1368 f:\sp\public\sdk\inc\basetsd.h +FILE 1369 f:\sp\public\sdk\inc\stralign.h +FILE 1370 f:\sp\public\sdk\inc\tvout.h +FILE 1371 f:\sp\public\sdk\inc\winsvc.h +FILE 1372 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1373 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1374 f:\sp\public\sdk\inc\wingdi.h +FILE 1375 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1376 f:\sp\public\sdk\inc\pshpack4.h +FILE 1377 f:\sp\public\sdk\inc\winerror.h +FILE 1378 f:\sp\public\sdk\inc\pshpack8.h +FILE 1379 f:\sp\public\sdk\inc\reason.h +FILE 1380 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1381 f:\sp\public\sdk\inc\wincon.h +FILE 1382 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1383 f:\sp\public\sdk\inc\pshpack2.h +FILE 1384 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1385 f:\sp\public\sdk\inc\mcx.h +FILE 1386 f:\sp\public\sdk\inc\winuser.h +FILE 1387 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1388 f:\sp\public\sdk\inc\winnls.h +FILE 1389 f:\sp\public\sdk\inc\guiddef.h +FILE 1390 f:\sp\public\sdk\inc\windows.h +FILE 1391 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 1392 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1393 f:\sp\public\sdk\inc\specstrings.h +FILE 1394 f:\sp\public\sdk\inc\basetsd.h +FILE 1395 f:\sp\public\sdk\inc\stralign.h +FILE 1396 f:\sp\public\sdk\inc\tvout.h +FILE 1397 f:\sp\public\sdk\inc\winsvc.h +FILE 1398 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1399 f:\sp\public\sdk\inc\wingdi.h +FILE 1400 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1401 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1402 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1403 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1404 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1405 f:\sp\public\sdk\inc\pshpack4.h +FILE 1406 f:\sp\public\sdk\inc\poppack.h +FILE 1407 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1408 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1409 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.c +FILE 1410 f:\sp\public\sdk\inc\winnetwk.h +FILE 1411 f:\sp\public\sdk\inc\imm.h +FILE 1412 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1413 f:\sp\public\sdk\inc\windef.h +FILE 1414 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1415 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1416 f:\sp\public\sdk\inc\pshpack1.h +FILE 1417 f:\sp\public\sdk\inc\ddbanned.h +FILE 1418 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1419 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1420 f:\sp\public\sdk\inc\winver.h +FILE 1421 f:\sp\public\sdk\inc\winnt.h +FILE 1422 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1423 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1424 f:\sp\public\sdk\inc\winreg.h +FILE 1425 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1426 f:\sp\public\sdk\inc\winbase.h +FILE 1427 f:\sp\public\sdk\inc\poppack.h +FILE 1428 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 1429 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 1430 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1431 f:\sp\public\sdk\inc\winnetwk.h +FILE 1432 f:\sp\public\sdk\inc\imm.h +FILE 1433 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1434 f:\sp\public\sdk\inc\windef.h +FILE 1435 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1436 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1437 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1438 f:\sp\public\sdk\inc\pshpack1.h +FILE 1439 f:\sp\public\sdk\inc\winver.h +FILE 1440 f:\sp\public\sdk\inc\windows.h +FILE 1441 f:\sp\public\sdk\inc\winnt.h +FILE 1442 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1443 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1444 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1445 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1446 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1447 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1448 f:\sp\public\sdk\inc\winreg.h +FILE 1449 f:\sp\public\sdk\inc\winbase.h +FILE 1450 f:\sp\vctools\crt_bld\self_x86\crt\src\setenv.c +FILE 1451 f:\sp\public\sdk\inc\winerror.h +FILE 1452 f:\sp\public\sdk\inc\pshpack8.h +FILE 1453 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1454 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1455 f:\sp\public\sdk\inc\reason.h +FILE 1456 f:\sp\public\sdk\inc\wincon.h +FILE 1457 f:\sp\public\sdk\inc\ddbanned.h +FILE 1458 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1459 f:\sp\public\sdk\inc\pshpack2.h +FILE 1460 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1461 f:\sp\public\sdk\inc\mcx.h +FILE 1462 f:\sp\public\sdk\inc\winuser.h +FILE 1463 f:\sp\public\sdk\inc\winnls.h +FILE 1464 f:\sp\public\sdk\inc\guiddef.h +FILE 1465 f:\sp\public\sdk\inc\specstrings.h +FILE 1466 f:\sp\public\sdk\inc\basetsd.h +FILE 1467 f:\sp\public\sdk\inc\stralign.h +FILE 1468 f:\sp\public\sdk\inc\tvout.h +FILE 1469 f:\sp\public\sdk\inc\winsvc.h +FILE 1470 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1471 f:\sp\public\sdk\inc\wingdi.h +FILE 1472 f:\sp\public\sdk\inc\pshpack4.h +FILE 1473 f:\sp\public\sdk\inc\poppack.h +FILE 1474 f:\sp\public\sdk\inc\winnetwk.h +FILE 1475 f:\sp\public\sdk\inc\imm.h +FILE 1476 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1477 f:\sp\public\sdk\inc\windef.h +FILE 1478 f:\sp\public\sdk\inc\pshpack1.h +FILE 1479 f:\sp\public\sdk\inc\winver.h +FILE 1480 f:\sp\public\sdk\inc\windows.h +FILE 1481 f:\sp\public\sdk\inc\winnt.h +FILE 1482 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1483 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1484 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1485 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1486 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1487 f:\sp\public\sdk\inc\winreg.h +FILE 1488 f:\sp\public\sdk\inc\winbase.h +FILE 1489 f:\sp\vctools\crt_bld\self_x86\crt\src\rand_s.c +FILE 1490 f:\sp\public\sdk\inc\winerror.h +FILE 1491 f:\sp\public\sdk\inc\pshpack8.h +FILE 1492 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1493 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1494 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1495 f:\sp\public\sdk\inc\reason.h +FILE 1496 f:\sp\public\sdk\inc\wincon.h +FILE 1497 f:\sp\public\sdk\inc\ddbanned.h +FILE 1498 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1499 f:\sp\public\sdk\inc\pshpack2.h +FILE 1500 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1501 f:\sp\public\sdk\inc\mcx.h +FILE 1502 f:\sp\public\sdk\inc\winuser.h +FILE 1503 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 1504 f:\sp\public\sdk\inc\winnls.h +FILE 1505 f:\sp\public\sdk\inc\guiddef.h +FILE 1506 f:\sp\public\sdk\inc\specstrings.h +FILE 1507 f:\sp\public\sdk\inc\basetsd.h +FILE 1508 f:\sp\public\sdk\inc\stralign.h +FILE 1509 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1510 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1511 f:\sp\public\sdk\inc\tvout.h +FILE 1512 f:\sp\public\sdk\inc\winsvc.h +FILE 1513 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1514 f:\sp\public\sdk\inc\wingdi.h +FILE 1515 f:\sp\public\sdk\inc\pshpack4.h +FILE 1516 f:\sp\public\sdk\inc\poppack.h +FILE 1517 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1518 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1519 f:\sp\public\sdk\inc\winnetwk.h +FILE 1520 f:\sp\public\sdk\inc\imm.h +FILE 1521 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1522 f:\sp\public\sdk\inc\windef.h +FILE 1523 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1524 f:\sp\public\sdk\inc\pshpack1.h +FILE 1525 f:\sp\public\sdk\inc\winver.h +FILE 1526 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1527 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1528 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1529 f:\sp\public\sdk\inc\winnt.h +FILE 1530 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1531 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1532 f:\sp\public\sdk\inc\winreg.h +FILE 1533 f:\sp\vctools\crt_bld\self_x86\crt\src\purevirt.c +FILE 1534 f:\sp\public\sdk\inc\winbase.h +FILE 1535 f:\sp\public\sdk\inc\winerror.h +FILE 1536 f:\sp\public\sdk\inc\pshpack8.h +FILE 1537 f:\sp\public\sdk\inc\reason.h +FILE 1538 f:\sp\public\sdk\inc\wincon.h +FILE 1539 f:\sp\public\sdk\inc\ddbanned.h +FILE 1540 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1541 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1542 f:\sp\public\sdk\inc\pshpack2.h +FILE 1543 f:\sp\public\sdk\inc\mcx.h +FILE 1544 f:\sp\public\sdk\inc\winuser.h +FILE 1545 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1546 f:\sp\public\sdk\inc\winnls.h +FILE 1547 f:\sp\public\sdk\inc\guiddef.h +FILE 1548 f:\sp\public\sdk\inc\windows.h +FILE 1549 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1550 f:\sp\public\sdk\inc\specstrings.h +FILE 1551 f:\sp\public\sdk\inc\basetsd.h +FILE 1552 f:\sp\public\sdk\inc\stralign.h +FILE 1553 f:\sp\public\sdk\inc\tvout.h +FILE 1554 f:\sp\public\sdk\inc\winsvc.h +FILE 1555 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1556 f:\sp\public\sdk\inc\wingdi.h +FILE 1557 f:\sp\public\sdk\inc\pshpack4.h +FILE 1558 f:\sp\public\sdk\inc\poppack.h +FILE 1559 f:\sp\public\sdk\inc\winnetwk.h +FILE 1560 f:\sp\public\sdk\inc\imm.h +FILE 1561 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1562 f:\sp\public\sdk\inc\windef.h +FILE 1563 f:\sp\public\sdk\inc\pshpack1.h +FILE 1564 f:\sp\public\sdk\inc\winver.h +FILE 1565 f:\sp\public\sdk\inc\windows.h +FILE 1566 f:\sp\public\sdk\inc\winnt.h +FILE 1567 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1568 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1569 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1570 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1571 f:\sp\public\sdk\inc\winreg.h +FILE 1572 f:\sp\public\sdk\inc\winbase.h +FILE 1573 f:\sp\vctools\crt_bld\self_x86\crt\src\pesect.c +FILE 1574 f:\sp\public\sdk\inc\winerror.h +FILE 1575 f:\sp\public\sdk\inc\pshpack8.h +FILE 1576 f:\sp\public\sdk\inc\reason.h +FILE 1577 f:\sp\public\sdk\inc\wincon.h +FILE 1578 f:\sp\public\sdk\inc\ddbanned.h +FILE 1579 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1580 f:\sp\public\sdk\inc\pshpack2.h +FILE 1581 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1582 f:\sp\public\sdk\inc\mcx.h +FILE 1583 f:\sp\public\sdk\inc\winuser.h +FILE 1584 f:\sp\public\sdk\inc\winnls.h +FILE 1585 f:\sp\public\sdk\inc\guiddef.h +FILE 1586 f:\sp\public\sdk\inc\specstrings.h +FILE 1587 f:\sp\public\sdk\inc\basetsd.h +FILE 1588 f:\sp\public\sdk\inc\stralign.h +FILE 1589 f:\sp\public\sdk\inc\tvout.h +FILE 1590 f:\sp\public\sdk\inc\winsvc.h +FILE 1591 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1592 f:\sp\public\sdk\inc\wingdi.h +FILE 1593 f:\sp\public\sdk\inc\pshpack4.h +FILE 1594 f:\sp\public\sdk\inc\winerror.h +FILE 1595 f:\sp\public\sdk\inc\pshpack1.h +FILE 1596 f:\sp\public\sdk\inc\pshpack8.h +FILE 1597 f:\sp\public\sdk\inc\winver.h +FILE 1598 f:\sp\public\sdk\inc\pshpack2.h +FILE 1599 f:\sp\public\sdk\inc\winreg.h +FILE 1600 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1601 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1602 f:\sp\public\sdk\inc\guiddef.h +FILE 1603 f:\sp\public\sdk\inc\windows.h +FILE 1604 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1605 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 1606 f:\sp\public\sdk\inc\specstrings.h +FILE 1607 f:\sp\public\sdk\inc\basetsd.h +FILE 1608 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1609 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1610 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1611 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1612 f:\sp\public\sdk\inc\pshpack4.h +FILE 1613 f:\sp\public\sdk\inc\reason.h +FILE 1614 f:\sp\public\sdk\inc\wincon.h +FILE 1615 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1616 f:\sp\public\sdk\inc\poppack.h +FILE 1617 f:\sp\public\sdk\inc\mcx.h +FILE 1618 f:\sp\public\sdk\inc\winuser.h +FILE 1619 f:\sp\public\sdk\inc\winnls.h +FILE 1620 f:\sp\vctools\crt_bld\self_x86\crt\src\nlsdata2.c +FILE 1621 f:\sp\public\sdk\inc\stralign.h +FILE 1622 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1623 f:\sp\public\sdk\inc\windef.h +FILE 1624 f:\sp\public\sdk\inc\tvout.h +FILE 1625 f:\sp\public\sdk\inc\winsvc.h +FILE 1626 f:\sp\public\sdk\inc\wingdi.h +FILE 1627 f:\sp\public\sdk\inc\ddbanned.h +FILE 1628 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1629 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1630 f:\sp\public\sdk\inc\winnt.h +FILE 1631 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1632 f:\sp\public\sdk\inc\winnetwk.h +FILE 1633 f:\sp\public\sdk\inc\imm.h +FILE 1634 f:\sp\public\sdk\inc\winbase.h +FILE 1635 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1636 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1637 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1638 f:\sp\vctools\crt_bld\self_x86\crt\src\nlsdata1.c +FILE 1639 f:\sp\public\sdk\inc\ddbanned.h +FILE 1640 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1641 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1642 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1643 f:\sp\vctools\crt_bld\self_x86\crt\src\nlsint.h +FILE 1644 f:\sp\public\sdk\inc\reason.h +FILE 1645 f:\sp\public\sdk\inc\wincon.h +FILE 1646 f:\sp\public\sdk\inc\pshpack2.h +FILE 1647 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1648 f:\sp\public\sdk\inc\mcx.h +FILE 1649 f:\sp\public\sdk\inc\winuser.h +FILE 1650 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1651 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1652 f:\sp\public\sdk\inc\winnls.h +FILE 1653 f:\sp\public\sdk\inc\guiddef.h +FILE 1654 f:\sp\public\sdk\inc\windows.h +FILE 1655 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1656 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1657 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1658 f:\sp\public\sdk\inc\specstrings.h +FILE 1659 f:\sp\public\sdk\inc\basetsd.h +FILE 1660 f:\sp\public\sdk\inc\stralign.h +FILE 1661 f:\sp\public\sdk\inc\tvout.h +FILE 1662 f:\sp\public\sdk\inc\winsvc.h +FILE 1663 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1664 f:\sp\public\sdk\inc\wingdi.h +FILE 1665 f:\sp\public\sdk\inc\pshpack4.h +FILE 1666 f:\sp\public\sdk\inc\poppack.h +FILE 1667 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 1668 f:\sp\public\sdk\inc\winnetwk.h +FILE 1669 f:\sp\public\sdk\inc\imm.h +FILE 1670 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1671 f:\sp\public\sdk\inc\windef.h +FILE 1672 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1673 f:\sp\vctools\crt_bld\self_x86\crt\src\onexit.c +FILE 1674 f:\sp\public\sdk\inc\pshpack1.h +FILE 1675 f:\sp\public\sdk\inc\winver.h +FILE 1676 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1677 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1678 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1679 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1680 f:\sp\public\sdk\inc\winnt.h +FILE 1681 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1682 f:\sp\public\sdk\inc\ddbanned.h +FILE 1683 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1684 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1685 f:\sp\public\sdk\inc\winreg.h +FILE 1686 f:\sp\public\sdk\inc\winbase.h +FILE 1687 f:\sp\public\sdk\inc\winerror.h +FILE 1688 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1689 f:\sp\public\sdk\inc\pshpack8.h +FILE 1690 f:\sp\public\sdk\inc\winbase.h +FILE 1691 f:\sp\public\sdk\inc\winerror.h +FILE 1692 f:\sp\public\sdk\inc\pshpack1.h +FILE 1693 f:\sp\public\sdk\inc\pshpack8.h +FILE 1694 f:\sp\public\sdk\inc\winver.h +FILE 1695 f:\sp\public\sdk\inc\pshpack2.h +FILE 1696 f:\sp\public\sdk\inc\winreg.h +FILE 1697 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1698 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1699 f:\sp\public\sdk\inc\guiddef.h +FILE 1700 f:\sp\public\sdk\inc\windows.h +FILE 1701 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1702 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1703 f:\sp\public\sdk\inc\specstrings.h +FILE 1704 f:\sp\public\sdk\inc\basetsd.h +FILE 1705 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1706 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1707 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1708 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1709 f:\sp\public\sdk\inc\pshpack4.h +FILE 1710 f:\sp\public\sdk\inc\reason.h +FILE 1711 f:\sp\public\sdk\inc\wincon.h +FILE 1712 f:\sp\public\sdk\inc\poppack.h +FILE 1713 f:\sp\public\sdk\inc\mcx.h +FILE 1714 f:\sp\public\sdk\inc\winuser.h +FILE 1715 f:\sp\public\sdk\inc\winnls.h +FILE 1716 f:\sp\vctools\crt_bld\self_x86\crt\src\lconv.c +FILE 1717 f:\sp\public\sdk\inc\stralign.h +FILE 1718 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1719 f:\sp\public\sdk\inc\windef.h +FILE 1720 f:\sp\public\sdk\inc\tvout.h +FILE 1721 f:\sp\public\sdk\inc\winsvc.h +FILE 1722 f:\sp\public\sdk\inc\wingdi.h +FILE 1723 f:\sp\public\sdk\inc\ddbanned.h +FILE 1724 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1725 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1726 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1727 f:\sp\public\sdk\inc\winnt.h +FILE 1728 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1729 f:\sp\public\sdk\inc\winnetwk.h +FILE 1730 f:\sp\public\sdk\inc\imm.h +FILE 1731 f:\sp\public\sdk\inc\guiddef.h +FILE 1732 f:\sp\public\sdk\inc\winnt.h +FILE 1733 f:\sp\public\sdk\inc\winnls.h +FILE 1734 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1735 f:\sp\public\sdk\inc\pshpack1.h +FILE 1736 f:\sp\public\sdk\inc\winerror.h +FILE 1737 f:\sp\public\sdk\inc\winreg.h +FILE 1738 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1739 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 1740 f:\sp\public\sdk\inc\tvout.h +FILE 1741 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1742 f:\sp\vctools\crt_bld\self_x86\crt\src\invarg.c +FILE 1743 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1744 f:\sp\public\sdk\inc\wincon.h +FILE 1745 f:\sp\public\sdk\inc\imm.h +FILE 1746 f:\sp\public\sdk\inc\winbase.h +FILE 1747 f:\sp\public\sdk\inc\wingdi.h +FILE 1748 f:\sp\public\sdk\inc\winver.h +FILE 1749 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1750 f:\sp\public\sdk\inc\windows.h +FILE 1751 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1752 f:\sp\public\sdk\inc\pshpack2.h +FILE 1753 f:\sp\public\sdk\inc\reason.h +FILE 1754 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 1755 f:\sp\public\sdk\inc\specstrings.h +FILE 1756 f:\sp\public\sdk\inc\basetsd.h +FILE 1757 f:\sp\public\sdk\inc\pshpack4.h +FILE 1758 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1759 f:\sp\public\sdk\inc\winnetwk.h +FILE 1760 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1761 f:\sp\public\sdk\inc\stralign.h +FILE 1762 f:\sp\public\sdk\inc\poppack.h +FILE 1763 f:\sp\public\sdk\inc\winsvc.h +FILE 1764 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1765 f:\sp\public\sdk\inc\windef.h +FILE 1766 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1767 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1768 f:\sp\public\sdk\inc\winuser.h +FILE 1769 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1770 f:\sp\public\sdk\inc\ddbanned.h +FILE 1771 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1772 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1773 f:\sp\public\sdk\inc\mcx.h +FILE 1774 f:\sp\public\sdk\inc\pshpack8.h +FILE 1775 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1776 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1777 f:\sp\public\sdk\inc\pshpack4.h +FILE 1778 f:\sp\public\sdk\inc\poppack.h +FILE 1779 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1780 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1781 f:\sp\public\sdk\inc\winnetwk.h +FILE 1782 f:\sp\public\sdk\inc\imm.h +FILE 1783 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1784 f:\sp\public\sdk\inc\windef.h +FILE 1785 f:\sp\public\sdk\inc\pshpack1.h +FILE 1786 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1787 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1788 f:\sp\public\sdk\inc\winver.h +FILE 1789 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1790 f:\sp\public\sdk\inc\winnt.h +FILE 1791 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1792 f:\sp\public\sdk\inc\winreg.h +FILE 1793 f:\sp\vctools\crt_bld\self_x86\crt\src\inittime.c +FILE 1794 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1795 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1796 f:\sp\public\sdk\inc\winbase.h +FILE 1797 f:\sp\public\sdk\inc\winerror.h +FILE 1798 f:\sp\public\sdk\inc\pshpack8.h +FILE 1799 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1800 f:\sp\public\sdk\inc\reason.h +FILE 1801 f:\sp\public\sdk\inc\ddbanned.h +FILE 1802 f:\sp\public\sdk\inc\wincon.h +FILE 1803 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1804 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1805 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1806 f:\sp\public\sdk\inc\pshpack2.h +FILE 1807 f:\sp\public\sdk\inc\mcx.h +FILE 1808 f:\sp\public\sdk\inc\winuser.h +FILE 1809 f:\sp\public\sdk\inc\winnls.h +FILE 1810 f:\sp\public\sdk\inc\guiddef.h +FILE 1811 f:\sp\public\sdk\inc\stralign.h +FILE 1812 f:\sp\public\sdk\inc\specstrings.h +FILE 1813 f:\sp\public\sdk\inc\basetsd.h +FILE 1814 f:\sp\public\sdk\inc\windows.h +FILE 1815 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1816 f:\sp\public\sdk\inc\tvout.h +FILE 1817 f:\sp\public\sdk\inc\winsvc.h +FILE 1818 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1819 f:\sp\public\sdk\inc\wingdi.h +FILE 1820 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1821 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1822 f:\sp\public\sdk\inc\pshpack4.h +FILE 1823 f:\sp\public\sdk\inc\poppack.h +FILE 1824 f:\sp\public\sdk\inc\winnt.h +FILE 1825 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1826 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1827 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1828 f:\sp\public\sdk\inc\winnetwk.h +FILE 1829 f:\sp\public\sdk\inc\imm.h +FILE 1830 f:\sp\public\sdk\inc\pshpack1.h +FILE 1831 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1832 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1833 f:\sp\public\sdk\inc\winver.h +FILE 1834 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1835 f:\sp\public\sdk\inc\guiddef.h +FILE 1836 f:\sp\public\sdk\inc\specstrings.h +FILE 1837 f:\sp\public\sdk\inc\basetsd.h +FILE 1838 f:\sp\public\sdk\inc\windows.h +FILE 1839 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1840 f:\sp\public\sdk\inc\winreg.h +FILE 1841 f:\sp\vctools\crt_bld\self_x86\crt\src\initnum.c +FILE 1842 f:\sp\vctools\crt_bld\self_x86\crt\src\nlsint.h +FILE 1843 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1844 f:\sp\public\sdk\inc\winbase.h +FILE 1845 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1846 f:\sp\public\sdk\inc\winerror.h +FILE 1847 f:\sp\public\sdk\inc\pshpack8.h +FILE 1848 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1849 f:\sp\public\sdk\inc\reason.h +FILE 1850 f:\sp\public\sdk\inc\ddbanned.h +FILE 1851 f:\sp\public\sdk\inc\wincon.h +FILE 1852 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1853 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1854 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1855 f:\sp\public\sdk\inc\pshpack2.h +FILE 1856 f:\sp\public\sdk\inc\mcx.h +FILE 1857 f:\sp\public\sdk\inc\winuser.h +FILE 1858 f:\sp\public\sdk\inc\winnls.h +FILE 1859 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1860 f:\sp\public\sdk\inc\windef.h +FILE 1861 f:\sp\public\sdk\inc\stralign.h +FILE 1862 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1863 f:\sp\public\sdk\inc\tvout.h +FILE 1864 f:\sp\public\sdk\inc\winsvc.h +FILE 1865 f:\sp\public\sdk\inc\wingdi.h +FILE 1866 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1867 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1868 f:\sp\public\sdk\inc\pshpack4.h +FILE 1869 f:\sp\public\sdk\inc\poppack.h +FILE 1870 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1871 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1872 f:\sp\public\sdk\inc\winnetwk.h +FILE 1873 f:\sp\public\sdk\inc\imm.h +FILE 1874 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1875 f:\sp\public\sdk\inc\windef.h +FILE 1876 f:\sp\public\sdk\inc\pshpack1.h +FILE 1877 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1878 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1879 f:\sp\public\sdk\inc\winver.h +FILE 1880 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1881 f:\sp\public\sdk\inc\winnt.h +FILE 1882 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1883 f:\sp\public\sdk\inc\winreg.h +FILE 1884 f:\sp\vctools\crt_bld\self_x86\crt\src\initmon.c +FILE 1885 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1886 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1887 f:\sp\public\sdk\inc\winbase.h +FILE 1888 f:\sp\public\sdk\inc\winerror.h +FILE 1889 f:\sp\public\sdk\inc\pshpack8.h +FILE 1890 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1891 f:\sp\public\sdk\inc\reason.h +FILE 1892 f:\sp\public\sdk\inc\ddbanned.h +FILE 1893 f:\sp\public\sdk\inc\wincon.h +FILE 1894 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1895 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1896 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1897 f:\sp\public\sdk\inc\pshpack2.h +FILE 1898 f:\sp\public\sdk\inc\mcx.h +FILE 1899 f:\sp\public\sdk\inc\winuser.h +FILE 1900 f:\sp\public\sdk\inc\winnls.h +FILE 1901 f:\sp\public\sdk\inc\guiddef.h +FILE 1902 f:\sp\public\sdk\inc\stralign.h +FILE 1903 f:\sp\public\sdk\inc\specstrings.h +FILE 1904 f:\sp\public\sdk\inc\basetsd.h +FILE 1905 f:\sp\public\sdk\inc\windows.h +FILE 1906 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1907 f:\sp\public\sdk\inc\tvout.h +FILE 1908 f:\sp\public\sdk\inc\winsvc.h +FILE 1909 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1910 f:\sp\public\sdk\inc\wingdi.h +FILE 1911 f:\sp\public\sdk\inc\winbase.h +FILE 1912 f:\sp\public\sdk\inc\winerror.h +FILE 1913 f:\sp\public\sdk\inc\pshpack1.h +FILE 1914 f:\sp\public\sdk\inc\pshpack8.h +FILE 1915 f:\sp\public\sdk\inc\winver.h +FILE 1916 f:\sp\public\sdk\inc\pshpack2.h +FILE 1917 f:\sp\public\sdk\inc\winreg.h +FILE 1918 f:\sp\public\sdk\inc\guiddef.h +FILE 1919 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1920 f:\sp\public\sdk\inc\specstrings.h +FILE 1921 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1922 f:\sp\public\sdk\inc\basetsd.h +FILE 1923 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1924 f:\sp\public\sdk\inc\windows.h +FILE 1925 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 1926 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 1927 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1928 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1929 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1930 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1931 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1932 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 1933 f:\sp\public\sdk\inc\pshpack4.h +FILE 1934 f:\sp\public\sdk\inc\reason.h +FILE 1935 f:\sp\public\sdk\inc\wincon.h +FILE 1936 f:\sp\public\sdk\inc\poppack.h +FILE 1937 f:\sp\vctools\crt_bld\self_x86\crt\src\inithelp.c +FILE 1938 f:\sp\public\sdk\inc\mcx.h +FILE 1939 f:\sp\public\sdk\inc\winuser.h +FILE 1940 f:\sp\public\sdk\inc\winnls.h +FILE 1941 f:\sp\public\sdk\inc\stralign.h +FILE 1942 f:\sp\public\sdk\inc\tvout.h +FILE 1943 f:\sp\public\sdk\inc\winsvc.h +FILE 1944 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1945 f:\sp\public\sdk\inc\wingdi.h +FILE 1946 f:\sp\public\sdk\inc\windef.h +FILE 1947 f:\sp\public\sdk\inc\ddbanned.h +FILE 1948 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1949 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1950 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 1951 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1952 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1953 f:\sp\public\sdk\inc\winnetwk.h +FILE 1954 f:\sp\public\sdk\inc\imm.h +FILE 1955 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1956 f:\sp\public\sdk\inc\winnt.h +FILE 1957 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1958 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 1959 f:\sp\public\sdk\inc\pshpack4.h +FILE 1960 f:\sp\public\sdk\inc\poppack.h +FILE 1961 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 1962 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 1963 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 1964 f:\sp\public\sdk\inc\winnetwk.h +FILE 1965 f:\sp\public\sdk\inc\imm.h +FILE 1966 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 1967 f:\sp\public\sdk\inc\windef.h +FILE 1968 f:\sp\public\sdk\inc\pshpack1.h +FILE 1969 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 1970 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 1971 f:\sp\public\sdk\inc\winver.h +FILE 1972 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 1973 f:\sp\public\sdk\inc\winnt.h +FILE 1974 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 1975 f:\sp\public\sdk\inc\winreg.h +FILE 1976 f:\sp\vctools\crt_bld\self_x86\crt\src\initctyp.c +FILE 1977 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 1978 f:\sp\public\sdk\inc\winbase.h +FILE 1979 f:\sp\public\sdk\inc\winerror.h +FILE 1980 f:\sp\public\sdk\inc\pshpack8.h +FILE 1981 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 1982 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 1983 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 1984 f:\sp\public\sdk\inc\reason.h +FILE 1985 f:\sp\public\sdk\inc\ddbanned.h +FILE 1986 f:\sp\public\sdk\inc\wincon.h +FILE 1987 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 1988 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 1989 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 1990 f:\sp\public\sdk\inc\pshpack2.h +FILE 1991 f:\sp\public\sdk\inc\mcx.h +FILE 1992 f:\sp\public\sdk\inc\winuser.h +FILE 1993 f:\sp\public\sdk\inc\winnls.h +FILE 1994 f:\sp\public\sdk\inc\guiddef.h +FILE 1995 f:\sp\public\sdk\inc\stralign.h +FILE 1996 f:\sp\public\sdk\inc\specstrings.h +FILE 1997 f:\sp\public\sdk\inc\basetsd.h +FILE 1998 f:\sp\public\sdk\inc\windows.h +FILE 1999 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2000 f:\sp\public\sdk\inc\tvout.h +FILE 2001 f:\sp\public\sdk\inc\winsvc.h +FILE 2002 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2003 f:\sp\public\sdk\inc\wingdi.h +FILE 2004 f:\sp\public\sdk\inc\poppack.h +FILE 2005 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 2006 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2007 f:\sp\public\sdk\inc\winnetwk.h +FILE 2008 f:\sp\public\sdk\inc\imm.h +FILE 2009 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2010 f:\sp\public\sdk\inc\windef.h +FILE 2011 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2012 f:\sp\public\sdk\inc\pshpack1.h +FILE 2013 f:\sp\public\sdk\inc\winver.h +FILE 2014 f:\sp\public\sdk\inc\windows.h +FILE 2015 f:\sp\public\sdk\inc\winnt.h +FILE 2016 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2017 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2018 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2019 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2020 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2021 f:\sp\public\sdk\inc\winreg.h +FILE 2022 f:\sp\public\sdk\inc\winbase.h +FILE 2023 f:\sp\vctools\crt_bld\self_x86\crt\src\initcrit.c +FILE 2024 f:\sp\public\sdk\inc\winerror.h +FILE 2025 f:\sp\public\sdk\inc\pshpack8.h +FILE 2026 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2027 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2028 f:\sp\public\sdk\inc\reason.h +FILE 2029 f:\sp\public\sdk\inc\wincon.h +FILE 2030 f:\sp\public\sdk\inc\ddbanned.h +FILE 2031 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2032 f:\sp\public\sdk\inc\pshpack2.h +FILE 2033 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2034 f:\sp\public\sdk\inc\mcx.h +FILE 2035 f:\sp\public\sdk\inc\winuser.h +FILE 2036 f:\sp\public\sdk\inc\winnls.h +FILE 2037 f:\sp\public\sdk\inc\guiddef.h +FILE 2038 f:\sp\public\sdk\inc\specstrings.h +FILE 2039 f:\sp\public\sdk\inc\basetsd.h +FILE 2040 f:\sp\public\sdk\inc\stralign.h +FILE 2041 f:\sp\public\sdk\inc\tvout.h +FILE 2042 f:\sp\public\sdk\inc\winsvc.h +FILE 2043 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2044 f:\sp\public\sdk\inc\wingdi.h +FILE 2045 f:\sp\public\sdk\inc\pshpack4.h +FILE 2046 f:\sp\public\sdk\inc\poppack.h +FILE 2047 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2048 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2049 f:\sp\public\sdk\inc\winnetwk.h +FILE 2050 f:\sp\public\sdk\inc\imm.h +FILE 2051 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2052 f:\sp\public\sdk\inc\windef.h +FILE 2053 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2054 f:\sp\public\sdk\inc\pshpack1.h +FILE 2055 f:\sp\public\sdk\inc\winver.h +FILE 2056 f:\sp\public\sdk\inc\windows.h +FILE 2057 f:\sp\public\sdk\inc\winnt.h +FILE 2058 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2059 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2060 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2061 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2062 f:\sp\public\sdk\inc\winreg.h +FILE 2063 f:\sp\public\sdk\inc\winbase.h +FILE 2064 f:\sp\vctools\crt_bld\self_x86\crt\src\initcoll.c +FILE 2065 f:\sp\public\sdk\inc\winerror.h +FILE 2066 f:\sp\public\sdk\inc\pshpack8.h +FILE 2067 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2068 f:\sp\public\sdk\inc\reason.h +FILE 2069 f:\sp\public\sdk\inc\wincon.h +FILE 2070 f:\sp\public\sdk\inc\ddbanned.h +FILE 2071 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2072 f:\sp\public\sdk\inc\pshpack2.h +FILE 2073 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2074 f:\sp\public\sdk\inc\mcx.h +FILE 2075 f:\sp\public\sdk\inc\winuser.h +FILE 2076 f:\sp\public\sdk\inc\winnls.h +FILE 2077 f:\sp\public\sdk\inc\guiddef.h +FILE 2078 f:\sp\public\sdk\inc\specstrings.h +FILE 2079 f:\sp\public\sdk\inc\basetsd.h +FILE 2080 f:\sp\public\sdk\inc\stralign.h +FILE 2081 f:\sp\public\sdk\inc\tvout.h +FILE 2082 f:\sp\public\sdk\inc\winsvc.h +FILE 2083 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2084 f:\sp\public\sdk\inc\wingdi.h +FILE 2085 f:\sp\public\sdk\inc\pshpack4.h +FILE 2086 f:\sp\public\sdk\inc\poppack.h +FILE 2087 f:\sp\public\sdk\inc\winnetwk.h +FILE 2088 f:\sp\public\sdk\inc\imm.h +FILE 2089 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2090 f:\sp\public\sdk\inc\windef.h +FILE 2091 f:\binaries.x86ret\vcboot\inc\mm3dnow.h +FILE 2092 f:\sp\public\sdk\inc\pshpack1.h +FILE 2093 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 2094 f:\sp\public\sdk\inc\winver.h +FILE 2095 f:\sp\public\sdk\inc\windows.h +FILE 2096 f:\sp\public\sdk\inc\winnt.h +FILE 2097 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2098 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2099 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2100 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2101 f:\sp\public\sdk\inc\winreg.h +FILE 2102 f:\sp\public\sdk\inc\winbase.h +FILE 2103 f:\sp\vctools\crt_bld\self_x86\crt\src\gs_support.c +FILE 2104 f:\sp\public\sdk\inc\winerror.h +FILE 2105 f:\sp\public\sdk\inc\pshpack8.h +FILE 2106 f:\sp\vctools\crt_bld\self_x86\crt\src\intrin.h +FILE 2107 f:\sp\vctools\crt_bld\self_x86\crt\src\setjmp.h +FILE 2108 f:\sp\public\sdk\inc\reason.h +FILE 2109 f:\sp\public\sdk\inc\wincon.h +FILE 2110 f:\sp\public\sdk\inc\ddbanned.h +FILE 2111 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2112 f:\sp\public\sdk\inc\pshpack2.h +FILE 2113 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2114 f:\sp\public\sdk\inc\mcx.h +FILE 2115 f:\sp\public\sdk\inc\winuser.h +FILE 2116 f:\sp\public\sdk\inc\winnls.h +FILE 2117 f:\sp\public\sdk\inc\guiddef.h +FILE 2118 f:\sp\public\sdk\inc\specstrings.h +FILE 2119 f:\sp\public\sdk\inc\basetsd.h +FILE 2120 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 2121 f:\sp\public\sdk\inc\stralign.h +FILE 2122 f:\sp\public\sdk\inc\tvout.h +FILE 2123 f:\sp\public\sdk\inc\winsvc.h +FILE 2124 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2125 f:\sp\public\sdk\inc\wingdi.h +FILE 2126 f:\binaries.x86ret\vcboot\inc\emmintrin.h +FILE 2127 f:\binaries.x86ret\vcboot\inc\xmmintrin.h +FILE 2128 f:\binaries.x86ret\vcboot\inc\mmintrin.h +FILE 2129 f:\sp\public\sdk\inc\pshpack4.h +FILE 2130 f:\sp\public\sdk\inc\poppack.h +FILE 2131 f:\sp\public\sdk\inc\winnetwk.h +FILE 2132 f:\sp\public\sdk\inc\imm.h +FILE 2133 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2134 f:\sp\public\sdk\inc\windef.h +FILE 2135 f:\sp\public\sdk\inc\pshpack1.h +FILE 2136 f:\sp\public\sdk\inc\winver.h +FILE 2137 f:\sp\public\sdk\inc\windows.h +FILE 2138 f:\sp\public\sdk\inc\winnt.h +FILE 2139 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2140 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2141 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2142 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2143 f:\sp\public\sdk\inc\winreg.h +FILE 2144 f:\sp\public\sdk\inc\winbase.h +FILE 2145 f:\sp\vctools\crt_bld\self_x86\crt\src\gs_report.c +FILE 2146 f:\sp\public\sdk\inc\winerror.h +FILE 2147 f:\sp\public\sdk\inc\pshpack8.h +FILE 2148 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2149 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2150 f:\sp\public\sdk\inc\reason.h +FILE 2151 f:\sp\public\sdk\inc\wincon.h +FILE 2152 f:\sp\public\sdk\inc\ddbanned.h +FILE 2153 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2154 f:\sp\public\sdk\inc\pshpack2.h +FILE 2155 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2156 f:\sp\public\sdk\inc\mcx.h +FILE 2157 f:\sp\public\sdk\inc\winuser.h +FILE 2158 f:\sp\public\sdk\inc\winnls.h +FILE 2159 f:\sp\public\sdk\inc\guiddef.h +FILE 2160 f:\sp\public\sdk\inc\specstrings.h +FILE 2161 f:\sp\public\sdk\inc\basetsd.h +FILE 2162 f:\sp\public\sdk\inc\stralign.h +FILE 2163 f:\sp\public\sdk\inc\tvout.h +FILE 2164 f:\sp\public\sdk\inc\winsvc.h +FILE 2165 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2166 f:\sp\public\sdk\inc\wingdi.h +FILE 2167 f:\sp\public\sdk\inc\pshpack4.h +FILE 2168 f:\sp\public\sdk\inc\poppack.h +FILE 2169 f:\sp\public\sdk\inc\winnetwk.h +FILE 2170 f:\sp\public\sdk\inc\imm.h +FILE 2171 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2172 f:\sp\public\sdk\inc\windef.h +FILE 2173 f:\sp\public\sdk\inc\pshpack1.h +FILE 2174 f:\sp\public\sdk\inc\winver.h +FILE 2175 f:\sp\public\sdk\inc\windows.h +FILE 2176 f:\sp\public\sdk\inc\winnt.h +FILE 2177 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2178 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2179 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2180 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2181 f:\sp\public\sdk\inc\winreg.h +FILE 2182 f:\sp\public\sdk\inc\winbase.h +FILE 2183 f:\sp\vctools\crt_bld\self_x86\crt\src\gs_cookie.c +FILE 2184 f:\sp\public\sdk\inc\winerror.h +FILE 2185 f:\sp\public\sdk\inc\pshpack8.h +FILE 2186 f:\sp\public\sdk\inc\reason.h +FILE 2187 f:\sp\public\sdk\inc\wincon.h +FILE 2188 f:\sp\public\sdk\inc\ddbanned.h +FILE 2189 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2190 f:\sp\public\sdk\inc\pshpack2.h +FILE 2191 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2192 f:\sp\public\sdk\inc\mcx.h +FILE 2193 f:\sp\public\sdk\inc\winuser.h +FILE 2194 f:\sp\public\sdk\inc\winnls.h +FILE 2195 f:\sp\public\sdk\inc\guiddef.h +FILE 2196 f:\sp\public\sdk\inc\specstrings.h +FILE 2197 f:\sp\public\sdk\inc\basetsd.h +FILE 2198 f:\sp\public\sdk\inc\stralign.h +FILE 2199 f:\sp\public\sdk\inc\tvout.h +FILE 2200 f:\sp\public\sdk\inc\winsvc.h +FILE 2201 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2202 f:\sp\public\sdk\inc\wingdi.h +FILE 2203 f:\sp\public\sdk\inc\pshpack4.h +FILE 2204 f:\sp\public\sdk\inc\winerror.h +FILE 2205 f:\sp\public\sdk\inc\pshpack1.h +FILE 2206 f:\sp\public\sdk\inc\pshpack8.h +FILE 2207 f:\sp\public\sdk\inc\winver.h +FILE 2208 f:\sp\public\sdk\inc\pshpack2.h +FILE 2209 f:\sp\public\sdk\inc\winreg.h +FILE 2210 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2211 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2212 f:\sp\public\sdk\inc\guiddef.h +FILE 2213 f:\sp\public\sdk\inc\windows.h +FILE 2214 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2215 f:\sp\public\sdk\inc\specstrings.h +FILE 2216 f:\sp\public\sdk\inc\basetsd.h +FILE 2217 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2218 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2219 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2220 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2221 f:\sp\public\sdk\inc\pshpack4.h +FILE 2222 f:\sp\public\sdk\inc\reason.h +FILE 2223 f:\sp\public\sdk\inc\wincon.h +FILE 2224 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2225 f:\sp\public\sdk\inc\poppack.h +FILE 2226 f:\sp\public\sdk\inc\mcx.h +FILE 2227 f:\sp\public\sdk\inc\winuser.h +FILE 2228 f:\sp\public\sdk\inc\winnls.h +FILE 2229 f:\sp\vctools\crt_bld\self_x86\crt\src\glstatus.c +FILE 2230 f:\sp\public\sdk\inc\stralign.h +FILE 2231 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2232 f:\sp\public\sdk\inc\windef.h +FILE 2233 f:\sp\public\sdk\inc\tvout.h +FILE 2234 f:\sp\public\sdk\inc\winsvc.h +FILE 2235 f:\sp\public\sdk\inc\wingdi.h +FILE 2236 f:\sp\public\sdk\inc\ddbanned.h +FILE 2237 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2238 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2239 f:\sp\public\sdk\inc\winnt.h +FILE 2240 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2241 f:\sp\public\sdk\inc\winnetwk.h +FILE 2242 f:\sp\public\sdk\inc\imm.h +FILE 2243 f:\sp\public\sdk\inc\winbase.h +FILE 2244 f:\sp\public\sdk\inc\pshpack4.h +FILE 2245 f:\sp\public\sdk\inc\poppack.h +FILE 2246 f:\sp\public\sdk\inc\winnt.h +FILE 2247 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2248 f:\sp\public\sdk\inc\winnetwk.h +FILE 2249 f:\sp\public\sdk\inc\imm.h +FILE 2250 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2251 f:\sp\public\sdk\inc\pshpack1.h +FILE 2252 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2253 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2254 f:\sp\public\sdk\inc\winver.h +FILE 2255 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2256 f:\sp\public\sdk\inc\guiddef.h +FILE 2257 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2258 f:\sp\public\sdk\inc\specstrings.h +FILE 2259 f:\sp\public\sdk\inc\basetsd.h +FILE 2260 f:\sp\public\sdk\inc\windows.h +FILE 2261 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2262 f:\sp\public\sdk\inc\winreg.h +FILE 2263 f:\sp\vctools\crt_bld\self_x86\crt\src\getqloc.c +FILE 2264 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2265 f:\sp\public\sdk\inc\winbase.h +FILE 2266 f:\sp\public\sdk\inc\winerror.h +FILE 2267 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2268 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2269 f:\sp\public\sdk\inc\pshpack8.h +FILE 2270 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2271 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2272 f:\sp\public\sdk\inc\reason.h +FILE 2273 f:\sp\public\sdk\inc\ddbanned.h +FILE 2274 f:\sp\public\sdk\inc\wincon.h +FILE 2275 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2276 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2277 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2278 f:\sp\public\sdk\inc\pshpack2.h +FILE 2279 f:\sp\public\sdk\inc\mcx.h +FILE 2280 f:\sp\public\sdk\inc\winuser.h +FILE 2281 f:\sp\public\sdk\inc\winnls.h +FILE 2282 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2283 f:\sp\public\sdk\inc\windef.h +FILE 2284 f:\sp\public\sdk\inc\stralign.h +FILE 2285 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2286 f:\sp\public\sdk\inc\tvout.h +FILE 2287 f:\sp\public\sdk\inc\winsvc.h +FILE 2288 f:\sp\public\sdk\inc\wingdi.h +FILE 2289 f:\sp\public\sdk\inc\reason.h +FILE 2290 f:\sp\public\sdk\inc\wincon.h +FILE 2291 f:\sp\public\sdk\inc\pshpack2.h +FILE 2292 f:\sp\public\sdk\inc\mcx.h +FILE 2293 f:\sp\public\sdk\inc\winuser.h +FILE 2294 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2295 f:\sp\public\sdk\inc\winnls.h +FILE 2296 f:\sp\public\sdk\inc\guiddef.h +FILE 2297 f:\sp\public\sdk\inc\windows.h +FILE 2298 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2299 f:\sp\public\sdk\inc\specstrings.h +FILE 2300 f:\sp\public\sdk\inc\basetsd.h +FILE 2301 f:\sp\public\sdk\inc\stralign.h +FILE 2302 f:\sp\public\sdk\inc\tvout.h +FILE 2303 f:\sp\public\sdk\inc\winsvc.h +FILE 2304 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2305 f:\sp\public\sdk\inc\wingdi.h +FILE 2306 f:\sp\public\sdk\inc\pshpack4.h +FILE 2307 f:\sp\public\sdk\inc\poppack.h +FILE 2308 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 2309 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2310 f:\sp\public\sdk\inc\winnetwk.h +FILE 2311 f:\sp\public\sdk\inc\imm.h +FILE 2312 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2313 f:\sp\public\sdk\inc\windef.h +FILE 2314 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 2315 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 2316 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2317 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2318 f:\sp\vctools\crt_bld\self_x86\crt\src\getenv.c +FILE 2319 f:\sp\public\sdk\inc\pshpack1.h +FILE 2320 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2321 f:\sp\public\sdk\inc\winver.h +FILE 2322 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2323 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2324 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2325 f:\sp\public\sdk\inc\winnt.h +FILE 2326 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2327 f:\sp\public\sdk\inc\ddbanned.h +FILE 2328 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2329 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2330 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2331 f:\sp\public\sdk\inc\winreg.h +FILE 2332 f:\sp\public\sdk\inc\winbase.h +FILE 2333 f:\sp\public\sdk\inc\winerror.h +FILE 2334 f:\sp\public\sdk\inc\pshpack8.h +FILE 2335 f:\sp\public\sdk\inc\poppack.h +FILE 2336 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2337 f:\sp\public\sdk\inc\winnetwk.h +FILE 2338 f:\sp\public\sdk\inc\imm.h +FILE 2339 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2340 f:\sp\public\sdk\inc\windef.h +FILE 2341 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2342 f:\sp\public\sdk\inc\pshpack1.h +FILE 2343 f:\sp\public\sdk\inc\winver.h +FILE 2344 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2345 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2346 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2347 f:\sp\public\sdk\inc\winnt.h +FILE 2348 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2349 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2350 f:\sp\public\sdk\inc\winreg.h +FILE 2351 f:\sp\vctools\crt_bld\self_x86\crt\src\errmode.c +FILE 2352 f:\sp\public\sdk\inc\winbase.h +FILE 2353 f:\sp\public\sdk\inc\winerror.h +FILE 2354 f:\sp\public\sdk\inc\pshpack8.h +FILE 2355 f:\sp\public\sdk\inc\reason.h +FILE 2356 f:\sp\public\sdk\inc\wincon.h +FILE 2357 f:\sp\public\sdk\inc\ddbanned.h +FILE 2358 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2359 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2360 f:\sp\public\sdk\inc\pshpack2.h +FILE 2361 f:\sp\public\sdk\inc\mcx.h +FILE 2362 f:\sp\public\sdk\inc\winuser.h +FILE 2363 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2364 f:\sp\public\sdk\inc\winnls.h +FILE 2365 f:\sp\public\sdk\inc\guiddef.h +FILE 2366 f:\sp\public\sdk\inc\windows.h +FILE 2367 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2368 f:\sp\public\sdk\inc\specstrings.h +FILE 2369 f:\sp\public\sdk\inc\basetsd.h +FILE 2370 f:\sp\public\sdk\inc\stralign.h +FILE 2371 f:\sp\public\sdk\inc\tvout.h +FILE 2372 f:\sp\public\sdk\inc\winsvc.h +FILE 2373 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2374 f:\sp\public\sdk\inc\wingdi.h +FILE 2375 f:\sp\public\sdk\inc\pshpack4.h +FILE 2376 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2377 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2378 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2379 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2380 f:\sp\vctools\crt_bld\self_x86\crt\src\dbghook.c +FILE 2381 f:\sp\public\sdk\inc\ddbanned.h +FILE 2382 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2383 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2384 f:\sp\public\sdk\inc\poppack.h +FILE 2385 f:\sp\public\sdk\inc\winnetwk.h +FILE 2386 f:\sp\public\sdk\inc\imm.h +FILE 2387 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2388 f:\sp\public\sdk\inc\windef.h +FILE 2389 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2390 f:\sp\public\sdk\inc\pshpack1.h +FILE 2391 f:\sp\public\sdk\inc\winver.h +FILE 2392 f:\sp\public\sdk\inc\windows.h +FILE 2393 f:\sp\public\sdk\inc\winnt.h +FILE 2394 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2395 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2396 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2397 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2398 f:\sp\public\sdk\inc\winreg.h +FILE 2399 f:\sp\vctools\crt_bld\self_x86\crt\src\wchar.h +FILE 2400 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.c +FILE 2401 f:\sp\public\sdk\inc\winbase.h +FILE 2402 f:\sp\vctools\crt_bld\self_x86\crt\src\wtime.inl +FILE 2403 f:\sp\public\sdk\inc\winerror.h +FILE 2404 f:\sp\public\sdk\inc\pshpack8.h +FILE 2405 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2406 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2407 f:\sp\public\sdk\inc\reason.h +FILE 2408 f:\sp\public\sdk\inc\wincon.h +FILE 2409 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2410 f:\sp\public\sdk\inc\ddbanned.h +FILE 2411 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2412 f:\sp\public\sdk\inc\pshpack2.h +FILE 2413 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2414 f:\sp\public\sdk\inc\mcx.h +FILE 2415 f:\sp\public\sdk\inc\winuser.h +FILE 2416 f:\sp\public\sdk\inc\winnls.h +FILE 2417 f:\sp\public\sdk\inc\guiddef.h +FILE 2418 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 2419 f:\sp\public\sdk\inc\specstrings.h +FILE 2420 f:\sp\public\sdk\inc\basetsd.h +FILE 2421 f:\sp\public\sdk\inc\stralign.h +FILE 2422 f:\sp\public\sdk\inc\tvout.h +FILE 2423 f:\sp\public\sdk\inc\winsvc.h +FILE 2424 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2425 f:\sp\public\sdk\inc\wingdi.h +FILE 2426 f:\sp\public\sdk\inc\pshpack4.h +FILE 2427 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2428 f:\sp\public\sdk\inc\mcx.h +FILE 2429 f:\sp\public\sdk\inc\winuser.h +FILE 2430 f:\sp\public\sdk\inc\winnls.h +FILE 2431 f:\sp\public\sdk\inc\stralign.h +FILE 2432 f:\sp\public\sdk\inc\tvout.h +FILE 2433 f:\sp\public\sdk\inc\winsvc.h +FILE 2434 f:\sp\public\sdk\inc\wingdi.h +FILE 2435 f:\sp\public\sdk\inc\pshpack4.h +FILE 2436 f:\sp\public\sdk\inc\winnt.h +FILE 2437 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2438 f:\sp\public\sdk\inc\poppack.h +FILE 2439 f:\sp\public\sdk\inc\winnetwk.h +FILE 2440 f:\sp\public\sdk\inc\imm.h +FILE 2441 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 2442 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 2443 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2444 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2445 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2446 f:\sp\public\sdk\inc\pshpack1.h +FILE 2447 f:\sp\vctools\crt_bld\self_x86\crt\src\crtmbox.c +FILE 2448 f:\sp\public\sdk\inc\winver.h +FILE 2449 f:\sp\public\sdk\inc\guiddef.h +FILE 2450 f:\sp\public\sdk\inc\windows.h +FILE 2451 f:\sp\public\sdk\inc\specstrings.h +FILE 2452 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2453 f:\sp\public\sdk\inc\basetsd.h +FILE 2454 f:\sp\public\sdk\inc\winreg.h +FILE 2455 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2456 f:\sp\public\sdk\inc\winbase.h +FILE 2457 f:\sp\public\sdk\inc\ddbanned.h +FILE 2458 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2459 f:\sp\public\sdk\inc\winerror.h +FILE 2460 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2461 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2462 f:\sp\public\sdk\inc\pshpack8.h +FILE 2463 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2464 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2465 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2466 f:\sp\public\sdk\inc\reason.h +FILE 2467 f:\sp\public\sdk\inc\wincon.h +FILE 2468 f:\sp\public\sdk\inc\pshpack2.h +FILE 2469 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2470 f:\sp\public\sdk\inc\windef.h +FILE 2471 f:\sp\public\sdk\inc\poppack.h +FILE 2472 f:\sp\vctools\crt_bld\self_x86\crt\src\fltintrn.h +FILE 2473 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2474 f:\sp\public\sdk\inc\winnetwk.h +FILE 2475 f:\sp\public\sdk\inc\imm.h +FILE 2476 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2477 f:\sp\public\sdk\inc\windef.h +FILE 2478 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2479 f:\sp\public\sdk\inc\pshpack1.h +FILE 2480 f:\sp\public\sdk\inc\winver.h +FILE 2481 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2482 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2483 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2484 f:\sp\public\sdk\inc\winnt.h +FILE 2485 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2486 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2487 f:\sp\public\sdk\inc\winreg.h +FILE 2488 f:\sp\vctools\crt_bld\self_x86\crt\src\cmiscdat.c +FILE 2489 f:\sp\public\sdk\inc\winbase.h +FILE 2490 f:\sp\public\sdk\inc\winerror.h +FILE 2491 f:\sp\public\sdk\inc\pshpack8.h +FILE 2492 f:\sp\public\sdk\inc\reason.h +FILE 2493 f:\sp\public\sdk\inc\wincon.h +FILE 2494 f:\sp\public\sdk\inc\ddbanned.h +FILE 2495 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2496 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2497 f:\sp\public\sdk\inc\pshpack2.h +FILE 2498 f:\sp\public\sdk\inc\mcx.h +FILE 2499 f:\sp\public\sdk\inc\winuser.h +FILE 2500 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2501 f:\sp\public\sdk\inc\winnls.h +FILE 2502 f:\sp\public\sdk\inc\guiddef.h +FILE 2503 f:\sp\public\sdk\inc\windows.h +FILE 2504 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2505 f:\sp\public\sdk\inc\specstrings.h +FILE 2506 f:\sp\public\sdk\inc\basetsd.h +FILE 2507 f:\sp\public\sdk\inc\stralign.h +FILE 2508 f:\sp\public\sdk\inc\tvout.h +FILE 2509 f:\sp\public\sdk\inc\winsvc.h +FILE 2510 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2511 f:\sp\public\sdk\inc\wingdi.h +FILE 2512 f:\sp\public\sdk\inc\pshpack4.h +FILE 2513 f:\sp\public\sdk\inc\pshpack4.h +FILE 2514 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 2515 f:\sp\vctools\crt_bld\self_x86\crt\src\signal.h +FILE 2516 f:\sp\public\sdk\inc\poppack.h +FILE 2517 f:\sp\public\sdk\inc\winnetwk.h +FILE 2518 f:\sp\public\sdk\inc\imm.h +FILE 2519 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2520 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2521 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2522 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2523 f:\sp\public\sdk\inc\windef.h +FILE 2524 f:\sp\public\sdk\inc\pshpack1.h +FILE 2525 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2526 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2527 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2528 f:\sp\public\sdk\inc\winver.h +FILE 2529 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2530 f:\sp\public\sdk\inc\winnt.h +FILE 2531 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2532 f:\sp\public\sdk\inc\winreg.h +FILE 2533 f:\sp\vctools\crt_bld\self_x86\crt\src\abort.c +FILE 2534 f:\sp\public\sdk\inc\winbase.h +FILE 2535 f:\sp\public\sdk\inc\winerror.h +FILE 2536 f:\sp\public\sdk\inc\pshpack8.h +FILE 2537 f:\sp\public\sdk\inc\reason.h +FILE 2538 f:\sp\public\sdk\inc\ddbanned.h +FILE 2539 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2540 f:\sp\public\sdk\inc\wincon.h +FILE 2541 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2542 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2543 f:\sp\public\sdk\inc\pshpack2.h +FILE 2544 f:\sp\public\sdk\inc\mcx.h +FILE 2545 f:\sp\public\sdk\inc\winuser.h +FILE 2546 f:\sp\public\sdk\inc\winnls.h +FILE 2547 f:\sp\public\sdk\inc\guiddef.h +FILE 2548 f:\sp\public\sdk\inc\stralign.h +FILE 2549 f:\sp\public\sdk\inc\specstrings.h +FILE 2550 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2551 f:\sp\public\sdk\inc\basetsd.h +FILE 2552 f:\sp\public\sdk\inc\windows.h +FILE 2553 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2554 f:\sp\public\sdk\inc\tvout.h +FILE 2555 f:\sp\public\sdk\inc\winsvc.h +FILE 2556 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2557 f:\sp\public\sdk\inc\wingdi.h +FILE 2558 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 2559 f:\sp\public\sdk\inc\wincon.h +FILE 2560 f:\sp\public\sdk\inc\imm.h +FILE 2561 f:\sp\public\sdk\inc\winbase.h +FILE 2562 f:\sp\public\sdk\inc\wingdi.h +FILE 2563 f:\sp\public\sdk\inc\winver.h +FILE 2564 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2565 f:\sp\public\sdk\inc\windows.h +FILE 2566 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2567 f:\sp\public\sdk\inc\pshpack2.h +FILE 2568 f:\sp\public\sdk\inc\reason.h +FILE 2569 f:\sp\vctools\crt_bld\self_x86\crt\src\a_str.c +FILE 2570 f:\sp\public\sdk\inc\specstrings.h +FILE 2571 f:\sp\public\sdk\inc\basetsd.h +FILE 2572 f:\sp\public\sdk\inc\pshpack4.h +FILE 2573 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2574 f:\sp\public\sdk\inc\winnetwk.h +FILE 2575 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2576 f:\sp\public\sdk\inc\stralign.h +FILE 2577 f:\sp\public\sdk\inc\poppack.h +FILE 2578 f:\sp\public\sdk\inc\winsvc.h +FILE 2579 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2580 f:\sp\public\sdk\inc\windef.h +FILE 2581 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2582 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2583 f:\sp\public\sdk\inc\winuser.h +FILE 2584 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2585 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2586 f:\sp\public\sdk\inc\mcx.h +FILE 2587 f:\sp\public\sdk\inc\pshpack8.h +FILE 2588 f:\sp\public\sdk\inc\guiddef.h +FILE 2589 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2590 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2591 f:\sp\public\sdk\inc\winnt.h +FILE 2592 f:\sp\public\sdk\inc\winnls.h +FILE 2593 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2594 f:\sp\public\sdk\inc\pshpack1.h +FILE 2595 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2596 f:\sp\public\sdk\inc\winerror.h +FILE 2597 f:\sp\public\sdk\inc\winreg.h +FILE 2598 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2599 f:\sp\public\sdk\inc\ddbanned.h +FILE 2600 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2601 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2602 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2603 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2604 f:\sp\public\sdk\inc\tvout.h +FILE 2605 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2606 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 2607 f:\sp\public\sdk\inc\wincon.h +FILE 2608 f:\sp\public\sdk\inc\imm.h +FILE 2609 f:\sp\public\sdk\inc\winbase.h +FILE 2610 f:\sp\public\sdk\inc\wingdi.h +FILE 2611 f:\sp\public\sdk\inc\winver.h +FILE 2612 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2613 f:\sp\public\sdk\inc\windows.h +FILE 2614 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2615 f:\sp\public\sdk\inc\pshpack2.h +FILE 2616 f:\sp\public\sdk\inc\reason.h +FILE 2617 f:\sp\vctools\crt_bld\self_x86\crt\src\a_map.c +FILE 2618 f:\sp\public\sdk\inc\specstrings.h +FILE 2619 f:\sp\public\sdk\inc\basetsd.h +FILE 2620 f:\sp\public\sdk\inc\pshpack4.h +FILE 2621 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2622 f:\sp\public\sdk\inc\winnetwk.h +FILE 2623 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2624 f:\sp\public\sdk\inc\stralign.h +FILE 2625 f:\sp\public\sdk\inc\poppack.h +FILE 2626 f:\sp\public\sdk\inc\winsvc.h +FILE 2627 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2628 f:\sp\public\sdk\inc\windef.h +FILE 2629 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2630 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2631 f:\sp\public\sdk\inc\winuser.h +FILE 2632 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2633 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2634 f:\sp\public\sdk\inc\mcx.h +FILE 2635 f:\sp\public\sdk\inc\pshpack8.h +FILE 2636 f:\sp\public\sdk\inc\guiddef.h +FILE 2637 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2638 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2639 f:\sp\public\sdk\inc\winnt.h +FILE 2640 f:\sp\public\sdk\inc\winnls.h +FILE 2641 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2642 f:\sp\public\sdk\inc\pshpack1.h +FILE 2643 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2644 f:\sp\public\sdk\inc\winerror.h +FILE 2645 f:\sp\public\sdk\inc\winreg.h +FILE 2646 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2647 f:\sp\public\sdk\inc\ddbanned.h +FILE 2648 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2649 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2650 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2651 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2652 f:\sp\public\sdk\inc\tvout.h +FILE 2653 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2654 f:\sp\public\sdk\inc\wincon.h +FILE 2655 f:\sp\public\sdk\inc\imm.h +FILE 2656 f:\sp\public\sdk\inc\winbase.h +FILE 2657 f:\sp\public\sdk\inc\wingdi.h +FILE 2658 f:\sp\public\sdk\inc\winver.h +FILE 2659 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2660 f:\sp\public\sdk\inc\windows.h +FILE 2661 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2662 f:\sp\public\sdk\inc\pshpack2.h +FILE 2663 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2664 f:\sp\public\sdk\inc\reason.h +FILE 2665 f:\sp\vctools\crt_bld\self_x86\crt\src\a_loc.c +FILE 2666 f:\sp\public\sdk\inc\specstrings.h +FILE 2667 f:\sp\public\sdk\inc\basetsd.h +FILE 2668 f:\sp\public\sdk\inc\pshpack4.h +FILE 2669 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2670 f:\sp\public\sdk\inc\winnetwk.h +FILE 2671 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2672 f:\sp\public\sdk\inc\stralign.h +FILE 2673 f:\sp\public\sdk\inc\poppack.h +FILE 2674 f:\sp\public\sdk\inc\winsvc.h +FILE 2675 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2676 f:\sp\public\sdk\inc\windef.h +FILE 2677 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2678 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2679 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2680 f:\sp\public\sdk\inc\winuser.h +FILE 2681 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2682 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2683 f:\sp\public\sdk\inc\mcx.h +FILE 2684 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 2685 f:\sp\public\sdk\inc\pshpack8.h +FILE 2686 f:\sp\public\sdk\inc\guiddef.h +FILE 2687 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2688 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2689 f:\sp\public\sdk\inc\winnt.h +FILE 2690 f:\sp\public\sdk\inc\winnls.h +FILE 2691 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2692 f:\sp\public\sdk\inc\pshpack1.h +FILE 2693 f:\sp\public\sdk\inc\winerror.h +FILE 2694 f:\sp\public\sdk\inc\winreg.h +FILE 2695 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2696 f:\sp\public\sdk\inc\ddbanned.h +FILE 2697 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2698 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2699 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2700 f:\sp\public\sdk\inc\tvout.h +FILE 2701 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2702 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2703 f:\sp\public\sdk\inc\poppack.h +FILE 2704 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2705 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2706 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2707 f:\sp\public\sdk\inc\winnetwk.h +FILE 2708 f:\sp\public\sdk\inc\imm.h +FILE 2709 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2710 f:\sp\public\sdk\inc\windef.h +FILE 2711 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2712 f:\sp\public\sdk\inc\pshpack1.h +FILE 2713 f:\sp\public\sdk\inc\winver.h +FILE 2714 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2715 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2716 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2717 f:\sp\public\sdk\inc\winnt.h +FILE 2718 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2719 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2720 f:\sp\public\sdk\inc\winreg.h +FILE 2721 f:\sp\vctools\crt_bld\self_x86\crt\src\a_env.c +FILE 2722 f:\sp\public\sdk\inc\winbase.h +FILE 2723 f:\sp\public\sdk\inc\winerror.h +FILE 2724 f:\sp\public\sdk\inc\pshpack8.h +FILE 2725 f:\sp\public\sdk\inc\reason.h +FILE 2726 f:\sp\public\sdk\inc\wincon.h +FILE 2727 f:\sp\public\sdk\inc\ddbanned.h +FILE 2728 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2729 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2730 f:\sp\public\sdk\inc\pshpack2.h +FILE 2731 f:\sp\public\sdk\inc\mcx.h +FILE 2732 f:\sp\public\sdk\inc\winuser.h +FILE 2733 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2734 f:\sp\public\sdk\inc\winnls.h +FILE 2735 f:\sp\public\sdk\inc\guiddef.h +FILE 2736 f:\sp\public\sdk\inc\windows.h +FILE 2737 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2738 f:\sp\public\sdk\inc\specstrings.h +FILE 2739 f:\sp\public\sdk\inc\basetsd.h +FILE 2740 f:\sp\public\sdk\inc\stralign.h +FILE 2741 f:\sp\public\sdk\inc\tvout.h +FILE 2742 f:\sp\public\sdk\inc\winsvc.h +FILE 2743 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2744 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2745 f:\sp\public\sdk\inc\wingdi.h +FILE 2746 f:\sp\public\sdk\inc\pshpack4.h +FILE 2747 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 2748 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 2749 f:\sp\public\sdk\inc\wincon.h +FILE 2750 f:\sp\public\sdk\inc\imm.h +FILE 2751 f:\sp\public\sdk\inc\winbase.h +FILE 2752 f:\sp\public\sdk\inc\wingdi.h +FILE 2753 f:\sp\public\sdk\inc\winver.h +FILE 2754 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2755 f:\sp\public\sdk\inc\windows.h +FILE 2756 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2757 f:\sp\public\sdk\inc\pshpack2.h +FILE 2758 f:\sp\public\sdk\inc\reason.h +FILE 2759 f:\sp\vctools\crt_bld\self_x86\crt\src\a_cmp.c +FILE 2760 f:\sp\public\sdk\inc\specstrings.h +FILE 2761 f:\sp\public\sdk\inc\basetsd.h +FILE 2762 f:\sp\public\sdk\inc\pshpack4.h +FILE 2763 f:\sp\public\sdk\inc\winnetwk.h +FILE 2764 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2765 f:\sp\public\sdk\inc\stralign.h +FILE 2766 f:\sp\public\sdk\inc\poppack.h +FILE 2767 f:\sp\public\sdk\inc\winsvc.h +FILE 2768 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2769 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2770 f:\sp\public\sdk\inc\windef.h +FILE 2771 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2772 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2773 f:\sp\public\sdk\inc\winuser.h +FILE 2774 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2775 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2776 f:\sp\public\sdk\inc\mcx.h +FILE 2777 f:\sp\public\sdk\inc\pshpack8.h +FILE 2778 f:\sp\public\sdk\inc\guiddef.h +FILE 2779 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2780 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2781 f:\sp\public\sdk\inc\winnt.h +FILE 2782 f:\sp\public\sdk\inc\winnls.h +FILE 2783 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2784 f:\sp\public\sdk\inc\pshpack1.h +FILE 2785 f:\sp\public\sdk\inc\winerror.h +FILE 2786 f:\sp\public\sdk\inc\winreg.h +FILE 2787 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2788 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2789 f:\sp\public\sdk\inc\ddbanned.h +FILE 2790 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2791 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2792 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 2793 f:\sp\public\sdk\inc\tvout.h +FILE 2794 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2795 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\misc\i386\sehprolg4.asm +FILE 2796 f:\sp\public\sdk\inc\poppack.h +FILE 2797 f:\sp\public\sdk\inc\winnetwk.h +FILE 2798 f:\sp\public\sdk\inc\imm.h +FILE 2799 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2800 f:\sp\public\sdk\inc\windef.h +FILE 2801 f:\sp\public\sdk\inc\pshpack1.h +FILE 2802 f:\sp\public\sdk\inc\winver.h +FILE 2803 f:\sp\public\sdk\inc\windows.h +FILE 2804 f:\sp\public\sdk\inc\winnt.h +FILE 2805 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2806 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2807 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2808 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2809 f:\sp\public\sdk\inc\winreg.h +FILE 2810 f:\sp\public\sdk\inc\winbase.h +FILE 2811 f:\sp\vctools\crt_bld\self_x86\crt\src\intel\secchk.c +FILE 2812 f:\sp\public\sdk\inc\winerror.h +FILE 2813 f:\sp\public\sdk\inc\pshpack8.h +FILE 2814 f:\sp\vctools\crt_bld\self_x86\crt\src\process.h +FILE 2815 f:\sp\public\sdk\inc\reason.h +FILE 2816 f:\sp\public\sdk\inc\wincon.h +FILE 2817 f:\sp\public\sdk\inc\ddbanned.h +FILE 2818 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2819 f:\sp\public\sdk\inc\pshpack2.h +FILE 2820 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2821 f:\sp\public\sdk\inc\mcx.h +FILE 2822 f:\sp\public\sdk\inc\winuser.h +FILE 2823 f:\sp\public\sdk\inc\winnls.h +FILE 2824 f:\sp\public\sdk\inc\guiddef.h +FILE 2825 f:\sp\public\sdk\inc\specstrings.h +FILE 2826 f:\sp\public\sdk\inc\basetsd.h +FILE 2827 f:\sp\public\sdk\inc\stralign.h +FILE 2828 f:\sp\public\sdk\inc\tvout.h +FILE 2829 f:\sp\public\sdk\inc\winsvc.h +FILE 2830 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2831 f:\sp\public\sdk\inc\wingdi.h +FILE 2832 f:\sp\public\sdk\inc\pshpack4.h +FILE 2833 f:\sp\public\sdk\inc\poppack.h +FILE 2834 f:\sp\public\sdk\inc\winnetwk.h +FILE 2835 f:\sp\public\sdk\inc\imm.h +FILE 2836 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2837 f:\sp\public\sdk\inc\windef.h +FILE 2838 f:\sp\public\sdk\inc\pshpack1.h +FILE 2839 f:\sp\public\sdk\inc\winver.h +FILE 2840 f:\sp\public\sdk\inc\windows.h +FILE 2841 f:\sp\public\sdk\inc\winnt.h +FILE 2842 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2843 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2844 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2845 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2846 f:\sp\public\sdk\inc\winreg.h +FILE 2847 f:\sp\public\sdk\inc\winbase.h +FILE 2848 f:\sp\vctools\crt_bld\self_x86\crt\src\intel\loadcfg.c +FILE 2849 f:\sp\public\sdk\inc\winerror.h +FILE 2850 f:\sp\public\sdk\inc\pshpack8.h +FILE 2851 f:\sp\public\sdk\inc\reason.h +FILE 2852 f:\sp\public\sdk\inc\wincon.h +FILE 2853 f:\sp\public\sdk\inc\ddbanned.h +FILE 2854 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2855 f:\sp\public\sdk\inc\pshpack2.h +FILE 2856 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2857 f:\sp\public\sdk\inc\mcx.h +FILE 2858 f:\sp\public\sdk\inc\winuser.h +FILE 2859 f:\sp\public\sdk\inc\winnls.h +FILE 2860 f:\sp\public\sdk\inc\guiddef.h +FILE 2861 f:\sp\public\sdk\inc\specstrings.h +FILE 2862 f:\sp\public\sdk\inc\basetsd.h +FILE 2863 f:\sp\public\sdk\inc\stralign.h +FILE 2864 f:\sp\public\sdk\inc\tvout.h +FILE 2865 f:\sp\public\sdk\inc\winsvc.h +FILE 2866 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2867 f:\sp\public\sdk\inc\wingdi.h +FILE 2868 f:\sp\public\sdk\inc\pshpack4.h +FILE 2869 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\misc\i386\exsup4.asm +FILE 2870 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\h\exsup.inc +FILE 2871 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\misc\i386\exsup.asm +FILE 2872 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\h\pversion.inc +FILE 2873 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\h\cmacros.inc +FILE 2874 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\h\exsup.inc +FILE 2875 F:\SP\vctools\crt_bld\SELF_X86\crt\prebuild\misc\i386\nlgsupp.asm +FILE 2876 f:\sp\public\sdk\inc\ntldr.h +FILE 2877 f:\sp\public\sdk\inc\ntpoapi.h +FILE 2878 f:\sp\public\sdk\inc\ntexapi.h +FILE 2879 f:\sp\public\sdk\inc\pshpack1.h +FILE 2880 f:\sp\public\sdk\inc\pshpack8.h +FILE 2881 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 2882 f:\sp\public\sdk\inc\ntdef.h +FILE 2883 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 2884 f:\sp\public\sdk\inc\mce.h +FILE 2885 f:\sp\public\sdk\inc\poppack.h +FILE 2886 f:\sp\public\sdk\inc\ntimage.h +FILE 2887 f:\sp\public\sdk\inc\pshpack2.h +FILE 2888 f:\sp\public\sdk\inc\ntpsapi.h +FILE 2889 f:\sp\public\sdk\inc\nti386.h +FILE 2890 f:\sp\public\sdk\inc\nt.h +FILE 2891 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 2892 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 2893 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 2894 f:\sp\public\sdk\inc\specstrings.h +FILE 2895 f:\sp\public\sdk\inc\basetsd.h +FILE 2896 f:\sp\public\sdk\inc\ntxcapi.h +FILE 2897 f:\sp\public\sdk\inc\guiddef.h +FILE 2898 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\misc\i386\chandler4.c +FILE 2899 f:\sp\public\sdk\inc\ntstatus.h +FILE 2900 f:\sp\public\sdk\inc\ntkeapi.h +FILE 2901 f:\sp\public\sdk\inc\ntconfig.h +FILE 2902 f:\sp\public\sdk\inc\ntregapi.h +FILE 2903 f:\sp\public\sdk\inc\ntmmapi.h +FILE 2904 f:\sp\public\sdk\inc\ntobapi.h +FILE 2905 f:\sp\public\sdk\inc\nxi386.h +FILE 2906 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\process.h +FILE 2907 f:\sp\public\sdk\inc\ntioapi.h +FILE 2908 f:\sp\public\sdk\inc\devioctl.h +FILE 2909 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 2910 f:\sp\public\sdk\inc\ntseapi.h +FILE 2911 f:\sp\public\sdk\inc\ddbanned.h +FILE 2912 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 2913 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 2914 f:\sp\public\sdk\inc\ntnls.h +FILE 2915 f:\sp\public\sdk\inc\ntelfapi.h +FILE 2916 f:\sp\public\sdk\inc\pshpack4.h +FILE 2917 f:\sp\public\sdk\inc\ntiolog.h +FILE 2918 f:\sp\public\sdk\inc\ntlpcapi.h +FILE 2919 f:\sp\public\sdk\inc\ntpnpapi.h +FILE 2920 f:\sp\public\sdk\inc\cfg.h +FILE 2921 f:\sp\public\sdk\inc\pebteb.h +FILE 2922 f:\sp\public\sdk\inc\wincon.h +FILE 2923 f:\sp\public\sdk\inc\imm.h +FILE 2924 f:\sp\public\sdk\inc\winbase.h +FILE 2925 f:\sp\public\sdk\inc\wingdi.h +FILE 2926 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 2927 f:\sp\public\sdk\inc\winver.h +FILE 2928 f:\sp\public\sdk\inc\pshpack2.h +FILE 2929 f:\sp\public\sdk\inc\reason.h +FILE 2930 f:\sp\vctools\crt_bld\self_x86\crt\src\mbdata.h +FILE 2931 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 2932 f:\sp\vctools\crt_bld\self_x86\crt\src\mbsnbico.c +FILE 2933 f:\sp\public\sdk\inc\specstrings.h +FILE 2934 f:\sp\public\sdk\inc\basetsd.h +FILE 2935 f:\sp\public\sdk\inc\pshpack4.h +FILE 2936 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2937 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 2938 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2939 f:\sp\public\sdk\inc\winnetwk.h +FILE 2940 f:\sp\public\sdk\inc\stralign.h +FILE 2941 f:\sp\public\sdk\inc\poppack.h +FILE 2942 f:\sp\public\sdk\inc\winsvc.h +FILE 2943 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2944 f:\sp\public\sdk\inc\windef.h +FILE 2945 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 2946 f:\sp\public\sdk\inc\winuser.h +FILE 2947 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2948 f:\sp\public\sdk\inc\windows.h +FILE 2949 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2950 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2951 f:\sp\public\sdk\inc\mcx.h +FILE 2952 f:\sp\public\sdk\inc\pshpack8.h +FILE 2953 f:\sp\public\sdk\inc\guiddef.h +FILE 2954 f:\sp\public\sdk\inc\winnt.h +FILE 2955 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2956 f:\sp\public\sdk\inc\winnls.h +FILE 2957 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 2958 f:\sp\public\sdk\inc\pshpack1.h +FILE 2959 f:\sp\public\sdk\inc\winerror.h +FILE 2960 f:\sp\public\sdk\inc\winreg.h +FILE 2961 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 2962 f:\sp\public\sdk\inc\ddbanned.h +FILE 2963 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 2964 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 2965 f:\sp\public\sdk\inc\tvout.h +FILE 2966 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2967 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2968 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 2969 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 2970 f:\sp\public\sdk\inc\wincon.h +FILE 2971 f:\sp\public\sdk\inc\imm.h +FILE 2972 f:\sp\public\sdk\inc\winbase.h +FILE 2973 f:\sp\public\sdk\inc\wingdi.h +FILE 2974 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 2975 f:\sp\public\sdk\inc\winver.h +FILE 2976 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 2977 f:\sp\public\sdk\inc\windows.h +FILE 2978 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 2979 f:\sp\public\sdk\inc\pshpack2.h +FILE 2980 f:\sp\public\sdk\inc\reason.h +FILE 2981 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 2982 f:\sp\vctools\crt_bld\self_x86\crt\src\mbschr.c +FILE 2983 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 2984 f:\sp\public\sdk\inc\specstrings.h +FILE 2985 f:\sp\public\sdk\inc\basetsd.h +FILE 2986 f:\sp\public\sdk\inc\pshpack4.h +FILE 2987 f:\sp\public\sdk\inc\winnetwk.h +FILE 2988 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 2989 f:\sp\public\sdk\inc\stralign.h +FILE 2990 f:\sp\public\sdk\inc\poppack.h +FILE 2991 f:\sp\public\sdk\inc\winsvc.h +FILE 2992 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 2993 f:\sp\public\sdk\inc\windef.h +FILE 2994 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 2995 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 2996 f:\sp\public\sdk\inc\winuser.h +FILE 2997 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 2998 f:\sp\public\sdk\inc\mcx.h +FILE 2999 f:\sp\public\sdk\inc\pshpack8.h +FILE 3000 f:\sp\public\sdk\inc\guiddef.h +FILE 3001 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 3002 f:\sp\public\sdk\inc\winnt.h +FILE 3003 f:\sp\public\sdk\inc\winnls.h +FILE 3004 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3005 f:\sp\public\sdk\inc\pshpack1.h +FILE 3006 f:\sp\public\sdk\inc\winerror.h +FILE 3007 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 3008 f:\sp\public\sdk\inc\winreg.h +FILE 3009 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3010 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 3011 f:\sp\public\sdk\inc\ddbanned.h +FILE 3012 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3013 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3014 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3015 f:\sp\public\sdk\inc\tvout.h +FILE 3016 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3017 f:\sp\vctools\crt_bld\self_x86\crt\src\mbdata.h +FILE 3018 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 3019 f:\sp\public\sdk\inc\wincon.h +FILE 3020 f:\sp\public\sdk\inc\imm.h +FILE 3021 f:\sp\public\sdk\inc\winbase.h +FILE 3022 f:\sp\public\sdk\inc\wingdi.h +FILE 3023 f:\sp\public\sdk\inc\winver.h +FILE 3024 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3025 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3026 f:\sp\public\sdk\inc\pshpack2.h +FILE 3027 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 3028 f:\sp\public\sdk\inc\reason.h +FILE 3029 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.c +FILE 3030 f:\sp\public\sdk\inc\specstrings.h +FILE 3031 f:\sp\public\sdk\inc\basetsd.h +FILE 3032 f:\sp\public\sdk\inc\pshpack4.h +FILE 3033 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 3034 f:\sp\public\sdk\inc\winnetwk.h +FILE 3035 f:\sp\public\sdk\inc\stralign.h +FILE 3036 f:\sp\public\sdk\inc\poppack.h +FILE 3037 f:\sp\public\sdk\inc\winsvc.h +FILE 3038 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3039 f:\sp\public\sdk\inc\windef.h +FILE 3040 f:\sp\public\sdk\inc\winuser.h +FILE 3041 f:\sp\public\sdk\inc\windows.h +FILE 3042 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3043 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3044 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3045 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3046 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3047 f:\sp\public\sdk\inc\mcx.h +FILE 3048 f:\sp\public\sdk\inc\pshpack8.h +FILE 3049 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3050 f:\sp\public\sdk\inc\guiddef.h +FILE 3051 f:\sp\public\sdk\inc\winnt.h +FILE 3052 f:\sp\public\sdk\inc\winnls.h +FILE 3053 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3054 f:\sp\vctools\crt_bld\self_x86\crt\src\mbdata.h +FILE 3055 f:\sp\public\sdk\inc\pshpack1.h +FILE 3056 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 3057 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 3058 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 3059 f:\sp\public\sdk\inc\winerror.h +FILE 3060 f:\sp\vctools\crt_bld\self_x86\crt\src\sect_attribs.h +FILE 3061 f:\sp\public\sdk\inc\winreg.h +FILE 3062 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3063 f:\sp\public\sdk\inc\ddbanned.h +FILE 3064 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 3065 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3066 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 3067 f:\sp\public\sdk\inc\tvout.h +FILE 3068 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3069 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3070 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3071 f:\sp\public\sdk\inc\wincon.h +FILE 3072 f:\sp\public\sdk\inc\imm.h +FILE 3073 f:\sp\public\sdk\inc\winbase.h +FILE 3074 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3075 f:\sp\public\sdk\inc\wingdi.h +FILE 3076 f:\sp\public\sdk\inc\windef.h +FILE 3077 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 3078 f:\sp\public\sdk\inc\winver.h +FILE 3079 f:\sp\public\sdk\inc\pshpack2.h +FILE 3080 f:\sp\public\sdk\inc\reason.h +FILE 3081 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 3082 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 3083 f:\sp\vctools\crt_bld\self_x86\crt\src\ismbbyte.c +FILE 3084 f:\sp\public\sdk\inc\winnt.h +FILE 3085 f:\sp\public\sdk\inc\specstrings.h +FILE 3086 f:\sp\public\sdk\inc\basetsd.h +FILE 3087 f:\sp\public\sdk\inc\pshpack4.h +FILE 3088 f:\sp\public\sdk\inc\winnetwk.h +FILE 3089 f:\sp\public\sdk\inc\stralign.h +FILE 3090 f:\sp\public\sdk\inc\poppack.h +FILE 3091 f:\sp\public\sdk\inc\winsvc.h +FILE 3092 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3093 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3094 f:\sp\public\sdk\inc\winuser.h +FILE 3095 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3096 f:\sp\public\sdk\inc\mcx.h +FILE 3097 f:\sp\public\sdk\inc\pshpack8.h +FILE 3098 f:\sp\public\sdk\inc\guiddef.h +FILE 3099 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3100 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 3101 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3102 f:\sp\public\sdk\inc\windows.h +FILE 3103 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3104 f:\sp\public\sdk\inc\winnls.h +FILE 3105 f:\sp\public\sdk\inc\pshpack1.h +FILE 3106 f:\sp\public\sdk\inc\winerror.h +FILE 3107 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 3108 f:\sp\public\sdk\inc\winreg.h +FILE 3109 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3110 f:\sp\public\sdk\inc\ddbanned.h +FILE 3111 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3112 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3113 f:\sp\public\sdk\inc\tvout.h +FILE 3114 f:\sp\vctools\crt_bld\self_x86\crt\src\mbdata.h +FILE 3115 f:\sp\public\sdk\inc\poppack.h +FILE 3116 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3117 f:\sp\public\sdk\inc\winnetwk.h +FILE 3118 f:\sp\public\sdk\inc\imm.h +FILE 3119 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3120 f:\sp\public\sdk\inc\windef.h +FILE 3121 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3122 f:\sp\public\sdk\inc\pshpack1.h +FILE 3123 f:\sp\vctools\crt_bld\self_x86\crt\src\msdos.h +FILE 3124 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 3125 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 3126 f:\sp\public\sdk\inc\winver.h +FILE 3127 f:\sp\public\sdk\inc\windows.h +FILE 3128 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3129 f:\sp\public\sdk\inc\winnt.h +FILE 3130 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3131 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3132 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3133 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3134 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3135 f:\sp\public\sdk\inc\winreg.h +FILE 3136 f:\sp\public\sdk\inc\winbase.h +FILE 3137 f:\sp\vctools\crt_bld\self_x86\crt\src\ioinit.c +FILE 3138 f:\sp\public\sdk\inc\winerror.h +FILE 3139 f:\sp\public\sdk\inc\pshpack8.h +FILE 3140 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3141 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3142 f:\sp\public\sdk\inc\reason.h +FILE 3143 f:\sp\public\sdk\inc\wincon.h +FILE 3144 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3145 f:\sp\public\sdk\inc\ddbanned.h +FILE 3146 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3147 f:\sp\public\sdk\inc\pshpack2.h +FILE 3148 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3149 f:\sp\public\sdk\inc\mcx.h +FILE 3150 f:\sp\public\sdk\inc\winuser.h +FILE 3151 f:\sp\public\sdk\inc\winnls.h +FILE 3152 f:\sp\public\sdk\inc\guiddef.h +FILE 3153 f:\sp\public\sdk\inc\specstrings.h +FILE 3154 f:\sp\public\sdk\inc\basetsd.h +FILE 3155 f:\sp\public\sdk\inc\stralign.h +FILE 3156 f:\sp\public\sdk\inc\tvout.h +FILE 3157 f:\sp\public\sdk\inc\winsvc.h +FILE 3158 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3159 f:\sp\public\sdk\inc\wingdi.h +FILE 3160 f:\sp\public\sdk\inc\pshpack4.h +FILE 3161 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\ulldvrm.asm +FILE 3162 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 3163 F:\SP\vctools\crt_bld\SELF_X86\crt\src\mm.inc +FILE 3164 F:\SP\vctools\crt_bld\SELF_X86\crt\src\intel\llmul.asm +FILE 3165 F:\SP\vctools\crt_bld\SELF_X86\crt\src\cruntime.inc +FILE 3166 F:\SP\vctools\crt_bld\SELF_X86\crt\src\mm.inc +FILE 3167 f:\sp\public\sdk\inc\poppack.h +FILE 3168 f:\sp\public\sdk\inc\winnetwk.h +FILE 3169 f:\sp\public\sdk\inc\imm.h +FILE 3170 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3171 f:\sp\public\sdk\inc\windef.h +FILE 3172 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3173 f:\sp\public\sdk\inc\pshpack1.h +FILE 3174 f:\sp\public\sdk\inc\winver.h +FILE 3175 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3176 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3177 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3178 f:\sp\public\sdk\inc\winnt.h +FILE 3179 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3180 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3181 f:\sp\public\sdk\inc\winreg.h +FILE 3182 f:\sp\vctools\crt_bld\self_x86\crt\src\_newmode.c +FILE 3183 f:\sp\public\sdk\inc\winbase.h +FILE 3184 f:\sp\public\sdk\inc\winerror.h +FILE 3185 f:\sp\public\sdk\inc\pshpack8.h +FILE 3186 f:\sp\public\sdk\inc\reason.h +FILE 3187 f:\sp\public\sdk\inc\wincon.h +FILE 3188 f:\sp\public\sdk\inc\ddbanned.h +FILE 3189 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3190 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3191 f:\sp\public\sdk\inc\pshpack2.h +FILE 3192 f:\sp\public\sdk\inc\mcx.h +FILE 3193 f:\sp\public\sdk\inc\winuser.h +FILE 3194 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3195 f:\sp\public\sdk\inc\winnls.h +FILE 3196 f:\sp\public\sdk\inc\guiddef.h +FILE 3197 f:\sp\public\sdk\inc\windows.h +FILE 3198 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3199 f:\sp\public\sdk\inc\specstrings.h +FILE 3200 f:\sp\public\sdk\inc\basetsd.h +FILE 3201 f:\sp\public\sdk\inc\stralign.h +FILE 3202 f:\sp\public\sdk\inc\tvout.h +FILE 3203 f:\sp\public\sdk\inc\winsvc.h +FILE 3204 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3205 f:\sp\public\sdk\inc\wingdi.h +FILE 3206 f:\sp\public\sdk\inc\pshpack4.h +FILE 3207 f:\sp\vctools\crt_bld\self_x86\crt\src\new.h +FILE 3208 f:\sp\public\sdk\inc\winerror.h +FILE 3209 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcsup.h +FILE 3210 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 3211 f:\sp\public\sdk\inc\winreg.h +FILE 3212 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3213 f:\sp\public\sdk\inc\tvout.h +FILE 3214 f:\sp\vctools\crt_bld\self_x86\crt\src\delete.cpp +FILE 3215 f:\sp\public\sdk\inc\wincon.h +FILE 3216 f:\sp\public\sdk\inc\imm.h +FILE 3217 f:\sp\public\sdk\inc\winbase.h +FILE 3218 f:\sp\public\sdk\inc\wingdi.h +FILE 3219 f:\sp\public\sdk\inc\winver.h +FILE 3220 f:\sp\public\sdk\inc\windows.h +FILE 3221 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3222 f:\sp\public\sdk\inc\pshpack2.h +FILE 3223 f:\sp\public\sdk\inc\reason.h +FILE 3224 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3225 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3226 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3227 f:\sp\public\sdk\inc\specstrings.h +FILE 3228 f:\sp\public\sdk\inc\basetsd.h +FILE 3229 f:\sp\public\sdk\inc\pshpack4.h +FILE 3230 f:\sp\public\sdk\inc\winnetwk.h +FILE 3231 f:\sp\public\sdk\inc\stralign.h +FILE 3232 f:\sp\public\sdk\inc\poppack.h +FILE 3233 f:\sp\public\sdk\inc\winsvc.h +FILE 3234 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3235 f:\sp\public\sdk\inc\windef.h +FILE 3236 f:\sp\public\sdk\inc\winuser.h +FILE 3237 f:\sp\public\sdk\inc\mcx.h +FILE 3238 f:\sp\public\sdk\inc\pshpack8.h +FILE 3239 f:\sp\public\sdk\inc\ddbanned.h +FILE 3240 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3241 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3242 f:\sp\public\sdk\inc\guiddef.h +FILE 3243 f:\sp\public\sdk\inc\winnt.h +FILE 3244 f:\sp\public\sdk\inc\winnls.h +FILE 3245 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3246 f:\sp\public\sdk\inc\pshpack1.h +FILE 3247 f:\sp\public\sdk\inc\tvout.h +FILE 3248 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3249 f:\sp\vctools\crt_bld\self_x86\crt\src\process.h +FILE 3250 f:\sp\public\sdk\inc\wincon.h +FILE 3251 f:\sp\public\sdk\inc\imm.h +FILE 3252 f:\sp\public\sdk\inc\winbase.h +FILE 3253 f:\sp\public\sdk\inc\wingdi.h +FILE 3254 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3255 f:\sp\public\sdk\inc\winver.h +FILE 3256 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3257 f:\sp\public\sdk\inc\windows.h +FILE 3258 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3259 f:\sp\public\sdk\inc\pshpack2.h +FILE 3260 f:\sp\vctools\crt_bld\self_x86\crt\src\handler.cpp +FILE 3261 f:\sp\public\sdk\inc\reason.h +FILE 3262 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3263 f:\sp\public\sdk\inc\specstrings.h +FILE 3264 f:\sp\public\sdk\inc\basetsd.h +FILE 3265 f:\sp\public\sdk\inc\pshpack4.h +FILE 3266 f:\sp\public\sdk\inc\winnetwk.h +FILE 3267 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 3268 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3269 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3270 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3271 f:\sp\public\sdk\inc\stralign.h +FILE 3272 f:\sp\public\sdk\inc\poppack.h +FILE 3273 f:\sp\public\sdk\inc\winsvc.h +FILE 3274 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3275 f:\sp\public\sdk\inc\windef.h +FILE 3276 f:\sp\public\sdk\inc\winuser.h +FILE 3277 f:\sp\public\sdk\inc\mcx.h +FILE 3278 f:\sp\public\sdk\inc\pshpack8.h +FILE 3279 f:\sp\public\sdk\inc\guiddef.h +FILE 3280 f:\sp\public\sdk\inc\winnt.h +FILE 3281 f:\sp\public\sdk\inc\winnls.h +FILE 3282 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3283 f:\sp\public\sdk\inc\pshpack1.h +FILE 3284 f:\sp\public\sdk\inc\winerror.h +FILE 3285 f:\sp\public\sdk\inc\ddbanned.h +FILE 3286 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3287 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3288 f:\sp\public\sdk\inc\winreg.h +FILE 3289 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3290 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3291 f:\sp\vctools\crt_bld\self_x86\crt\src\new.h +FILE 3292 f:\sp\public\sdk\inc\winsvc.h +FILE 3293 f:\sp\public\sdk\inc\wingdi.h +FILE 3294 f:\sp\public\sdk\inc\pshpack4.h +FILE 3295 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3296 f:\sp\public\sdk\inc\poppack.h +FILE 3297 f:\sp\public\sdk\inc\winnt.h +FILE 3298 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3299 f:\sp\public\sdk\inc\winnetwk.h +FILE 3300 f:\sp\public\sdk\inc\imm.h +FILE 3301 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3302 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 3303 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3304 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3305 f:\sp\public\sdk\inc\pshpack1.h +FILE 3306 f:\sp\public\sdk\inc\winver.h +FILE 3307 f:\sp\public\sdk\inc\guiddef.h +FILE 3308 f:\sp\public\sdk\inc\specstrings.h +FILE 3309 f:\sp\public\sdk\inc\basetsd.h +FILE 3310 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3311 f:\sp\vctools\crt_bld\self_x86\crt\src\sbheap.c +FILE 3312 f:\sp\public\sdk\inc\windows.h +FILE 3313 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3314 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3315 f:\sp\public\sdk\inc\winreg.h +FILE 3316 f:\sp\public\sdk\inc\winbase.h +FILE 3317 f:\sp\public\sdk\inc\winerror.h +FILE 3318 f:\sp\public\sdk\inc\pshpack8.h +FILE 3319 f:\sp\public\sdk\inc\ddbanned.h +FILE 3320 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3321 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3322 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3323 f:\sp\public\sdk\inc\reason.h +FILE 3324 f:\sp\public\sdk\inc\wincon.h +FILE 3325 f:\sp\public\sdk\inc\pshpack2.h +FILE 3326 f:\sp\public\sdk\inc\mcx.h +FILE 3327 f:\sp\public\sdk\inc\winuser.h +FILE 3328 f:\sp\public\sdk\inc\winnls.h +FILE 3329 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3330 f:\sp\public\sdk\inc\windef.h +FILE 3331 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3332 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3333 f:\sp\public\sdk\inc\stralign.h +FILE 3334 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3335 f:\sp\public\sdk\inc\tvout.h +FILE 3336 f:\sp\public\sdk\inc\winver.h +FILE 3337 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcsup.h +FILE 3338 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 3339 f:\sp\public\sdk\inc\guiddef.h +FILE 3340 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3341 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3342 f:\sp\public\sdk\inc\specstrings.h +FILE 3343 f:\sp\public\sdk\inc\basetsd.h +FILE 3344 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3345 f:\sp\public\sdk\inc\windows.h +FILE 3346 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3347 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3348 f:\sp\public\sdk\inc\winreg.h +FILE 3349 f:\sp\public\sdk\inc\winbase.h +FILE 3350 f:\sp\public\sdk\inc\winerror.h +FILE 3351 f:\sp\public\sdk\inc\pshpack8.h +FILE 3352 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3353 f:\sp\public\sdk\inc\reason.h +FILE 3354 f:\sp\public\sdk\inc\wincon.h +FILE 3355 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3356 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3357 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3358 f:\sp\public\sdk\inc\pshpack2.h +FILE 3359 f:\sp\public\sdk\inc\mcx.h +FILE 3360 f:\sp\public\sdk\inc\winuser.h +FILE 3361 f:\sp\public\sdk\inc\winnls.h +FILE 3362 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3363 f:\sp\public\sdk\inc\windef.h +FILE 3364 f:\sp\public\sdk\inc\stralign.h +FILE 3365 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3366 f:\sp\public\sdk\inc\tvout.h +FILE 3367 f:\sp\public\sdk\inc\winsvc.h +FILE 3368 f:\sp\vctools\crt_bld\self_x86\crt\src\realloc.c +FILE 3369 f:\sp\public\sdk\inc\wingdi.h +FILE 3370 f:\sp\public\sdk\inc\pshpack4.h +FILE 3371 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3372 f:\sp\public\sdk\inc\poppack.h +FILE 3373 f:\sp\public\sdk\inc\winnt.h +FILE 3374 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3375 f:\sp\public\sdk\inc\winnetwk.h +FILE 3376 f:\sp\public\sdk\inc\ddbanned.h +FILE 3377 f:\sp\public\sdk\inc\imm.h +FILE 3378 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3379 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3380 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3381 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3382 f:\sp\public\sdk\inc\pshpack1.h +FILE 3383 f:\sp\public\sdk\inc\pshpack2.h +FILE 3384 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3385 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3386 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3387 f:\sp\public\sdk\inc\mcx.h +FILE 3388 f:\sp\public\sdk\inc\winuser.h +FILE 3389 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3390 f:\sp\public\sdk\inc\winnls.h +FILE 3391 f:\sp\public\sdk\inc\guiddef.h +FILE 3392 f:\sp\public\sdk\inc\windows.h +FILE 3393 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3394 f:\sp\public\sdk\inc\specstrings.h +FILE 3395 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3396 f:\sp\public\sdk\inc\basetsd.h +FILE 3397 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3398 f:\sp\public\sdk\inc\stralign.h +FILE 3399 f:\sp\public\sdk\inc\tvout.h +FILE 3400 f:\sp\public\sdk\inc\winsvc.h +FILE 3401 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3402 f:\sp\public\sdk\inc\wingdi.h +FILE 3403 f:\sp\public\sdk\inc\pshpack4.h +FILE 3404 f:\sp\public\sdk\inc\poppack.h +FILE 3405 f:\sp\public\sdk\inc\winnetwk.h +FILE 3406 f:\sp\public\sdk\inc\imm.h +FILE 3407 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3408 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3409 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3410 f:\sp\public\sdk\inc\windef.h +FILE 3411 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3412 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3413 f:\sp\vctools\crt_bld\self_x86\crt\src\msize.c +FILE 3414 f:\sp\public\sdk\inc\pshpack1.h +FILE 3415 f:\sp\public\sdk\inc\winver.h +FILE 3416 f:\sp\public\sdk\inc\winnt.h +FILE 3417 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3418 f:\sp\public\sdk\inc\winreg.h +FILE 3419 f:\sp\public\sdk\inc\ddbanned.h +FILE 3420 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3421 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3422 f:\sp\public\sdk\inc\winbase.h +FILE 3423 f:\sp\public\sdk\inc\winerror.h +FILE 3424 f:\sp\public\sdk\inc\pshpack8.h +FILE 3425 f:\sp\public\sdk\inc\reason.h +FILE 3426 f:\sp\public\sdk\inc\wincon.h +FILE 3427 f:\sp\public\sdk\inc\pshpack2.h +FILE 3428 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3429 f:\sp\public\sdk\inc\mcx.h +FILE 3430 f:\sp\public\sdk\inc\winuser.h +FILE 3431 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3432 f:\sp\public\sdk\inc\winnls.h +FILE 3433 f:\sp\public\sdk\inc\guiddef.h +FILE 3434 f:\sp\public\sdk\inc\windows.h +FILE 3435 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3436 f:\sp\public\sdk\inc\specstrings.h +FILE 3437 f:\sp\public\sdk\inc\basetsd.h +FILE 3438 f:\sp\public\sdk\inc\stralign.h +FILE 3439 f:\sp\public\sdk\inc\tvout.h +FILE 3440 f:\sp\public\sdk\inc\winsvc.h +FILE 3441 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3442 f:\sp\public\sdk\inc\wingdi.h +FILE 3443 f:\sp\public\sdk\inc\pshpack4.h +FILE 3444 f:\sp\public\sdk\inc\poppack.h +FILE 3445 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3446 f:\sp\public\sdk\inc\winnetwk.h +FILE 3447 f:\sp\public\sdk\inc\imm.h +FILE 3448 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3449 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3450 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3451 f:\sp\public\sdk\inc\windef.h +FILE 3452 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3453 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3454 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3455 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.c +FILE 3456 f:\sp\public\sdk\inc\pshpack1.h +FILE 3457 f:\sp\public\sdk\inc\winver.h +FILE 3458 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcsup.h +FILE 3459 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 3460 f:\sp\vctools\crt_bld\self_x86\crt\src\rterr.h +FILE 3461 f:\sp\public\sdk\inc\winnt.h +FILE 3462 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3463 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3464 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3465 f:\sp\public\sdk\inc\winreg.h +FILE 3466 f:\sp\public\sdk\inc\ddbanned.h +FILE 3467 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3468 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3469 f:\sp\public\sdk\inc\winbase.h +FILE 3470 f:\sp\public\sdk\inc\winerror.h +FILE 3471 f:\sp\public\sdk\inc\pshpack8.h +FILE 3472 f:\sp\public\sdk\inc\reason.h +FILE 3473 f:\sp\public\sdk\inc\wincon.h +FILE 3474 f:\sp\public\sdk\inc\winver.h +FILE 3475 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3476 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3477 f:\sp\public\sdk\inc\winnt.h +FILE 3478 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3479 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3480 f:\sp\public\sdk\inc\winreg.h +FILE 3481 f:\sp\public\sdk\inc\winbase.h +FILE 3482 f:\sp\public\sdk\inc\winerror.h +FILE 3483 f:\sp\public\sdk\inc\pshpack8.h +FILE 3484 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3485 f:\sp\public\sdk\inc\reason.h +FILE 3486 f:\sp\public\sdk\inc\wincon.h +FILE 3487 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3488 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3489 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3490 f:\sp\public\sdk\inc\pshpack2.h +FILE 3491 f:\sp\public\sdk\inc\mcx.h +FILE 3492 f:\sp\public\sdk\inc\winuser.h +FILE 3493 f:\sp\public\sdk\inc\winnls.h +FILE 3494 f:\sp\public\sdk\inc\guiddef.h +FILE 3495 f:\sp\public\sdk\inc\stralign.h +FILE 3496 f:\sp\public\sdk\inc\specstrings.h +FILE 3497 f:\sp\public\sdk\inc\basetsd.h +FILE 3498 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3499 f:\sp\public\sdk\inc\windows.h +FILE 3500 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3501 f:\sp\public\sdk\inc\tvout.h +FILE 3502 f:\sp\public\sdk\inc\winsvc.h +FILE 3503 f:\sp\vctools\crt_bld\self_x86\crt\src\heapinit.c +FILE 3504 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3505 f:\sp\public\sdk\inc\wingdi.h +FILE 3506 f:\sp\public\sdk\inc\pshpack4.h +FILE 3507 f:\sp\public\sdk\inc\poppack.h +FILE 3508 f:\sp\public\sdk\inc\winnetwk.h +FILE 3509 f:\sp\public\sdk\inc\ddbanned.h +FILE 3510 f:\sp\public\sdk\inc\imm.h +FILE 3511 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3512 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3513 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3514 f:\sp\public\sdk\inc\windef.h +FILE 3515 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3516 f:\sp\public\sdk\inc\pshpack1.h +FILE 3517 f:\sp\public\sdk\inc\pshpack2.h +FILE 3518 f:\sp\public\sdk\inc\mcx.h +FILE 3519 f:\sp\public\sdk\inc\winuser.h +FILE 3520 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3521 f:\sp\public\sdk\inc\winnls.h +FILE 3522 f:\sp\public\sdk\inc\guiddef.h +FILE 3523 f:\sp\public\sdk\inc\windows.h +FILE 3524 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3525 f:\sp\public\sdk\inc\specstrings.h +FILE 3526 f:\sp\public\sdk\inc\basetsd.h +FILE 3527 f:\sp\public\sdk\inc\stralign.h +FILE 3528 f:\sp\public\sdk\inc\tvout.h +FILE 3529 f:\sp\public\sdk\inc\winsvc.h +FILE 3530 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3531 f:\sp\public\sdk\inc\wingdi.h +FILE 3532 f:\sp\public\sdk\inc\pshpack4.h +FILE 3533 f:\sp\public\sdk\inc\poppack.h +FILE 3534 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3535 f:\sp\public\sdk\inc\winnetwk.h +FILE 3536 f:\sp\public\sdk\inc\imm.h +FILE 3537 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3538 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3539 f:\sp\public\sdk\inc\windef.h +FILE 3540 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3541 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3542 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3543 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3544 f:\sp\public\sdk\inc\pshpack1.h +FILE 3545 f:\sp\vctools\crt_bld\self_x86\crt\src\free.c +FILE 3546 f:\sp\public\sdk\inc\winver.h +FILE 3547 f:\sp\public\sdk\inc\winnt.h +FILE 3548 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3549 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcsup.h +FILE 3550 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 3551 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3552 f:\sp\public\sdk\inc\winreg.h +FILE 3553 f:\sp\public\sdk\inc\ddbanned.h +FILE 3554 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3555 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3556 f:\sp\public\sdk\inc\winbase.h +FILE 3557 f:\sp\public\sdk\inc\winerror.h +FILE 3558 f:\sp\public\sdk\inc\pshpack8.h +FILE 3559 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3560 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3561 f:\sp\public\sdk\inc\reason.h +FILE 3562 f:\sp\public\sdk\inc\wincon.h +FILE 3563 f:\sp\public\sdk\inc\pshpack2.h +FILE 3564 f:\sp\public\sdk\inc\mcx.h +FILE 3565 f:\sp\public\sdk\inc\winuser.h +FILE 3566 f:\sp\public\sdk\inc\winnls.h +FILE 3567 f:\sp\public\sdk\inc\guiddef.h +FILE 3568 f:\sp\public\sdk\inc\windows.h +FILE 3569 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3570 f:\sp\public\sdk\inc\specstrings.h +FILE 3571 f:\sp\public\sdk\inc\basetsd.h +FILE 3572 f:\sp\public\sdk\inc\stralign.h +FILE 3573 f:\sp\public\sdk\inc\tvout.h +FILE 3574 f:\sp\public\sdk\inc\winsvc.h +FILE 3575 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3576 f:\sp\public\sdk\inc\wingdi.h +FILE 3577 f:\sp\public\sdk\inc\pshpack4.h +FILE 3578 f:\sp\public\sdk\inc\poppack.h +FILE 3579 f:\sp\public\sdk\inc\winnetwk.h +FILE 3580 f:\sp\public\sdk\inc\imm.h +FILE 3581 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3582 f:\sp\public\sdk\inc\windef.h +FILE 3583 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3584 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3585 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3586 f:\sp\public\sdk\inc\pshpack1.h +FILE 3587 f:\sp\vctools\crt_bld\self_x86\crt\src\crtheap.c +FILE 3588 f:\sp\public\sdk\inc\winver.h +FILE 3589 f:\sp\public\sdk\inc\winnt.h +FILE 3590 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3591 f:\sp\public\sdk\inc\winreg.h +FILE 3592 f:\sp\public\sdk\inc\ddbanned.h +FILE 3593 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3594 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3595 f:\sp\public\sdk\inc\winbase.h +FILE 3596 f:\sp\public\sdk\inc\winerror.h +FILE 3597 f:\sp\public\sdk\inc\pshpack8.h +FILE 3598 f:\sp\public\sdk\inc\reason.h +FILE 3599 f:\sp\public\sdk\inc\wincon.h +FILE 3600 f:\sp\public\sdk\inc\pshpack2.h +FILE 3601 f:\sp\public\sdk\inc\mcx.h +FILE 3602 f:\sp\public\sdk\inc\winuser.h +FILE 3603 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3604 f:\sp\public\sdk\inc\winnls.h +FILE 3605 f:\sp\public\sdk\inc\stralign.h +FILE 3606 f:\sp\public\sdk\inc\tvout.h +FILE 3607 f:\sp\public\sdk\inc\winsvc.h +FILE 3608 f:\sp\public\sdk\inc\wingdi.h +FILE 3609 f:\sp\public\sdk\inc\winnt.h +FILE 3610 f:\sp\public\sdk\inc\pshpack4.h +FILE 3611 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3612 f:\sp\public\sdk\inc\poppack.h +FILE 3613 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3614 f:\sp\public\sdk\inc\winnetwk.h +FILE 3615 f:\sp\public\sdk\inc\imm.h +FILE 3616 f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.h +FILE 3617 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3618 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3619 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 3620 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3621 f:\sp\public\sdk\inc\pshpack1.h +FILE 3622 f:\sp\vctools\crt_bld\self_x86\crt\src\calloc.c +FILE 3623 f:\sp\public\sdk\inc\winver.h +FILE 3624 f:\sp\vctools\crt_bld\self_x86\crt\src\winheap.h +FILE 3625 f:\sp\public\sdk\inc\guiddef.h +FILE 3626 f:\sp\public\sdk\inc\windows.h +FILE 3627 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3628 f:\sp\public\sdk\inc\specstrings.h +FILE 3629 f:\sp\public\sdk\inc\basetsd.h +FILE 3630 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcsup.h +FILE 3631 f:\sp\vctools\crt_bld\self_x86\crt\src\rtcapi.h +FILE 3632 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3633 f:\sp\public\sdk\inc\winreg.h +FILE 3634 f:\sp\public\sdk\inc\ddbanned.h +FILE 3635 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3636 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3637 f:\sp\public\sdk\inc\winbase.h +FILE 3638 f:\sp\public\sdk\inc\winerror.h +FILE 3639 f:\sp\public\sdk\inc\pshpack8.h +FILE 3640 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3641 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3642 f:\sp\public\sdk\inc\reason.h +FILE 3643 f:\sp\public\sdk\inc\wincon.h +FILE 3644 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3645 f:\sp\public\sdk\inc\windef.h +FILE 3646 f:\sp\public\sdk\inc\wincon.h +FILE 3647 f:\sp\public\sdk\inc\imm.h +FILE 3648 f:\sp\public\sdk\inc\winbase.h +FILE 3649 f:\sp\public\sdk\inc\wingdi.h +FILE 3650 f:\sp\public\sdk\inc\winver.h +FILE 3651 f:\sp\public\sdk\inc\pshpack2.h +FILE 3652 f:\sp\public\sdk\inc\reason.h +FILE 3653 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sect_attribs.h +FILE 3654 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\eh\unhandld.cpp +FILE 3655 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\eh.h +FILE 3656 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 3657 f:\sp\public\sdk\inc\specstrings.h +FILE 3658 f:\sp\public\sdk\inc\basetsd.h +FILE 3659 f:\sp\public\sdk\inc\pshpack4.h +FILE 3660 f:\sp\public\sdk\inc\winnetwk.h +FILE 3661 f:\sp\public\sdk\inc\stralign.h +FILE 3662 f:\sp\public\sdk\inc\poppack.h +FILE 3663 f:\sp\public\sdk\inc\winsvc.h +FILE 3664 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 3665 f:\sp\public\sdk\inc\windef.h +FILE 3666 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ehhooks.h +FILE 3667 f:\sp\public\sdk\inc\winuser.h +FILE 3668 f:\sp\public\sdk\inc\windows.h +FILE 3669 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 3670 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 3671 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 3672 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ehassert.h +FILE 3673 f:\sp\public\sdk\inc\mcx.h +FILE 3674 f:\sp\public\sdk\inc\pshpack8.h +FILE 3675 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 3676 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 3677 f:\sp\public\sdk\inc\guiddef.h +FILE 3678 f:\sp\public\sdk\inc\winnt.h +FILE 3679 f:\sp\public\sdk\inc\winnls.h +FILE 3680 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 3681 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdlib.h +FILE 3682 f:\sp\public\sdk\inc\pshpack1.h +FILE 3683 f:\sp\public\sdk\inc\winerror.h +FILE 3684 f:\sp\vctools\langapi\include\ehdata.h +FILE 3685 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stddef.h +FILE 3686 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 3687 f:\sp\public\sdk\inc\winreg.h +FILE 3688 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 3689 f:\sp\public\sdk\inc\ddbanned.h +FILE 3690 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 3691 f:\sp\public\sdk\inc\tvout.h +FILE 3692 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 3693 f:\sp\public\sdk\inc\specstrings.h +FILE 3694 f:\sp\public\sdk\inc\basetsd.h +FILE 3695 f:\sp\public\sdk\inc\pshpack4.h +FILE 3696 f:\sp\public\sdk\inc\winnetwk.h +FILE 3697 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 3698 f:\sp\public\sdk\inc\stralign.h +FILE 3699 f:\sp\public\sdk\inc\poppack.h +FILE 3700 f:\sp\public\sdk\inc\winsvc.h +FILE 3701 f:\sp\public\sdk\inc\winuser.h +FILE 3702 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 3703 f:\sp\public\sdk\inc\windef.h +FILE 3704 f:\sp\vctools\langapi\undname\undname.cxx +FILE 3705 f:\sp\public\sdk\inc\mcx.h +FILE 3706 f:\sp\public\sdk\inc\pshpack8.h +FILE 3707 f:\sp\public\sdk\inc\guiddef.h +FILE 3708 f:\sp\vctools\langapi\undname\utf8.h +FILE 3709 f:\sp\public\sdk\inc\winnls.h +FILE 3710 f:\sp\public\sdk\inc\pshpack1.h +FILE 3711 f:\sp\public\sdk\inc\winnt.h +FILE 3712 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 3713 f:\sp\public\sdk\inc\winerror.h +FILE 3714 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\swprintf.inl +FILE 3715 f:\sp\vctools\langapi\undname\undname.hxx +FILE 3716 f:\sp\vctools\langapi\undname\undname.h +FILE 3717 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdlib.h +FILE 3718 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 3719 f:\sp\public\sdk\inc\winreg.h +FILE 3720 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 3721 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 3722 f:\sp\public\sdk\inc\tvout.h +FILE 3723 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdio.h +FILE 3724 f:\sp\public\sdk\inc\wincon.h +FILE 3725 f:\sp\public\sdk\inc\imm.h +FILE 3726 f:\sp\public\sdk\inc\winbase.h +FILE 3727 f:\sp\public\sdk\inc\wingdi.h +FILE 3728 f:\sp\public\sdk\inc\winver.h +FILE 3729 f:\sp\public\sdk\inc\pshpack2.h +FILE 3730 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\mtdll.h +FILE 3731 f:\sp\public\sdk\inc\windows.h +FILE 3732 f:\sp\public\sdk\inc\reason.h +FILE 3733 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 3734 f:\sp\public\sdk\inc\ddbanned.h +FILE 3735 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 3736 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 3737 f:\sp\vctools\langapi\undname\undname.inl +FILE 3738 f:\sp\public\sdk\inc\guiddef.h +FILE 3739 f:\sp\public\sdk\inc\winnt.h +FILE 3740 f:\sp\public\sdk\inc\winnls.h +FILE 3741 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 3742 f:\sp\public\sdk\inc\pshpack1.h +FILE 3743 f:\sp\public\sdk\inc\winerror.h +FILE 3744 f:\sp\public\sdk\inc\winreg.h +FILE 3745 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 3746 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdlib.h +FILE 3747 f:\sp\public\sdk\inc\tvout.h +FILE 3748 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\eh\typname.cpp +FILE 3749 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 3750 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\cstddef +FILE 3751 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stddef.h +FILE 3752 f:\sp\public\sdk\inc\wincon.h +FILE 3753 f:\sp\public\sdk\inc\imm.h +FILE 3754 f:\sp\public\sdk\inc\winbase.h +FILE 3755 f:\sp\public\sdk\inc\wingdi.h +FILE 3756 f:\sp\public\sdk\inc\winver.h +FILE 3757 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 3758 f:\sp\public\sdk\inc\windows.h +FILE 3759 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 3760 f:\sp\public\sdk\inc\pshpack2.h +FILE 3761 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\mtdll.h +FILE 3762 f:\sp\public\sdk\inc\reason.h +FILE 3763 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sect_attribs.h +FILE 3764 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\dbgint.h +FILE 3765 f:\sp\public\sdk\inc\specstrings.h +FILE 3766 f:\sp\public\sdk\inc\basetsd.h +FILE 3767 f:\sp\public\sdk\inc\pshpack4.h +FILE 3768 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\typeinfo.h +FILE 3769 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\typeinfo +FILE 3770 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\exception +FILE 3771 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\xstddef +FILE 3772 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\eh.h +FILE 3773 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\yvals.h +FILE 3774 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\use_ansi.h +FILE 3775 f:\sp\public\sdk\inc\winnetwk.h +FILE 3776 f:\sp\vctools\langapi\undname\undname.h +FILE 3777 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 3778 f:\sp\public\sdk\inc\stralign.h +FILE 3779 f:\sp\public\sdk\inc\poppack.h +FILE 3780 f:\sp\public\sdk\inc\winsvc.h +FILE 3781 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 3782 f:\sp\public\sdk\inc\windef.h +FILE 3783 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 3784 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 3785 f:\sp\public\sdk\inc\winuser.h +FILE 3786 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 3787 f:\sp\public\sdk\inc\ddbanned.h +FILE 3788 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 3789 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 3790 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\malloc.h +FILE 3791 f:\sp\public\sdk\inc\mcx.h +FILE 3792 f:\sp\public\sdk\inc\pshpack8.h +FILE 3793 f:\sp\public\sdk\inc\winnls.h +FILE 3794 f:\sp\public\sdk\inc\pshpack1.h +FILE 3795 f:\sp\public\sdk\inc\winnt.h +FILE 3796 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 3797 f:\sp\public\sdk\inc\winerror.h +FILE 3798 f:\sp\public\sdk\inc\winreg.h +FILE 3799 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 3800 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 3801 f:\sp\public\sdk\inc\tvout.h +FILE 3802 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\dbgint.h +FILE 3803 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 3804 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\cstddef +FILE 3805 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stddef.h +FILE 3806 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\eh\typinfo.cpp +FILE 3807 f:\sp\public\sdk\inc\wincon.h +FILE 3808 f:\sp\public\sdk\inc\imm.h +FILE 3809 f:\sp\public\sdk\inc\winbase.h +FILE 3810 f:\sp\public\sdk\inc\wingdi.h +FILE 3811 f:\sp\public\sdk\inc\winver.h +FILE 3812 f:\sp\public\sdk\inc\pshpack2.h +FILE 3813 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\mtdll.h +FILE 3814 f:\sp\public\sdk\inc\reason.h +FILE 3815 f:\sp\public\sdk\inc\windows.h +FILE 3816 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 3817 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdlib.h +FILE 3818 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 3819 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 3820 f:\sp\public\sdk\inc\specstrings.h +FILE 3821 f:\sp\public\sdk\inc\basetsd.h +FILE 3822 f:\sp\public\sdk\inc\pshpack4.h +FILE 3823 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\typeinfo +FILE 3824 f:\sp\public\sdk\inc\winnetwk.h +FILE 3825 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\exception +FILE 3826 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\xstddef +FILE 3827 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\eh.h +FILE 3828 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\yvals.h +FILE 3829 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\stdhpp\use_ansi.h +FILE 3830 f:\sp\public\sdk\inc\stralign.h +FILE 3831 f:\sp\public\sdk\inc\poppack.h +FILE 3832 f:\sp\public\sdk\inc\winsvc.h +FILE 3833 f:\sp\public\sdk\inc\winuser.h +FILE 3834 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 3835 f:\sp\public\sdk\inc\windef.h +FILE 3836 f:\sp\vctools\langapi\undname\undname.h +FILE 3837 f:\sp\public\sdk\inc\ddbanned.h +FILE 3838 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\malloc.h +FILE 3839 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 3840 f:\sp\public\sdk\inc\mcx.h +FILE 3841 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 3842 f:\sp\public\sdk\inc\pshpack8.h +FILE 3843 f:\sp\public\sdk\inc\guiddef.h +FILE 3844 f:\sp\public\sdk\inc\poppack.h +FILE 3845 f:\sp\public\sdk\inc\winsvc.h +FILE 3846 f:\sp\public\sdk\inc\windows.h +FILE 3847 f:\sp\public\sdk\inc\winuser.h +FILE 3848 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdarg.h +FILE 3849 f:\sp\public\sdk\inc\windef.h +FILE 3850 f:\sp\public\sdk\inc\mcx.h +FILE 3851 f:\sp\public\sdk\inc\pshpack8.h +FILE 3852 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stdlib.h +FILE 3853 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\limits.h +FILE 3854 f:\sp\public\sdk\inc\guiddef.h +FILE 3855 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\eh\hooks.cpp +FILE 3856 f:\sp\public\sdk\inc\winnls.h +FILE 3857 f:\sp\public\sdk\inc\pshpack1.h +FILE 3858 f:\sp\public\sdk\inc\winnt.h +FILE 3859 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ctype.h +FILE 3860 f:\sp\public\sdk\inc\winerror.h +FILE 3861 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\mtdll.h +FILE 3862 f:\sp\public\sdk\inc\winreg.h +FILE 3863 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\string.h +FILE 3864 f:\sp\public\sdk\inc\tvout.h +FILE 3865 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\eh.h +FILE 3866 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\errno.h +FILE 3867 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\stddef.h +FILE 3868 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdefs.h +FILE 3869 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\sal.h +FILE 3870 f:\sp\public\sdk\inc\wincon.h +FILE 3871 f:\sp\public\sdk\inc\imm.h +FILE 3872 f:\sp\public\sdk\inc\winbase.h +FILE 3873 f:\sp\public\sdk\inc\wingdi.h +FILE 3874 f:\sp\public\sdk\inc\winver.h +FILE 3875 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ehhooks.h +FILE 3876 f:\sp\public\sdk\inc\pshpack2.h +FILE 3877 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\excpt.h +FILE 3878 f:\sp\public\sdk\inc\reason.h +FILE 3879 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\ehassert.h +FILE 3880 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\internal.h +FILE 3881 f:\sp\public\sdk\inc\specstrings.h +FILE 3882 f:\sp\public\sdk\inc\basetsd.h +FILE 3883 f:\sp\public\sdk\inc\pshpack4.h +FILE 3884 f:\sp\public\sdk\inc\ddbanned.h +FILE 3885 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\vadefs.h +FILE 3886 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\cruntime.h +FILE 3887 f:\sp\public\sdk\inc\winnetwk.h +FILE 3888 f:\sp\vctools\crt_bld\self_x86\crt\prebuild\h\crtdbg.h +FILE 3889 f:\sp\public\sdk\inc\stralign.h +FILE 3890 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3891 f:\sp\public\sdk\inc\pshpack4.h +FILE 3892 f:\sp\public\sdk\inc\reason.h +FILE 3893 f:\sp\public\sdk\inc\wincon.h +FILE 3894 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3895 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3896 f:\sp\public\sdk\inc\poppack.h +FILE 3897 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3898 f:\sp\public\sdk\inc\mcx.h +FILE 3899 f:\sp\public\sdk\inc\winuser.h +FILE 3900 f:\sp\public\sdk\inc\winnls.h +FILE 3901 f:\sp\public\sdk\inc\stralign.h +FILE 3902 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3903 f:\sp\public\sdk\inc\windef.h +FILE 3904 f:\sp\public\sdk\inc\tvout.h +FILE 3905 f:\sp\public\sdk\inc\winsvc.h +FILE 3906 f:\sp\public\sdk\inc\wingdi.h +FILE 3907 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3908 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3909 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3910 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3911 f:\sp\public\sdk\inc\winnt.h +FILE 3912 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3913 f:\sp\public\sdk\inc\winnetwk.h +FILE 3914 f:\sp\public\sdk\inc\imm.h +FILE 3915 f:\sp\vctools\crt_bld\self_x86\crt\src\dosmap.c +FILE 3916 f:\sp\public\sdk\inc\winbase.h +FILE 3917 f:\sp\public\sdk\inc\winerror.h +FILE 3918 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3919 f:\sp\public\sdk\inc\pshpack1.h +FILE 3920 f:\sp\public\sdk\inc\pshpack8.h +FILE 3921 f:\sp\public\sdk\inc\winver.h +FILE 3922 f:\sp\public\sdk\inc\ddbanned.h +FILE 3923 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3924 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3925 f:\sp\public\sdk\inc\pshpack2.h +FILE 3926 f:\sp\public\sdk\inc\winreg.h +FILE 3927 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 3928 f:\sp\public\sdk\inc\guiddef.h +FILE 3929 f:\sp\public\sdk\inc\windows.h +FILE 3930 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3931 f:\sp\public\sdk\inc\specstrings.h +FILE 3932 f:\sp\public\sdk\inc\basetsd.h +FILE 3933 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 3934 f:\sp\public\sdk\inc\mcx.h +FILE 3935 f:\sp\public\sdk\inc\pshpack8.h +FILE 3936 f:\sp\public\sdk\inc\guiddef.h +FILE 3937 f:\sp\public\sdk\inc\winnt.h +FILE 3938 f:\sp\public\sdk\inc\winnls.h +FILE 3939 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 3940 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 3941 f:\sp\public\sdk\inc\pshpack1.h +FILE 3942 f:\sp\public\sdk\inc\winerror.h +FILE 3943 f:\sp\vctools\crt_bld\self_x86\crt\src\tolower.c +FILE 3944 f:\sp\public\sdk\inc\winreg.h +FILE 3945 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3946 f:\sp\public\sdk\inc\tvout.h +FILE 3947 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3948 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3949 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 3950 f:\sp\public\sdk\inc\wincon.h +FILE 3951 f:\sp\vctools\crt_bld\self_x86\crt\src\stddef.h +FILE 3952 f:\sp\public\sdk\inc\imm.h +FILE 3953 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3954 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 3955 f:\sp\public\sdk\inc\winbase.h +FILE 3956 f:\sp\public\sdk\inc\wingdi.h +FILE 3957 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3958 f:\sp\public\sdk\inc\winver.h +FILE 3959 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 3960 f:\sp\public\sdk\inc\windows.h +FILE 3961 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3962 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 3963 f:\sp\public\sdk\inc\pshpack2.h +FILE 3964 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 3965 f:\sp\public\sdk\inc\reason.h +FILE 3966 f:\sp\public\sdk\inc\specstrings.h +FILE 3967 f:\sp\public\sdk\inc\basetsd.h +FILE 3968 f:\sp\public\sdk\inc\pshpack4.h +FILE 3969 f:\sp\public\sdk\inc\winnetwk.h +FILE 3970 f:\sp\public\sdk\inc\ddbanned.h +FILE 3971 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 3972 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 3973 f:\sp\public\sdk\inc\stralign.h +FILE 3974 f:\sp\public\sdk\inc\poppack.h +FILE 3975 f:\sp\public\sdk\inc\winsvc.h +FILE 3976 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 3977 f:\sp\public\sdk\inc\windef.h +FILE 3978 f:\sp\public\sdk\inc\winuser.h +FILE 3979 f:\sp\public\sdk\inc\winsvc.h +FILE 3980 f:\sp\public\sdk\inc\winuser.h +FILE 3981 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 3982 f:\sp\public\sdk\inc\mcx.h +FILE 3983 f:\sp\public\sdk\inc\pshpack8.h +FILE 3984 f:\sp\public\sdk\inc\guiddef.h +FILE 3985 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 3986 f:\sp\public\sdk\inc\windows.h +FILE 3987 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 3988 f:\sp\public\sdk\inc\winnls.h +FILE 3989 f:\sp\vctools\crt_bld\self_x86\crt\src\strtoq.c +FILE 3990 f:\sp\public\sdk\inc\pshpack1.h +FILE 3991 f:\sp\public\sdk\inc\winerror.h +FILE 3992 f:\sp\public\sdk\inc\winreg.h +FILE 3993 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 3994 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 3995 f:\sp\public\sdk\inc\tvout.h +FILE 3996 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 3997 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 3998 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 3999 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4000 f:\sp\public\sdk\inc\wincon.h +FILE 4001 f:\sp\public\sdk\inc\imm.h +FILE 4002 f:\sp\public\sdk\inc\winbase.h +FILE 4003 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4004 f:\sp\public\sdk\inc\wingdi.h +FILE 4005 f:\sp\public\sdk\inc\windef.h +FILE 4006 f:\sp\public\sdk\inc\winver.h +FILE 4007 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 4008 f:\sp\public\sdk\inc\pshpack2.h +FILE 4009 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4010 f:\sp\public\sdk\inc\reason.h +FILE 4011 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4012 f:\sp\public\sdk\inc\winnt.h +FILE 4013 f:\sp\public\sdk\inc\specstrings.h +FILE 4014 f:\sp\public\sdk\inc\basetsd.h +FILE 4015 f:\sp\public\sdk\inc\pshpack4.h +FILE 4016 f:\sp\public\sdk\inc\ddbanned.h +FILE 4017 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4018 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4019 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4020 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4021 f:\sp\public\sdk\inc\winnetwk.h +FILE 4022 f:\sp\public\sdk\inc\stralign.h +FILE 4023 f:\sp\public\sdk\inc\poppack.h +FILE 4024 f:\sp\public\sdk\inc\winsvc.h +FILE 4025 f:\sp\public\sdk\inc\winuser.h +FILE 4026 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4027 f:\sp\public\sdk\inc\mcx.h +FILE 4028 f:\sp\public\sdk\inc\pshpack8.h +FILE 4029 f:\sp\public\sdk\inc\guiddef.h +FILE 4030 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 4031 f:\sp\public\sdk\inc\windows.h +FILE 4032 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4033 f:\sp\public\sdk\inc\winnls.h +FILE 4034 f:\sp\vctools\crt_bld\self_x86\crt\src\strtol.c +FILE 4035 f:\sp\public\sdk\inc\pshpack1.h +FILE 4036 f:\sp\public\sdk\inc\winerror.h +FILE 4037 f:\sp\public\sdk\inc\winreg.h +FILE 4038 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4039 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 4040 f:\sp\public\sdk\inc\tvout.h +FILE 4041 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 4042 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 4043 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4044 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4045 f:\sp\public\sdk\inc\wincon.h +FILE 4046 f:\sp\public\sdk\inc\imm.h +FILE 4047 f:\sp\public\sdk\inc\winbase.h +FILE 4048 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4049 f:\sp\public\sdk\inc\wingdi.h +FILE 4050 f:\sp\public\sdk\inc\windef.h +FILE 4051 f:\sp\public\sdk\inc\winver.h +FILE 4052 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 4053 f:\sp\public\sdk\inc\pshpack2.h +FILE 4054 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4055 f:\sp\public\sdk\inc\reason.h +FILE 4056 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4057 f:\sp\public\sdk\inc\winnt.h +FILE 4058 f:\sp\public\sdk\inc\specstrings.h +FILE 4059 f:\sp\public\sdk\inc\basetsd.h +FILE 4060 f:\sp\public\sdk\inc\pshpack4.h +FILE 4061 f:\sp\public\sdk\inc\ddbanned.h +FILE 4062 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4063 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4064 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4065 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4066 f:\sp\public\sdk\inc\winnetwk.h +FILE 4067 f:\sp\public\sdk\inc\stralign.h +FILE 4068 f:\sp\public\sdk\inc\poppack.h +FILE 4069 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 4070 f:\sp\public\sdk\inc\winreg.h +FILE 4071 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4072 f:\sp\public\sdk\inc\tvout.h +FILE 4073 f:\sp\vctools\crt_bld\self_x86\crt\src\dbgint.h +FILE 4074 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 4075 f:\sp\public\sdk\inc\wincon.h +FILE 4076 f:\sp\public\sdk\inc\imm.h +FILE 4077 f:\sp\public\sdk\inc\winbase.h +FILE 4078 f:\sp\vctools\crt_bld\self_x86\crt\src\isctype.c +FILE 4079 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4080 f:\sp\public\sdk\inc\wingdi.h +FILE 4081 f:\sp\public\sdk\inc\windef.h +FILE 4082 f:\sp\public\sdk\inc\winver.h +FILE 4083 f:\sp\public\sdk\inc\pshpack2.h +FILE 4084 f:\sp\public\sdk\inc\reason.h +FILE 4085 f:\sp\public\sdk\inc\winnt.h +FILE 4086 f:\sp\public\sdk\inc\specstrings.h +FILE 4087 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 4088 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 4089 f:\sp\public\sdk\inc\basetsd.h +FILE 4090 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4091 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4092 f:\sp\public\sdk\inc\pshpack4.h +FILE 4093 f:\sp\public\sdk\inc\winnetwk.h +FILE 4094 f:\sp\public\sdk\inc\stralign.h +FILE 4095 f:\sp\public\sdk\inc\poppack.h +FILE 4096 f:\sp\public\sdk\inc\winsvc.h +FILE 4097 f:\sp\public\sdk\inc\winuser.h +FILE 4098 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4099 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4100 f:\sp\public\sdk\inc\mcx.h +FILE 4101 f:\sp\public\sdk\inc\pshpack8.h +FILE 4102 f:\sp\public\sdk\inc\guiddef.h +FILE 4103 f:\sp\public\sdk\inc\ddbanned.h +FILE 4104 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4105 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 4106 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4107 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4108 f:\sp\public\sdk\inc\windows.h +FILE 4109 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4110 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4111 f:\sp\public\sdk\inc\winnls.h +FILE 4112 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4113 f:\sp\public\sdk\inc\pshpack1.h +FILE 4114 f:\sp\public\sdk\inc\winerror.h +FILE 4115 f:\sp\vctools\crt_bld\self_x86\crt\src\swprintf.inl +FILE 4116 f:\sp\public\sdk\inc\winreg.h +FILE 4117 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4118 f:\sp\public\sdk\inc\tvout.h +FILE 4119 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4120 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4121 f:\sp\public\sdk\inc\wincon.h +FILE 4122 f:\sp\public\sdk\inc\imm.h +FILE 4123 f:\sp\public\sdk\inc\winbase.h +FILE 4124 f:\sp\vctools\crt_bld\self_x86\crt\src\iswctype.c +FILE 4125 f:\sp\public\sdk\inc\wingdi.h +FILE 4126 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4127 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4128 f:\sp\public\sdk\inc\winver.h +FILE 4129 f:\sp\vctools\crt_bld\self_x86\crt\src\awint.h +FILE 4130 f:\sp\public\sdk\inc\windows.h +FILE 4131 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4132 f:\sp\public\sdk\inc\pshpack2.h +FILE 4133 f:\sp\public\sdk\inc\reason.h +FILE 4134 f:\sp\public\sdk\inc\specstrings.h +FILE 4135 f:\sp\vctools\crt_bld\self_x86\crt\src\stdio.h +FILE 4136 f:\sp\public\sdk\inc\basetsd.h +FILE 4137 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4138 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4139 f:\sp\public\sdk\inc\pshpack4.h +FILE 4140 f:\sp\public\sdk\inc\winnetwk.h +FILE 4141 f:\sp\public\sdk\inc\stralign.h +FILE 4142 f:\sp\public\sdk\inc\poppack.h +FILE 4143 f:\sp\public\sdk\inc\winsvc.h +FILE 4144 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4145 f:\sp\public\sdk\inc\windef.h +FILE 4146 f:\sp\public\sdk\inc\winuser.h +FILE 4147 f:\sp\public\sdk\inc\mcx.h +FILE 4148 f:\sp\public\sdk\inc\pshpack8.h +FILE 4149 f:\sp\public\sdk\inc\guiddef.h +FILE 4150 f:\sp\public\sdk\inc\ddbanned.h +FILE 4151 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4152 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4153 f:\sp\public\sdk\inc\winnt.h +FILE 4154 f:\sp\public\sdk\inc\winnls.h +FILE 4155 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4156 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 4157 f:\sp\public\sdk\inc\pshpack1.h +FILE 4158 f:\sp\public\sdk\inc\winerror.h +FILE 4159 f:\sp\public\sdk\inc\winsvc.h +FILE 4160 f:\sp\public\sdk\inc\winuser.h +FILE 4161 f:\sp\public\sdk\inc\mcx.h +FILE 4162 f:\sp\public\sdk\inc\pshpack8.h +FILE 4163 f:\sp\public\sdk\inc\guiddef.h +FILE 4164 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 4165 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4166 f:\sp\public\sdk\inc\windows.h +FILE 4167 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4168 f:\sp\public\sdk\inc\winnls.h +FILE 4169 f:\sp\vctools\crt_bld\self_x86\crt\src\_wctype.c +FILE 4170 f:\sp\public\sdk\inc\pshpack1.h +FILE 4171 f:\sp\public\sdk\inc\winerror.h +FILE 4172 f:\sp\public\sdk\inc\winreg.h +FILE 4173 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4174 f:\sp\public\sdk\inc\tvout.h +FILE 4175 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4176 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4177 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4178 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4179 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4180 f:\sp\public\sdk\inc\wincon.h +FILE 4181 f:\sp\public\sdk\inc\imm.h +FILE 4182 f:\sp\public\sdk\inc\winbase.h +FILE 4183 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4184 f:\sp\public\sdk\inc\wingdi.h +FILE 4185 f:\sp\public\sdk\inc\windef.h +FILE 4186 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 4187 f:\sp\public\sdk\inc\winver.h +FILE 4188 f:\sp\public\sdk\inc\pshpack2.h +FILE 4189 f:\sp\public\sdk\inc\reason.h +FILE 4190 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 4191 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4192 f:\sp\public\sdk\inc\winnt.h +FILE 4193 f:\sp\public\sdk\inc\specstrings.h +FILE 4194 f:\sp\public\sdk\inc\basetsd.h +FILE 4195 f:\sp\public\sdk\inc\pshpack4.h +FILE 4196 f:\sp\public\sdk\inc\ddbanned.h +FILE 4197 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4198 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4199 f:\sp\public\sdk\inc\winnetwk.h +FILE 4200 f:\sp\public\sdk\inc\stralign.h +FILE 4201 f:\sp\public\sdk\inc\poppack.h +FILE 4202 f:\sp\public\sdk\inc\mcx.h +FILE 4203 f:\sp\public\sdk\inc\pshpack8.h +FILE 4204 f:\sp\public\sdk\inc\guiddef.h +FILE 4205 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4206 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4207 f:\sp\public\sdk\inc\windows.h +FILE 4208 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4209 f:\sp\public\sdk\inc\winnls.h +FILE 4210 f:\sp\public\sdk\inc\pshpack1.h +FILE 4211 f:\sp\public\sdk\inc\winerror.h +FILE 4212 f:\sp\public\sdk\inc\winreg.h +FILE 4213 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4214 f:\sp\vctools\crt_bld\self_x86\crt\src\_ctype.c +FILE 4215 f:\sp\public\sdk\inc\tvout.h +FILE 4216 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4217 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4218 f:\sp\public\sdk\inc\wincon.h +FILE 4219 f:\sp\public\sdk\inc\imm.h +FILE 4220 f:\sp\public\sdk\inc\winbase.h +FILE 4221 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4222 f:\sp\public\sdk\inc\wingdi.h +FILE 4223 f:\sp\public\sdk\inc\windef.h +FILE 4224 f:\sp\public\sdk\inc\winver.h +FILE 4225 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4226 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4227 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4228 f:\sp\public\sdk\inc\pshpack2.h +FILE 4229 f:\sp\public\sdk\inc\reason.h +FILE 4230 f:\sp\public\sdk\inc\winnt.h +FILE 4231 f:\sp\vctools\crt_bld\self_x86\crt\src\locale.h +FILE 4232 f:\sp\public\sdk\inc\specstrings.h +FILE 4233 f:\sp\public\sdk\inc\basetsd.h +FILE 4234 f:\sp\public\sdk\inc\pshpack4.h +FILE 4235 f:\sp\public\sdk\inc\winnetwk.h +FILE 4236 f:\sp\public\sdk\inc\stralign.h +FILE 4237 f:\sp\public\sdk\inc\poppack.h +FILE 4238 f:\sp\public\sdk\inc\winsvc.h +FILE 4239 f:\sp\public\sdk\inc\ddbanned.h +FILE 4240 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4241 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4242 f:\sp\public\sdk\inc\winuser.h +FILE 4243 f:\sp\public\sdk\inc\pshpack2.h +FILE 4244 f:\sp\public\sdk\inc\mcx.h +FILE 4245 f:\sp\public\sdk\inc\winuser.h +FILE 4246 f:\sp\public\sdk\inc\winnls.h +FILE 4247 f:\sp\public\sdk\inc\stralign.h +FILE 4248 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4249 f:\sp\public\sdk\inc\windef.h +FILE 4250 f:\sp\public\sdk\inc\tvout.h +FILE 4251 f:\sp\public\sdk\inc\winsvc.h +FILE 4252 f:\sp\vctools\crt_bld\self_x86\crt\src\internal_securecrt.h +FILE 4253 f:\sp\public\sdk\inc\wingdi.h +FILE 4254 f:\sp\public\sdk\inc\pshpack4.h +FILE 4255 f:\sp\public\sdk\inc\poppack.h +FILE 4256 f:\sp\public\sdk\inc\winnt.h +FILE 4257 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4258 f:\sp\public\sdk\inc\winnetwk.h +FILE 4259 f:\sp\public\sdk\inc\imm.h +FILE 4260 f:\sp\vctools\crt_bld\self_x86\crt\src\xtoa.c +FILE 4261 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 4262 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdbg.h +FILE 4263 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4264 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4265 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 4266 f:\sp\vctools\crt_bld\self_x86\crt\src\xtoas.c +FILE 4267 f:\sp\public\sdk\inc\pshpack1.h +FILE 4268 f:\sp\public\sdk\inc\winver.h +FILE 4269 f:\sp\vctools\crt_bld\self_x86\crt\src\errno.h +FILE 4270 f:\sp\public\sdk\inc\guiddef.h +FILE 4271 f:\sp\public\sdk\inc\specstrings.h +FILE 4272 f:\sp\public\sdk\inc\basetsd.h +FILE 4273 f:\sp\public\sdk\inc\winreg.h +FILE 4274 f:\sp\public\sdk\inc\ddbanned.h +FILE 4275 f:\sp\vctools\crt_bld\self_x86\crt\src\internal.h +FILE 4276 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4277 f:\sp\public\sdk\inc\windows.h +FILE 4278 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4279 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4280 f:\sp\public\sdk\inc\winbase.h +FILE 4281 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4282 f:\sp\public\sdk\inc\winerror.h +FILE 4283 f:\sp\public\sdk\inc\pshpack8.h +FILE 4284 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 4285 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4286 f:\sp\public\sdk\inc\reason.h +FILE 4287 f:\sp\public\sdk\inc\wincon.h +FILE 4288 f:\sp\public\sdk\inc\poppack.h +FILE 4289 f:\sp\public\sdk\inc\winnetwk.h +FILE 4290 f:\sp\public\sdk\inc\imm.h +FILE 4291 f:\sp\vctools\crt_bld\self_x86\crt\src\stdarg.h +FILE 4292 f:\sp\public\sdk\inc\windef.h +FILE 4293 f:\sp\public\sdk\inc\pshpack1.h +FILE 4294 f:\sp\public\sdk\inc\winver.h +FILE 4295 f:\sp\vctools\crt_bld\self_x86\crt\src\mtdll.h +FILE 4296 f:\sp\vctools\crt_bld\self_x86\crt\src\crtdefs.h +FILE 4297 f:\sp\vctools\crt_bld\self_x86\crt\src\sal.h +FILE 4298 f:\sp\public\sdk\inc\winnt.h +FILE 4299 f:\sp\vctools\crt_bld\self_x86\crt\src\ctype.h +FILE 4300 f:\sp\public\sdk\inc\winreg.h +FILE 4301 f:\sp\vctools\crt_bld\self_x86\crt\src\atox.c +FILE 4302 f:\sp\public\sdk\inc\winbase.h +FILE 4303 f:\sp\public\sdk\inc\winerror.h +FILE 4304 f:\sp\public\sdk\inc\pshpack8.h +FILE 4305 f:\sp\vctools\crt_bld\self_x86\crt\src\setlocal.h +FILE 4306 f:\sp\vctools\crt_bld\self_x86\crt\src\oscalls.h +FILE 4307 f:\sp\public\sdk\inc\reason.h +FILE 4308 f:\sp\public\sdk\inc\wincon.h +FILE 4309 f:\sp\public\sdk\inc\ddbanned.h +FILE 4310 f:\sp\vctools\crt_bld\self_x86\crt\src\vadefs.h +FILE 4311 f:\sp\vctools\crt_bld\self_x86\crt\src\cruntime.h +FILE 4312 f:\sp\public\sdk\inc\pshpack2.h +FILE 4313 f:\sp\vctools\crt_bld\self_x86\crt\src\tchar.h +FILE 4314 f:\sp\vctools\crt_bld\self_x86\crt\src\stdlib.h +FILE 4315 f:\sp\vctools\crt_bld\self_x86\crt\src\mbstring.h +FILE 4316 f:\sp\public\sdk\inc\mcx.h +FILE 4317 f:\sp\public\sdk\inc\winuser.h +FILE 4318 f:\sp\vctools\crt_bld\self_x86\crt\src\limits.h +FILE 4319 f:\sp\public\sdk\inc\winnls.h +FILE 4320 f:\sp\public\sdk\inc\guiddef.h +FILE 4321 f:\sp\public\sdk\inc\windows.h +FILE 4322 f:\sp\vctools\crt_bld\self_x86\crt\src\excpt.h +FILE 4323 f:\sp\vctools\crt_bld\self_x86\crt\src\mbctype.h +FILE 4324 f:\sp\public\sdk\inc\specstrings.h +FILE 4325 f:\sp\public\sdk\inc\basetsd.h +FILE 4326 f:\sp\public\sdk\inc\stralign.h +FILE 4327 f:\sp\public\sdk\inc\tvout.h +FILE 4328 f:\sp\public\sdk\inc\winsvc.h +FILE 4329 f:\sp\vctools\crt_bld\self_x86\crt\src\string.h +FILE 4330 f:\sp\public\sdk\inc\wingdi.h +FILE 4331 f:\sp\public\sdk\inc\pshpack4.h +PUBLIC 1005 0 @ILT+0(?h@C@google_breakpad@@SAPADABV12@@Z) +PUBLIC 100a 0 @ILT+5(?set_member@C@google_breakpad@@QAEXH@Z) +PUBLIC 100f 0 @ILT+10(??_EC@google_breakpad@@UAEPAXI@Z) +PUBLIC 1014 0 @ILT+15(??_EC@google_breakpad@@UAEPAXI@Z) +PUBLIC 1019 0 @ILT+20(?f@C@google_breakpad@@QAEXXZ) +PUBLIC 101e 0 @ILT+25(_main) +PUBLIC 1023 0 @ILT+30(??0C@google_breakpad@@QAE@XZ) +PUBLIC 1028 0 @ILT+35(??1C@google_breakpad@@UAE@XZ) +PUBLIC 102d 0 @ILT+40(?g@C@google_breakpad@@UAEHXZ) +FUNC 1060 54 8 main +1060 6 57 1 +1066 8 58 1 +106e e 59 1 +107c 8 60 1 +1084 b 61 1 +108f f 62 1 +109e 12 64 1 +10b0 4 65 1 +FUNC 10c0 a 0 google_breakpad::i +10c0 3 51 1 +10c3 5 52 1 +10c8 2 53 1 +FUNC 10f0 21 0 google_breakpad::C::C() +10f0 21 37 1 +FUNC 1120 14 0 google_breakpad::C::~C() +1120 14 38 1 +FUNC 1140 16 8 google_breakpad::C::set_member(int) +1140 16 40 1 +FUNC 1160 1e 0 google_breakpad::C::f() +1160 1e 43 1 +FUNC 1190 10 0 google_breakpad::C::g() +1190 10 44 1 +FUNC 11b0 7 4 google_breakpad::C::h(google_breakpad::C const &) +11b0 7 45 1 +FUNC 11c0 2c 0 google_breakpad::C::`vector deleting destructor'(unsigned int) +FUNC 11f7 f 4 type_info::name(__type_info_node *) +11f7 0 44 3806 +11f7 c 45 3806 +1203 3 46 3806 +FUNC 1206 e 0 type_info::~type_info() +1206 0 49 3806 +1206 d 50 3806 +1213 1 51 3806 +FUNC 1214 1c 0 type_info::`vector deleting destructor'(unsigned int) +FUNC 1230 f 4 type_info::_name_internal_method(__type_info_node *) +1230 0 54 3806 +1230 c 55 3806 +123c 3 56 3806 +FUNC 123f 8 0 type_info::_type_info_dtor_internal_method() +123f 0 59 3806 +123f 7 60 3806 +1246 1 61 3806 +FUNC 1247 1b 4 type_info::operator==(type_info const &) +1247 0 89 3806 +1247 18 90 3806 +125f 3 91 3806 +FUNC 1262 1c 4 type_info::operator!=(type_info const &) +1262 0 98 3806 +1262 19 99 3806 +127b 3 100 3806 +FUNC 127e 1f 4 type_info::before(type_info const &) +127e 0 103 3806 +127e 1c 104 3806 +129a 3 105 3806 +FUNC 129d 4 0 type_info::raw_name() +129d 0 108 3806 +129d 3 109 3806 +12a0 1 110 3806 +FUNC 12a1 b 4 type_info::type_info(type_info const &) +12a1 8 113 3806 +12a9 3 123 3806 +FUNC 12ac 5 4 type_info::operator=(type_info const &) +12ac 2 127 3806 +12ae 3 135 3806 +FUNC 12b1 5 4 operator delete(void *) +12b1 0 20 3214 +12b1 5 23 3214 +FUNC 12b6 a 4 _set_osplatform +12b6 a 385 1009 +FUNC 12c0 a 4 _set_osver +12c0 a 386 1009 +FUNC 12ca a 4 _set_winver +12ca a 387 1009 +FUNC 12d4 a 4 _set_winmajor +12d4 a 388 1009 +FUNC 12de a 4 _set_winminor +12de a 389 1009 +FUNC 12e8 24 4 fast_error_exit +12e8 0 375 1022 +12e8 9 384 1022 +12f1 5 386 1022 +12f6 9 388 1022 +12ff c 389 1022 +130b 1 390 1022 +FUNC 130c 41 0 check_managed_app +130c 0 413 1022 +130c b 418 1022 +1317 5 422 1022 +131c a 424 1022 +1326 2 425 1022 +1328 9 427 1022 +1331 2 428 1022 +1333 7 433 1022 +133a 2 434 1022 +133c d 437 1022 +1349 1 438 1022 +134a 2 419 1022 +134c 1 438 1022 +FUNC 134d 1b6 0 __tmainCRTStartup +134d c 203 1022 +1359 19 233 1022 +1372 4 234 1022 +1376 8 235 1022 +137e a 236 1022 +1388 2 242 1022 +138a 7 243 1022 +1391 3 244 1022 +1394 4 243 1022 +1398 9 244 1022 +13a1 2 245 1022 +13a3 6 248 1022 +13a9 6 249 1022 +13af 6 250 1022 +13b5 9 256 1022 +13be 9 257 1022 +13c7 8 258 1022 +13cf 6 259 1022 +13d5 d 260 1022 +13e2 6 262 1022 +13e8 5 263 1022 +13ed 6 264 1022 +13f3 6 265 1022 +13f9 6 266 1022 +13ff 8 271 1022 +1407 c 273 1022 +1413 8 274 1022 +141b 9 276 1022 +1424 8 277 1022 +142c 5 286 1022 +1431 4 294 1022 +1435 9 296 1022 +143e 8 297 1022 +1446 b 300 1022 +1451 a 303 1022 +145b 9 305 1022 +1464 8 306 1022 +146c 9 307 1022 +1475 8 308 1022 +147d 8 310 1022 +1485 4 311 1022 +1489 7 312 1022 +1490 a 326 1022 +149a 18 327 1022 +14b2 6 330 1022 +14b8 6 331 1022 +14be 5 333 1022 +14c3 2 335 1022 +14c5 17 336 1022 +14dc 6 342 1022 +14e2 6 344 1022 +14e8 6 345 1022 +14ee 5 347 1022 +14f3 7 349 1022 +14fa 3 351 1022 +14fd 6 352 1022 +FUNC 1503 a 0 mainCRTStartup +1503 0 186 1022 +1503 5 193 1022 +1508 5 195 1022 +FUNC 150d 22 18 _invoke_watson_if_error +150d 3 754 3783 +1510 6 755 3783 +1516 17 759 3783 +152d 2 760 3783 +FUNC 152f 70 4 type_info::_Type_info_dtor(type_info *) +152f c 62 3748 +153b 8 63 3748 +1543 4 64 3748 +1547 a 65 3748 +1551 d 70 3748 +155e 4 72 3748 +1562 4 74 3748 +1566 6 79 3748 +156c 7 80 3748 +1573 9 94 3748 +157c 4 101 3748 +1580 c 103 3748 +158c 6 107 3748 +1592 2 83 3748 +1594 2 72 3748 +1596 9 104 3748 +FUNC 159f f5 8 type_info::_Name_base(type_info const *,__type_info_node *) +159f c 109 3748 +15ab e 113 3748 +15b9 24 124 3748 +15dd 7 125 3748 +15e4 16 132 3748 +15fa 2 133 3748 +15fc 5 132 3748 +1601 b 136 3748 +160c 5 142 3748 +1611 a 149 3748 +161b 4 150 3748 +161f 11 157 3748 +1630 20 158 3748 +1650 5 159 3748 +1655 9 165 3748 +165e 3 166 3748 +1661 2 167 3748 +1663 7 173 3748 +166a 9 180 3748 +1673 c 181 3748 +167f 3 188 3748 +1682 6 189 3748 +1688 3 181 3748 +168b 9 182 3748 +FUNC 1694 70 4 type_info::_Type_info_dtor_internal(type_info *) +1694 c 197 3748 +16a0 8 198 3748 +16a8 4 199 3748 +16ac a 200 3748 +16b6 d 205 3748 +16c3 4 207 3748 +16c7 4 209 3748 +16cb 6 214 3748 +16d1 7 215 3748 +16d8 9 229 3748 +16e1 4 236 3748 +16e5 c 238 3748 +16f1 6 242 3748 +16f7 2 218 3748 +16f9 2 207 3748 +16fb 9 239 3748 +FUNC 1704 31 10 __unDNameHelper +1704 3 249 3748 +1707 7 250 3748 +170e 7 252 3748 +1715 1e 260 3748 +1733 2 261 3748 +FUNC 1735 eb 8 type_info::_Name_base_internal(type_info const *,__type_info_node *) +1735 c 265 3748 +1741 e 269 3748 +174f 1a 273 3748 +1769 7 274 3748 +1770 16 281 3748 +1786 2 282 3748 +1788 5 281 3748 +178d b 285 3748 +1798 5 291 3748 +179d a 298 3748 +17a7 4 299 3748 +17ab 11 306 3748 +17bc 20 307 3748 +17dc 5 308 3748 +17e1 9 314 3748 +17ea 3 315 3748 +17ed 2 316 3748 +17ef 7 322 3748 +17f6 9 329 3748 +17ff c 330 3748 +180b 3 337 3748 +180e 6 338 3748 +1814 3 330 3748 +1817 9 331 3748 +FUNC 1820 53 4 __clean_type_info_names_internal +1820 c 346 3748 +182c 8 347 3748 +1834 4 348 3748 +1838 6 352 3748 +183e 4 354 3748 +1842 3 356 3748 +1845 7 357 3748 +184c 8 358 3748 +1854 4 354 3748 +1858 c 359 3748 +1864 6 363 3748 +186a 9 361 3748 +FUNC 1880 88 8 strcmp +1880 0 65 593 +1880 4 73 593 +1884 4 74 593 +1888 6 76 593 +188e 2 77 593 +1890 2 81 593 +1892 2 83 593 +1894 2 84 593 +1896 2 85 593 +1898 2 86 593 +189a 3 87 593 +189d 2 88 593 +189f 2 89 593 +18a1 2 90 593 +18a3 3 92 593 +18a6 3 94 593 +18a9 2 95 593 +18ab 2 96 593 +18ad 2 97 593 +18af 3 98 593 +18b2 2 99 593 +18b4 3 100 593 +18b7 3 101 593 +18ba 2 102 593 +18bc 4 103 593 +18c0 2 107 593 +18c2 2 108 593 +18c4 2 115 593 +18c6 2 116 593 +18c8 3 117 593 +18cb 1 118 593 +18cc 6 122 593 +18d2 2 123 593 +18d4 2 125 593 +18d6 3 126 593 +18d9 2 127 593 +18db 2 128 593 +18dd 3 129 593 +18e0 2 130 593 +18e2 2 131 593 +18e4 6 133 593 +18ea 2 134 593 +18ec 3 139 593 +18ef 3 140 593 +18f2 2 141 593 +18f4 2 142 593 +18f6 2 143 593 +18f8 2 144 593 +18fa 3 145 593 +18fd 2 146 593 +18ff 2 147 593 +1901 2 148 593 +1903 3 149 593 +1906 2 150 593 +FUNC 1908 8e 4 free +1908 c 42 3545 +1914 7 47 3545 +191b 9 53 3545 +1924 8 57 3545 +192c 4 58 3545 +1930 e 60 3545 +193e 9 61 3545 +1947 c 64 3545 +1953 6 68 3545 +1959 3 70 3545 +195c 2 106 3545 +195e 9 65 3545 +1967 f 109 3545 +1976 4 110 3545 +197a 16 112 3545 +1990 6 115 3545 +FUNC 1996 3d 4 __CxxUnhandledExceptionFilter(_EXCEPTION_POINTERS *) +1996 0 67 3654 +1996 33 68 3654 +19c9 5 69 3654 +19ce 2 72 3654 +19d0 3 73 3654 +FUNC 19d3 e 0 __CxxSetUnhandledExceptionFilter +19d3 0 86 3654 +19d3 b 89 3654 +19de 2 90 3654 +19e0 1 91 3654 +FUNC 19e1 24 4 _amsg_exit +19e1 0 446 974 +19e1 5 449 974 +19e6 9 450 974 +19ef b 451 974 +19fa a 452 974 +1a04 1 453 974 +FUNC 1a05 26 4 __crtCorExitProcess +1a05 0 650 974 +1a05 b 654 974 +1a10 4 655 974 +1a14 c 656 974 +1a20 4 657 974 +1a24 6 658 974 +1a2a 1 668 974 +FUNC 1a2b 15 4 __crtExitProcess +1a2b 0 673 974 +1a2b a 674 974 +1a35 b 683 974 +FUNC 1a40 9 0 _lockexit +1a40 0 733 974 +1a40 8 734 974 +1a48 1 735 974 +FUNC 1a49 9 0 _unlockexit +1a49 0 759 974 +1a49 8 760 974 +1a51 1 761 974 +FUNC 1a52 18 4 _initterm +1a52 3 841 974 +1a55 2 855 974 +1a57 6 853 974 +1a5d 2 854 974 +1a5f 3 855 974 +1a62 7 848 974 +1a69 1 857 974 +FUNC 1a6a 20 8 _initterm_e +1a6a 1 890 974 +1a6b c 899 974 +1a77 6 904 974 +1a7d 2 905 974 +1a7f 3 906 974 +1a82 7 899 974 +1a89 1 910 974 +FUNC 1a8a 37 4 _get_osplatform +1a8a 0 929 974 +1a8a 27 931 974 +1ab1 1 939 974 +1ab2 9 934 974 +1abb 2 936 974 +1abd 3 938 974 +1ac0 1 939 974 +FUNC 1ac1 3c 4 _get_osver +1ac1 0 958 974 +1ac1 27 960 974 +1ae8 1 968 974 +1ae9 8 963 974 +1af1 8 965 974 +1af9 3 967 974 +1afc 1 968 974 +FUNC 1afd 3c 4 _get_winver +1afd 0 987 974 +1afd 27 989 974 +1b24 1 997 974 +1b25 8 992 974 +1b2d 8 994 974 +1b35 3 996 974 +1b38 1 997 974 +FUNC 1b39 3c 4 _get_winmajor +1b39 0 1016 974 +1b39 27 1018 974 +1b60 1 1026 974 +1b61 8 1021 974 +1b69 8 1023 974 +1b71 3 1025 974 +1b74 1 1026 974 +FUNC 1b75 3c 4 _get_winminor +1b75 0 1045 974 +1b75 27 1047 974 +1b9c 1 1055 974 +1b9d 8 1050 974 +1ba5 8 1052 974 +1bad 3 1054 974 +1bb0 1 1055 974 +FUNC 1bb1 37 4 _get_wpgmptr +1bb1 0 1074 974 +1bb1 27 1076 974 +1bd8 1 1085 974 +1bd9 9 1080 974 +1be2 2 1082 974 +1be4 3 1084 974 +1be7 1 1085 974 +FUNC 1be8 37 4 _get_pgmptr +1be8 0 1104 974 +1be8 27 1106 974 +1c0f 1 1115 974 +1c10 9 1110 974 +1c19 2 1112 974 +1c1b 3 1114 974 +1c1e 1 1115 974 +FUNC 1c1f 92 4 _cinit +1c1f 0 263 974 +1c1f 18 273 974 +1c37 b 275 974 +1c42 5 277 974 +1c47 f 283 974 +1c56 4 284 974 +1c5a 4 285 974 +1c5e a 288 974 +1c68 20 293 974 +1c88 1a 306 974 +1ca2 c 308 974 +1cae 2 312 974 +1cb0 1 313 974 +FUNC 1cb1 e2 c doexit +1cb1 c 499 974 +1cbd 8 517 974 +1cc5 5 518 974 +1cca b 520 974 +1cd5 6 521 974 +1cdb 8 524 974 +1ce3 5 526 974 +1ce8 e 542 974 +1cf6 12 543 974 +1d08 5 545 974 +1d0d b 546 974 +1d18 10 551 974 +1d28 9 552 974 +1d31 2 553 974 +1d33 10 558 974 +1d43 10 566 974 +1d53 c 584 974 +1d5f 6 588 974 +1d65 6 592 974 +1d6b 8 594 974 +1d73 8 596 974 +1d7b 3 584 974 +1d7e 6 585 974 +1d84 9 586 974 +1d8d 6 597 974 +FUNC 1d93 11 4 exit +1d93 0 397 974 +1d93 10 398 974 +1da3 1 399 974 +FUNC 1da4 11 4 _exit +1da4 0 405 974 +1da4 10 406 974 +1db4 1 407 974 +FUNC 1db5 f 0 _cexit +1db5 0 412 974 +1db5 e 413 974 +1dc3 1 414 974 +FUNC 1dc4 f 0 _c_exit +1dc4 0 419 974 +1dc4 e 420 974 +1dd2 1 421 974 +FUNC 1dd3 4c 0 _init_pointers +1dd3 1 786 974 +1dd4 7 787 974 +1ddb 6 789 974 +1de1 6 790 974 +1de7 6 791 974 +1ded 6 792 974 +1df3 6 793 974 +1df9 6 794 974 +1dff 6 795 974 +1e05 6 796 974 +1e0b 13 799 974 +1e1e 1 800 974 +FUNC 1e1f 1a0 4 _NMSG_WRITE +1e1f 2 174 832 +1e21 a 178 832 +1e2b f 179 832 +1e3a a 182 832 +1e44 2a 203 832 +1e6e c 215 832 +1e7a 2a 224 832 +1ea4 1e 227 832 +1ec2 26 228 832 +1ee8 d 231 832 +1ef5 b 233 832 +1f00 2f 234 832 +1f2f 20 237 832 +1f4f 22 238 832 +1f71 15 242 832 +1f86 a 205 832 +1f90 9 206 832 +1f99 24 212 832 +1fbd 2 245 832 +FUNC 1fbf 20 4 _GET_RTERRMSG +1fbf 0 268 832 +1fbf 2 271 832 +1fc1 13 272 832 +1fd4 2 275 832 +1fd6 1 276 832 +1fd7 7 273 832 +1fde 1 276 832 +FUNC 1fdf 39 0 _FF_MSGBANNER +1fdf 0 141 832 +1fdf 22 145 832 +2001 a 147 832 +200b c 148 832 +2017 1 150 832 +FUNC 2018 1 4 _initp_misc_winxfltr +2018 0 105 1166 +2018 1 106 1166 +FUNC 2019 32 4 xcptlookup +2019 0 410 1166 +2019 b 411 1166 +2024 14 418 1166 +2038 e 425 1166 +2046 2 428 1166 +2048 2 426 1166 +204a 1 429 1166 +FUNC 204b 15e 8 _XcptFilter +204b 6 206 1166 +2051 7 213 1166 +2058 8 214 1166 +2060 34 219 1166 +2094 2 221 1166 +2096 2 225 1166 +2098 3 227 1166 +209b 7 234 1166 +20a2 7 235 1166 +20a9 5 243 1166 +20ae 4 248 1166 +20b2 8 249 1166 +20ba 3 255 1166 +20bd 6 259 1166 +20c3 6 273 1166 +20c9 6 274 1166 +20cf c 283 1166 +20db 17 291 1166 +20f2 1e 294 1166 +2110 3 291 1166 +2113 c 321 1166 +211f 9 323 1166 +2128 7 325 1166 +212f 9 327 1166 +2138 7 329 1166 +213f 9 331 1166 +2148 7 333 1166 +214f 9 335 1166 +2158 7 337 1166 +215f 9 339 1166 +2168 7 341 1166 +216f 9 343 1166 +2178 7 345 1166 +217f 7 347 1166 +2186 8 356 1166 +218e 3 361 1166 +2191 2 363 1166 +2193 4 368 1166 +2197 3 369 1166 +219a 7 375 1166 +21a1 6 377 1166 +21a7 2 379 1166 +FUNC 21a9 1b 8 __CppXcptFilter +21a9 0 145 1166 +21a9 b 146 1166 +21b4 c 147 1166 +21c0 1 151 1166 +21c1 2 149 1166 +21c3 1 151 1166 +FUNC 21c4 db 0 _setenvp +21c4 1 77 694 +21c5 c 85 694 +21d1 5 86 694 +21d6 8 91 694 +21de 4 98 694 +21e2 8 99 694 +21ea 4 110 694 +21ee 1 111 694 +21ef 11 112 694 +2200 15 117 694 +2215 2 118 694 +2217 9 121 694 +2220 9 123 694 +2229 6 125 694 +222f 10 127 694 +223f 1c 133 694 +225b 3 134 694 +225e 6 121 694 +2264 b 138 694 +226f 6 139 694 +2275 2 142 694 +2277 a 149 694 +2281 7 152 694 +2288 17 153 694 +FUNC 229f a 4 _set_pgmptr +229f a 334 717 +FUNC 22a9 198 c parse_cmdline +22a9 4 218 736 +22ad 6 226 736 +22b3 8 230 736 +22bb 14 231 736 +22cf 3 250 736 +22d2 5 252 736 +22d7 5 254 736 +22dc 9 255 736 +22e5 2 256 736 +22e7 2 258 736 +22e9 4 259 736 +22ed 8 260 736 +22f5 2 262 736 +22f7 f 264 736 +2306 2 265 736 +2308 6 266 736 +230e a 267 736 +2318 1 268 736 +2319 1a 272 736 +2333 4 277 736 +2337 4 278 736 +233b 4 281 736 +233f 9 286 736 +2348 a 287 736 +2352 3 288 736 +2355 1 275 736 +2356 2 276 736 +2358 9 291 736 +2361 6 295 736 +2367 9 296 736 +2370 2 297 736 +2372 3 311 736 +2375 4 315 736 +2379 1 318 736 +237a 1 319 736 +237b 5 316 736 +2380 5 321 736 +2385 5 324 736 +238a e 325 736 +2398 2 326 736 +239a 2 327 736 +239c d 329 736 +23a9 2 332 736 +23ab 5 336 736 +23b0 4 337 736 +23b4 4 338 736 +23b8 6 339 736 +23be 3 338 736 +23c1 14 343 736 +23d5 4 348 736 +23d9 2 349 736 +23db 10 350 736 +23eb b 351 736 +23f6 2 352 736 +23f8 a 354 736 +2402 2 355 736 +2404 a 356 736 +240e 1 357 736 +240f 2 358 736 +2411 5 361 736 +2416 1 363 736 +2417 5 372 736 +241c 4 376 736 +2420 7 377 736 +2427 2 378 736 +2429 8 379 736 +2431 9 382 736 +243a 3 383 736 +243d 2 384 736 +243f 2 385 736 +FUNC 2441 b9 0 _setargv +2441 7 88 736 +2448 c 97 736 +2454 5 98 736 +2459 18 104 736 +2471 19 120 736 +248a 11 127 736 +249b 15 132 736 +24b0 a 136 736 +24ba 2 138 736 +24bc 8 140 736 +24c4 3 141 736 +24c7 2 142 736 +24c9 13 149 736 +24dc c 153 736 +24e8 6 157 736 +24ee 4 172 736 +24f2 6 134 736 +24f8 2 173 736 +FUNC 24fa 135 0 __crtGetEnvironmentStringsA +24fa 2 43 2721 +24fc 1a 57 2721 +2516 8 59 2721 +251e c 60 2721 +252a b 62 2721 +2535 e 63 2721 +2543 9 68 2721 +254c 4 71 2721 +2550 8 72 2721 +2558 7 73 2721 +255f 7 77 2721 +2566 7 78 2721 +256d 7 79 2721 +2574 1b 93 2721 +258f 13 97 2721 +25a2 11 111 2721 +25b3 a 113 2721 +25bd 8 114 2721 +25c5 7 99 2721 +25cc 4 100 2721 +25d0 6 123 2721 +25d6 2 152 2721 +25d8 a 126 2721 +25e2 6 127 2721 +25e8 4 133 2721 +25ec 5 134 2721 +25f1 5 135 2721 +25f6 5 138 2721 +25fb d 140 2721 +2608 7 141 2721 +260f 5 142 2721 +2614 b 145 2721 +261f 7 147 2721 +2626 6 149 2721 +262c 3 153 2721 +FUNC 262f 240 0 _ioinit +262f c 111 3137 +263b 5 122 3137 +2640 a 127 3137 +264a 7 128 3137 +2651 f 137 3137 +2660 6 139 3137 +2666 5 142 3137 +266b 6 143 3137 +2671 8 145 3137 +2679 4 146 3137 +267d 3 147 3137 +2680 4 148 3137 +2684 3 149 3137 +2687 4 151 3137 +268b 4 152 3137 +268f 4 153 3137 +2693 13 145 3137 +26a6 15 161 3137 +26bb 2 166 3137 +26bd 3 172 3137 +26c0 6 173 3137 +26c6 b 179 3137 +26d1 5 185 3137 +26d6 f 191 3137 +26e5 9 204 3137 +26ee 7 205 3137 +26f5 8 207 3137 +26fd 4 208 3137 +2701 3 209 3137 +2704 4 210 3137 +2708 4 211 3137 +270c 4 212 3137 +2710 4 213 3137 +2714 4 214 3137 +2718 f 207 3137 +2727 9 185 3137 +2730 2 284 3137 +2732 6 197 3137 +2738 8 221 3137 +2740 24 234 3137 +2764 15 236 3137 +2779 7 237 3137 +2780 5 238 3137 +2785 18 241 3137 +279d 3 243 3137 +27a0 d 221 3137 +27ad 2 253 3137 +27af b 255 3137 +27ba c 258 3137 +27c6 6 306 3137 +27cc 4 262 3137 +27d0 30 266 3137 +2800 2 271 3137 +2802 a 277 3137 +280c 6 278 3137 +2812 5 279 3137 +2817 4 280 3137 +281b 14 284 3137 +282f 3 286 3137 +2832 2 288 3137 +2834 4 297 3137 +2838 6 298 3137 +283e a 253 3137 +2848 c 313 3137 +2854 4 315 3137 +2858 7 128 3137 +285f a 129 3137 +2869 6 316 3137 +FUNC 286f 4c 0 _ioterm +286f 2 341 3137 +2871 5 345 3137 +2876 6 347 3137 +287c 8 353 3137 +2884 9 355 3137 +288d 11 356 3137 +289e 4 353 3137 +28a2 7 361 3137 +28a9 11 362 3137 +28ba 1 365 3137 +FUNC 28bb 24 0 _RTC_Initialize +FUNC 28df 24 0 _RTC_Terminate +FUNC 2903 6c 0 _use_encode_pointer +2903 7 66 641 +290a 2 72 641 +290c 12 75 641 +291e 7 76 641 +2925 5 78 641 +292a 7 82 641 +2931 5 85 641 +2936 e 91 641 +2944 1f 93 641 +2963 4 95 641 +2967 6 100 641 +296d 2 101 641 +FUNC 296f 6e 4 _encode_pointer +296f 1 120 641 +2970 2b 129 641 +299b 8 145 641 +29a3 d 133 641 +29b0 d 135 641 +29bd c 138 641 +29c9 4 148 641 +29cd a 150 641 +29d7 5 153 641 +29dc 1 154 641 +FUNC 29dd 9 0 _encoded_null +29dd 0 173 641 +29dd 8 174 641 +29e5 1 175 641 +FUNC 29e6 6e 4 _decode_pointer +29e6 1 194 641 +29e7 2b 203 641 +2a12 8 219 641 +2a1a d 207 641 +2a27 d 209 641 +2a34 c 212 641 +2a40 4 222 641 +2a44 a 224 641 +2a4e 5 227 641 +2a53 1 228 641 +FUNC 2a54 9 4 __crtTlsAlloc +2a54 0 240 641 +2a54 6 241 641 +2a5a 3 242 641 +FUNC 2a5d 15 4 __fls_getvalue +2a5d 0 258 641 +2a5d 12 259 641 +2a6f 3 260 641 +FUNC 2a72 6 0 __get_flsindex +2a72 0 272 641 +2a72 5 273 641 +2a77 1 274 641 +FUNC 2a78 32 0 __set_flsgetvalue +2a78 1 286 641 +2a79 e 288 641 +2a87 4 289 641 +2a8b e 291 641 +2a99 d 292 641 +2aa6 3 294 641 +2aa9 1 298 641 +FUNC 2aaa 19 8 __fls_setvalue +2aaa 0 315 641 +2aaa 16 316 641 +2ac0 3 317 641 +FUNC 2ac3 3d 0 _mtterm +2ac3 0 473 641 +2ac3 a 480 641 +2acd f 481 641 +2adc 7 482 641 +2ae3 a 485 641 +2aed 7 486 641 +2af4 7 487 641 +2afb 5 494 641 +FUNC 2b00 bf 8 _initptd +2b00 c 521 641 +2b0c e 522 641 +2b1a a 524 641 +2b24 6 525 641 +2b2a 4 527 641 +2b2e 9 529 641 +2b37 16 532 641 +2b4d 10 533 641 +2b5d 3 540 641 +2b60 7 544 641 +2b67 7 545 641 +2b6e 8 546 641 +2b76 7 547 641 +2b7d 8 551 641 +2b85 4 552 641 +2b89 6 553 641 +2b8f 4 561 641 +2b93 8 562 641 +2b9b 9 563 641 +2ba4 c 565 641 +2bb0 6 568 641 +2bb6 9 566 641 +FUNC 2bbf 77 0 _getptd_noexit +2bbf 2 588 641 +2bc1 6 592 641 +2bc7 15 600 641 +2bdc 14 608 641 +2bf0 19 610 641 +2c09 a 616 641 +2c13 6 618 641 +2c19 6 619 641 +2c1f 2 621 641 +2c21 7 627 641 +2c28 2 628 641 +2c2a 8 633 641 +2c32 3 635 641 +2c35 1 636 641 +FUNC 2c36 18 0 _getptd +2c36 1 657 641 +2c37 7 658 641 +2c3e 4 659 641 +2c42 8 660 641 +2c4a 3 662 641 +2c4d 1 663 641 +FUNC 2c4e 121 4 _freefls +2c4e c 691 641 +2c5a b 702 641 +2c65 7 703 641 +2c6c 7 704 641 +2c73 7 706 641 +2c7a 7 707 641 +2c81 7 709 641 +2c88 7 710 641 +2c8f 7 712 641 +2c96 7 713 641 +2c9d 7 715 641 +2ca4 7 716 641 +2cab 7 718 641 +2cb2 7 719 641 +2cb9 a 721 641 +2cc3 7 722 641 +2cca 8 724 641 +2cd2 4 725 641 +2cd6 1a 728 641 +2cf0 7 729 641 +2cf7 c 731 641 +2d03 8 735 641 +2d0b 7 737 641 +2d12 7 738 641 +2d19 7 740 641 +2d20 15 743 641 +2d35 7 744 641 +2d3c c 747 641 +2d48 7 751 641 +2d4f 8 754 641 +2d57 3 731 641 +2d5a 9 732 641 +2d63 3 747 641 +2d66 9 748 641 +FUNC 2d6f 69 4 _freeptd +2d6f 0 778 641 +2d6f a 783 641 +2d79 1b 795 641 +2d94 13 796 641 +2da7 16 802 641 +2dbd 7 804 641 +2dc4 a 807 641 +2dce 9 811 641 +2dd7 1 813 641 +FUNC 2dd8 6 0 __threadid +2dd8 0 837 641 +2dd8 6 838 641 +FUNC 2dde 6 0 __threadhandle +2dde 0 844 641 +2dde 6 845 641 +FUNC 2de4 184 0 _mtinit +2de4 1 346 641 +2de5 d 355 641 +2df2 4 356 641 +2df6 5 357 641 +2dfb 3 358 641 +2dfe 2 444 641 +2e00 e 362 641 +2e0e d 365 641 +2e1b d 368 641 +2e28 d 371 641 +2e35 2a 372 641 +2e5f a 375 641 +2e69 1a 379 641 +2e83 25 388 641 +2ea8 5 393 641 +2ead b 400 641 +2eb8 10 401 641 +2ec8 10 402 641 +2ed8 18 403 641 +2ef0 7 410 641 +2ef7 2 412 641 +2ef9 1b 418 641 +2f14 2 420 641 +2f16 2d 428 641 +2f43 a 438 641 +2f4d 6 440 641 +2f53 6 441 641 +2f59 5 443 641 +2f5e 5 430 641 +2f63 4 389 641 +2f67 1 444 641 +FUNC 2f68 5b 0 __heap_select +2f68 6 70 3503 +2f6e 23 143 3503 +2f91 1b 144 3503 +2fac d 145 3503 +2fb9 3 146 3503 +2fbc 2 164 3503 +2fbe 3 161 3503 +2fc1 2 164 3503 +FUNC 2fc3 5a 4 _heap_init +2fc3 0 192 3503 +2fc3 20 199 3503 +2fe3 2 200 3503 +2fe5 1 240 3503 +2fe6 5 204 3503 +2feb a 206 3503 +2ff5 f 209 3503 +3004 c 211 3503 +3010 7 212 3503 +3017 2 213 3503 +3019 3 239 3503 +301c 1 240 3503 +FUNC 301d 74 0 _heap_term +301d 1 261 3503 +301e c 264 3503 +302a 1b 270 3503 +3045 f 273 3503 +3054 b 276 3503 +305f d 278 3503 +306c 11 281 3503 +307d c 300 3503 +3089 7 301 3503 +3090 1 302 3503 +FUNC 3091 6 0 _get_heap_handle +3091 0 320 3503 +3091 5 322 3503 +3096 1 323 3503 +FUNC 3098 45 0 _SEH_prolog4 +FUNC 30dd 14 0 _SEH_epilog4 +FUNC 3100 24 0 ValidateLocalCookies +FUNC 3130 196 10 _except_handler4 +FUNC 32c6 94 0 __security_init_cookie +32c6 6 97 2103 +32cc 21 114 2103 +32ed 7 116 2103 +32f4 3 117 2103 +32f7 a 127 2103 +3301 6 132 2103 +3307 8 135 2103 +330f 8 136 2103 +3317 8 137 2103 +331f 10 139 2103 +332f 2 144 2103 +3331 4 161 2103 +3335 7 163 2103 +333c 4 166 2103 +3340 7 168 2103 +3347 6 172 2103 +334d b 173 2103 +3358 2 175 2103 +FUNC 335a a 4 _initp_misc_invarg +335a 0 38 1742 +335a 9 39 1742 +3363 1 40 1742 +FUNC 3364 fc 14 _invoke_watson +3364 1c 111 1742 +3380 6 128 1742 +3386 6 129 1742 +338c 6 130 1742 +3392 3 131 1742 +3395 3 132 1742 +3398 3 133 1742 +339b 7 134 1742 +33a2 7 135 1742 +33a9 4 136 1742 +33ad 4 137 1742 +33b1 4 138 1742 +33b5 4 139 1742 +33b9 1 140 1742 +33ba 6 141 1742 +33c0 6 147 1742 +33c6 19 148 1742 +33df 3 150 1742 +33e2 13 163 1742 +33f5 6 168 1742 +33fb 13 169 1742 +340e 6 171 1742 +3414 a 174 1742 +341e a 176 1742 +3428 8 180 1742 +3430 8 181 1742 +3438 12 184 1742 +344a 16 185 1742 +FUNC 3460 22 4 _set_invalid_parameter_handler +3460 1 207 1742 +3461 b 211 1742 +346c d 212 1742 +3479 5 214 1742 +347e 3 216 1742 +3481 1 217 1742 +FUNC 3482 d 0 _get_invalid_parameter_handler +3482 0 221 1742 +3482 c 225 1742 +348e 1 228 1742 +FUNC 348f 9 14 _invoke_watson(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int) +348f 3 266 1742 +3492 1 274 1742 +3493 5 273 1742 +FUNC 3498 24 14 _invalid_parameter +3498 3 70 1742 +349b b 77 1742 +34a6 5 78 1742 +34ab 1 89 1742 +34ac 2 80 1742 +34ae 8 86 1742 +34b6 1 89 1742 +34b7 5 88 1742 +FUNC 34bc 10 0 _invalid_parameter_noinfo +34bc 0 98 1742 +34bc f 99 1742 +34cb 1 100 1742 +FUNC 34cc 9 14 _invalid_parameter(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int) +34cc 3 249 1742 +34cf 1 257 1742 +34d0 5 256 1742 +FUNC 34d5 49 0 _mtinitlocks +34d5 2 137 785 +34d7 7 144 785 +34de 11 145 785 +34ef 2 146 785 +34f1 15 148 785 +3506 6 144 785 +350c 5 157 785 +3511 d 158 785 +FUNC 351e 55 0 _mtdeletelocks +351e 1 188 785 +351f d 194 785 +352c c 196 785 +3538 3 200 785 +353b 6 206 785 +3541 f 207 785 +3550 6 215 785 +3556 c 217 785 +3562 10 221 785 +3572 1 224 785 +FUNC 3573 15 4 _unlock +3573 3 371 785 +3576 10 375 785 +3586 2 376 785 +FUNC 3588 18 4 _lockerr_exit +3588 0 403 785 +3588 c 404 785 +3594 b 405 785 +359f 1 406 785 +FUNC 35a0 c3 4 _mtinitlocknum +35a0 c 259 785 +35ac 6 261 785 +35b2 a 269 785 +35bc 5 270 785 +35c1 7 271 785 +35c8 c 272 785 +35d4 e 276 785 +35e2 4 277 785 +35e6 e 279 785 +35f4 b 280 785 +35ff 4 281 785 +3603 8 284 785 +360b 3 285 785 +360e 4 287 785 +3612 11 288 785 +3623 7 289 785 +362a b 290 785 +3635 3 291 785 +3638 2 292 785 +363a 2 293 785 +363c 2 296 785 +363e 7 297 785 +3645 c 300 785 +3651 3 304 785 +3654 6 305 785 +365a 9 301 785 +FUNC 3663 31 4 _lock +3663 3 333 785 +3666 10 338 785 +3676 b 340 785 +3681 8 341 785 +3689 9 348 785 +3692 2 349 785 +FUNC 3694 65 c strcpy_s +3694 0 13 448 +3694 30 18 448 +36c4 c 19 448 +36d0 2 21 448 +36d2 d 23 448 +36df 4 27 448 +36e3 2 29 448 +36e5 e 30 448 +36f3 5 33 448 +36f8 1 34 448 +FUNC 3700 8b 4 strlen +3700 0 54 547 +3700 4 63 547 +3704 6 64 547 +370a 2 65 547 +370c 2 69 547 +370e 3 70 547 +3711 2 71 547 +3713 2 72 547 +3715 6 73 547 +371b 2 74 547 +371d 13 76 547 +3730 2 81 547 +3732 5 82 547 +3737 2 83 547 +3739 3 84 547 +373c 2 85 547 +373e 3 86 547 +3741 5 87 547 +3746 2 88 547 +3748 3 90 547 +374b 2 91 547 +374d 2 92 547 +374f 2 93 547 +3751 2 94 547 +3753 5 95 547 +3758 2 96 547 +375a 5 97 547 +375f 2 98 547 +3761 2 99 547 +3763 3 103 547 +3766 4 104 547 +376a 2 105 547 +376c 1 106 547 +376d 3 108 547 +3770 4 109 547 +3774 2 110 547 +3776 1 111 547 +3777 3 113 547 +377a 4 114 547 +377e 2 115 547 +3780 1 116 547 +3781 3 118 547 +3784 4 119 547 +3788 2 120 547 +378a 1 121 547 +FUNC 378b 6 0 HeapManager::Block::Block() +378b 6 90 3704 +FUNC 3791 1b 8 HeapManager::Constructor(void * (*)(unsigned int),void (*)(void *)) +3791 6 100 3704 +3797 7 101 3704 +379e 5 102 3704 +37a3 3 103 3704 +37a6 3 104 3704 +37a9 3 105 3704 +FUNC 37ac 26 0 HeapManager::Destructor() +37ac 9 110 3704 +37b5 2 111 3704 +37b7 5 113 3704 +37bc 15 115 3704 +37d1 1 118 3704 +FUNC 37d2 63 0 UnDecorator::getNumberOfDimensions() +37d2 0 1663 3704 +37d2 c 1664 3704 +37de 2 1665 3704 +37e0 1 1696 3704 +37e1 a 1666 3704 +37eb d 1667 3704 +37f8 1 1696 3704 +37f9 4 1670 3704 +37fd 4 1677 3704 +3801 a 1679 3704 +380b 6 1680 3704 +3811 d 1684 3704 +381e 5 1675 3704 +3823 e 1690 3704 +3831 3 1691 3704 +3834 1 1696 3704 +FUNC 3835 474 0 UnDecorator::getTypeEncoding() +3835 f 2335 3704 +3844 2 2336 3704 +3846 5 2341 3704 +384b 9 2345 3704 +3854 c 2351 3704 +3860 9 2423 3704 +3869 2 2426 3704 +386b 2a 2427 3704 +3895 8 2450 3704 +389d 2 2451 3704 +389f 24 2454 3704 +38c3 7 2462 3704 +38ca 5 2463 3704 +38cf 6 2353 3704 +38d5 8 2358 3704 +38dd b 2362 3704 +38e8 5 2363 3704 +38ed 2 2364 3704 +38ef 5 2365 3704 +38f4 9 2369 3704 +38fd 1b 2373 3704 +3918 11 2377 3704 +3929 a 2393 3704 +3933 10 2388 3704 +3943 2 2389 3704 +3945 18 2384 3704 +395d 2 2385 3704 +395f 12 2380 3704 +3971 16 2399 3704 +3987 11 2418 3704 +3998 a 2406 3704 +39a2 5 2407 3704 +39a7 15 2410 3704 +39bc 5 2422 3704 +39c1 1b 2427 3704 +39dc a 2430 3704 +39e6 5 2431 3704 +39eb 7 2472 3704 +39f2 a 2478 3704 +39fc c 2483 3704 +3a08 5 2485 3704 +3a0d 5 2486 3704 +3a12 5 2487 3704 +3a17 5 2490 3704 +3a1c 5 2505 3704 +3a21 5 2508 3704 +3a26 5 2509 3704 +3a2b 5 2434 3704 +3a30 5 2435 3704 +3a35 1a 2427 3704 +3a4f 30 2568 3704 +3a7f 5 2529 3704 +3a84 4 2530 3704 +3a88 a 2531 3704 +3a92 2 2532 3704 +3a94 a 2533 3704 +3a9e 5 2537 3704 +3aa3 5 2538 3704 +3aa8 2 2539 3704 +3aaa 5 2540 3704 +3aaf e 2544 3704 +3abd 6 2560 3704 +3ac3 10 2555 3704 +3ad3 2 2556 3704 +3ad5 18 2551 3704 +3aed 2 2552 3704 +3aef 12 2547 3704 +3b01 2 2564 3704 +3b03 a 2442 3704 +3b0d 2 2443 3704 +3b0f a 2438 3704 +3b19 2 2439 3704 +3b1b 5 2445 3704 +3b20 c 2574 3704 +3b2c 14 2577 3704 +3b40 a 2579 3704 +3b4a 18 2586 3704 +3b62 1a 2589 3704 +3b7c 1b 2590 3704 +3b97 5 2591 3704 +3b9c 1a 2594 3704 +3bb6 1b 2595 3704 +3bd1 5 2596 3704 +3bd6 1a 2599 3704 +3bf0 10 2600 3704 +3c00 2 2601 3704 +3c02 7 2604 3704 +3c09 2 2605 3704 +3c0b a 2608 3704 +3c15 2 2609 3704 +3c17 a 2612 3704 +3c21 2 2613 3704 +3c23 a 2616 3704 +3c2d 2 2617 3704 +3c2f a 2620 3704 +3c39 2 2621 3704 +3c3b a 2624 3704 +3c45 7 2634 3704 +3c4c 7 2635 3704 +3c53 7 2637 3704 +3c5a 10 2639 3704 +3c6a 3f 2648 3704 +FUNC 3ca9 b 0 UnDecorator::doUnderScore() +3ca9 b 4259 3704 +FUNC 3cb4 d 0 UnDecorator::doMSKeywords() +3cb4 d 4260 3704 +FUNC 3cc1 e 0 UnDecorator::doPtr64() +3cc1 e 4261 3704 +FUNC 3ccf e 0 UnDecorator::doFunctionReturns() +3ccf e 4262 3704 +FUNC 3cdd e 0 UnDecorator::doAllocationModel() +3cdd e 4263 3704 +FUNC 3ceb e 0 UnDecorator::doAllocationLanguage() +3ceb e 4264 3704 +FUNC 3cf9 12 0 UnDecorator::doThisTypes() +3cf9 12 4271 3704 +FUNC 3d0b e 0 UnDecorator::doAccessSpecifiers() +3d0b e 4272 3704 +FUNC 3d19 e 0 UnDecorator::doThrowTypes() +3d19 e 4273 3704 +FUNC 3d27 e 0 UnDecorator::doMemberTypes() +3d27 e 4274 3704 +FUNC 3d35 b 0 UnDecorator::doNameOnly() +3d35 b 4279 3704 +FUNC 3d40 b 0 UnDecorator::doTypeOnly() +3d40 b 4280 3704 +FUNC 3d4b b 0 UnDecorator::haveTemplateParameters() +3d4b b 4281 3704 +FUNC 3d56 e 0 UnDecorator::doEcsu() +3d56 e 4282 3704 +FUNC 3d64 b 0 UnDecorator::doNoIdentCharCheck() +3d64 b 4283 3704 +FUNC 3d6f e 0 UnDecorator::doEllipsis() +3d6f e 4284 3704 +FUNC 3d7d 19 4 UnDecorator::UScore(Tokens) +3d7d 0 4288 3704 +3d7d 9 4293 3704 +3d86 d 4294 3704 +3d93 2 4296 3704 +3d95 1 4298 3704 +FUNC 3d96 84 8 HeapManager::getMemory(unsigned int,int) +3d96 2 134 3737 +3d98 a 137 3737 +3da2 9 139 3737 +3dab 6 140 3737 +3db1 4 146 3737 +3db5 3 147 3737 +3db8 8 149 3737 +3dc0 7 153 3737 +3dc7 2 154 3737 +3dc9 1c 159 3737 +3de5 4 164 3737 +3de9 7 168 3737 +3df0 2 169 3737 +3df2 2 170 3737 +3df4 3 171 3737 +3df7 8 175 3737 +3dff 2 182 3737 +3e01 4 179 3737 +3e05 5 183 3737 +3e0a d 187 3737 +3e17 3 190 3737 +FUNC 3e1a d 0 DName::DName() +3e1a 2 210 3737 +3e1c 3 211 3737 +3e1f 7 220 3737 +3e26 1 221 3737 +FUNC 3e27 12 4 DName::DName(DNameNode *) +3e27 2 224 3737 +3e29 4 225 3737 +3e2d 9 234 3737 +3e36 3 235 3737 +FUNC 3e39 9c 4 DName::DName(DName const &) +3e39 2 259 3737 +3e3b 17 260 3737 +3e52 10 261 3737 +3e62 d 262 3737 +3e6f d 263 3737 +3e7c 10 264 3737 +3e8c 4 265 3737 +3e90 e 266 3737 +3e9e 13 267 3737 +3eb1 10 268 3737 +3ec1 11 269 3737 +3ed2 3 270 3737 +FUNC 3ed5 a 0 DName::status() +3ed5 a 481 3737 +FUNC 3edf 5 0 DName::clearStatus() +3edf 5 482 3737 +FUNC 3ee4 7 0 DName::setPtrRef() +3ee4 7 484 3737 +FUNC 3eeb a 0 DName::isPtrRef() +3eeb a 485 3737 +FUNC 3ef5 8 0 DName::setIsArray() +3ef5 8 490 3737 +FUNC 3efd a 0 DName::isArray() +3efd a 491 3737 +FUNC 3f07 a 0 DName::isNoTE() +3f07 a 492 3737 +FUNC 3f11 8 0 DName::setIsNoTE() +3f11 8 493 3737 +FUNC 3f19 a 0 DName::isPinPtr() +3f19 a 494 3737 +FUNC 3f23 8 0 DName::setIsPinPtr() +3f23 8 495 3737 +FUNC 3f2b a 0 DName::isComArray() +3f2b a 496 3737 +FUNC 3f35 8 0 DName::setIsComArray() +3f35 8 497 3737 +FUNC 3f3d a 0 DName::isVCallThunk() +3f3d a 498 3737 +FUNC 3f47 8 0 DName::setIsVCallThunk() +3f47 8 499 3737 +FUNC 3f4f 7b 4 DName::operator=(DName const &) +3f4f 3 879 3737 +3f52 12 880 3737 +3f64 17 882 3737 +3f7b d 883 3737 +3f88 d 884 3737 +3f95 d 885 3737 +3fa2 10 886 3737 +3fb2 10 887 3737 +3fc2 5 889 3737 +3fc7 3 897 3737 +FUNC 3fca 9 0 Replicator::isFull() +3fca 9 1001 3737 +FUNC 3fd3 25 4 Replicator::operator[](int) +3fd3 0 1028 3737 +3fd3 9 1029 3737 +3fdc b 1031 3737 +3fe7 6 1034 3737 +3fed 5 1032 3737 +3ff2 3 1030 3737 +3ff5 3 1036 3737 +FUNC 3ff8 d 0 DNameNode::DNameNode() +3ff8 d 1048 3737 +FUNC 4005 4 0 DNameNode::nextNode() +4005 4 1052 3737 +FUNC 4009 29 4 DNameNode::operator+=(DNameNode *) +4009 2 1131 3737 +400b 8 1132 3737 +4013 8 1134 3737 +401b b 1139 3737 +4026 4 1144 3737 +402a 2 1147 3737 +402c 3 1148 3737 +402f 3 1156 3737 +FUNC 4032 16 4 charNode::charNode(char) +4032 16 1166 3737 +FUNC 4048 4 0 charNode::length() +4048 4 1168 3737 +FUNC 404c 4 0 charNode::getLastChar() +404c 4 1170 3737 +FUNC 4050 1b 8 charNode::getString(char *,int) +4050 0 1173 3737 +4050 f 1174 3737 +405f 5 1175 3737 +4064 2 1176 3737 +4066 2 1177 3737 +4068 3 1183 3737 +FUNC 406b 4 0 pcharNode::length() +406b 4 1189 3737 +FUNC 406f 2f 4 pDNameNode::pDNameNode(DName *) +406f 2f 1244 3737 +FUNC 409e 25 4 DNameStatusNode::DNameStatusNode(DNameStatus) +409e 25 1261 3737 +FUNC 40c3 4 0 DNameStatusNode::length() +40c3 4 1263 3737 +FUNC 40c7 d 0 DNameStatusNode::getLastChar() +40c7 d 1266 3737 +FUNC 40d4 e 0 und_strlen +40d4 0 1283 3737 +40d4 6 1286 3737 +40da 7 1287 3737 +40e1 1 1291 3737 +FUNC 40e2 20 8 und_strncpy +40e2 0 1295 3737 +40e2 1b 1296 3737 +40fd 4 1299 3737 +4101 1 1301 3737 +FUNC 4102 25 4 und_strncmp +4102 0 1304 3737 +4102 7 1305 3737 +4109 2 1306 3737 +410b 1 1315 3737 +410c a 1308 3737 +4116 1 1310 3737 +4117 1 1311 3737 +4118 6 1308 3737 +411e 8 1314 3737 +4126 1 1315 3737 +FUNC 4127 33 0 UnDecorator::getDataIndirectType() +4127 33 4033 3704 +FUNC 415a 34 0 UnDecorator::getThisType() +415a 34 4034 3704 +FUNC 418e 13 c operator new(unsigned int,HeapManager &,int) +418e 13 131 3737 +FUNC 41a1 56 4 DName::DName(DName *) +41a1 0 274 3737 +41a1 a 275 3737 +41ab 23 277 3737 +41ce 13 278 3737 +41e1 2 281 3737 +41e3 4 283 3737 +41e7 3 284 3737 +41ea 7 295 3737 +41f1 6 296 3737 +FUNC 41f7 61 4 DName::DName(DNameStatus) +41f7 2 457 3737 +41f9 21 458 3737 +421a 1e 459 3737 +4238 7 467 3737 +423f 9 469 3737 +4248 a 470 3737 +4252 6 472 3737 +FUNC 4258 17 0 DName::isValid() +4258 17 478 3737 +FUNC 426f 15 0 DName::isEmpty() +426f 15 479 3737 +FUNC 4284 14 0 DName::isUDC() +4284 14 486 3737 +FUNC 4298 e 0 DName::setIsUDC() +4298 e 487 3737 +FUNC 42a6 14 0 DName::isUDTThunk() +42a6 14 488 3737 +FUNC 42ba 25 0 DName::length() +42ba 1 502 3737 +42bb 2 503 3737 +42bd a 506 3737 +42c7 4 507 3737 +42cb b 508 3737 +42d6 5 507 3737 +42db 3 510 3737 +42de 1 512 3737 +FUNC 42df 38 0 DName::getLastChar() +42df 2 516 3737 +42e1 2 517 3737 +42e3 9 519 3737 +42ec 6 520 3737 +42f2 a 521 3737 +42fc 2 522 3737 +42fe 7 520 3737 +4305 11 524 3737 +4316 1 526 3737 +FUNC 4317 91 8 DName::getString(char *,int) +4317 7 530 3737 +431e 9 531 3737 +4327 5 535 3737 +432c 7 537 3737 +4333 e 538 3737 +4341 c 544 3737 +434d d 550 3737 +435a 4 553 3737 +435e 8 555 3737 +4366 4 561 3737 +436a 6 565 3737 +4370 2 566 3737 +4372 b 570 3737 +437d 4 574 3737 +4381 2 578 3737 +4383 3 579 3737 +4386 3 586 3737 +4389 4 553 3737 +438d 4 590 3737 +4391 2 593 3737 +4393 6 594 3737 +4399 6 595 3737 +439f 5 599 3737 +43a4 4 601 3737 +FUNC 43a8 35 4 DName::operator|=(DName const &) +43a8 3 832 3737 +43ab 19 835 3737 +43c4 13 836 3737 +43d7 3 840 3737 +43da 3 842 3737 +FUNC 43dd 81 4 DName::operator=(DNameStatus) +43dd 2 928 3737 +43df 10 929 3737 +43ef 12 937 3737 +4401 26 945 3737 +4427 6 947 3737 +442d e 948 3737 +443b 10 933 3737 +444b d 934 3737 +4458 3 954 3737 +445b 3 956 3737 +FUNC 445e 1e 0 Replicator::Replicator() +445e 1e 1004 3737 +FUNC 447c 47 4 Replicator::operator+=(DName const &) +447c 3 1009 3737 +447f 12 1010 3737 +4491 20 1012 3737 +44b1 4 1017 3737 +44b5 8 1018 3737 +44bd 3 1022 3737 +44c0 3 1024 3737 +FUNC 44c3 47 0 DNameNode::clone() +44c3 3 1055 3737 +44c6 43 1056 3737 +4509 1 1057 3737 +FUNC 450a 65 8 pcharNode::pcharNode(char const *,int) +450a 1 1197 3737 +450b 1f 1200 3737 +452a c 1201 3737 +4536 8 1205 3737 +453e c 1207 3737 +454a a 1210 3737 +4554 b 1211 3737 +455f 2 1214 3737 +4561 3 1216 3737 +4564 4 1217 3737 +4568 7 1220 3737 +FUNC 456f 12 0 pcharNode::getLastChar() +456f 12 1191 3737 +FUNC 4581 31 8 pcharNode::getString(char *,int) +4581 0 1224 3737 +4581 b 1227 3737 +458c 2 1228 3737 +458e 21 1232 3737 +45af 3 1234 3737 +FUNC 45b2 f 0 pDNameNode::length() +45b2 f 1246 3737 +FUNC 45c1 f 0 pDNameNode::getLastChar() +45c1 f 1248 3737 +FUNC 45d0 1d 8 pDNameNode::getString(char *,int) +45d0 1d 1251 3737 +FUNC 45ed 33 8 DNameStatusNode::getString(char *,int) +45ed 0 1269 3737 +45ed b 1272 3737 +45f8 2 1273 3737 +45fa 23 1277 3737 +461d 3 1279 3737 +FUNC 4620 73 14 UnDecorator::UnDecorator(char *,char const *,int,char * (*)(long),unsigned long) +4620 16 736 3704 +4636 8 737 3704 +463e 5 738 3704 +4643 9 740 3704 +464c a 741 3704 +4656 5 745 3704 +465b 2 747 3704 +465d 6 748 3704 +4663 6 749 3704 +4669 8 754 3704 +4671 15 755 3704 +4686 d 758 3704 +FUNC 4693 2f 4 UnDecorator::getReturnType(DName *) +4693 3 2906 3704 +4696 8 2907 3704 +469e 15 2911 3704 +46b3 d 2915 3704 +46c0 2 2917 3704 +FUNC 46c2 f 0 UnDecorator::getStorageConvention() +46c2 f 4032 3704 +FUNC 46d1 79 4 DName::operator+=(DNameStatus) +46d1 4 799 3737 +46d5 17 800 3737 +46ec 20 804 3737 +470c 4 807 3737 +4710 7 809 3737 +4717 6 811 3737 +471d 8 812 3737 +4725 2 815 3737 +4727 3 816 3737 +472a 5 818 3737 +472f e 819 3737 +473d 7 801 3737 +4744 3 825 3737 +4747 3 827 3737 +FUNC 474a 68 4 DName::operator=(DName *) +474a 3 901 3737 +474d 12 902 3737 +475f 7 903 3737 +4766 29 911 3737 +478f 6 913 3737 +4795 c 914 3737 +47a1 2 917 3737 +47a3 9 918 3737 +47ac 3 922 3737 +47af 3 924 3737 +FUNC 47b2 a6 8 DName::doPchar(char const *,int) +47b2 3 962 3737 +47b5 1e 963 3737 +47d3 6 964 3737 +47d9 c 965 3737 +47e5 10 966 3737 +47f5 5 970 3737 +47fa 23 984 3737 +481d 6 986 3737 +4823 9 987 3737 +482c 2 988 3737 +482e 1b 977 3737 +4849 c 993 3737 +4855 3 995 3737 +FUNC 4858 26 4 DName::DName(char) +4858 3 238 3737 +485b 3 244 3737 +485e 7 248 3737 +4865 7 252 3737 +486c c 253 3737 +4878 6 255 3737 +FUNC 487e 31 4 DName::DName(char const *) +487e 0 300 3737 +487e 16 312 3737 +4894 15 313 3737 +48a9 6 315 3737 +FUNC 48af d0 8 DName::DName(char const * &,char) +48af 7 319 3737 +48b6 d 329 3737 +48c3 f 333 3737 +48d2 8 334 3737 +48da 9 342 3737 +48e3 40 343 3737 +4923 b 344 3737 +492e 9 355 3737 +4937 8 359 3737 +493f 8 361 3737 +4947 9 363 3737 +4950 3 364 3737 +4953 2 367 3737 +4955 3 347 3737 +4958 a 378 3737 +4962 8 380 3737 +496a 6 368 3737 +4970 7 371 3737 +4977 6 372 3737 +497d 2 375 3737 +FUNC 497f 69 8 DName::DName(unsigned __int64) +497f 15 384 3737 +4994 3 390 3737 +4997 a 398 3737 +49a1 4 402 3737 +49a5 13 406 3737 +49b8 3 407 3737 +49bb c 409 3737 +49c7 e 411 3737 +49d5 13 413 3737 +FUNC 49e8 96 8 DName::DName(__int64) +49e8 10 416 3737 +49f8 26 436 3737 +4a1e 15 438 3737 +4a33 10 443 3737 +4a43 5 444 3737 +4a48 c 446 3737 +4a54 6 448 3737 +4a5a 4 449 3737 +4a5e e 452 3737 +4a6c 12 453 3737 +FUNC 4a7e 2e 4 DName::operator+(DNameStatus) +4a7e 1 675 3737 +4a7f c 676 3737 +4a8b 9 679 3737 +4a94 b 680 3737 +4a9f 2 681 3737 +4aa1 5 682 3737 +4aa6 3 686 3737 +4aa9 3 688 3737 +FUNC 4aac 62 4 DName::operator+=(DName const &) +4aac 2 739 3737 +4aae f 740 3737 +4abd 13 741 3737 +4ad0 2 742 3737 +4ad2 9 743 3737 +4adb 6 744 3737 +4ae1 2 745 3737 +4ae3 7 747 3737 +4aea 6 749 3737 +4af0 9 750 3737 +4af9 2 751 3737 +4afb d 752 3737 +4b08 3 758 3737 +4b0b 3 760 3737 +FUNC 4b0e 8b 4 DName::operator+=(DName *) +4b0e 2 764 3737 +4b10 a 765 3737 +4b1a 9 766 3737 +4b23 8 767 3737 +4b2b 10 768 3737 +4b3b 8 789 3737 +4b43 20 770 3737 +4b63 4 773 3737 +4b67 7 775 3737 +4b6e 6 777 3737 +4b74 8 778 3737 +4b7c 2 781 3737 +4b7e 3 782 3737 +4b81 5 784 3737 +4b86 d 785 3737 +4b93 3 793 3737 +4b96 3 795 3737 +FUNC 4b99 1c 4 DName::operator=(char) +4b99 1 847 3737 +4b9a 15 854 3737 +4baf 3 856 3737 +4bb2 3 858 3737 +FUNC 4bb5 2a 4 DName::operator=(char const *) +4bb5 0 862 3737 +4bb5 24 869 3737 +4bd9 3 873 3737 +4bdc 3 875 3737 +FUNC 4bdf a6 0 UnDecorator::getCallingConvention() +4bdf 5 2825 3704 +4be4 f 2826 3704 +4bf3 c 2828 3704 +4bff 5 2835 3704 +4c04 1a 2845 3704 +4c1e 20 2852 3704 +4c3e 2 2875 3704 +4c40 2 2876 3704 +4c42 2 2871 3704 +4c44 2 2872 3704 +4c46 2 2867 3704 +4c48 2 2868 3704 +4c4a 2 2863 3704 +4c4c 2 2864 3704 +4c4e 1 2859 3704 +4c4f 2 2860 3704 +4c51 13 2855 3704 +4c64 e 2891 3704 +4c72 4 2895 3704 +4c76 d 2899 3704 +4c83 2 2901 3704 +FUNC 4c85 37 0 UnDecorator::getVCallThunkType() +4c85 3 4057 3704 +4c88 9 4059 3704 +4c91 5 4066 3704 +4c96 4 4059 3704 +4c9a 4 4066 3704 +4c9e 6 4061 3704 +4ca4 c 4062 3704 +4cb0 a 4064 3704 +4cba 2 4170 3704 +FUNC 4cbc 51 4 DName::operator+(DName const &) +4cbc 1 639 3737 +4cbd c 640 3737 +4cc9 b 643 3737 +4cd4 b 644 3737 +4cdf d 645 3737 +4cec 11 646 3737 +4cfd 2 647 3737 +4cff 8 648 3737 +4d07 3 652 3737 +4d0a 3 654 3737 +FUNC 4d0d 2e 4 DName::operator+(DName *) +4d0d 1 658 3737 +4d0e c 659 3737 +4d1a 9 662 3737 +4d23 b 663 3737 +4d2e 2 664 3737 +4d30 5 665 3737 +4d35 3 669 3737 +4d38 3 671 3737 +FUNC 4d3b 6a 4 DName::operator+=(char) +4d3b 1 693 3737 +4d3c b 694 3737 +4d47 9 695 3737 +4d50 6 696 3737 +4d56 2 697 3737 +4d58 7 699 3737 +4d5f 6 701 3737 +4d65 2b 702 3737 +4d90 2 703 3737 +4d92 c 704 3737 +4d9e 4 710 3737 +4da2 3 712 3737 +FUNC 4da5 6c 4 DName::operator+=(char const *) +4da5 2 716 3737 +4da7 f 717 3737 +4db6 9 718 3737 +4dbf 6 719 3737 +4dc5 2 720 3737 +4dc7 7 722 3737 +4dce 6 724 3737 +4dd4 28 725 3737 +4dfc 2 726 3737 +4dfe d 727 3737 +4e0b 3 733 3737 +4e0e 3 735 3737 +FUNC 4e11 e0 0 UnDecorator::getArgumentList() +4e11 7 3076 3704 +4e18 12 3078 3704 +4e2a 29 3081 3704 +4e53 6 3085 3704 +4e59 4 3086 3704 +4e5d 2 3087 3704 +4e5f e 3088 3704 +4e6d 6 3093 3704 +4e73 6 3095 3704 +4e79 5 3100 3704 +4e7e 1 3102 3704 +4e7f 11 3106 3704 +4e90 2 3109 3704 +4e92 16 3116 3704 +4ea8 19 3121 3704 +4ec1 9 3122 3704 +4eca 17 3126 3704 +4ee1 b 3132 3704 +4eec 3 3141 3704 +4eef 2 3143 3704 +FUNC 4ef1 4f 4 UnDecorator::getVdispMapType(DName const &) +4ef1 6 4230 3704 +4ef7 d 4231 3704 +4f04 c 4232 3704 +4f10 12 4233 3704 +4f22 9 4234 3704 +4f2b a 4236 3704 +4f35 6 4237 3704 +4f3b 3 4238 3704 +4f3e 2 4239 3704 +FUNC 4f40 22 8 operator+(char,DName const &) +4f40 22 198 3737 +FUNC 4f62 22 8 operator+(DNameStatus,DName const &) +4f62 22 201 3737 +FUNC 4f84 22 8 operator+(char const *,DName const &) +4f84 22 204 3737 +FUNC 4fa6 2e 4 DName::operator+(char) +4fa6 1 605 3737 +4fa7 c 606 3737 +4fb3 9 609 3737 +4fbc b 610 3737 +4fc7 2 611 3737 +4fc9 5 612 3737 +4fce 3 616 3737 +4fd1 3 618 3737 +FUNC 4fd4 2e 4 DName::operator+(char const *) +4fd4 1 622 3737 +4fd5 c 623 3737 +4fe1 9 626 3737 +4fea b 627 3737 +4ff5 2 628 3737 +4ff7 5 629 3737 +4ffc 3 633 3737 +4fff 3 635 3737 +FUNC 5002 141 4 UnDecorator::getDimension(bool) +5002 7 1616 3704 +5009 10 1618 3704 +5019 e 1620 3704 +5027 6 1623 3704 +502d f 1624 3704 +503c 8 1625 3704 +5044 47 1626 3704 +508b 4 1629 3704 +508f 4 1636 3704 +5093 8 1638 3704 +509b 20 1639 3704 +50bb d 1643 3704 +50c8 4 1634 3704 +50cc b 1649 3704 +50d7 2 1650 3704 +50d9 5 1652 3704 +50de 13 1653 3704 +50f1 c 1637 3704 +50fd 4 1641 3704 +5101 a 1653 3704 +510b 36 1655 3704 +5141 2 1659 3704 +FUNC 5143 d4 0 UnDecorator::getEnumType() +5143 6 2762 3704 +5149 1a 2766 3704 +5163 12 2770 3704 +5175 5 2774 3704 +517a 2 2775 3704 +517c 5 2779 3704 +5181 2 2780 3704 +5183 5 2786 3704 +5188 2 2787 3704 +518a d 2791 3704 +5197 1f 2801 3704 +51b6 1e 2807 3704 +51d4 e 2814 3704 +51e2 4 2795 3704 +51e6 d 2818 3704 +51f3 24 2820 3704 +FUNC 5217 c4 0 UnDecorator::getArgumentTypes() +5217 3 3035 3704 +521a 18 3036 3704 +5232 9 3046 3704 +523b 7 3051 3704 +5242 13 3052 3704 +5255 c 3064 3704 +5261 36 3058 3704 +5297 b 3061 3704 +52a2 21 3039 3704 +52c3 16 3042 3704 +52d9 2 3072 3704 +FUNC 52db 7e 0 UnDecorator::getThrowTypes() +52db 3 3148 3704 +52de e 3149 3704 +52ec 2 3150 3704 +52ee 21 3151 3704 +530f 1f 3153 3704 +532e 29 3155 3704 +5357 2 3157 3704 +FUNC 5359 125 c UnDecorator::getExtendedDataIndirectType(char &,bool &,int) +5359 6 3636 3704 +535f 1a 3641 3704 +5379 1c 3643 3704 +5395 a 3669 3704 +539f 6 3670 3704 +53a5 b 3672 3704 +53b0 a 3674 3704 +53ba 21 3675 3704 +53db 17 3678 3704 +53f2 a 3680 3704 +53fc 6 3689 3704 +5402 2 3691 3704 +5404 17 3693 3704 +541b 1e 3700 3704 +5439 6 3663 3704 +543f 2 3665 3704 +5441 3 3656 3704 +5444 d 3657 3704 +5451 2 3659 3704 +5453 6 3647 3704 +5459 13 3649 3704 +546c 10 3703 3704 +547c 2 3704 3704 +FUNC 547e 15f 4 UnDecorator::getArrayType(DName const &) +547e 3 3986 3704 +5481 12 3987 3704 +5493 7 3989 3704 +549a 4 3991 3704 +549e 2 3992 3704 +54a0 4 3994 3704 +54a4 9 3995 3704 +54ad 2a 4026 3704 +54d7 2 4028 3704 +54d9 c 3998 3704 +54e5 9 4000 3704 +54ee d 4001 3704 +54fb 35 4005 3704 +5530 b 4009 3704 +553b 4 4010 3704 +553f 8 4011 3704 +5547 2 4012 3704 +5549 2c 4013 3704 +5575 d 4017 3704 +5582 9 4018 3704 +558b 12 4019 3704 +559d a 4023 3704 +55a7 36 4024 3704 +FUNC 55dd 31 0 UnDecorator::getLexicalFrame() +55dd 31 4031 3704 +FUNC 560e 12 0 UnDecorator::getDisplacement() +560e 12 4048 3704 +FUNC 5620 12 0 UnDecorator::getCallIndex() +5620 12 4049 3704 +FUNC 5632 12 0 UnDecorator::getGuardNumber() +5632 12 4050 3704 +FUNC 5644 150 4 UnDecorator::getVfTableType(DName const &) +5644 7 4174 3704 +564b d 4175 3704 +5658 1d 4178 3704 +5675 2c 4180 3704 +56a1 f 4182 3704 +56b0 e 4184 3704 +56be 5 4186 3704 +56c3 11 4188 3704 +56d4 2d 4190 3704 +5701 b 4194 3704 +570c 7 4195 3704 +5713 10 4199 3704 +5723 a 4200 3704 +572d b 4188 3704 +5738 b 4204 3704 +5743 a 4206 3704 +574d 7 4207 3704 +5754 9 4209 3704 +575d a 4216 3704 +5767 6 4217 3704 +576d 2 4220 3704 +576f 9 4221 3704 +5778 17 4222 3704 +578f 3 4224 3704 +5792 2 4226 3704 +FUNC 5794 a0 8 UnDecorator::getStringEncoding(char *,int) +5794 6 1447 3704 +579a b 1448 3704 +57a5 22 1451 3704 +57c7 6 1456 3704 +57cd b 1459 3704 +57d8 b 1462 3704 +57e3 13 1464 3704 +57f6 c 1466 3704 +5802 5 1469 3704 +5807 6 1470 3704 +580d 4 1471 3704 +5811 14 1477 3704 +5825 d 1452 3704 +5832 2 1478 3704 +FUNC 5834 50 0 UnDecorator::getSignedDimension() +5834 5 1603 3704 +5839 b 1604 3704 +5844 c 1605 3704 +5850 2 1606 3704 +5852 23 1608 3704 +5875 d 1611 3704 +5882 2 1612 3704 +FUNC 5884 2bb 0 UnDecorator::getTemplateConstant() +5884 15 1877 3704 +5899 f 1884 3704 +58a8 32 1885 3704 +58da 9 1921 3704 +58e3 b 1922 3704 +58ee 20 1924 3704 +590e 12 1931 3704 +5920 e 1932 3704 +592e 3 1937 3704 +5931 7 1939 3704 +5938 6 1941 3704 +593e 4 1942 3704 +5942 2 1944 3704 +5944 4 1945 3704 +5948 2a 1950 3704 +5972 a 1900 3704 +597c 6 1902 3704 +5982 11 1903 3704 +5993 1b 1906 3704 +59ae b 1892 3704 +59b9 6 2034 3704 +59bf 7 1954 3704 +59c6 26 1885 3704 +59ec b 1990 3704 +59f7 c 1991 3704 +5a03 10 1992 3704 +5a13 9 1966 3704 +5a1c c 1968 3704 +5a28 e 1971 3704 +5a36 10 1973 3704 +5a46 6 1975 3704 +5a4c 6 1976 3704 +5a52 3 1980 3704 +5a55 29 1981 3704 +5a7e a 1983 3704 +5a88 a 2001 3704 +5a92 a 2003 3704 +5a9c 13 2007 3704 +5aaf a 2008 3704 +5ab9 11 2012 3704 +5aca 13 2015 3704 +5add a 2016 3704 +5ae7 13 2021 3704 +5afa a 2022 3704 +5b04 13 2026 3704 +5b17 d 2029 3704 +5b24 7 1913 3704 +5b2b 14 2041 3704 +FUNC 5b3f d9 8 UnDecorator::getPtrRefDataType(DName const &,int) +5b3f 3 3937 3704 +5b42 11 3940 3704 +5b53 b 3944 3704 +5b5e 12 3948 3704 +5b70 12 3949 3704 +5b82 10 3951 3704 +5b92 5 3957 3704 +5b97 16 3961 3704 +5bad d 3967 3704 +5bba c 3968 3704 +5bc6 b 3970 3704 +5bd1 6 3972 3704 +5bd7 1e 3974 3704 +5bf5 e 3976 3704 +5c03 13 3980 3704 +5c16 2 3982 3704 +FUNC 5c18 14 4 UnDecorator::getVbTableType(DName const &) +5c18 14 4053 3704 +FUNC 5c2c 1b8 0 UnDecorator::getTemplateArgumentList() +5c2c 14 1775 3704 +5c40 c 1777 3704 +5c4c 7 1778 3704 +5c53 2a 1781 3704 +5c7d 6 1785 3704 +5c83 4 1786 3704 +5c87 2 1787 3704 +5c89 e 1788 3704 +5c97 8 1793 3704 +5c9f 5 1798 3704 +5ca4 1 1800 3704 +5ca5 11 1804 3704 +5cb6 5 1807 3704 +5cbb 7 1810 3704 +5cc2 7 1816 3704 +5cc9 6 1817 3704 +5ccf 12 1818 3704 +5ce1 a 1820 3704 +5ceb 5 1821 3704 +5cf0 e 1822 3704 +5cfe 5 1824 3704 +5d03 9 1830 3704 +5d0c c 1832 3704 +5d18 e 1835 3704 +5d26 10 1837 3704 +5d36 6 1839 3704 +5d3c 1 1840 3704 +5d3d 2 1842 3704 +5d3f 25 1843 3704 +5d64 2 1846 3704 +5d66 10 1847 3704 +5d76 2 1850 3704 +5d78 1f 1851 3704 +5d97 17 1857 3704 +5dae 9 1858 3704 +5db7 16 1862 3704 +5dcd 17 1873 3704 +FUNC 5de4 56f 8 UnDecorator::getOperatorName(bool,bool *) +5de4 b 1095 3704 +5def 53 1103 3704 +5e42 13 1183 3704 +5e55 c 1439 3704 +5e61 1d 1440 3704 +5e7e 11 1442 3704 +5e8f 5 1444 3704 +5e94 3 1124 3704 +5e97 8 1126 3704 +5e9f 21 1127 3704 +5ec0 c 1129 3704 +5ecc a 1130 3704 +5ed6 a 1133 3704 +5ee0 7 1135 3704 +5ee7 3 1136 3704 +5eea 9 1144 3704 +5ef3 5 1145 3704 +5ef8 6 1148 3704 +5efe 2 1154 3704 +5f00 15 1156 3704 +5f15 18 1160 3704 +5f2d 1a 1161 3704 +5f47 10 1166 3704 +5f57 b 1167 3704 +5f62 5 1170 3704 +5f67 6 1106 3704 +5f6d f 1108 3704 +5f7c 21 1103 3704 +5f9d 3d 1220 3704 +5fda 18 1240 3704 +5ff2 b 1234 3704 +5ffd 5 1235 3704 +6002 13 1245 3704 +6015 7 1247 3704 +601c 8 1249 3704 +6024 18 1220 3704 +603c 13 1255 3704 +604f 7 1256 3704 +6056 2 1257 3704 +6058 16 1335 3704 +606e 7 1356 3704 +6075 6 1350 3704 +607b 2 1352 3704 +607d 25 1220 3704 +60a2 13 1290 3704 +60b5 17 1291 3704 +60cc 24 1292 3704 +60f0 14 1313 3704 +6104 6 1316 3704 +610a 5 1317 3704 +610f 10 1302 3704 +611f 20 1303 3704 +613f 20 1304 3704 +615f 20 1305 3704 +617f 22 1306 3704 +61a1 12 1307 3704 +61b3 c 1296 3704 +61bf 2b 1297 3704 +61ea 13 1281 3704 +61fd 17 1282 3704 +6214 1a 1283 3704 +622e 5 1284 3704 +6233 2d 1220 3704 +6260 25 1364 3704 +6285 10 1373 3704 +6295 13 1378 3704 +62a8 a 1397 3704 +62b2 13 1399 3704 +62c5 a 1403 3704 +62cf 6 1405 3704 +62d5 2 1408 3704 +62d7 13 1410 3704 +62ea d 1413 3704 +62f7 5 1415 3704 +62fc 10 1278 3704 +630c b 1330 3704 +6317 5 1428 3704 +631c 3 1187 3704 +631f 13 1216 3704 +6332 8 1437 3704 +633a 19 1438 3704 +FUNC 6353 153 4 UnDecorator::getTemplateName(bool) +6353 5 1700 3704 +6358 1f 1704 3704 +6377 16 1714 3704 +638d 1d 1716 3704 +63aa 23 1725 3704 +63cd e 1729 3704 +63db 6 1730 3704 +63e1 12 1732 3704 +63f3 2 1734 3704 +63f5 16 1735 3704 +640b c 1738 3704 +6417 7 1739 3704 +641e 6 1746 3704 +6424 21 1747 3704 +6445 c 1749 3704 +6451 a 1750 3704 +645b a 1753 3704 +6465 6 1755 3704 +646b 6 1756 3704 +6471 23 1769 3704 +6494 d 1705 3704 +64a1 5 1771 3704 +FUNC 64a6 1ea 4 UnDecorator::getZName(bool) +64a6 10 1007 3704 +64b6 11 1008 3704 +64c7 3 1013 3704 +64ca 26 1043 3704 +64f0 b 1024 3704 +64fb 5 1026 3704 +6500 16 1028 3704 +6516 16 1030 3704 +652c 17 1031 3704 +6543 7 1033 3704 +654a 25 1040 3704 +656f 5 1042 3704 +6574 29 1043 3704 +659d 8 1045 3704 +65a5 b 1051 3704 +65b0 c 1053 3704 +65bc e 1056 3704 +65ca 10 1058 3704 +65da 4 1060 3704 +65de b 1061 3704 +65e9 2 1063 3704 +65eb a 1064 3704 +65f5 10 1065 3704 +6605 2 1068 3704 +6607 d 1069 3704 +6614 2a 1070 3704 +663e 2 1073 3704 +6640 1a 1076 3704 +665a 11 1083 3704 +666b 9 1084 3704 +6674 f 1087 3704 +6683 d 1090 3704 +FUNC 6690 e4 0 UnDecorator::getScopedName() +6690 7 2727 3704 +6697 e 2728 3704 +66a5 15 2733 3704 +66ba 1a 2737 3704 +66d4 2a 2738 3704 +66fe b 2742 3704 +6709 8 2743 3704 +6711 4 2744 3704 +6715 1b 2745 3704 +6730 b 2746 3704 +673b 7 2747 3704 +6742 2 2748 3704 +6744 2b 2749 3704 +676f 3 2753 3704 +6772 2 2755 3704 +FUNC 6774 f 0 UnDecorator::getECSUName() +6774 f 2758 3704 +FUNC 6783 100 0 UnDecorator::getECSUDataType() +6783 3 3392 3704 +6786 20 3395 3704 +67a6 37 3399 3704 +67dd 5 3424 3704 +67e2 2 3425 3704 +67e4 5 3420 3704 +67e9 2 3421 3704 +67eb 26 3431 3704 +6811 2 3432 3704 +6813 5 3415 3704 +6818 2 3416 3704 +681a 5 3411 3704 +681f 2 3412 3704 +6821 d 3407 3704 +682e 7 3439 3704 +6835 4 3441 3704 +6839 c 3442 3704 +6845 16 3446 3704 +685b e 3450 3704 +6869 18 3404 3704 +6881 2 3452 3704 +FUNC 6883 46 0 UnDecorator::getSymbolName() +6883 3 989 3704 +6886 a 990 3704 +6890 6 991 3704 +6896 c 992 3704 +68a2 16 997 3704 +68b8 f 1001 3704 +68c7 2 1003 3704 +FUNC 68c9 92 0 UnDecorator::getBasedType() +68c9 6 2653 3704 +68cf 13 2654 3704 +68e2 a 2659 3704 +68ec 17 2661 3704 +6903 c 2707 3704 +690f 13 2699 3704 +6922 2 2700 3704 +6924 d 2674 3704 +6931 2 2711 3704 +6933 a 2712 3704 +693d d 2716 3704 +694a f 2720 3704 +6959 2 2722 3704 +FUNC 695b b42 4 UnDecorator::composeDeclaration(DName const &) +695b 6 2045 3704 +6961 e 2046 3704 +696f 5 2047 3704 +6974 a 2048 3704 +697e b 2053 3704 +6989 f 2054 3704 +6998 8 2055 3704 +69a0 15 2056 3704 +69b5 8 2057 3704 +69bd 10 2058 3704 +69cd 83 2075 3704 +6a50 7 2081 3704 +6a57 19 2082 3704 +6a70 21 2083 3704 +6a91 2 2084 3704 +6a93 15 2085 3704 +6aa8 27 2090 3704 +6acf 33 2092 3704 +6b02 9 2094 3704 +6b0b 9 2096 3704 +6b14 2b 2098 3704 +6b3f d 2101 3704 +6b4c 9 2103 3704 +6b55 2d 2105 3704 +6b82 2e 2107 3704 +6bb0 5 2111 3704 +6bb5 3 2114 3704 +6bb8 3 2115 3704 +6bbb 3 2116 3704 +6bbe 3 2117 3704 +6bc1 3 2118 3704 +6bc4 26 2121 3704 +6bea 12 2123 3704 +6bfc 19 2125 3704 +6c15 19 2126 3704 +6c2e 2 2127 3704 +6c30 12 2129 3704 +6c42 19 2131 3704 +6c5b 1b 2134 3704 +6c76 13 2141 3704 +6c89 a 2142 3704 +6c93 15 2143 3704 +6ca8 2 2144 3704 +6caa f 2145 3704 +6cb9 10 2147 3704 +6cc9 9 2151 3704 +6cd2 22 2152 3704 +6cf4 2 2153 3704 +6cf6 13 2168 3704 +6d09 c 2172 3704 +6d15 14 2173 3704 +6d29 1a 2174 3704 +6d43 2 2175 3704 +6d45 b 2176 3704 +6d50 5 2182 3704 +6d55 6 2185 3704 +6d5b 27 2187 3704 +6d82 b 2189 3704 +6d8d 5 2190 3704 +6d92 1b 2194 3704 +6dad 15 2195 3704 +6dc2 1d 2202 3704 +6ddf 16 2204 3704 +6df5 55 2205 3704 +6e4a 12 2206 3704 +6e5c 2b 2207 3704 +6e87 2 2208 3704 +6e89 d 2209 3704 +6e96 1a 2211 3704 +6eb0 2e 2218 3704 +6ede 12 2222 3704 +6ef0 c 2223 3704 +6efc c 2227 3704 +6f08 15 2228 3704 +6f1d 2 2229 3704 +6f1f f 2230 3704 +6f2e 1a 2235 3704 +6f48 b 2237 3704 +6f53 3 2238 3704 +6f56 5 2243 3704 +6f5b b 2245 3704 +6f66 1c 2250 3704 +6f82 13 2251 3704 +6f95 e 2252 3704 +6fa3 2 2253 3704 +6fa5 10 2254 3704 +6fb5 3d 2255 3704 +6ff2 c 2256 3704 +6ffe e 2257 3704 +700c 4c 2258 3704 +7058 a 2259 3704 +7062 4b 2260 3704 +70ad 7 2261 3704 +70b4 4b 2262 3704 +70ff f 2263 3704 +710e f 2264 3704 +711d 6 2268 3704 +7123 61 2277 3704 +7184 15 2281 3704 +7199 2 2283 3704 +719b 18 2285 3704 +71b3 2d 2292 3704 +71e0 12 2294 3704 +71f2 37 2296 3704 +7229 23 2297 3704 +724c b7 2299 3704 +7303 23 2300 3704 +7326 12 2306 3704 +7338 37 2307 3704 +736f b 2308 3704 +737a 37 2309 3704 +73b1 b 2310 3704 +73bc 30 2311 3704 +73ec 23 2312 3704 +740f 36 2319 3704 +7445 1e 2320 3704 +7463 8 2325 3704 +746b 1e 2326 3704 +7489 12 2329 3704 +749b 2 2331 3704 +FUNC 749d 211 0 UnDecorator::getDecoratedName() +749d 7 861 3704 +74a4 e 864 3704 +74b2 a 868 3704 +74bc b 873 3704 +74c7 8 874 3704 +74cf 11 876 3704 +74e0 10 878 3704 +74f0 6 882 3704 +74f6 9 903 3704 +74ff 9 906 3704 +7508 8 910 3704 +7510 6 912 3704 +7516 5 910 3704 +751b 2 915 3704 +751d a 918 3704 +7527 19 919 3704 +7540 6 920 3704 +7546 f 924 3704 +7555 8 925 3704 +755d 17 929 3704 +7574 a 930 3704 +757e c 932 3704 +758a 8 933 3704 +7592 5 934 3704 +7597 18 935 3704 +75af a 936 3704 +75b9 13 937 3704 +75cc b 938 3704 +75d7 2 940 3704 +75d9 29 941 3704 +7602 4 945 3704 +7606 10 946 3704 +7616 9 948 3704 +761f 3 950 3704 +7622 1c 955 3704 +763e f 959 3704 +764d 4 976 3704 +7651 6 962 3704 +7657 14 964 3704 +766b 19 967 3704 +7684 5 968 3704 +7689 10 971 3704 +7699 2 979 3704 +769b 2 980 3704 +769d f 982 3704 +76ac 2 984 3704 +FUNC 76ae 28b 0 UnDecorator::getScope() +76ae d 1482 3704 +76bb f 1483 3704 +76ca 2a 1489 3704 +76f4 14 1492 3704 +7708 b 1495 3704 +7713 16 1496 3704 +7729 5 1498 3704 +772e 17 1499 3704 +7745 3 1500 3704 +7748 f 1506 3704 +7757 2a 1507 3704 +7781 10 1566 3704 +7791 5 1567 3704 +7796 34 1561 3704 +77ca 4 1562 3704 +77ce 5 1563 3704 +77d3 e 1510 3704 +77e1 5 1514 3704 +77e6 22 1515 3704 +7808 e 1518 3704 +7816 6 1519 3704 +781c 5 1522 3704 +7821 2a 1523 3704 +784b 2 1524 3704 +784d f 1546 3704 +785c 1a 1548 3704 +7876 b 1550 3704 +7881 9 1551 3704 +788a 2 1554 3704 +788c f 1530 3704 +789b 2 1570 3704 +789d 21 1571 3704 +78be a 1489 3704 +78c8 f 1577 3704 +78d7 18 1590 3704 +78ef 2 1591 3704 +78f1 b 1580 3704 +78fc 7 1581 3704 +7903 2 1582 3704 +7905 2b 1583 3704 +7930 4 1597 3704 +7934 5 1599 3704 +FUNC 7939 341 4 UnDecorator::getFunctionIndirectType(DName const &) +7939 3 3461 3704 +793c e 3462 3704 +794a 15 3463 3704 +795f f 3465 3704 +796e 10 3466 3704 +797e 7 3469 3704 +7985 a 3471 3704 +798f 6 3473 3704 +7995 7 3475 3704 +799c d 3477 3704 +79a9 17 3482 3704 +79c0 9 3485 3704 +79c9 3 3486 3704 +79cc 5 3490 3704 +79d1 f 3491 3704 +79e0 6 3496 3704 +79e6 13 3497 3704 +79f9 b 3501 3704 +7a04 1e 3503 3704 +7a22 8 3505 3704 +7a2a 29 3506 3704 +7a53 2 3507 3704 +7a55 17 3508 3704 +7a6c f 3510 3704 +7a7b 4 3511 3704 +7a7f 10 3518 3704 +7a8f 15 3519 3704 +7aa4 9 3527 3704 +7aad d 3528 3704 +7aba 30 3529 3704 +7aea 2 3530 3704 +7aec 11 3521 3704 +7afd 7 3514 3704 +7b04 16 3516 3704 +7b1a 13 3531 3704 +7b2d d 3535 3704 +7b3a 22 3537 3704 +7b5c 2 3546 3704 +7b5e 13 3547 3704 +7b71 c 3551 3704 +7b7d 28 3552 3704 +7ba5 1e 3557 3704 +7bc3 c 3558 3704 +7bcf 2e 3561 3704 +7bfd 10 3563 3704 +7c0d c 3564 3704 +7c19 c 3566 3704 +7c25 15 3567 3704 +7c3a 2 3568 3704 +7c3c f 3569 3704 +7c4b 4 3573 3704 +7c4f b 3574 3704 +7c5a e 3580 3704 +7c68 10 3576 3704 +7c78 2 3581 3704 +FUNC 7c7a 4e4 10 UnDecorator::getDataIndirectType(DName const &,char,DName const &,int) +7c7a 6 3707 3704 +7c80 23 3711 3704 +7ca3 4 3713 3704 +7ca7 17 3715 3704 +7cbe c 3717 3704 +7cca 10 3719 3704 +7cda e 3723 3704 +7ce8 6 3725 3704 +7cee 15 3726 3704 +7d03 17 3732 3704 +7d1a 11 3751 3704 +7d2b a 3752 3704 +7d35 32 3753 3704 +7d67 5 3754 3704 +7d6c 11 3743 3704 +7d7d a 3744 3704 +7d87 25 3745 3704 +7dac 2 3746 3704 +7dae 8 3747 3704 +7db6 2 3749 3704 +7db8 19 3735 3704 +7dd1 a 3736 3704 +7ddb 14 3737 3704 +7def 5 3738 3704 +7df4 11 3739 3704 +7e05 6 3766 3704 +7e0b a 3768 3704 +7e15 17 3770 3704 +7e2c 10 3772 3704 +7e3c 1a 3778 3704 +7e56 5 3780 3704 +7e5b 6 3782 3704 +7e61 9 3787 3704 +7e6a b 3789 3704 +7e75 19 3791 3704 +7e8e c 3793 3704 +7e9a 24 3794 3704 +7ebe c 3796 3704 +7eca 22 3797 3704 +7eec 9 3801 3704 +7ef5 5 3805 3704 +7efa 7 3806 3704 +7f01 6 3810 3704 +7f07 1e 3812 3704 +7f25 8 3814 3704 +7f2d 1b 3815 3704 +7f48 2 3816 3704 +7f4a 16 3817 3704 +7f60 a 3819 3704 +7f6a 13 3828 3704 +7f7d b 3833 3704 +7f88 c 3834 3704 +7f94 8 3835 3704 +7f9c 6 3836 3704 +7fa2 b 3842 3704 +7fad b 3843 3704 +7fb8 3 3863 3704 +7fbb 6 3864 3704 +7fc1 22 3866 3704 +7fe3 9 3871 3704 +7fec 13 3872 3704 +7fff 5 3876 3704 +8004 1e 3877 3704 +8022 5 3879 3704 +8027 1e 3880 3704 +8045 5 3884 3704 +804a e 3885 3704 +8058 14 3889 3704 +806c 28 3895 3704 +8094 2 3890 3704 +8096 b 3891 3704 +80a1 2 3892 3704 +80a3 c 3898 3704 +80af 17 3899 3704 +80c6 4 3902 3704 +80ca 6 3904 3704 +80d0 7 3906 3704 +80d7 8 3774 3704 +80df 13 3918 3704 +80f2 12 3922 3704 +8104 29 3925 3704 +812d 10 3923 3704 +813d c 3928 3704 +8149 3 3929 3704 +814c 10 3931 3704 +815c 2 3933 3704 +FUNC 815e 14c 0 UnDecorator::operator char *() +815e 6 762 3704 +8164 4 763 3704 +8168 f 764 3704 +8177 9 770 3704 +8180 c 772 3704 +818c 7 775 3704 +8193 1d 776 3704 +81b0 4 782 3704 +81b4 16 783 3704 +81ca 9 785 3704 +81d3 5 794 3704 +81d8 9 795 3704 +81e1 13 799 3704 +81f4 e 808 3704 +8202 2 809 3704 +8204 2 848 3704 +8206 1a 810 3704 +8220 e 813 3704 +822e e 811 3704 +823c 9 817 3704 +8245 e 819 3704 +8253 d 820 3704 +8260 a 824 3704 +826a f 825 3704 +8279 5 828 3704 +827e 2 829 3704 +8280 2 830 3704 +8282 5 831 3704 +8287 1 832 3704 +8288 5 833 3704 +828d 1 835 3704 +828e 5 834 3704 +8293 2 838 3704 +8295 a 839 3704 +829f 9 841 3704 +82a8 2 848 3704 +FUNC 82aa 116 c UnDecorator::getPtrRefType(DName const &,DName const &,char) +82aa 5 3585 3704 +82af f 3588 3704 +82be d 3589 3704 +82cb b 3591 3704 +82d6 20 3594 3704 +82f6 b 3595 3704 +8301 b 3597 3704 +830c 9 3598 3704 +8315 14 3600 3704 +8329 14 3606 3704 +833d 1b 3608 3704 +8358 a 3612 3704 +8362 b 3615 3704 +836d c 3617 3704 +8379 9 3618 3704 +8382 c 3620 3704 +838e c 3622 3704 +839a a 3623 3704 +83a4 b 3625 3704 +83af f 3629 3704 +83be 2 3632 3704 +FUNC 83c0 1b 8 UnDecorator::getPointerType(DName const &,DName const &) +83c0 1b 4037 3704 +FUNC 83db 1b 8 UnDecorator::getPointerTypeArray(DName const &,DName const &) +83db 1b 4040 3704 +FUNC 83f6 1b 8 UnDecorator::getReferenceType(DName const &,DName const &) +83f6 1b 4043 3704 +FUNC 8411 a3 18 __unDName +8411 f 604 3704 +8420 9 606 3704 +8429 4 607 3704 +842d a 612 3704 +8437 2 613 3704 +8439 8 614 3704 +8441 3 615 3704 +8444 20 618 3704 +8464 1a 627 3704 +847e e 628 3704 +848c a 633 3704 +8496 c 636 3704 +84a2 3 643 3704 +84a5 6 645 3704 +84ab 9 637 3704 +FUNC 84b4 a3 1c __unDNameEx +84b4 f 684 3704 +84c3 9 687 3704 +84cc 4 688 3704 +84d0 a 693 3704 +84da 2 694 3704 +84dc 8 695 3704 +84e4 3 696 3704 +84e7 20 699 3704 +8507 1a 708 3704 +8521 e 709 3704 +852f a 714 3704 +8539 c 717 3704 +8545 3 724 3704 +8548 6 726 3704 +854e 9 718 3704 +FUNC 8557 387 4 UnDecorator::getBasicDataType(DName const &) +8557 3 3162 3704 +855a 15 3163 3704 +856f 6 3165 3704 +8575 4 3168 3704 +8579 35 3173 3704 +85ae 5 3178 3704 +85b3 5 3179 3704 +85b8 5 3183 3704 +85bd 5 3184 3704 +85c2 5 3188 3704 +85c7 5 3189 3704 +85cc 5 3193 3704 +85d1 5 3194 3704 +85d6 5 3203 3704 +85db 5 3204 3704 +85e0 2a 3173 3704 +860a 3c 3222 3704 +8646 5 3231 3704 +864b 5 3232 3704 +8650 22 3273 3704 +8672 5 3235 3704 +8677 5 3236 3704 +867c f 3222 3704 +868b 5 3243 3704 +8690 5 3244 3704 +8695 5 3239 3704 +869a 5 3240 3704 +869f 5 3247 3704 +86a4 5 3248 3704 +86a9 1b 3222 3704 +86c4 3 3264 3704 +86c7 6 3262 3704 +86cd 10 3264 3704 +86dd 10 3266 3704 +86ed 11 3267 3704 +86fe 5 3275 3704 +8703 2 3276 3704 +8705 5 3255 3704 +870a 2 3257 3704 +870c 3 3224 3704 +870f 12 3343 3704 +8721 9 3345 3704 +872a 7 3347 3704 +8731 16 3348 3704 +8747 6 3352 3704 +874d d 3353 3704 +875a 5 3355 3704 +875f 5 3227 3704 +8764 2 3278 3704 +8766 d 3281 3704 +8773 2 3282 3704 +8775 5 3219 3704 +877a 2 3220 3704 +877c 3 3287 3704 +877f 5 3290 3704 +8784 d 3207 3704 +8791 d 3212 3704 +879e 9 3297 3704 +87a7 1f 3301 3704 +87c6 19 3314 3704 +87df c 3322 3704 +87eb 2 3326 3704 +87ed c 3307 3704 +87f9 2 3308 3704 +87fb 1e 3311 3704 +8819 10 3332 3704 +8829 18 3333 3704 +8841 5 3337 3704 +8846 c 3360 3704 +8852 5 3367 3704 +8857 d 3369 3704 +8864 5 3371 3704 +8869 d 3372 3704 +8876 2 3373 3704 +8878 5 3374 3704 +887d d 3375 3704 +888a 17 3380 3704 +88a1 16 3385 3704 +88b7 27 3387 3704 +FUNC 88de 13e 4 UnDecorator::getPrimaryDataType(DName const &) +88de 7 2962 3704 +88e5 2b 2966 3704 +8910 12 3027 3704 +8922 d 2972 3704 +892f c 2974 3704 +893b a 2975 3704 +8945 b 2981 3704 +8950 6 2984 3704 +8956 1e 2986 3704 +8974 7 2996 3704 +897b 2 2997 3704 +897d 6 2998 3704 +8983 f 3000 3704 +8992 8 3002 3704 +899a 10 3004 3704 +89aa 2f 3022 3704 +89d9 16 3012 3704 +89ef 17 3008 3704 +8a06 14 2969 3704 +8a1a 2 3030 3704 +FUNC 8a1c b1 4 UnDecorator::getDataType(DName *) +8a1c 6 2922 3704 +8a22 b 2923 3704 +8a2d 15 2928 3704 +8a42 10 2954 3704 +8a52 6 2934 3704 +8a58 c 2936 3704 +8a64 f 2937 3704 +8a73 13 2939 3704 +8a86 6 2944 3704 +8a8c 29 2946 3704 +8ab5 2 2947 3704 +8ab7 14 2931 3704 +8acb 2 2957 3704 +FUNC 8acd 64 4 UnDecorator::getExternalDataType(DName const &) +8acd 7 4244 3704 +8ad4 1e 4247 3704 +8af2 9 4248 3704 +8afb 30 4253 3704 +8b2b 4 4255 3704 +8b2f 2 4257 3704 +FUNC 8b31 4f 4 V6_HeapAlloc +8b31 c 27 3455 +8b3d 4 28 3455 +8b41 b 29 3455 +8b4c 8 31 3455 +8b54 4 32 3455 +8b58 a 33 3455 +8b62 c 35 3455 +8b6e 3 39 3455 +8b71 6 40 3455 +8b77 9 36 3455 +FUNC 8b80 75 4 _heap_alloc +8b80 0 90 3455 +8b80 9 95 3455 +8b89 5 96 3455 +8b8e 7 97 3455 +8b95 c 98 3455 +8ba1 a 104 3455 +8bab 18 105 3455 +8bc3 1 129 3455 +8bc4 a 107 3455 +8bce 9 108 3455 +8bd7 2 109 3455 +8bd9 4 121 3455 +8bdd 1 122 3455 +8bde 6 124 3455 +8be4 10 126 3455 +8bf4 1 129 3455 +FUNC 8bf5 c3 4 malloc +8bf5 1 155 3455 +8bf6 16 159 3455 +8c0c 65 163 3455 +8c71 4 168 3455 +8c75 b 172 3455 +8c80 b 179 3455 +8c8b 2 183 3455 +8c8d 7 174 3455 +8c94 8 193 3455 +8c9c 5 195 3455 +8ca1 1 196 3455 +8ca2 7 185 3455 +8ca9 b 186 3455 +8cb4 3 187 3455 +8cb7 1 196 3455 +FUNC 8cb8 3b 4 _get_errno_from_oserr +8cb8 0 119 3915 +8cb8 6 123 3915 +8cbe f 124 3915 +8ccd 8 133 3915 +8cd5 3 134 3915 +8cd8 1 139 3915 +8cd9 7 125 3915 +8ce0 1 139 3915 +8ce1 11 135 3915 +8cf2 1 139 3915 +FUNC 8cf3 13 0 _errno +8cf3 0 280 3915 +8cf3 5 281 3915 +8cf8 4 282 3915 +8cfc 5 283 3915 +8d01 1 288 3915 +8d02 3 285 3915 +8d05 1 288 3915 +FUNC 8d06 13 0 __doserrno +8d06 0 293 3915 +8d06 5 294 3915 +8d0b 4 295 3915 +8d0f 5 296 3915 +8d14 1 300 3915 +8d15 3 298 3915 +8d18 1 300 3915 +FUNC 8d19 1e 4 _dosmaperr +8d19 1 110 3915 +8d1a 9 111 3915 +8d23 13 113 3915 +8d36 1 114 3915 +FUNC 8d37 1b 4 _set_errno +8d37 0 157 3915 +8d37 5 158 3915 +8d3c 4 159 3915 +8d40 3 161 3915 +8d43 1 168 3915 +8d44 b 165 3915 +8d4f 2 166 3915 +8d51 1 168 3915 +FUNC 8d52 2a 4 _get_errno +8d52 1 187 3915 +8d53 1b 189 3915 +8d6e 1 195 3915 +8d6f 9 193 3915 +8d78 3 194 3915 +8d7b 1 195 3915 +FUNC 8d7c 1b 4 _set_doserrno +8d7c 0 213 3915 +8d7c 5 214 3915 +8d81 4 215 3915 +8d85 3 217 3915 +8d88 1 224 3915 +8d89 b 221 3915 +8d94 2 222 3915 +8d96 1 224 3915 +FUNC 8d97 2a 4 _get_doserrno +8d97 1 243 3915 +8d98 1b 245 3915 +8db3 1 251 3915 +8db4 9 249 3915 +8dbd 3 250 3915 +8dc0 1 251 3915 +FUNC 8dc1 21 0 _get_sbh_threshold +8dc1 0 61 3311 +8dc1 9 64 3311 +8dca 2 66 3311 +8dcc 1 81 3311 +8dcd 14 69 3311 +8de1 1 81 3311 +FUNC 8de2 46 4 _set_amblksiz +8de2 0 214 3311 +8de2 2b 216 3311 +8e0d 1 224 3311 +8e0e 11 217 3311 +8e1f 5 220 3311 +8e24 3 223 3311 +8e27 1 224 3311 +FUNC 8e28 3c 4 _get_amblksiz +8e28 0 243 3311 +8e28 27 245 3311 +8e4f 1 253 3311 +8e50 8 246 3311 +8e58 8 249 3311 +8e60 3 252 3311 +8e63 1 253 3311 +FUNC 8e64 48 4 __sbh_heap_init +8e64 0 274 3311 +8e64 1c 275 3311 +8e80 1 285 3311 +8e81 4 278 3311 +8e85 7 280 3311 +8e8c c 281 3311 +8e98 13 284 3311 +8eab 1 285 3311 +FUNC 8eac 2b 4 __sbh_find_block +8eac 0 306 3311 +8eac 12 307 3311 +8ebe 7 316 3311 +8ec5 8 317 3311 +8ecd 3 319 3311 +8ed0 4 314 3311 +8ed4 2 321 3311 +8ed6 1 322 3311 +FUNC 8ed7 314 8 __sbh_free_block +8ed7 6 381 3311 +8edd 7 399 3311 +8ee4 9 402 3311 +8eed 18 407 3311 +8f05 3 408 3311 +8f08 d 412 3311 +8f15 3 416 3311 +8f18 5 417 3311 +8f1d 6 420 3311 +8f23 b 424 3311 +8f2e 4 429 3311 +8f32 5 430 3311 +8f37 3 431 3311 +8f3a 8 434 3311 +8f42 3 439 3311 +8f45 b 441 3311 +8f50 e 442 3311 +8f5e 5 443 3311 +8f63 2 445 3311 +8f65 5 448 3311 +8f6a 11 449 3311 +8f7b 9 450 3311 +8f84 9 455 3311 +8f8d 15 459 3311 +8fa2 6 463 3311 +8fa8 5 464 3311 +8fad 3 465 3311 +8fb0 f 468 3311 +8fbf 3 474 3311 +8fc2 6 477 3311 +8fc8 b 478 3311 +8fd3 2 479 3311 +8fd5 3 483 3311 +8fd8 6 484 3311 +8fde 7 485 3311 +8fe5 2 486 3311 +8fe7 4 489 3311 +8feb b 493 3311 +8ff6 3 498 3311 +8ff9 11 501 3311 +900a 6 502 3311 +9010 5 503 3311 +9015 2 505 3311 +9017 e 508 3311 +9025 6 509 3311 +902b 6 511 3311 +9031 c 516 3311 +903d c 517 3311 +9049 8 520 3311 +9051 e 524 3311 +905f 6 528 3311 +9065 3 529 3311 +9068 6 530 3311 +906e 3 531 3311 +9071 6 532 3311 +9077 8 535 3311 +907f 18 541 3311 +9097 e 542 3311 +90a5 f 543 3311 +90b4 2 545 3311 +90b6 6 547 3311 +90bc 10 548 3311 +90cc 13 550 3311 +90df 5 556 3311 +90e4 4 558 3311 +90e8 b 561 3311 +90f3 d 564 3311 +9100 6 568 3311 +9106 1a 569 3311 +9120 15 573 3311 +9135 16 577 3311 +914b 19 578 3311 +9164 9 579 3311 +916d 6 583 3311 +9173 8 586 3311 +917b 16 589 3311 +9191 25 595 3311 +91b6 14 599 3311 +91ca 4 600 3311 +91ce a 603 3311 +91d8 8 608 3311 +91e0 9 609 3311 +91e9 2 611 3311 +FUNC 91eb b0 0 __sbh_alloc_new_region +91eb 0 891 3311 +91eb 13 897 3311 +91fe 1e 900 3311 +921c 4 901 3311 +9220 12 905 3311 +9232 9 909 3311 +923b 18 913 3311 +9253 2 914 3311 +9255 1a 918 3311 +926f 10 920 3311 +927f 2 921 3311 +9281 9 927 3311 +928a 6 930 3311 +9290 6 933 3311 +9296 4 935 3311 +929a 1 936 3311 +FUNC 929b 106 4 __sbh_alloc_new_group +929b 5 958 3311 +92a0 3 959 3311 +92a3 9 972 3311 +92ac 4 973 3311 +92b0 2 976 3311 +92b2 1 977 3311 +92b3 4 974 3311 +92b7 15 981 3311 +92cc c 986 3311 +92d8 1f 993 3311 +92f7 8 994 3311 +92ff 6 998 3311 +9305 12 1001 3311 +9317 4 1004 3311 +931b 7 1005 3311 +9322 8 1011 3311 +932a 10 1013 3311 +933a 12 1016 3311 +934c 3 1001 3311 +934f 8 1021 3311 +9357 6 1023 3311 +935d 3 1024 3311 +9360 6 1027 3311 +9366 3 1028 3311 +9369 5 1030 3311 +936e a 1031 3311 +9378 9 1032 3311 +9381 b 1033 3311 +938c e 1036 3311 +939a 5 1038 3311 +939f 2 1039 3311 +FUNC 93a1 2df c __sbh_resize_block +93a1 6 1061 3311 +93a7 c 1080 3311 +93b3 b 1083 3311 +93be 3 1084 3311 +93c1 12 1085 3311 +93d3 7 1089 3311 +93da 14 1096 3311 +93ee 13 1099 3311 +9401 7 1105 3311 +9408 8 1106 3311 +9410 6 1107 3311 +9416 8 1110 3311 +941e 3 1115 3311 +9421 9 1117 3311 +942a 11 1118 3311 +943b 5 1119 3311 +9440 2 1121 3311 +9442 5 1124 3311 +9447 14 1125 3311 +945b 6 1126 3311 +9461 9 1131 3311 +946a 9 1132 3311 +9473 12 1135 3311 +9485 a 1141 3311 +948f 9 1142 3311 +9498 3 1143 3311 +949b 9 1147 3311 +94a4 6 1148 3311 +94aa 6 1149 3311 +94b0 3 1150 3311 +94b3 6 1151 3311 +94b9 8 1154 3311 +94c1 18 1160 3311 +94d9 e 1161 3311 +94e7 6 1162 3311 +94ed 2 1164 3311 +94ef 6 1166 3311 +94f5 10 1167 3311 +9505 13 1169 3311 +9518 c 1174 3311 +9524 9 1176 3311 +952d 6 1180 3311 +9533 9 1182 3311 +953c 7 1100 3311 +9543 6 1186 3311 +9549 3 1189 3311 +954c d 1195 3311 +9559 7 1198 3311 +9560 b 1199 3311 +956b 3 1200 3311 +956e a 1203 3311 +9578 7 1208 3311 +957f 5 1209 3311 +9584 3 1210 3311 +9587 8 1213 3311 +958f 3 1218 3311 +9592 b 1221 3311 +959d e 1222 3311 +95ab 5 1223 3311 +95b0 2 1225 3311 +95b2 5 1228 3311 +95b7 11 1229 3311 +95c8 9 1231 3311 +95d1 9 1236 3311 +95da 9 1237 3311 +95e3 9 1240 3311 +95ec 4 1241 3311 +95f0 5 1242 3311 +95f5 3 1243 3311 +95f8 6 1249 3311 +95fe 3 1250 3311 +9601 6 1251 3311 +9607 3 1252 3311 +960a 6 1253 3311 +9610 8 1256 3311 +9618 18 1262 3311 +9630 e 1263 3311 +963e 6 1264 3311 +9644 2 1266 3311 +9646 6 1268 3311 +964c 10 1269 3311 +965c 13 1271 3311 +966f 5 1276 3311 +9674 4 1278 3311 +9678 6 1281 3311 +967e 2 1282 3311 +FUNC 9680 cd 0 __sbh_heapmin +9680 0 1302 3311 +9680 d 1306 3311 +968d 6 1310 3311 +9693 17 1311 3311 +96aa 15 1314 3311 +96bf 16 1318 3311 +96d5 19 1319 3311 +96ee 9 1320 3311 +96f7 f 1325 3311 +9706 11 1328 3311 +9717 28 1333 3311 +973f 6 1334 3311 +9745 7 1338 3311 +974c 1 1340 3311 +FUNC 974d 2e2 0 __sbh_heap_check +974d 3 1361 3311 +9750 12 1391 3311 +9762 8 1393 3311 +976a 16 1398 3311 +9780 3 1401 3311 +9783 8 1402 3311 +978b 6 1406 3311 +9791 9 1407 3311 +979a c 1408 3311 +97a6 3 1409 3311 +97a9 3 1410 3311 +97ac 6 1411 3311 +97b2 4 1418 3311 +97b6 1b 1421 3311 +97d1 9 1424 3311 +97da 9 1428 3311 +97e3 1c 1438 3311 +97ff 2 1445 3311 +9801 7 1446 3311 +9808 1 1449 3311 +9809 c 1452 3311 +9815 3 1456 3311 +9818 2 1458 3311 +981a 6 1462 3311 +9820 5 1463 3311 +9825 3 1464 3311 +9828 9 1465 3311 +9831 1e 1470 3311 +984f c 1475 3311 +985b 2 1479 3311 +985d 4 1481 3311 +9861 6 1484 3311 +9867 10 1488 3311 +9877 e 1492 3311 +9885 2 1498 3311 +9887 4 1502 3311 +988b 20 1505 3311 +98ab 19 1509 3311 +98c4 8 1514 3311 +98cc 3 1518 3311 +98cf 6 1520 3311 +98d5 8 1524 3311 +98dd 4 1527 3311 +98e1 e 1532 3311 +98ef 8 1536 3311 +98f7 6 1541 3311 +98fd 5 1542 3311 +9902 3 1543 3311 +9905 8 1544 3311 +990d c 1549 3311 +9919 11 1554 3311 +992a 6 1559 3311 +9930 3 1561 3311 +9933 e 1563 3311 +9941 3 1564 3311 +9944 2 1566 3311 +9946 8 1568 3311 +994e 3 1569 3311 +9951 1c 1575 3311 +996d c 1580 3311 +9979 10 1585 3311 +9989 17 1591 3311 +99a0 7 1595 3311 +99a7 7 1596 3311 +99ae 16 1597 3311 +99c4 f 1602 3311 +99d3 18 1606 3311 +99eb 5 1608 3311 +99f0 2 1609 3311 +99f2 4 1403 3311 +99f6 4 1425 3311 +99fa 4 1453 3311 +99fe 4 1485 3311 +9a02 4 1471 3311 +9a06 4 1439 3311 +9a0a 4 1493 3311 +9a0e 4 1537 3311 +9a12 4 1545 3311 +9a16 4 1550 3311 +9a1a 4 1510 3311 +9a1e 4 1581 3311 +9a22 4 1576 3311 +9a26 4 1592 3311 +9a2a 5 1603 3311 +FUNC 9a2f a8 4 _set_sbh_threshold +9a2f 1 102 3311 +9a30 a 104 3311 +9a3a 3 106 3311 +9a3d 1 195 3311 +9a3e a 109 3311 +9a48 25 112 3311 +9a6d 5 113 3311 +9a72 4 114 3311 +9a76 2 195 3311 +9a78 6 173 3311 +9a7e 2 175 3311 +9a80 5 179 3311 +9a85 2d 185 3311 +9ab2 6 186 3311 +9ab8 a 187 3311 +9ac2 5 188 3311 +9ac7 b 193 3311 +9ad2 4 194 3311 +9ad6 1 195 3311 +FUNC 9ad7 2e3 4 __sbh_alloc_block +9ad7 6 632 3311 +9add 5 633 3311 +9ae2 15 650 3311 +9af7 5 668 3311 +9afc 7 669 3311 +9b03 5 671 3311 +9b08 4 672 3311 +9b0c 2 674 3311 +9b0e d 677 3311 +9b1b a 682 3311 +9b25 e 686 3311 +9b33 3 688 3311 +9b36 2 683 3311 +9b38 5 688 3311 +9b3d 4 692 3311 +9b41 8 694 3311 +9b49 e 698 3311 +9b57 3 700 3311 +9b5a 2 695 3311 +9b5c 5 700 3311 +9b61 6 705 3311 +9b67 6 709 3311 +9b6d 6 711 3311 +9b73 4 707 3311 +9b77 4 715 3311 +9b7b 8 717 3311 +9b83 6 720 3311 +9b89 3 722 3311 +9b8c 2 718 3311 +9b8e 5 722 3311 +9b93 4 726 3311 +9b97 e 727 3311 +9ba5 7 728 3311 +9bac 12 733 3311 +9bbe 2 734 3311 +9bc0 6 737 3311 +9bc6 3 739 3311 +9bc9 2 740 3311 +9bcb 1c 745 3311 +9be7 4 749 3311 +9beb 14 751 3311 +9bff e 752 3311 +9c0d 3 751 3311 +9c10 12 754 3311 +9c22 a 760 3311 +9c2c d 763 3311 +9c39 2 768 3311 +9c3b 2 767 3311 +9c3d 1 768 3311 +9c3e 4 765 3311 +9c42 7 770 3311 +9c49 5 775 3311 +9c4e 6 776 3311 +9c54 8 777 3311 +9c5c 3 778 3311 +9c5f 8 781 3311 +9c67 8 784 3311 +9c6f 3 788 3311 +9c72 e 791 3311 +9c80 15 792 3311 +9c95 8 793 3311 +9c9d 2 795 3311 +9c9f f 798 3311 +9cae f 799 3311 +9cbd e 800 3311 +9ccb 1c 809 3311 +9ce7 6 813 3311 +9ced 3 814 3311 +9cf0 6 815 3311 +9cf6 3 816 3311 +9cf9 6 817 3311 +9cff 8 820 3311 +9d07 18 826 3311 +9d1f b 827 3311 +9d2a 10 829 3311 +9d3a 2 831 3311 +9d3c 6 833 3311 +9d42 d 835 3311 +9d4f 16 837 3311 +9d65 3 831 3311 +9d68 4 844 3311 +9d6c 2 846 3311 +9d6e 9 848 3311 +9d77 a 853 3311 +9d81 4 855 3311 +9d85 e 858 3311 +9d93 13 862 3311 +9da6 7 863 3311 +9dad 5 866 3311 +9db2 6 868 3311 +9db8 2 869 3311 +FUNC 9dba 39 0 terminate() +9dba c 94 3855 +9dc6 8 107 3855 +9dce 4 111 3855 +9dd2 4 116 3855 +9dd6 2 120 3855 +9dd8 2 121 3855 +9dda 7 122 3855 +9de1 7 127 3855 +9de8 5 135 3855 +9ded 6 136 3855 +FUNC 9df3 13 0 unexpected() +9df3 0 149 3855 +9df3 8 159 3855 +9dfb 4 163 3855 +9dff 2 167 3855 +9e01 5 173 3855 +FUNC 9e06 37 0 _inconsistency() +9e06 c 187 3855 +9e12 c 196 3855 +9e1e 4 197 3855 +9e22 4 202 3855 +9e26 2 203 3855 +9e28 2 204 3855 +9e2a 7 205 3855 +9e31 7 211 3855 +9e38 5 217 3855 +FUNC 9e3d 11 4 _initp_eh_hooks +9e3d 0 74 3855 +9e3d 10 80 3855 +9e4d 1 81 3855 +FUNC 9e4e b9 4 _onexit_nolock +9e4e 5 104 1673 +9e53 b 107 1673 +9e5e 13 108 1673 +9e71 16 112 1673 +9e87 d 122 1673 +9e94 d 127 1673 +9ea1 14 129 1673 +9eb5 3 134 1673 +9eb8 14 136 1673 +9ecc 3 147 1673 +9ecf f 149 1673 +9ede e 156 1673 +9eec c 157 1673 +9ef8 7 159 1673 +9eff 6 114 1673 +9f05 2 160 1673 +FUNC 9f07 2f 0 __onexitinit +9f07 1 205 1673 +9f08 b 208 1673 +9f13 9 209 1673 +9f1c e 211 1673 +9f2a 4 216 1673 +9f2e 1 221 1673 +9f2f 3 218 1673 +9f32 3 220 1673 +9f35 1 221 1673 +FUNC 9f36 3c 4 _onexit +9f36 c 85 1673 +9f42 5 88 1673 +9f47 4 90 1673 +9f4b c 91 1673 +9f57 c 93 1673 +9f63 3 97 1673 +9f66 6 98 1673 +9f6c 6 94 1673 +FUNC 9f72 12 4 atexit +9f72 0 165 1673 +9f72 11 166 1673 +9f83 1 167 1673 +FUNC 9f84 1f 0 _initp_misc_cfltcvt_tab +9f84 2 54 2488 +9f86 8 56 2488 +9f8e 14 58 2488 +9fa2 1 60 2488 +FUNC 9fb0 29 4 _ValidateImageBase +9fb0 0 44 1573 +9fb0 b 50 1573 +9fbb 2 52 1573 +9fbd 1 68 1573 +9fbe 5 55 1573 +9fc3 6 56 1573 +9fc9 2 58 1573 +9fcb d 62 1573 +9fd8 1 68 1573 +FUNC 9fe0 42 8 _FindPESection +9fe0 0 92 1573 +9fe0 9 99 1573 +9fe9 19 108 1573 +a002 10 111 1573 +a012 a 108 1573 +a01c 5 123 1573 +a021 1 124 1573 +FUNC a030 bb 4 _IsNonwritableInCurrentImage +a030 33 149 1573 +a063 7 156 1573 +a06a f 164 1573 +a079 2 166 1573 +a07b 8 174 1573 +a083 e 175 1573 +a091 2 176 1573 +a093 2 178 1573 +a095 12 185 1573 +a0a7 12 195 1573 +a0b9 17 187 1573 +a0d0 9 193 1573 +a0d9 12 195 1573 +FUNC a0eb 19 4 _initp_misc_winsig +a0eb 0 57 1199 +a0eb 9 58 1199 +a0f4 5 59 1199 +a0f9 5 60 1199 +a0fe 5 61 1199 +a103 1 62 1199 +FUNC a104 9b 4 ctrlevent_capture +a104 c 89 1199 +a110 9 94 1199 +a119 3 95 1199 +a11c 5 102 1199 +a121 5 103 1199 +a126 e 104 1199 +a134 7 105 1199 +a13b 2 107 1199 +a13d 5 108 1199 +a142 e 109 1199 +a150 7 110 1199 +a157 1 109 1199 +a158 9 113 1199 +a161 7 117 1199 +a168 c 120 1199 +a174 5 124 1199 +a179 4 128 1199 +a17d 2 120 1199 +a17f 8 121 1199 +a187 6 130 1199 +a18d 7 131 1199 +a194 3 138 1199 +a197 8 139 1199 +FUNC a19f 34 4 siglookup +a19f 0 634 1199 +a19f b 635 1199 +a1aa 15 645 1199 +a1bf f 649 1199 +a1ce 2 653 1199 +a1d0 2 658 1199 +a1d2 1 659 1199 +FUNC a1d3 d 0 __get_sigabrt +a1d3 0 676 1199 +a1d3 c 677 1199 +a1df 1 678 1199 +FUNC a1e0 9 0 __fpecode +a1e0 0 699 1199 +a1e0 8 700 1199 +a1e8 1 701 1199 +FUNC a1e9 9 0 __pxcptinfoptrs +a1e9 0 721 1199 +a1e9 8 722 1199 +a1f1 1 723 1199 +FUNC a1f2 23d 8 signal +a1f2 c 219 1199 +a1fe 4 224 1199 +a202 3 230 1199 +a205 3 244 1199 +a208 12 230 1199 +a21a 2f 244 1199 +a249 13 327 1199 +a25c 7 334 1199 +a263 8 335 1199 +a26b a 342 1199 +a275 17 346 1199 +a28c 10 352 1199 +a29c 13 367 1199 +a2af 3 380 1199 +a2b2 e 382 1199 +a2c0 3 395 1199 +a2c3 17 401 1199 +a2da 5 390 1199 +a2df 5 401 1199 +a2e4 8 246 1199 +a2ec 4 247 1199 +a2f0 12 254 1199 +a302 14 257 1199 +a316 6 259 1199 +a31c 2 261 1199 +a31e f 263 1199 +a32d a 264 1199 +a337 18 268 1199 +a34f f 288 1199 +a35e 4 289 1199 +a362 b 291 1199 +a36d 2 293 1199 +a36f f 279 1199 +a37e 4 280 1199 +a382 b 282 1199 +a38d 2 284 1199 +a38f f 296 1199 +a39e 4 297 1199 +a3a2 b 299 1199 +a3ad 2 301 1199 +a3af f 271 1199 +a3be 4 272 1199 +a3c2 c 274 1199 +a3ce c 305 1199 +a3da 9 309 1199 +a3e3 4 407 1199 +a3e7 3 305 1199 +a3ea 9 306 1199 +a3f3 19 410 1199 +a40c 1a 419 1199 +a426 3 417 1199 +a429 6 423 1199 +FUNC a42f 1b0 4 raise +a42f c 452 1199 +a43b 5 459 1199 +a440 3 460 1199 +a443 1f 462 1199 +a462 a 488 1199 +a46c 4 489 1199 +a470 8 490 1199 +a478 a 465 1199 +a482 2 467 1199 +a484 11 492 1199 +a495 2 493 1199 +a497 f 462 1199 +a4a6 1c 500 1199 +a4c2 a 476 1199 +a4cc 2 478 1199 +a4ce a 470 1199 +a4d8 2 472 1199 +a4da a 481 1199 +a4e4 7 482 1199 +a4eb a 502 1199 +a4f5 2 510 1199 +a4f7 4 509 1199 +a4fb 6 510 1199 +a501 5 515 1199 +a506 7 520 1199 +a50d 5 527 1199 +a512 7 528 1199 +a519 5 530 1199 +a51e f 543 1199 +a52d 6 544 1199 +a533 3 545 1199 +a536 5 551 1199 +a53b 6 552 1199 +a541 7 553 1199 +a548 5 561 1199 +a54d 1c 568 1199 +a569 d 571 1199 +a576 5 568 1199 +a57b 7 574 1199 +a582 c 577 1199 +a58e 5 582 1199 +a593 8 588 1199 +a59b 2 589 1199 +a59d 6 577 1199 +a5a3 6 578 1199 +a5a9 9 579 1199 +a5b2 5 590 1199 +a5b7 f 597 1199 +a5c6 6 598 1199 +a5cc 5 603 1199 +a5d1 6 604 1199 +a5d7 2 607 1199 +a5d9 6 608 1199 +FUNC a5df a 4 _initp_misc_rand_s +a5df 0 58 1489 +a5df 9 59 1489 +a5e8 1 60 1489 +FUNC a5e9 104 4 rand_s +a5e9 3 66 1489 +a5ec b 67 1489 +a5f7 2b 68 1489 +a622 c 71 1489 +a62e d 77 1489 +a63b 4 78 1489 +a63f 1e 80 1489 +a65d e 83 1489 +a66b 4 84 1489 +a66f 2f 86 1489 +a69e 9 88 1489 +a6a7 5 89 1489 +a6ac 16 94 1489 +a6c2 7 103 1489 +a6c9 9 107 1489 +a6d2 b 109 1489 +a6dd 9 110 1489 +a6e6 6 112 1489 +a6ec 1 113 1489 +FUNC a6ed 15a 14 __getlocaleinfo +a6ed 1d 70 1937 +a70a 7 76 1937 +a711 87 109 1937 +a798 13 103 1937 +a7ab 5 114 1937 +a7b0 7 115 1937 +a7b7 3 141 1937 +a7ba 12 142 1937 +a7cc 20 106 1937 +a7ec 5 108 1937 +a7f1 7 109 1937 +a7f8 4 111 1937 +a7fc 5 118 1937 +a801 1a 126 1937 +a81b 2 127 1937 +a81d 2 129 1937 +a81f 10 134 1937 +a82f 16 135 1937 +a845 2 139 1937 +FUNC a847 a 4 _initp_misc_purevirt +a847 0 166 1937 +a847 9 167 1937 +a850 1 168 1937 +FUNC a851 a 4 _initp_misc_initcrit +a851 0 47 2023 +a851 9 48 2023 +a85a 1 49 2023 +FUNC a85b 10 8 __crtInitCritSecNoSpinCount +a85b 0 76 2023 +a85b a 77 2023 +a865 3 78 2023 +a868 3 79 2023 +FUNC a86b c5 8 __crtInitCritSecAndSpinCount +a86b c 109 2023 +a877 5 111 2023 +a87c e 112 2023 +a88a 4 114 2023 +a88e 1b 120 2023 +a8a9 4 121 2023 +a8ad 2 129 2023 +a8af b 130 2023 +a8ba 4 131 2023 +a8be e 134 2023 +a8cc 4 136 2023 +a8d0 5 149 2023 +a8d5 c 152 2023 +a8e1 3 155 2023 +a8e4 b 161 2023 +a8ef 2 162 2023 +a8f1 1a 163 2023 +a90b 9 170 2023 +a914 8 171 2023 +a91c 4 173 2023 +a920 7 174 2023 +a927 3 176 2023 +a92a 6 177 2023 +FUNC a930 a 4 _initp_heap_handler +a930 0 31 3260 +a930 9 32 3260 +a939 1 33 3260 +FUNC a93a 31 4 _set_new_handler(int (*)(unsigned int)) +a93a 1 53 3260 +a93b 7 57 3260 +a942 b 59 3260 +a94d b 60 3260 +a958 f 63 3260 +a967 3 65 3260 +a96a 1 66 3260 +FUNC a96b 9 4 _set_new_handler(int) +a96b 0 86 3260 +a96b 8 89 3260 +a973 1 90 3260 +FUNC a974 d 0 _query_new_handler() +a974 0 110 3260 +a974 c 111 3260 +a980 1 112 3260 +FUNC a981 22 4 _callnewh +a981 0 131 3260 +a981 b 133 3260 +a98c 10 135 3260 +a99c 3 138 3260 +a99f 1 139 3260 +a9a0 2 136 3260 +a9a2 1 139 3260 +FUNC a9a3 1bd c __crtMessageBoxA +a9a3 9 41 2447 +a9ac 5 49 2447 +a9b1 2 56 2447 +a9b3 18 64 2447 +a9cb d 66 2447 +a9d8 2 67 2447 +a9da 6 69 2447 +a9e0 10 76 2447 +a9f0 6 78 2447 +a9f6 6 80 2447 +a9fc 15 83 2447 +aa11 1a 86 2447 +aa2b 1c 88 2447 +aa47 6 89 2447 +aa4d 8 95 2447 +aa55 6 98 2447 +aa5b a 100 2447 +aa65 14 102 2447 +aa79 14 116 2447 +aa8d 6 119 2447 +aa93 d 120 2447 +aaa0 c 122 2447 +aaac 1f 127 2447 +aacb 1b 136 2447 +aae6 6 137 2447 +aaec 7 138 2447 +aaf3 2 139 2447 +aaf5 7 140 2447 +aafc 2 142 2447 +aafe a 144 2447 +ab08 6 146 2447 +ab0e 5 147 2447 +ab13 2 149 2447 +ab15 11 153 2447 +ab26 6 155 2447 +ab2c 5 156 2447 +ab31 8 158 2447 +ab39 b 165 2447 +ab44 5 166 2447 +ab49 10 168 2447 +ab59 5 173 2447 +ab5e 2 176 2447 +FUNC ab60 71 c strcat_s +ab60 0 13 490 +ab60 30 18 490 +ab90 c 19 490 +ab9c 2 21 490 +ab9e 4 23 490 +aba2 1 25 490 +aba3 3 26 490 +aba6 2 29 490 +aba8 2 32 490 +abaa d 35 490 +abb7 4 39 490 +abbb 2 41 490 +abbd e 42 490 +abcb 5 45 490 +abd0 1 46 490 +FUNC abd1 b3 10 strncpy_s +abd1 5 13 406 +abd6 14 17 406 +abea 5 65 406 +abef 2 66 406 +abf1 26 24 406 +ac17 5 25 406 +ac1c 2 28 406 +ac1e 2 29 406 +ac20 b 31 406 +ac2b 8 35 406 +ac33 d 37 406 +ac40 2 41 406 +ac42 12 45 406 +ac54 5 48 406 +ac59 2 50 406 +ac5b 4 54 406 +ac5f 6 56 406 +ac65 3 58 406 +ac68 c 59 406 +ac74 2 61 406 +ac76 e 62 406 +FUNC ac84 46 4 _set_error_mode +ac84 0 43 2351 +ac84 15 50 2351 +ac99 6 58 2351 +ac9f 1 65 2351 +aca0 5 54 2351 +aca5 7 55 2351 +acac 1 65 2351 +acad 1c 61 2351 +acc9 1 65 2351 +FUNC acca a 4 __set_app_type +acca 0 91 2351 +acca 9 96 2351 +acd3 1 97 2351 +FUNC acd4 6 0 __get_app_type +acd4 0 120 2351 +acd4 5 125 2351 +acd9 1 126 2351 +FUNC acda 21 4 wait_a_bit +acda 1 18 3587 +acdb b 19 3587 +ace6 6 20 3587 +acec 8 21 3587 +acf4 3 22 3587 +acf7 3 23 3587 +acfa 1 24 3587 +FUNC acfb 10 4 _set_malloc_crt_max_wait +acfb 0 32 3587 +acfb f 34 3587 +ad0a 1 36 3587 +FUNC ad0b 40 4 _malloc_crt +ad0b 2 39 3587 +ad0d 2 40 3587 +ad0f b 44 3587 +ad1a d 45 3587 +ad27 18 46 3587 +ad3f 7 47 3587 +ad46 4 50 3587 +ad4a 1 51 3587 +FUNC ad4b 48 8 _calloc_crt +ad4b 2 54 3587 +ad4d 2 55 3587 +ad4f 14 61 3587 +ad63 c 62 3587 +ad6f 18 63 3587 +ad87 7 64 3587 +ad8e 4 67 3587 +ad92 1 68 3587 +FUNC ad93 4b 8 _realloc_crt +ad93 2 71 3587 +ad95 2 72 3587 +ad97 f 76 3587 +ada6 14 77 3587 +adba 18 78 3587 +add2 7 79 3587 +add9 4 82 3587 +addd 1 83 3587 +FUNC adde 50 c _recalloc_crt +adde 2 86 3587 +ade0 2 87 3587 +ade2 16 91 3587 +adf8 12 92 3587 +ae0a 18 94 3587 +ae22 7 95 3587 +ae29 4 100 3587 +ae2d 1 101 3587 +FUNC ae2e 8 0 _malloc_crt_fastcall +ae2e 0 105 3587 +ae2e 7 106 3587 +ae35 1 107 3587 +FUNC ae36 a 0 _calloc_crt_fastcall +ae36 0 110 3587 +ae36 9 111 3587 +ae3f 1 112 3587 +FUNC ae40 a 0 _realloc_crt_fastcall +ae40 0 115 3587 +ae40 9 116 3587 +ae49 1 117 3587 +FUNC ae4a e 0 _LocaleUpdate::~_LocaleUpdate() +ae4a 0 282 3057 +ae4a 6 283 3057 +ae50 7 284 3057 +ae57 1 285 3057 +FUNC ae58 3 0 _LocaleUpdate::GetLocaleT() +ae58 2 287 3057 +ae5a 1 289 3057 +FUNC ae5b 2f 0 CPtoLCID +ae5b 0 329 3029 +ae5b 14 330 3029 +ae6f 2 345 3029 +ae71 1 346 3029 +ae72 5 342 3029 +ae77 1 346 3029 +ae78 5 339 3029 +ae7d 1 346 3029 +ae7e 5 336 3029 +ae83 1 346 3029 +ae84 5 333 3029 +ae89 1 346 3029 +FUNC ae8a 55 0 setSBCS +ae8a 4 363 3029 +ae8e 14 368 3029 +aea2 3 371 3029 +aea5 3 374 3029 +aea8 3 376 3029 +aeab 8 379 3029 +aeb3 a 381 3029 +aebd 9 382 3029 +aec6 b 384 3029 +aed1 d 385 3029 +aede 1 386 3029 +FUNC aedf 18a 0 setSBUpLow +aedf 1d 402 3029 +aefc f 412 3029 +af0b d 415 3029 +af18 c 416 3029 +af24 e 420 3029 +af32 3 419 3029 +af35 28 421 3029 +af5d 1d 427 3029 +af7a 23 432 3029 +af9d 25 437 3029 +afc2 2 442 3029 +afc4 a 443 3029 +afce 5 445 3029 +afd3 9 446 3029 +afdc 5 448 3029 +afe1 5 450 3029 +afe6 e 451 3029 +aff4 2 453 3029 +aff6 8 454 3029 +affe 5 442 3029 +b003 8 456 3029 +b00b 2c 472 3029 +b037 5 466 3029 +b03c 5 468 3029 +b041 7 469 3029 +b048 2 471 3029 +b04a 3 472 3029 +b04d 5 460 3029 +b052 17 474 3029 +FUNC b069 a4 0 __updatetmbcinfo +b069 c 496 3029 +b075 7 499 3029 +b07c 10 500 3029 +b08c 3 533 3029 +b08f 4 536 3029 +b093 8 538 3029 +b09b 2 541 3029 +b09d 6 542 3029 +b0a3 8 501 3029 +b0ab 4 503 3029 +b0af e 506 3029 +b0bd 17 512 3029 +b0d4 7 517 3029 +b0db 11 524 3029 +b0ec 7 525 3029 +b0f3 11 528 3029 +b104 9 530 3029 +FUNC b10d 82 4 _LocaleUpdate::_LocaleUpdate(localeinfo_struct *) +b10d 0 261 3057 +b10d f 262 3057 +b11c 8 264 3057 +b124 5 265 3057 +b129 6 266 3057 +b12f 1c 268 3057 +b14b 21 269 3057 +b16c 9 270 3057 +b175 4 272 3057 +b179 4 273 3057 +b17d 2 276 3057 +b17f a 278 3057 +b189 6 280 3057 +FUNC b18f 7a 0 getSystemCP +b18f 7 282 3029 +b196 b 284 3029 +b1a1 b 289 3029 +b1ac a 291 3029 +b1b6 14 292 3029 +b1ca 5 295 3029 +b1cf a 297 3029 +b1d9 8 298 3029 +b1e1 5 302 3029 +b1e6 12 305 3029 +b1f8 f 308 3029 +b207 2 309 3029 +FUNC b209 1d9 8 _setmbcp_nolock +b209 15 686 3029 +b21e b 693 3029 +b229 9 696 3029 +b232 7 698 3029 +b239 7 699 3029 +b240 3 703 3029 +b243 2 705 3029 +b245 19 708 3029 +b25e 2a 743 3029 +b288 13 751 3029 +b29b f 756 3029 +b2aa 15 761 3029 +b2bf 17 764 3029 +b2d6 c 766 3029 +b2e2 f 712 3029 +b2f1 15 715 3029 +b306 9 720 3029 +b30f 8 723 3029 +b317 12 724 3029 +b329 9 723 3029 +b332 5 720 3029 +b337 12 715 3029 +b349 20 731 3029 +b369 d 733 3029 +b376 7 736 3029 +b37d 5 737 3029 +b382 6 767 3029 +b388 10 766 3029 +b398 8 771 3029 +b3a0 7 772 3029 +b3a7 b 775 3029 +b3b2 3 778 3029 +b3b5 2 780 3029 +b3b7 3 782 3029 +b3ba 8 785 3029 +b3c2 2 789 3029 +b3c4 6 794 3029 +b3ca 6 797 3029 +b3d0 3 746 3029 +b3d3 f 802 3029 +FUNC b3e2 3c 0 _getmbcp +b3e2 6 819 3029 +b3e8 a 821 3029 +b3f2 9 822 3029 +b3fb 10 823 3029 +b40b 2 826 3029 +b40d f 825 3029 +b41c 2 826 3029 +FUNC b41e 19a 4 _setmbcp +b41e c 574 3029 +b42a 4 575 3029 +b42e a 579 3029 +b438 5 581 3029 +b43d 3 582 3029 +b440 b 585 3029 +b44b 9 587 3029 +b454 d 593 3029 +b461 8 595 3029 +b469 c 597 3029 +b475 3 607 3029 +b478 16 612 3029 +b48e 1a 614 3029 +b4a8 7 615 3029 +b4af 3 619 3029 +b4b2 9 620 3029 +b4bb 17 622 3029 +b4d2 8 624 3029 +b4da 4 625 3029 +b4de 8 630 3029 +b4e6 8 631 3029 +b4ee 8 632 3029 +b4f6 a 633 3029 +b500 d 634 3029 +b50d 3 633 3029 +b510 c 635 3029 +b51c a 636 3029 +b526 3 635 3029 +b529 c 637 3029 +b535 d 638 3029 +b542 3 637 3029 +b545 1c 640 3029 +b561 7 641 3029 +b568 6 645 3029 +b56e 3 646 3029 +b571 e 648 3029 +b57f 9 650 3029 +b588 2 653 3029 +b58a 5 654 3029 +b58f 8 660 3029 +b597 7 661 3029 +b59e b 662 3029 +b5a9 2 668 3029 +b5ab 4 673 3029 +b5af 3 682 3029 +b5b2 6 683 3029 +FUNC b5b8 1e 0 __initmbctable +b5b8 0 843 3029 +b5b8 9 853 3029 +b5c1 8 854 3029 +b5c9 a 855 3029 +b5d3 2 860 3029 +b5d5 1 861 3029 +FUNC b5d6 51 10 x_ismbbtype_l +b5d6 6 213 3083 +b5dc b 214 3083 +b5e7 4 219 3083 +b5eb 3a 222 3083 +b625 2 223 3083 +FUNC b627 15 8 _ismbbkalnum_l +b627 0 80 3083 +b627 14 81 3083 +b63b 1 82 3083 +FUNC b63c 13 4 _ismbbkalnum +b63c 0 85 3083 +b63c 12 86 3083 +b64e 1 87 3083 +FUNC b64f 15 8 _ismbbkprint_l +b64f 0 90 3083 +b64f 14 91 3083 +b663 1 92 3083 +FUNC b664 13 4 _ismbbkprint +b664 0 95 3083 +b664 12 96 3083 +b676 1 97 3083 +FUNC b677 15 8 _ismbbkpunct_l +b677 0 100 3083 +b677 14 101 3083 +b68b 1 102 3083 +FUNC b68c 13 4 _ismbbkpunct +b68c 0 105 3083 +b68c 12 106 3083 +b69e 1 107 3083 +FUNC b69f 18 8 _ismbbalnum_l +b69f 0 113 3083 +b69f 17 114 3083 +b6b6 1 115 3083 +FUNC b6b7 16 4 _ismbbalnum +b6b7 0 118 3083 +b6b7 15 119 3083 +b6cc 1 120 3083 +FUNC b6cd 18 8 _ismbbalpha_l +b6cd 0 123 3083 +b6cd 17 124 3083 +b6e4 1 125 3083 +FUNC b6e5 16 4 _ismbbalpha +b6e5 0 128 3083 +b6e5 15 129 3083 +b6fa 1 130 3083 +FUNC b6fb 18 8 _ismbbgraph_l +b6fb 0 133 3083 +b6fb 17 134 3083 +b712 1 135 3083 +FUNC b713 16 4 _ismbbgraph +b713 0 138 3083 +b713 15 139 3083 +b728 1 140 3083 +FUNC b729 18 8 _ismbbprint_l +b729 0 143 3083 +b729 17 144 3083 +b740 1 145 3083 +FUNC b741 16 4 _ismbbprint +b741 0 148 3083 +b741 15 149 3083 +b756 1 150 3083 +FUNC b757 15 8 _ismbbpunct_l +b757 0 153 3083 +b757 14 154 3083 +b76b 1 155 3083 +FUNC b76c 13 4 _ismbbpunct +b76c 0 158 3083 +b76c 12 159 3083 +b77e 1 160 3083 +FUNC b77f 15 8 _ismbblead_l +b77f 0 166 3083 +b77f 14 167 3083 +b793 1 168 3083 +FUNC b794 13 4 _ismbblead +b794 0 171 3083 +b794 12 172 3083 +b7a6 1 173 3083 +FUNC b7a7 15 8 _ismbbtrail_l +b7a7 0 176 3083 +b7a7 14 177 3083 +b7bb 1 178 3083 +FUNC b7bc 13 4 _ismbbtrail +b7bc 0 181 3083 +b7bc 12 182 3083 +b7ce 1 183 3083 +FUNC b7cf 53 8 _ismbbkana_l +b7cf 6 189 3083 +b7d5 b 190 3083 +b7e0 10 192 3083 +b7f0 1f 194 3083 +b80f 2 197 3083 +b811 f 196 3083 +b820 2 197 3083 +FUNC b822 e 4 _ismbbkana +b822 0 200 3083 +b822 d 201 3083 +b82f 1 202 3083 +FUNC b830 365 c memcpy +b830 3 101 614 +b833 1 113 614 +b834 1 114 614 +b835 3 116 614 +b838 3 117 614 +b83b 3 119 614 +b83e 2 129 614 +b840 2 131 614 +b842 2 132 614 +b844 2 134 614 +b846 2 135 614 +b848 2 137 614 +b84a 6 138 614 +b850 6 147 614 +b856 2 148 614 +b858 7 150 614 +b85f 2 151 614 +b861 1 153 614 +b862 1 154 614 +b863 3 155 614 +b866 3 156 614 +b869 2 157 614 +b86b 1 158 614 +b86c 1 159 614 +b86d 2 160 614 +b86f 1 163 614 +b870 1 164 614 +b871 1 165 614 +b872 5 166 614 +b877 6 179 614 +b87d 2 180 614 +b87f 3 182 614 +b882 3 183 614 +b885 3 185 614 +b888 2 186 614 +b88a 2 188 614 +b88c 8 190 614 +b894 2 208 614 +b896 5 209 614 +b89b 3 211 614 +b89e 2 212 614 +b8a0 3 214 614 +b8a3 2 215 614 +b8a5 7 217 614 +b8ac 8 221 614 +b8b4 14 225 614 +b8c8 2 232 614 +b8ca 2 233 614 +b8cc 2 235 614 +b8ce 3 236 614 +b8d1 3 238 614 +b8d4 3 239 614 +b8d7 3 241 614 +b8da 3 242 614 +b8dd 3 244 614 +b8e0 3 245 614 +b8e3 3 247 614 +b8e6 2 248 614 +b8e8 2 250 614 +b8ea a 252 614 +b8f4 2 256 614 +b8f6 2 257 614 +b8f8 2 259 614 +b8fa 3 260 614 +b8fd 3 262 614 +b900 3 263 614 +b903 3 265 614 +b906 3 266 614 +b909 3 268 614 +b90c 2 269 614 +b90e 2 271 614 +b910 8 273 614 +b918 2 277 614 +b91a 2 278 614 +b91c 2 280 614 +b91e 3 281 614 +b921 3 283 614 +b924 3 284 614 +b927 3 286 614 +b92a 2 287 614 +b92c 2 289 614 +b92e 2a 291 614 +b958 4 298 614 +b95c 4 300 614 +b960 4 302 614 +b964 4 304 614 +b968 4 306 614 +b96c 4 308 614 +b970 4 310 614 +b974 4 312 614 +b978 4 314 614 +b97c 4 316 614 +b980 4 318 614 +b984 4 320 614 +b988 4 322 614 +b98c 4 324 614 +b990 7 326 614 +b997 2 328 614 +b999 2 329 614 +b99b 19 331 614 +b9b4 3 340 614 +b9b7 1 341 614 +b9b8 1 342 614 +b9b9 3 344 614 +b9bc 2 348 614 +b9be 2 350 614 +b9c0 3 351 614 +b9c3 1 352 614 +b9c4 1 353 614 +b9c5 3 354 614 +b9c8 2 358 614 +b9ca 2 360 614 +b9cc 3 361 614 +b9cf 3 362 614 +b9d2 3 363 614 +b9d5 1 364 614 +b9d6 1 365 614 +b9d7 5 366 614 +b9dc 2 370 614 +b9de 2 372 614 +b9e0 3 373 614 +b9e3 3 374 614 +b9e6 3 375 614 +b9e9 3 376 614 +b9ec 3 377 614 +b9ef 1 378 614 +b9f0 1 379 614 +b9f1 3 380 614 +b9f4 4 391 614 +b9f8 4 392 614 +b9fc 6 397 614 +ba02 2 398 614 +ba04 3 400 614 +ba07 3 401 614 +ba0a 3 403 614 +ba0d 2 404 614 +ba0f 1 406 614 +ba10 2 407 614 +ba12 1 408 614 +ba13 9 410 614 +ba1c 2 414 614 +ba1e a 417 614 +ba28 2 422 614 +ba2a 5 423 614 +ba2f 3 425 614 +ba32 2 426 614 +ba34 3 428 614 +ba37 2 429 614 +ba39 7 431 614 +ba40 14 435 614 +ba54 3 442 614 +ba57 2 443 614 +ba59 3 445 614 +ba5c 3 446 614 +ba5f 3 448 614 +ba62 3 449 614 +ba65 3 451 614 +ba68 2 452 614 +ba6a 1 454 614 +ba6b 2 455 614 +ba6d 1 456 614 +ba6e a 458 614 +ba78 3 462 614 +ba7b 2 463 614 +ba7d 3 465 614 +ba80 3 466 614 +ba83 3 468 614 +ba86 3 469 614 +ba89 3 471 614 +ba8c 3 472 614 +ba8f 3 474 614 +ba92 2 475 614 +ba94 1 477 614 +ba95 2 478 614 +ba97 1 479 614 +ba98 8 481 614 +baa0 3 485 614 +baa3 2 486 614 +baa5 3 488 614 +baa8 3 489 614 +baab 3 491 614 +baae 3 492 614 +bab1 3 494 614 +bab4 3 495 614 +bab7 3 497 614 +baba 3 498 614 +babd 3 500 614 +bac0 6 501 614 +bac6 1 503 614 +bac7 2 504 614 +bac9 1 505 614 +baca 2a 507 614 +baf4 4 516 614 +baf8 4 518 614 +bafc 4 520 614 +bb00 4 522 614 +bb04 4 524 614 +bb08 4 526 614 +bb0c 4 528 614 +bb10 4 530 614 +bb14 4 532 614 +bb18 4 534 614 +bb1c 4 536 614 +bb20 4 538 614 +bb24 4 540 614 +bb28 4 542 614 +bb2c 7 544 614 +bb33 2 546 614 +bb35 2 547 614 +bb37 19 549 614 +bb50 3 558 614 +bb53 1 560 614 +bb54 1 561 614 +bb55 3 562 614 +bb58 3 566 614 +bb5b 3 568 614 +bb5e 3 569 614 +bb61 1 570 614 +bb62 1 571 614 +bb63 5 572 614 +bb68 3 576 614 +bb6b 3 578 614 +bb6e 3 579 614 +bb71 3 580 614 +bb74 3 581 614 +bb77 1 582 614 +bb78 1 583 614 +bb79 3 584 614 +bb7c 3 588 614 +bb7f 3 590 614 +bb82 3 591 614 +bb85 3 592 614 +bb88 3 593 614 +bb8b 3 594 614 +bb8e 3 595 614 +bb91 1 596 614 +bb92 1 597 614 +bb93 2 598 614 +FUNC bb95 6 0 ___setlc_active_func +bb95 0 90 1409 +bb95 5 91 1409 +bb9a 1 92 1409 +FUNC bb9b 6 0 ___unguarded_readlc_active_add_func +bb9b 0 104 1409 +bb9b 5 105 1409 +bba0 1 106 1409 +FUNC bba1 140 4 __freetlocinfo +bba1 3 144 1409 +bba4 26 152 1409 +bbca e 155 1409 +bbd8 6 157 1409 +bbde d 158 1409 +bbeb e 162 1409 +bbf9 6 164 1409 +bbff d 165 1409 +bc0c b 168 1409 +bc17 d 169 1409 +bc24 e 176 1409 +bc32 11 178 1409 +bc43 13 179 1409 +bc56 e 180 1409 +bc64 e 181 1409 +bc72 17 188 1409 +bc89 6 190 1409 +bc8f 9 191 1409 +bc98 6 194 1409 +bc9e 13 197 1409 +bcb1 7 199 1409 +bcb8 10 205 1409 +bcc8 d 207 1409 +bcd5 b 214 1409 +bce0 1 215 1409 +FUNC bce1 86 4 __addlocaleref +bce1 3 225 1409 +bce4 e 227 1409 +bcf2 a 228 1409 +bcfc 3 229 1409 +bcff a 231 1409 +bd09 3 232 1409 +bd0c a 234 1409 +bd16 3 235 1409 +bd19 a 237 1409 +bd23 3 238 1409 +bd26 6 240 1409 +bd2c f 242 1409 +bd3b 3 243 1409 +bd3e d 245 1409 +bd4b 9 246 1409 +bd54 12 248 1409 +bd66 1 249 1409 +FUNC bd67 8c 4 __removelocaleref +bd67 1 259 1409 +bd68 b 261 1409 +bd73 9 263 1409 +bd7c a 265 1409 +bd86 3 266 1409 +bd89 a 268 1409 +bd93 3 269 1409 +bd96 a 271 1409 +bda0 3 272 1409 +bda3 a 274 1409 +bdad 3 275 1409 +bdb0 6 277 1409 +bdb6 f 279 1409 +bdc5 3 280 1409 +bdc8 d 282 1409 +bdd5 9 283 1409 +bdde 11 285 1409 +bdef 3 287 1409 +bdf2 1 288 1409 +FUNC bdf3 24 0 _copytlocinfo_nolock +bdf3 3 302 1409 +bdf6 d 303 1409 +be03 7 304 1409 +be0a 3 305 1409 +be0d 9 306 1409 +be16 1 308 1409 +FUNC be17 3e 0 _updatetlocinfoEx_nolock +be17 0 321 1409 +be17 9 324 1409 +be20 2 326 1409 +be22 4 327 1409 +be26 8 334 1409 +be2e 5 339 1409 +be33 6 341 1409 +be39 e 350 1409 +be47 7 351 1409 +be4e 3 355 1409 +be51 1 356 1409 +be52 2 325 1409 +be54 1 356 1409 +FUNC be55 76 0 __updatetlocinfo +be55 c 382 1409 +be61 7 384 1409 +be68 10 386 1409 +be78 8 397 1409 +be80 4 399 1409 +be84 8 401 1409 +be8c 2 404 1409 +be8e 6 405 1409 +be94 8 387 1409 +be9c 4 388 1409 +bea0 11 390 1409 +beb1 e 392 1409 +bebf 8 394 1409 +bec7 4 395 1409 +FUNC becb 66 4 _configthreadlocale +becb 2 420 1409 +becd 5 434 1409 +bed2 10 435 1409 +bee2 19 437 1409 +befb 1d 456 1409 +bf18 3 444 1409 +bf1b 2 445 1409 +bf1d 6 440 1409 +bf23 2 441 1409 +bf25 7 452 1409 +bf2c 4 460 1409 +bf30 1 462 1409 +FUNC bf31 53 0 sync_legacy_variables_lk +bf31 0 489 1409 +bf31 e 490 1409 +bf3f 9 491 1409 +bf48 c 492 1409 +bf54 c 493 1409 +bf60 c 494 1409 +bf6c c 495 1409 +bf78 b 496 1409 +bf83 1 497 1409 +FUNC bf84 96 4 _free_locale +bf84 c 517 1409 +bf90 9 518 1409 +bf99 1c 522 1409 +bfb5 7 524 1409 +bfbc 4 526 1409 +bfc0 8 534 1409 +bfc8 3 535 1409 +bfcb 8 537 1409 +bfd3 11 540 1409 +bfe4 7 541 1409 +bfeb c 543 1409 +bff7 7 552 1409 +bffe 3 553 1409 +c001 7 554 1409 +c008 6 556 1409 +c00e 3 543 1409 +c011 9 545 1409 +FUNC c01a 5 4 __free_locale +c01a 0 562 1409 +c01a 5 563 1409 +FUNC c01f 88 0 _get_current_locale +c01f c 687 1409 +c02b 7 689 1409 +c032 14 691 1409 +c046 b 693 1409 +c051 4 694 1409 +c055 5 697 1409 +c05a 5 698 1409 +c05f 5 706 1409 +c064 6 707 1409 +c06a 8 708 1409 +c072 4 709 1409 +c076 8 710 1409 +c07e c 712 1409 +c08a 9 715 1409 +c093 2 717 1409 +c095 6 718 1409 +c09b 3 712 1409 +c09e 9 713 1409 +FUNC c0a7 5 0 __get_current_locale +c0a7 0 722 1409 +c0a7 5 723 1409 +FUNC c0ac 3 4 __init_dummy +c0ac 0 1283 1409 +c0ac 2 1284 1409 +c0ae 1 1285 1409 +FUNC c0af 3e c _strcats +c0af 2 1288 1409 +c0b1 f 1294 1409 +c0c0 26 1296 1409 +c0e6 6 1294 1409 +c0ec 1 1299 1409 +FUNC c0ed 129 8 __lc_strtolc +c0ed 6 1302 1409 +c0f3 11 1307 1409 +c104 c 1309 1409 +c110 7 1310 1409 +c117 b 1313 1409 +c122 25 1315 1409 +c147 6 1317 1409 +c14d 2 1318 1409 +c14f 15 1323 1409 +c164 1d 1328 1409 +c181 9 1329 1409 +c18a 10 1331 1409 +c19a c 1332 1409 +c1a6 14 1334 1409 +c1ba 28 1335 1409 +c1e2 9 1340 1409 +c1eb b 1348 1409 +c1f6 18 1350 1409 +c20e 6 1338 1409 +c214 2 1353 1409 +FUNC c216 6b c __lc_lctostr +c216 5 1356 1409 +c21b 25 1357 1409 +c240 7 1358 1409 +c247 16 1359 1409 +c25d c 1360 1409 +c269 16 1361 1409 +c27f 2 1362 1409 +FUNC c281 171 0 _setlocale_get_all +c281 4 1124 1409 +c285 3 1126 1409 +c288 1d 1134 1409 +c2a5 3 1137 1409 +c2a8 3 1139 1409 +c2ab 2 1140 1409 +c2ad 2f 1143 1409 +c2dc 26 1146 1409 +c302 10 1147 1409 +c312 5 1148 1409 +c317 4 1141 1409 +c31b 2f 1143 1409 +c34a a 1144 1409 +c354 8 1152 1409 +c35c 14 1154 1409 +c370 9 1156 1409 +c379 e 1159 1409 +c387 9 1161 1409 +c390 7 1165 1409 +c397 7 1166 1409 +c39e 9 1168 1409 +c3a7 15 1170 1409 +c3bc 9 1172 1409 +c3c5 e 1175 1409 +c3d3 9 1177 1409 +c3dc 12 1183 1409 +c3ee 4 1187 1409 +FUNC c3f2 1d4 18 _expandlocale +c3f2 15 1198 1409 +c407 41 1230 1409 +c448 14 1211 1409 +c45c b 1216 1409 +c467 26 1219 1409 +c48d 4 1220 1409 +c491 3 1222 1409 +c494 4 1223 1409 +c498 4 1224 1409 +c49c 7 1226 1409 +c4a3 2 1228 1409 +c4a5 8 1230 1409 +c4ad 6 1234 1409 +c4b3 2f 1236 1409 +c4e2 4 1241 1409 +c4e6 e 1243 1409 +c4f4 6 1244 1409 +c4fa 10 1246 1409 +c50a 6 1247 1409 +c510 9 1251 1409 +c519 10 1253 1409 +c529 a 1255 1409 +c533 2 1260 1409 +c535 8 1263 1409 +c53d 26 1267 1409 +c563 5 1271 1409 +c568 e 1272 1409 +c576 5 1273 1409 +c57b 10 1274 1409 +c58b 22 1276 1409 +c5ad 5 1277 1409 +c5b2 2 1212 1409 +c5b4 12 1278 1409 +FUNC c5c6 2f6 4 _setlocale_set_cat +c5c6 19 980 1409 +c5df 5 993 1409 +c5e4 2f 998 1409 +c613 7 1000 1409 +c61a 19 1002 1409 +c633 6 1004 1409 +c639 c 1007 1409 +c645 16 1008 1409 +c65b 2 1010 1409 +c65d 3 1013 1409 +c660 d 1014 1409 +c66d 2c 1015 1409 +c699 3 1016 1409 +c69c 39 1019 1409 +c6d5 6 1020 1409 +c6db 15 1021 1409 +c6f0 17 1022 1409 +c707 a 1029 1409 +c711 6 1031 1409 +c717 18 1037 1409 +c72f 7 1039 1409 +c736 8 1053 1409 +c73e 14 1054 1409 +c752 18 1055 1409 +c76a 2 1039 1409 +c76c a 1044 1409 +c776 d 1046 1409 +c783 b 1047 1409 +c78e 9 1058 1409 +c797 26 1066 1409 +c7bd 2 1069 1409 +c7bf 10 1071 1409 +c7cf 22 1072 1409 +c7f1 2 1081 1409 +c7f3 4 1082 1409 +c7f7 5 1083 1409 +c7fc 9 1085 1409 +c805 6 1088 1409 +c80b 9 1089 1409 +c814 12 1091 1409 +c826 6 1094 1409 +c82c e 1095 1409 +c83a f 1096 1409 +c849 9 1097 1409 +c852 5 1099 1409 +c857 24 1106 1409 +c87b 7 1109 1409 +c882 8 1110 1409 +c88a 6 1111 1409 +c890 18 1116 1409 +c8a8 3 1118 1409 +c8ab 11 1119 1409 +FUNC c8bc 1ce 4 _setlocale_nolock +c8bc 1a 873 1409 +c8d6 7 877 1409 +c8dd 5 904 1409 +c8e2 17 880 1409 +c8f9 5 882 1409 +c8fe 12 888 1409 +c910 1d 890 1409 +c92d 2 894 1409 +c92f d 898 1409 +c93c 1e 900 1409 +c95a 11 904 1409 +c96b 1d 907 1409 +c988 e 904 1409 +c996 1b 913 1409 +c9b1 6 916 1409 +c9b7 24 918 1409 +c9db 18 922 1409 +c9f3 3 923 1409 +c9f6 7 925 1409 +c9fd 1 926 1409 +c9fe 9 928 1409 +ca07 c 930 1409 +ca13 4 901 1409 +ca17 19 935 1409 +ca30 3 937 1409 +ca33 4 939 1409 +ca37 11 941 1409 +ca48 c 943 1409 +ca54 2 947 1409 +ca56 3 949 1409 +ca59 2 952 1409 +ca5b 3 953 1409 +ca5e 9 937 1409 +ca67 5 956 1409 +ca6c 2 961 1409 +ca6e 3 962 1409 +ca71 2 965 1409 +ca73 5 966 1409 +ca78 12 972 1409 +FUNC ca8a f3 8 _create_locale +ca8a 0 605 1409 +ca8a 10 609 1409 +ca9a 13 612 1409 +caad b 614 1409 +cab8 4 610 1409 +cabc c 658 1409 +cac8 8 617 1409 +cad0 7 619 1409 +cad7 2 621 1409 +cad9 14 623 1409 +caed 7 625 1409 +caf4 7 626 1409 +cafb 2 628 1409 +cafd c 630 1409 +cb09 14 632 1409 +cb1d 7 634 1409 +cb24 7 635 1409 +cb2b 9 637 1409 +cb34 2 640 1409 +cb36 13 642 1409 +cb49 8 644 1409 +cb51 7 645 1409 +cb58 7 646 1409 +cb5f 9 647 1409 +cb68 2 648 1409 +cb6a 2 650 1409 +cb6c 5 652 1409 +cb71 5 653 1409 +cb76 7 657 1409 +FUNC cb7d 5 8 __create_locale +cb7d 0 665 1409 +cb7d 5 666 1409 +FUNC cb82 170 8 setlocale +cb82 c 791 1409 +cb8e 5 792 1409 +cb93 25 797 1409 +cbb8 a 799 1409 +cbc2 5 801 1409 +cbc7 4 806 1409 +cbcb 3 807 1409 +cbce 1b 808 1409 +cbe9 8 818 1409 +cbf1 7 819 1409 +cbf8 a 820 1409 +cc02 8 822 1409 +cc0a 19 826 1409 +cc23 18 834 1409 +cc3b a 836 1409 +cc45 8 839 1409 +cc4d 7 840 1409 +cc54 a 841 1409 +cc5e 7 842 1409 +cc65 f 846 1409 +cc74 c 847 1409 +cc80 18 849 1409 +cc98 5 850 1409 +cc9d b 852 1409 +cca8 8 822 1409 +ccb0 9 823 1409 +ccb9 3 852 1409 +ccbc 9 853 1409 +ccc5 2 855 1409 +ccc7 6 856 1409 +cccd 8 857 1409 +ccd5 c 860 1409 +cce1 3 865 1409 +cce4 6 866 1409 +ccea 3 860 1409 +cced 5 862 1409 +FUNC ccf2 f 0 __security_check_cookie +ccf2 0 52 2811 +ccf2 6 55 2811 +ccf8 2 56 2811 +ccfa 2 57 2811 +ccfc 5 59 2811 +FUNC cd04 90 0 _local_unwind4 +FUNC cd94 46 0 _unwind_handler4 +FUNC cdda 1c 4 _seh_longjmp_unwind4 +FUNC cdf6 17 0 _EH4_CallFilterFunc +FUNC ce0d 19 0 _EH4_TransferToHandler +FUNC ce26 1a 0 _EH4_GlobalUnwind +FUNC ce40 17 8 _EH4_LocalUnwind +FUNC ce57 8 4 _crt_debugger_hook +ce57 0 62 2380 +ce57 7 65 2380 +ce5e 1 66 2380 +FUNC ce60 7a c memset +ce60 0 59 601 +ce60 4 68 601 +ce64 4 69 601 +ce68 2 71 601 +ce6a 2 72 601 +ce6c 2 74 601 +ce6e 4 75 601 +ce72 2 78 601 +ce74 2 79 601 +ce76 6 80 601 +ce7c 2 81 601 +ce7e 7 82 601 +ce85 2 83 601 +ce87 5 85 601 +ce8c 1 91 601 +ce8d 2 92 601 +ce8f 3 94 601 +ce92 2 95 601 +ce94 2 97 601 +ce96 3 98 601 +ce99 2 99 601 +ce9b 2 101 601 +ce9d 2 103 601 +ce9f 3 104 601 +cea2 3 105 601 +cea5 2 106 601 +cea7 2 110 601 +cea9 3 111 601 +ceac 2 113 601 +ceae 2 115 601 +ceb0 3 117 601 +ceb3 2 119 601 +ceb5 2 122 601 +ceb7 3 123 601 +ceba 3 124 601 +cebd 2 125 601 +cebf 2 127 601 +cec1 2 129 601 +cec3 2 130 601 +cec5 2 134 601 +cec7 3 135 601 +ceca 3 137 601 +cecd 2 138 601 +cecf 4 142 601 +ced3 1 143 601 +ced4 1 145 601 +ced5 4 148 601 +ced9 1 150 601 +FUNC ceda 2a 0 _purecall +ceda 0 43 1533 +ceda b 44 1533 +cee5 5 45 1533 +ceea 2 47 1533 +ceec 7 54 1533 +cef3 c 56 1533 +ceff 5 57 1533 +FUNC cf04 22 4 _set_purecall_handler +cf04 1 82 1533 +cf05 b 85 1533 +cf10 12 86 1533 +cf22 3 88 1533 +cf25 1 89 1533 +FUNC cf26 d 0 _get_purecall_handler +cf26 0 92 1533 +cf26 c 93 1533 +cf32 1 94 1533 +FUNC cf40 95 0 _aulldvrm +cf40 0 45 3161 +cf40 1 47 3161 +cf41 4 79 3161 +cf45 2 80 3161 +cf47 2 81 3161 +cf49 4 82 3161 +cf4d 4 83 3161 +cf51 2 84 3161 +cf53 2 85 3161 +cf55 2 86 3161 +cf57 4 87 3161 +cf5b 2 88 3161 +cf5d 2 89 3161 +cf5f 2 94 3161 +cf61 4 95 3161 +cf65 2 96 3161 +cf67 2 97 3161 +cf69 4 98 3161 +cf6d 2 99 3161 +cf6f 2 100 3161 +cf71 2 107 3161 +cf73 4 108 3161 +cf77 4 109 3161 +cf7b 4 110 3161 +cf7f 2 112 3161 +cf81 2 113 3161 +cf83 2 114 3161 +cf85 2 115 3161 +cf87 2 116 3161 +cf89 2 117 3161 +cf8b 2 118 3161 +cf8d 2 119 3161 +cf8f 4 128 3161 +cf93 2 129 3161 +cf95 4 130 3161 +cf99 2 131 3161 +cf9b 2 132 3161 +cf9d 2 133 3161 +cf9f 4 141 3161 +cfa3 2 142 3161 +cfa5 2 143 3161 +cfa7 4 144 3161 +cfab 2 145 3161 +cfad 1 147 3161 +cfae 4 148 3161 +cfb2 4 149 3161 +cfb6 2 151 3161 +cfb8 4 160 3161 +cfbc 4 161 3161 +cfc0 2 162 3161 +cfc2 2 163 3161 +cfc4 3 164 3161 +cfc7 2 169 3161 +cfc9 2 170 3161 +cfcb 2 171 3161 +cfcd 2 172 3161 +cfcf 2 173 3161 +cfd1 1 179 3161 +cfd2 3 181 3161 +FUNC cfe0 34 0 _allmul +cfe0 0 47 3164 +cfe0 4 62 3164 +cfe4 4 63 3164 +cfe8 2 64 3164 +cfea 4 65 3164 +cfee 2 66 3164 +cff0 4 68 3164 +cff4 2 69 3164 +cff6 3 71 3164 +cff9 1 74 3164 +cffa 2 81 3164 +cffc 2 82 3164 +cffe 4 84 3164 +d002 4 85 3164 +d006 2 86 3164 +d008 4 88 3164 +d00c 2 89 3164 +d00e 2 90 3164 +d010 1 92 3164 +d011 3 94 3164 +FUNC d014 11 4 atol +d014 0 55 4301 +d014 10 56 4301 +d024 1 57 4301 +FUNC d025 15 8 _atol_l +d025 0 64 4301 +d025 14 65 4301 +d039 1 66 4301 +FUNC d03a 5 4 atoi +d03a 0 99 4301 +d03a 5 100 4301 +FUNC d03f 5 8 _atoi_l +d03f 0 107 4301 +d03f 5 108 4301 +FUNC d044 11 4 _atoi64 +d044 0 143 4301 +d044 10 144 4301 +d054 1 145 4301 +FUNC d055 15 8 _atoi64_l +d055 0 151 4301 +d055 14 152 4301 +d069 1 153 4301 +FUNC d070 365 c memmove +d070 3 101 604 +d073 1 113 604 +d074 1 114 604 +d075 3 116 604 +d078 3 117 604 +d07b 3 119 604 +d07e 2 129 604 +d080 2 131 604 +d082 2 132 604 +d084 2 134 604 +d086 2 135 604 +d088 2 137 604 +d08a 6 138 604 +d090 6 147 604 +d096 2 148 604 +d098 7 150 604 +d09f 2 151 604 +d0a1 1 153 604 +d0a2 1 154 604 +d0a3 3 155 604 +d0a6 3 156 604 +d0a9 2 157 604 +d0ab 1 158 604 +d0ac 1 159 604 +d0ad 2 160 604 +d0af 1 163 604 +d0b0 1 164 604 +d0b1 1 165 604 +d0b2 5 166 604 +d0b7 6 179 604 +d0bd 2 180 604 +d0bf 3 182 604 +d0c2 3 183 604 +d0c5 3 185 604 +d0c8 2 186 604 +d0ca 2 188 604 +d0cc 8 190 604 +d0d4 2 208 604 +d0d6 5 209 604 +d0db 3 211 604 +d0de 2 212 604 +d0e0 3 214 604 +d0e3 2 215 604 +d0e5 7 217 604 +d0ec 8 221 604 +d0f4 14 225 604 +d108 2 232 604 +d10a 2 233 604 +d10c 2 235 604 +d10e 3 236 604 +d111 3 238 604 +d114 3 239 604 +d117 3 241 604 +d11a 3 242 604 +d11d 3 244 604 +d120 3 245 604 +d123 3 247 604 +d126 2 248 604 +d128 2 250 604 +d12a a 252 604 +d134 2 256 604 +d136 2 257 604 +d138 2 259 604 +d13a 3 260 604 +d13d 3 262 604 +d140 3 263 604 +d143 3 265 604 +d146 3 266 604 +d149 3 268 604 +d14c 2 269 604 +d14e 2 271 604 +d150 8 273 604 +d158 2 277 604 +d15a 2 278 604 +d15c 2 280 604 +d15e 3 281 604 +d161 3 283 604 +d164 3 284 604 +d167 3 286 604 +d16a 2 287 604 +d16c 2 289 604 +d16e 2a 291 604 +d198 4 298 604 +d19c 4 300 604 +d1a0 4 302 604 +d1a4 4 304 604 +d1a8 4 306 604 +d1ac 4 308 604 +d1b0 4 310 604 +d1b4 4 312 604 +d1b8 4 314 604 +d1bc 4 316 604 +d1c0 4 318 604 +d1c4 4 320 604 +d1c8 4 322 604 +d1cc 4 324 604 +d1d0 7 326 604 +d1d7 2 328 604 +d1d9 2 329 604 +d1db 19 331 604 +d1f4 3 340 604 +d1f7 1 341 604 +d1f8 1 342 604 +d1f9 3 344 604 +d1fc 2 348 604 +d1fe 2 350 604 +d200 3 351 604 +d203 1 352 604 +d204 1 353 604 +d205 3 354 604 +d208 2 358 604 +d20a 2 360 604 +d20c 3 361 604 +d20f 3 362 604 +d212 3 363 604 +d215 1 364 604 +d216 1 365 604 +d217 5 366 604 +d21c 2 370 604 +d21e 2 372 604 +d220 3 373 604 +d223 3 374 604 +d226 3 375 604 +d229 3 376 604 +d22c 3 377 604 +d22f 1 378 604 +d230 1 379 604 +d231 3 380 604 +d234 4 391 604 +d238 4 392 604 +d23c 6 397 604 +d242 2 398 604 +d244 3 400 604 +d247 3 401 604 +d24a 3 403 604 +d24d 2 404 604 +d24f 1 406 604 +d250 2 407 604 +d252 1 408 604 +d253 9 410 604 +d25c 2 414 604 +d25e a 417 604 +d268 2 422 604 +d26a 5 423 604 +d26f 3 425 604 +d272 2 426 604 +d274 3 428 604 +d277 2 429 604 +d279 7 431 604 +d280 14 435 604 +d294 3 442 604 +d297 2 443 604 +d299 3 445 604 +d29c 3 446 604 +d29f 3 448 604 +d2a2 3 449 604 +d2a5 3 451 604 +d2a8 2 452 604 +d2aa 1 454 604 +d2ab 2 455 604 +d2ad 1 456 604 +d2ae a 458 604 +d2b8 3 462 604 +d2bb 2 463 604 +d2bd 3 465 604 +d2c0 3 466 604 +d2c3 3 468 604 +d2c6 3 469 604 +d2c9 3 471 604 +d2cc 3 472 604 +d2cf 3 474 604 +d2d2 2 475 604 +d2d4 1 477 604 +d2d5 2 478 604 +d2d7 1 479 604 +d2d8 8 481 604 +d2e0 3 485 604 +d2e3 2 486 604 +d2e5 3 488 604 +d2e8 3 489 604 +d2eb 3 491 604 +d2ee 3 492 604 +d2f1 3 494 604 +d2f4 3 495 604 +d2f7 3 497 604 +d2fa 3 498 604 +d2fd 3 500 604 +d300 6 501 604 +d306 1 503 604 +d307 2 504 604 +d309 1 505 604 +d30a 2a 507 604 +d334 4 516 604 +d338 4 518 604 +d33c 4 520 604 +d340 4 522 604 +d344 4 524 604 +d348 4 526 604 +d34c 4 528 604 +d350 4 530 604 +d354 4 532 604 +d358 4 534 604 +d35c 4 536 604 +d360 4 538 604 +d364 4 540 604 +d368 4 542 604 +d36c 7 544 604 +d373 2 546 604 +d375 2 547 604 +d377 19 549 604 +d390 3 558 604 +d393 1 560 604 +d394 1 561 604 +d395 3 562 604 +d398 3 566 604 +d39b 3 568 604 +d39e 3 569 604 +d3a1 1 570 604 +d3a2 1 571 604 +d3a3 5 572 604 +d3a8 3 576 604 +d3ab 3 578 604 +d3ae 3 579 604 +d3b1 3 580 604 +d3b4 3 581 604 +d3b7 1 582 604 +d3b8 1 583 604 +d3b9 3 584 604 +d3bc 3 588 604 +d3bf 3 590 604 +d3c2 3 591 604 +d3c5 3 592 604 +d3c8 3 593 604 +d3cb 3 594 604 +d3ce 3 595 604 +d3d1 1 596 604 +d3d2 1 597 604 +d3d3 2 598 604 +FUNC d3d5 f3 0 abort +d3d5 1b 53 2533 +d3f0 a 56 2533 +d3fa 8 59 2533 +d402 5 68 2533 +d407 4 69 2533 +d40b 8 71 2533 +d413 d 78 2533 +d420 6 87 2533 +d426 6 88 2533 +d42c 6 89 2533 +d432 3 90 2533 +d435 3 91 2533 +d438 3 92 2533 +d43b 7 93 2533 +d442 7 94 2533 +d449 4 95 2533 +d44d 4 96 2533 +d451 4 97 2533 +d455 4 98 2533 +d459 1 99 2533 +d45a 6 100 2533 +d460 6 106 2533 +d466 19 107 2533 +d47f 3 109 2533 +d482 13 117 2533 +d495 9 122 2533 +d49e 3 123 2533 +d4a1 15 126 2533 +d4b6 a 128 2533 +d4c0 8 137 2533 +FUNC d4c8 1e 8 _set_abort_behavior +d4c8 0 158 2533 +d4c8 1d 160 2533 +d4e5 1 162 2533 +FUNC d4e6 a3 4 _msize +d4e6 c 43 3413 +d4f2 2d 47 3413 +d51f 9 51 3413 +d528 8 55 3413 +d530 3 56 3413 +d533 e 57 3413 +d541 e 59 3413 +d54f c 61 3413 +d55b 5 64 3413 +d560 10 88 3413 +d570 2 91 3413 +d572 6 93 3413 +d578 8 61 3413 +d580 9 62 3413 +FUNC d589 9 0 _fptrap +d589 0 46 917 +d589 8 47 917 +d591 1 48 917 +FUNC d592 54 8 _isalpha_l +d592 6 57 4214 +d598 b 58 4214 +d5a3 41 60 4214 +d5e4 2 61 4214 +FUNC d5e6 2b 4 isalpha +d5e6 0 66 4214 +d5e6 9 67 4214 +d5ef 13 69 4214 +d602 1 75 4214 +d603 d 73 4214 +d610 1 75 4214 +FUNC d611 4f 8 _isupper_l +d611 6 81 4214 +d617 b 82 4214 +d622 3c 84 4214 +d65e 2 85 4214 +FUNC d660 29 4 isupper +d660 0 90 4214 +d660 9 91 4214 +d669 11 93 4214 +d67a 1 99 4214 +d67b d 97 4214 +d688 1 99 4214 +FUNC d689 4f 8 _islower_l +d689 6 105 4214 +d68f b 106 4214 +d69a 3c 108 4214 +d6d6 2 109 4214 +FUNC d6d8 29 4 islower +d6d8 0 114 4214 +d6d8 9 115 4214 +d6e1 11 117 4214 +d6f2 1 123 4214 +d6f3 d 121 4214 +d700 1 123 4214 +FUNC d701 4f 8 _isdigit_l +d701 6 129 4214 +d707 b 130 4214 +d712 3c 132 4214 +d74e 2 133 4214 +FUNC d750 29 4 isdigit +d750 0 138 4214 +d750 9 139 4214 +d759 11 141 4214 +d76a 1 147 4214 +d76b d 145 4214 +d778 1 147 4214 +FUNC d779 54 8 _isxdigit_l +d779 6 153 4214 +d77f b 154 4214 +d78a 41 156 4214 +d7cb 2 157 4214 +FUNC d7cd 2b 4 isxdigit +d7cd 0 162 4214 +d7cd 9 163 4214 +d7d6 13 165 4214 +d7e9 1 171 4214 +d7ea d 169 4214 +d7f7 1 171 4214 +FUNC d7f8 4f 8 _isspace_l +d7f8 6 177 4214 +d7fe b 178 4214 +d809 3c 180 4214 +d845 2 181 4214 +FUNC d847 29 4 isspace +d847 0 186 4214 +d847 9 187 4214 +d850 11 189 4214 +d861 1 195 4214 +d862 d 193 4214 +d86f 1 195 4214 +FUNC d870 4f 8 _ispunct_l +d870 6 201 4214 +d876 b 202 4214 +d881 3c 204 4214 +d8bd 2 205 4214 +FUNC d8bf 29 4 ispunct +d8bf 0 210 4214 +d8bf 9 211 4214 +d8c8 11 213 4214 +d8d9 1 219 4214 +d8da d 217 4214 +d8e7 1 219 4214 +FUNC d8e8 54 8 _isalnum_l +d8e8 6 225 4214 +d8ee b 226 4214 +d8f9 41 228 4214 +d93a 2 229 4214 +FUNC d93c 2b 4 isalnum +d93c 0 234 4214 +d93c 9 235 4214 +d945 13 237 4214 +d958 1 243 4214 +d959 d 241 4214 +d966 1 243 4214 +FUNC d967 54 8 _isprint_l +d967 6 249 4214 +d96d b 250 4214 +d978 41 252 4214 +d9b9 2 253 4214 +FUNC d9bb 2b 4 isprint +d9bb 0 258 4214 +d9bb 9 259 4214 +d9c4 13 261 4214 +d9d7 1 267 4214 +d9d8 d 265 4214 +d9e5 1 267 4214 +FUNC d9e6 54 8 _isgraph_l +d9e6 6 273 4214 +d9ec b 274 4214 +d9f7 41 276 4214 +da38 2 277 4214 +FUNC da3a 2b 4 isgraph +da3a 0 282 4214 +da3a 9 283 4214 +da43 13 285 4214 +da56 1 291 4214 +da57 d 289 4214 +da64 1 291 4214 +FUNC da65 4f 8 _iscntrl_l +da65 6 297 4214 +da6b b 298 4214 +da76 3c 300 4214 +dab2 2 301 4214 +FUNC dab4 29 4 iscntrl +dab4 0 306 4214 +dab4 9 307 4214 +dabd 11 309 4214 +dace 1 315 4214 +dacf d 313 4214 +dadc 1 315 4214 +FUNC dadd d 4 __isascii +dadd 0 320 4214 +dadd c 321 4214 +dae9 1 322 4214 +FUNC daea 8 4 __toascii +daea 0 327 4214 +daea 7 328 4214 +daf1 1 329 4214 +FUNC daf2 1f 8 _iscsymf_l +daf2 0 335 4214 +daf2 1a 336 4214 +db0c 1 337 4214 +db0d 3 336 4214 +db10 1 337 4214 +FUNC db11 1a 4 __iscsymf +db11 0 341 4214 +db11 15 342 4214 +db26 1 343 4214 +db27 3 342 4214 +db2a 1 343 4214 +FUNC db2b 1f 8 _iscsym_l +db2b 0 349 4214 +db2b 1a 350 4214 +db45 1 351 4214 +db46 3 350 4214 +db49 1 351 4214 +FUNC db4a 1c 4 __iscsym +db4a 0 356 4214 +db4a 17 357 4214 +db61 1 358 4214 +db62 3 357 4214 +db65 1 358 4214 +FUNC db66 12 8 _MarkAllocaS +db66 0 207 1309 +db66 8 208 1309 +db6e 6 210 1309 +db74 3 211 1309 +db77 1 214 1309 +FUNC db78 1b 4 _freea +db78 0 249 1309 +db78 8 251 1309 +db80 3 253 1309 +db83 8 255 1309 +db8b 7 257 1309 +db92 1 266 1309 +FUNC db93 13b 18 __crtGetLocaleInfoW_stat +db93 f 60 1290 +dba2 14 68 1290 +dbb6 d 70 1290 +dbc3 8 71 1290 +dbcb b 73 1290 +dbd6 f 74 1290 +dbe5 5 79 1290 +dbea 13 81 1290 +dbfd 7 86 1290 +dc04 2 140 1290 +dc06 8 96 1290 +dc0e b 97 1290 +dc19 16 100 1290 +dc2f 7 101 1290 +dc36 48 104 1290 +dc7e 2 105 1290 +dc80 2 106 1290 +dc82 e 110 1290 +dc90 7 113 1290 +dc97 2 121 1290 +dc99 2 123 1290 +dc9b 17 130 1290 +dcb2 6 134 1290 +dcb8 4 136 1290 +dcbc 12 141 1290 +FUNC dcce 3b 18 __crtGetLocaleInfoW +dcce 6 151 1290 +dcd4 b 152 1290 +dcdf 28 161 1290 +dd07 2 162 1290 +FUNC dd09 13d 18 __crtGetLocaleInfoA_stat +dd09 f 60 2665 +dd18 17 68 2665 +dd2f a 70 2665 +dd39 8 71 2665 +dd41 b 73 2665 +dd4c f 74 2665 +dd5b 11 79 2665 +dd6c 4 86 2665 +dd70 5 96 2665 +dd75 b 97 2665 +dd80 13 100 2665 +dd93 7 101 2665 +dd9a 49 104 2665 +dde3 2 105 2665 +dde5 2 106 2665 +dde7 10 110 2665 +ddf7 3 114 2665 +ddfa 6 124 2665 +de00 2 126 2665 +de02 15 135 2665 +de17 7 139 2665 +de1e 4 141 2665 +de22 12 81 2665 +de34 12 145 2665 +FUNC de46 3b 18 __crtGetLocaleInfoA +de46 6 155 2665 +de4c b 156 2665 +de57 28 165 2665 +de7f 2 166 2665 +FUNC de81 11e c _calloc_impl +de81 c 23 3622 +de8d 9 28 3622 +de96 2e 30 3622 +dec4 9 32 3622 +decd 4 36 3622 +ded1 3 37 3622 +ded4 5 41 3622 +ded9 5 43 3622 +dede 9 46 3622 +dee7 9 50 3622 +def0 b 52 3622 +defb 8 56 3622 +df03 3 57 3622 +df06 c 58 3622 +df12 c 60 3622 +df1e 7 64 3622 +df25 d 65 3622 +df32 4 93 3622 +df36 11 94 3622 +df47 c 97 3622 +df53 f 109 3622 +df62 b 111 3622 +df6d 6 112 3622 +df73 5 113 3622 +df78 5 60 3622 +df7d 9 61 3622 +df86 4 100 3622 +df8a 7 102 3622 +df91 6 103 3622 +df97 2 105 3622 +df99 6 119 3622 +FUNC df9f 3f 8 calloc +df9f 4 145 3622 +dfa3 5 146 3622 +dfa8 14 147 3622 +dfbc 15 149 3622 +dfd1 8 151 3622 +dfd9 3 153 3622 +dfdc 2 154 3622 +FUNC dfde 21b 8 realloc +dfde c 64 3368 +dfea 7 69 3368 +dff1 e 70 3368 +dfff 7 73 3368 +e006 7 75 3368 +e00d 5 76 3368 +e012 d 81 3368 +e01f 5 88 3368 +e024 9 89 3368 +e02d 8 91 3368 +e035 3 92 3368 +e038 12 96 3368 +e04a 8 100 3368 +e052 f 102 3368 +e061 5 103 3368 +e066 e 104 3368 +e074 4 107 3368 +e078 10 108 3368 +e088 9 110 3368 +e091 a 111 3368 +e09b 5 118 3368 +e0a0 4 120 3368 +e0a4 6 121 3368 +e0aa 9 123 3368 +e0b3 15 124 3368 +e0c8 4 127 3368 +e0cc 10 128 3368 +e0dc c 129 3368 +e0e8 c 135 3368 +e0f4 6 142 3368 +e0fa 4 144 3368 +e0fe 1 145 3368 +e0ff 9 147 3368 +e108 14 148 3368 +e11c 6 135 3368 +e122 9 137 3368 +e12b 3 148 3368 +e12e 10 158 3368 +e13e f 181 3368 +e14d 5 186 3368 +e152 5 183 3368 +e157 11 186 3368 +e168 2 188 3368 +e16a 8 160 3368 +e172 5 170 3368 +e177 3 167 3368 +e17a 2 172 3368 +e17c 6 174 3368 +e182 2 155 3368 +e184 4 321 3368 +e188 1 322 3368 +e189 12 323 3368 +e19b c 332 3368 +e1a7 b 347 3368 +e1b2 5 319 3368 +e1b7 7 327 3368 +e1be b 328 3368 +e1c9 2 329 3368 +e1cb 6 356 3368 +e1d1 5 349 3368 +e1d6 5 350 3368 +e1db 4 334 3368 +e1df 16 341 3368 +e1f5 4 343 3368 +FUNC e1f9 79 c _recalloc +e1f9 3 744 3368 +e1fc a 749 3368 +e206 28 751 3368 +e22e 4 753 3368 +e232 9 754 3368 +e23b b 755 3368 +e246 b 756 3368 +e251 a 757 3368 +e25b 10 759 3368 +e26b 5 761 3368 +e270 2 762 3368 +FUNC e272 1a 4 strncnt +e272 0 48 2617 +e272 6 49 2617 +e278 6 52 2617 +e27e 1 53 2617 +e27f 5 52 2617 +e284 7 55 2617 +e28b 1 56 2617 +FUNC e28c 3a2 20 __crtLCMapStringA_stat +e28c 12 99 2617 +e29e d 108 2617 +e2ab 1b 109 2617 +e2c6 8 110 2617 +e2ce b 111 2617 +e2d9 a 112 2617 +e2e3 5 119 2617 +e2e8 19 120 2617 +e301 5 124 2617 +e306 1 125 2617 +e307 3 127 2617 +e30a 16 133 2617 +e320 9 213 2617 +e329 8 235 2617 +e331 8 236 2617 +e339 27 247 2617 +e360 6 248 2617 +e366 48 251 2617 +e3ae 3 252 2617 +e3b1 6 253 2617 +e3b7 19 262 2617 +e3d0 21 271 2617 +e3f1 8 274 2617 +e3f9 9 277 2617 +e402 9 279 2617 +e40b 12 288 2617 +e41d 5 292 2617 +e422 4b 298 2617 +e46d 4 299 2617 +e471 18 309 2617 +e489 3 312 2617 +e48c 6 322 2617 +e492 2 325 2617 +e494 17 335 2617 +e4ab 7 342 2617 +e4b2 8 344 2617 +e4ba 9 346 2617 +e4c3 b 141 2617 +e4ce 8 142 2617 +e4d6 5 143 2617 +e4db 8 144 2617 +e4e3 11 146 2617 +e4f4 7 147 2617 +e4fb 9 153 2617 +e504 15 155 2617 +e519 5 156 2617 +e51e 2 157 2617 +e520 1b 164 2617 +e53b 7 166 2617 +e542 41 169 2617 +e583 2 170 2617 +e585 28 196 2617 +e5ad 2 183 2617 +e5af 2 184 2617 +e5b1 25 190 2617 +e5d6 7 198 2617 +e5dd 2 199 2617 +e5df 1a 202 2617 +e5f9 5 204 2617 +e5fe 9 205 2617 +e607 c 206 2617 +e613 7 207 2617 +e61a 2 208 2617 +e61c 12 350 2617 +FUNC e62e 43 24 __crtLCMapStringA +e62e 6 363 2617 +e634 b 364 2617 +e63f 30 376 2617 +e66f 2 377 2617 +FUNC e671 1b8 1c __crtGetStringTypeA_stat +e671 f 66 2569 +e680 10 75 2569 +e690 18 79 2569 +e6a8 8 80 2569 +e6b0 b 82 2569 +e6bb f 83 2569 +e6ca 11 88 2569 +e6db 9 120 2569 +e6e4 8 141 2569 +e6ec 8 142 2569 +e6f4 27 153 2569 +e71b 6 154 2569 +e721 3e 157 2569 +e75f 2 158 2569 +e761 2 159 2569 +e763 f 161 2569 +e772 13 169 2569 +e785 11 174 2569 +e796 6 176 2569 +e79c 6 178 2569 +e7a2 2 90 2569 +e7a4 5 94 2569 +e7a9 8 95 2569 +e7b1 5 96 2569 +e7b6 8 97 2569 +e7be e 99 2569 +e7cc 4 100 2569 +e7d0 5 104 2569 +e7d5 17 106 2569 +e7ec 2 107 2569 +e7ee 2 108 2569 +e7f0 3 109 2569 +e7f3 15 112 2569 +e808 6 113 2569 +e80e 7 114 2569 +e815 2 115 2569 +e817 12 182 2569 +FUNC e829 40 20 __crtGetStringTypeA +e829 6 194 2569 +e82f b 195 2569 +e83a 2d 206 2569 +e867 2 207 2569 +FUNC e869 87 c fastcopy_I +FUNC e8f0 e3 c _VEC_memcpy +FUNC e9d3 14 0 _sse2_mathfcns_init +FUNC e9e7 14 4 _set_SSE2_enable +FUNC e9fb 6 0 __pwctype_func +e9fb 0 24 2400 +e9fb 5 25 2400 +ea00 1 26 2400 +FUNC ea01 29 0 __pctype_func +ea01 0 29 2400 +ea01 7 35 2400 +ea08 3 36 2400 +ea0b 18 38 2400 +ea23 6 39 2400 +ea29 1 40 2400 +FUNC ea2a 419 0 _get_lc_time +ea2a 6 94 1793 +ea30 12 104 1793 +ea42 3 105 1793 +ea45 2 170 1793 +ea47 9 108 1793 +ea50 16 112 1793 +ea66 15 113 1793 +ea7b 15 114 1793 +ea90 18 115 1793 +eaa8 15 116 1793 +eabd 13 117 1793 +ead0 14 118 1793 +eae4 18 120 1793 +eafc 15 121 1793 +eb11 15 122 1793 +eb26 15 123 1793 +eb3b 18 124 1793 +eb53 15 125 1793 +eb68 15 126 1793 +eb7d 15 128 1793 +eb92 18 129 1793 +ebaa 15 130 1793 +ebbf 15 131 1793 +ebd4 15 132 1793 +ebe9 18 133 1793 +ec01 15 134 1793 +ec16 15 135 1793 +ec2b 15 136 1793 +ec40 18 137 1793 +ec58 15 138 1793 +ec6d 15 139 1793 +ec82 15 141 1793 +ec97 18 142 1793 +ecaf 15 143 1793 +ecc4 15 144 1793 +ecd9 15 145 1793 +ecee 18 146 1793 +ed06 18 147 1793 +ed1e 18 148 1793 +ed36 18 149 1793 +ed4e 1b 150 1793 +ed69 18 151 1793 +ed81 18 152 1793 +ed99 18 154 1793 +edb1 1b 155 1793 +edcc 18 160 1793 +ede4 18 161 1793 +edfc 1b 163 1793 +ee17 20 165 1793 +ee37 a 169 1793 +ee41 2 170 1793 +FUNC ee43 190 4 __free_lc_time +ee43 1 179 1793 +ee44 c 180 1793 +ee50 8 183 1793 +ee58 8 184 1793 +ee60 8 185 1793 +ee68 8 186 1793 +ee70 8 187 1793 +ee78 8 188 1793 +ee80 7 189 1793 +ee87 8 191 1793 +ee8f 8 192 1793 +ee97 8 193 1793 +ee9f 8 194 1793 +eea7 8 195 1793 +eeaf 8 196 1793 +eeb7 8 197 1793 +eebf 8 199 1793 +eec7 b 200 1793 +eed2 8 201 1793 +eeda 8 202 1793 +eee2 8 203 1793 +eeea 8 204 1793 +eef2 8 205 1793 +eefa 8 206 1793 +ef02 8 207 1793 +ef0a 8 208 1793 +ef12 8 209 1793 +ef1a 8 210 1793 +ef22 8 212 1793 +ef2a 8 213 1793 +ef32 8 214 1793 +ef3a 8 215 1793 +ef42 8 216 1793 +ef4a b 217 1793 +ef55 b 218 1793 +ef60 b 219 1793 +ef6b b 220 1793 +ef76 b 221 1793 +ef81 b 222 1793 +ef8c b 223 1793 +ef97 b 225 1793 +efa2 b 226 1793 +efad b 228 1793 +efb8 b 229 1793 +efc3 f 230 1793 +efd2 1 232 1793 +FUNC efd3 73 4 __init_time +efd3 4 56 1793 +efd7 f 60 1793 +efe6 16 64 1793 +effc 4 65 1793 +f000 b 67 1793 +f00b 6 69 1793 +f011 8 70 1793 +f019 2 71 1793 +f01b 6 73 1793 +f021 2 74 1793 +f023 2 75 1793 +f025 18 78 1793 +f03d 2 82 1793 +f03f 6 83 1793 +f045 1 84 1793 +FUNC f046 33 0 fix_grouping +f046 0 32 1841 +f046 8 40 1841 +f04e a 43 1841 +f058 4 45 1841 +f05c 1 61 1841 +f05d 6 40 1841 +f063 1 63 1841 +f064 4 50 1841 +f068 2 52 1841 +f06a 7 55 1841 +f071 6 56 1841 +f077 2 60 1841 +FUNC f079 40 4 __free_lconv_num +f079 1 211 1841 +f07a 8 212 1841 +f082 a 215 1841 +f08c 7 216 1841 +f093 b 218 1841 +f09e 7 219 1841 +f0a5 b 221 1841 +f0b0 8 222 1841 +f0b8 1 223 1841 +FUNC f0b9 1c8 4 __init_numeric +f0b9 7 84 1841 +f0c0 4 92 1841 +f0c4 2 93 1841 +f0c6 11 96 1841 +f0d7 3 177 1841 +f0da 3 178 1841 +f0dd c 179 1841 +f0e9 14 102 1841 +f0fd 8 103 1841 +f105 9 108 1841 +f10e 13 113 1841 +f121 9 115 1841 +f12a 2 116 1841 +f12c 2 118 1841 +f12e 9 120 1841 +f137 12 125 1841 +f149 8 127 1841 +f151 a 128 1841 +f15b 7 129 1841 +f162 2 131 1841 +f164 19 140 1841 +f17d 15 142 1841 +f192 1b 144 1841 +f1ad 2 146 1841 +f1af c 148 1841 +f1bb 1e 154 1841 +f1d9 2 156 1841 +f1db 17 154 1841 +f1f2 b 164 1841 +f1fd 9 165 1841 +f206 c 166 1841 +f212 8 168 1841 +f21a 7 169 1841 +f221 2 170 1841 +f223 13 186 1841 +f236 11 191 1841 +f247 b 193 1841 +f252 d 194 1841 +f25f 9 197 1841 +f268 9 198 1841 +f271 9 200 1841 +f27a 5 201 1841 +f27f 2 202 1841 +FUNC f281 33 0 fix_grouping +f281 0 214 1884 +f281 8 222 1884 +f289 a 225 1884 +f293 4 227 1884 +f297 1 243 1884 +f298 6 222 1884 +f29e 1 245 1884 +f29f 4 232 1884 +f2a3 2 234 1884 +f2a5 7 237 1884 +f2ac 6 238 1884 +f2b2 2 242 1884 +FUNC f2b4 89 4 __free_lconv_mon +f2b4 1 255 1884 +f2b5 8 256 1884 +f2bd b 259 1884 +f2c8 7 260 1884 +f2cf b 262 1884 +f2da 7 263 1884 +f2e1 b 265 1884 +f2ec 7 266 1884 +f2f3 b 268 1884 +f2fe 7 269 1884 +f305 b 271 1884 +f310 7 272 1884 +f317 b 274 1884 +f322 7 275 1884 +f329 b 277 1884 +f334 8 278 1884 +f33c 1 279 1884 +FUNC f33d 2c4 4 __init_monetary +f33d 8 65 1884 +f345 6 73 1884 +f34b 13 77 1884 +f35e 3 187 1884 +f361 3 188 1884 +f364 a 189 1884 +f36e 11 83 1884 +f37f 8 84 1884 +f387 f 89 1884 +f396 7 91 1884 +f39d 2 92 1884 +f39f 2 94 1884 +f3a1 9 96 1884 +f3aa f 101 1884 +f3b9 6 103 1884 +f3bf 9 104 1884 +f3c8 2 105 1884 +f3ca 2 107 1884 +f3cc 4 112 1884 +f3d0 14 117 1884 +f3e4 14 119 1884 +f3f8 14 121 1884 +f40c 17 123 1884 +f423 14 125 1884 +f437 14 128 1884 +f44b 14 130 1884 +f45f 17 133 1884 +f476 14 135 1884 +f48a 14 137 1884 +f49e 14 139 1884 +f4b2 17 141 1884 +f4c9 14 143 1884 +f4dd 14 145 1884 +f4f1 17 147 1884 +f508 2 149 1884 +f50a 6 150 1884 +f510 6 151 1884 +f516 8 152 1884 +f51e b 153 1884 +f529 5 154 1884 +f52e 1c 157 1884 +f54a 2 159 1884 +f54c 17 157 1884 +f563 c 169 1884 +f56f 3 175 1884 +f572 32 181 1884 +f5a4 11 194 1884 +f5b5 15 199 1884 +f5ca b 201 1884 +f5d5 d 202 1884 +f5e2 9 204 1884 +f5eb 9 205 1884 +f5f4 6 206 1884 +f5fa 5 208 1884 +f5ff 2 209 1884 +FUNC f601 395 4 __init_ctype +f601 11 59 1976 +f612 6 60 1976 +f618 1f 82 1976 +f637 7 84 1976 +f63e 20 89 1976 +f65e 7 94 1976 +f665 10 98 1976 +f675 b 100 1976 +f680 b 102 1976 +f68b 12 104 1976 +f69d 2f 106 1976 +f6cc 5 109 1976 +f6d1 2 112 1976 +f6d3 e 113 1976 +f6e1 15 115 1976 +f6f6 a 118 1976 +f700 4 121 1976 +f704 8 124 1976 +f70c e 126 1976 +f71a 9 128 1976 +f723 b 129 1976 +f72e b 128 1976 +f739 2c 140 1976 +f765 33 155 1976 +f798 2d 166 1976 +f7c5 37 178 1976 +f7fc 11 180 1976 +f80d 17 182 1976 +f824 15 183 1976 +f839 d 180 1976 +f846 12 189 1976 +f858 f 190 1976 +f867 12 191 1976 +f879 18 195 1976 +f891 11 198 1976 +f8a2 13 199 1976 +f8b5 e 200 1976 +f8c3 e 201 1976 +f8d1 9 203 1976 +f8da 6 204 1976 +f8e0 9 206 1976 +f8e9 9 207 1976 +f8f2 9 208 1976 +f8fb 9 209 1976 +f904 9 210 1976 +f90d 9 213 1976 +f916 4 214 1976 +f91a 8 217 1976 +f922 8 218 1976 +f92a 8 219 1976 +f932 10 220 1976 +f942 13 227 1976 +f955 2 231 1976 +f957 6 232 1976 +f95d a 233 1976 +f967 a 234 1976 +f971 a 235 1976 +f97b a 236 1976 +f985 2 238 1976 +f987 f 240 1976 +FUNC f996 29 0 ___mb_cur_max_func +f996 0 248 1976 +f996 7 254 1976 +f99d 3 255 1976 +f9a0 18 257 1976 +f9b8 6 259 1976 +f9be 1 260 1976 +FUNC f9bf 16 4 ___mb_cur_max_l_func +f9bf 0 263 1976 +f9bf 15 264 1976 +f9d4 1 265 1976 +FUNC f9d5 26 0 ___lc_codepage_func +f9d5 0 268 1976 +f9d5 7 274 1976 +f9dc 3 275 1976 +f9df 18 277 1976 +f9f7 3 279 1976 +f9fa 1 280 1976 +FUNC f9fb 26 0 ___lc_collate_cp_func +f9fb 0 284 1976 +f9fb 7 290 1976 +fa02 3 291 1976 +fa05 18 293 1976 +fa1d 3 295 1976 +fa20 1 296 1976 +FUNC fa21 26 0 ___lc_handle_func +fa21 0 300 1976 +fa21 7 306 1976 +fa28 3 307 1976 +fa2b 18 309 1976 +fa43 3 311 1976 +fa46 1 312 1976 +FUNC fa47 3 4 __init_collate +fa47 0 41 2064 +fa47 2 42 2064 +fa49 1 43 2064 +FUNC fa4a fe 4 _Getdays_l +fa4a 9 111 190 +fa53 d 115 190 +fa60 9 117 190 +fa69 9 119 190 +fa72 28 120 190 +fa9a b 121 190 +faa5 c 123 190 +fab1 4 126 190 +fab5 30 128 190 +fae5 8 129 190 +faed 31 131 190 +fb1e 12 132 190 +fb30 3 134 190 +fb33 13 137 190 +fb46 2 138 190 +FUNC fb48 9 0 _Getdays +fb48 0 142 190 +fb48 8 143 190 +fb50 1 144 190 +FUNC fb51 fe 4 _Getmonths_l +fb51 9 150 190 +fb5a d 154 190 +fb67 16 156 190 +fb7d 2b 159 190 +fba8 b 160 190 +fbb3 8 162 190 +fbbb a 163 190 +fbc5 2d 167 190 +fbf2 8 168 190 +fbfa 2c 170 190 +fc26 11 171 190 +fc37 3 173 190 +fc3a 13 176 190 +fc4d 2 177 190 +FUNC fc4f 9 0 _Getmonths +fc4f 0 181 190 +fc4f 8 182 190 +fc57 1 183 190 +FUNC fc58 355 4 _Gettnames_l +fc58 9 189 190 +fc61 d 193 190 +fc6e 9 195 190 +fc77 9 197 190 +fc80 28 198 190 +fca8 d 199 190 +fcb5 29 200 190 +fcde 18 201 190 +fcf6 11 202 190 +fd07 f 203 190 +fd16 f 204 190 +fd25 7 205 190 +fd2c e 206 190 +fd3a 8 208 190 +fd42 12 212 190 +fd54 13 213 190 +fd67 6 214 190 +fd6d 2a 215 190 +fd97 6 216 190 +fd9d d 217 190 +fdaa 26 218 190 +fdd0 1c 219 190 +fdec 18 221 190 +fe04 6 222 190 +fe0a 26 223 190 +fe30 a 224 190 +fe3a 5 225 190 +fe3f 2a 226 190 +fe69 18 227 190 +fe81 30 230 190 +feb1 a 231 190 +febb 30 233 190 +feeb a 234 190 +fef5 30 236 190 +ff25 a 237 190 +ff2f 30 239 190 +ff5f a 240 190 +ff69 30 242 190 +ff99 12 245 190 +ffab 2 246 190 +FUNC ffad 9 0 _Gettnames +ffad 0 250 190 +ffad 8 251 190 +ffb5 1 252 190 +FUNC ffb6 20 0 _store_str +ffb6 0 869 190 +ffb6 f 871 190 +ffc5 7 872 190 +ffcc 9 873 190 +ffd5 1 875 190 +FUNC ffd6 36 0 _store_number +ffd6 0 965 190 +ffd6 8 973 190 +ffde c 976 190 +ffea 2 977 190 +ffec b 978 190 +fff7 2 981 190 +fff9 2 982 190 +fffb 1 983 190 +fffc 7 988 190 +10003 3 989 190 +10006 5 990 190 +1000b 1 991 190 +FUNC 1000c 79 4 _store_num +1000c 8 909 190 +10014 2 910 190 +10016 8 912 190 +1001e 33 913 190 +10051 2 914 190 +10053 4 917 190 +10057 8 918 190 +1005f b 919 190 +1006a c 921 190 +10076 5 923 190 +1007b 2 924 190 +1007d 2 926 190 +1007f 4 927 190 +10083 2 928 190 +FUNC 10085 3e6 10 _expandtime +10085 5 548 190 +1008a 4f 558 190 +100d9 16 659 190 +100ef 5 662 190 +100f4 16 587 190 +1010a 7 589 190 +10111 5 590 190 +10116 16 571 190 +1012c 7 573 190 +10133 5 574 190 +10138 5 822 190 +1013d 7 823 190 +10144 5 824 190 +10149 16 667 190 +1015f 10 668 190 +1016f 2 669 190 +10171 5 672 190 +10176 23 558 190 +10199 6 787 190 +1019f 5 789 190 +101a4 15 736 190 +101b9 2 737 190 +101bb 2 739 190 +101bd 5 740 190 +101c2 15 722 190 +101d7 2 723 190 +101d9 16 742 190 +101ef 4 743 190 +101f3 2 744 190 +101f5 5 745 190 +101fa 6 746 190 +10200 8 747 190 +10208 1 748 190 +10209 5 752 190 +1020e f 715 190 +1021d 5 718 190 +10222 3 696 190 +10225 2 699 190 +10227 1d 804 190 +10244 6 806 190 +1024a d 808 190 +10257 2 809 190 +10259 37 558 190 +10290 19 678 190 +102a9 8 680 190 +102b1 2 681 190 +102b3 15 650 190 +102c8 13 652 190 +102db 5 653 190 +102e0 1e 601 190 +102fe 2 603 190 +10300 5 606 190 +10305 2 607 190 +10307 2 608 190 +10309 25 615 190 +1032e 2 617 190 +10330 1 627 190 +10331 2 642 190 +10333 e 579 190 +10341 7 581 190 +10348 5 582 190 +1034d 2d 562 190 +1037a 6 564 190 +10380 5 565 190 +10385 e 687 190 +10393 3 689 190 +10396 5 690 190 +1039b 15 558 190 +103b0 2 834 190 +103b2 5 814 190 +103b7 19 817 190 +103d0 5 819 190 +103d5 d 795 190 +103e2 b 798 190 +103ed 5 799 190 +103f2 11 762 190 +10403 5 764 190 +10408 1 774 190 +10409 5 776 190 +1040e 16 729 190 +10424 6 731 190 +1042a 5 732 190 +1042f 16 704 190 +10445 3 705 190 +10448 b 706 190 +10453 2 707 190 +10455 e 708 190 +10463 6 839 190 +10469 2 840 190 +FUNC 1046b 45d 18 _store_winword +1046b 10 1035 190 +1047b 5 1043 190 +10480 a 1053 190 +1048a 3 1043 190 +1048d 6 1053 190 +10493 2 1054 190 +10495 6 1049 190 +1049b 2 1050 190 +1049d 6 1046 190 +104a3 10 1057 190 +104b3 4 1066 190 +104b7 8 1067 190 +104bf 6 1069 190 +104c5 d 1075 190 +104d2 a 1076 190 +104dc 8 1077 190 +104e4 4 1078 190 +104e8 2a 1085 190 +10512 b 1087 190 +1051d 31 1092 190 +1054e 7 1093 190 +10555 3 1097 190 +10558 13 1100 190 +1056b 10 1101 190 +1057b b 1102 190 +10586 b 1103 190 +10591 9 1106 190 +1059a 3 1291 190 +1059d 12 1292 190 +105af 11 1114 190 +105c0 5 1117 190 +105c5 b 1120 190 +105d0 37 1125 190 +10607 14 1274 190 +1061b c 1277 190 +10627 8 1283 190 +1062f 4 1284 190 +10633 9 1286 190 +1063c c 1287 190 +10648 5 1277 190 +1064d e 1128 190 +1065b 7 1133 190 +10662 7 1132 190 +10669 7 1130 190 +10670 2 1131 190 +10672 5 1134 190 +10677 a 1156 190 +10681 7 1158 190 +10688 2 1159 190 +1068a 5 1160 190 +1068f 11 1175 190 +106a0 5 1176 190 +106a5 11 1177 190 +106b6 6 1178 190 +106bc 2 1179 190 +106be 5 1180 190 +106c3 b 1225 190 +106ce 13 1226 190 +106e1 4 1228 190 +106e5 1a 1233 190 +106ff 9 1236 190 +10708 8 1242 190 +10710 4 1243 190 +10714 9 1246 190 +1071d 8 1247 190 +10725 5 1277 190 +1072a 1 1230 190 +1072b 5 1250 190 +10730 12 1136 190 +10742 7 1141 190 +10749 7 1140 190 +10750 7 1138 190 +10757 2 1139 190 +10759 5 1142 190 +1075e 29 1125 190 +10787 e 1144 190 +10795 7 1147 190 +1079c 2 1146 190 +1079e 5 1148 190 +107a3 7 1182 190 +107aa b 1183 190 +107b5 2 1184 190 +107b7 6 1185 190 +107bd 12 1187 190 +107cf 17 1188 190 +107e6 c 1191 190 +107f2 8 1197 190 +107fa 4 1198 190 +107fe 8 1201 190 +10806 2 1202 190 +10808 5 1203 190 +1080d 9 1204 190 +10816 1a 1205 190 +10830 9 1207 190 +10839 8 1212 190 +10841 4 1213 190 +10845 9 1215 190 +1084e 8 1216 190 +10856 2 1220 190 +10858 d 1168 190 +10865 7 1170 190 +1086c 2 1171 190 +1086e 2 1172 190 +10870 d 1162 190 +1087d 7 1164 190 +10884 2 1165 190 +10886 2 1166 190 +10888 d 1150 190 +10895 7 1152 190 +1089c 2 1153 190 +1089e 1b 1268 190 +108b9 3 1272 190 +108bc 5 1273 190 +108c1 7 1194 190 +FUNC 108c8 1af 18 _Strftime_l +108c8 6 356 190 +108ce 4 361 190 +108d2 13 362 190 +108e5 33 364 190 +10918 33 365 190 +1094b d 368 190 +10958 10 375 190 +10968 e 385 190 +10976 a 387 190 +10980 1e 435 190 +1099e 4 438 190 +109a2 a 446 190 +109ac 5 447 190 +109b1 b 452 190 +109bc 3 453 190 +109bf 2 454 190 +109c1 7 400 190 +109c8 1 405 190 +109c9 2 408 190 +109cb 5 409 190 +109d0 1 411 190 +109d1 1 412 190 +109d2 1d 415 190 +109ef 1 428 190 +109f0 5 385 190 +109f5 5 464 190 +109fa 5 469 190 +109ff 13 470 190 +10a12 3 441 190 +10a15 f 478 190 +10a24 b 481 190 +10a2f 2 483 190 +10a31 b 402 190 +10a3c 2 403 190 +10a3e 5 421 190 +10a43 7 423 190 +10a4a 2 464 190 +10a4c 18 485 190 +10a64 11 488 190 +10a75 2 490 190 +FUNC 10a77 1e 14 _strftime_l +10a77 3 291 190 +10a7a 19 292 190 +10a93 2 293 190 +FUNC 10a95 1d 10 strftime +10a95 0 300 190 +10a95 1c 301 190 +10ab1 1 302 190 +FUNC 10ab2 1e 14 _Strftime +10ab2 3 343 190 +10ab5 19 345 190 +10ace 2 346 190 +FUNC 10ad0 26 0 localeconv +10ad0 0 69 1716 +10ad0 5 75 1716 +10ad5 1b 78 1716 +10af0 5 79 1716 +10af5 1 80 1716 +FUNC 10b00 46 8 strcspn +10b00 4 191 591 +10b04 2 198 591 +10b06 1 199 591 +10b07 1 200 591 +10b08 1 201 591 +10b09 1 202 591 +10b0a 1 203 591 +10b0b 1 204 591 +10b0c 1 205 591 +10b0d 1 206 591 +10b0e 6 212 591 +10b14 2 216 591 +10b16 2 217 591 +10b18 2 218 591 +10b1a 3 219 591 +10b1d 4 220 591 +10b21 2 221 591 +10b23 3 227 591 +10b26 6 229 591 +10b2c 3 234 591 +10b2f 2 236 591 +10b31 2 237 591 +10b33 2 238 591 +10b35 3 239 591 +10b38 4 240 591 +10b3c 2 245 591 +10b3e 2 255 591 +10b40 3 257 591 +10b43 3 259 591 +FUNC 10b46 60 c TranslateName +10b46 3 340 2263 +10b49 3 342 2263 +10b4c 3 343 2263 +10b4f b 346 2263 +10b5a a 348 2263 +10b64 14 349 2263 +10b78 6 351 2263 +10b7e a 352 2263 +10b88 2 353 2263 +10b8a 4 354 2263 +10b8e 2 355 2263 +10b90 3 356 2263 +10b93 7 346 2263 +10b9a a 359 2263 +10ba4 2 360 2263 +FUNC 10ba6 14 0 GetLcidFromDefault +10ba6 0 761 2263 +10ba6 7 762 2263 +10bad c 763 2263 +10bb9 1 764 2263 +FUNC 10bba 77 0 ProcessCodePage +10bba 13 784 2263 +10bcd 1a 787 2263 +10be7 11 795 2263 +10bf8 8 799 2263 +10c00 2 801 2263 +10c02 18 791 2263 +10c1a 3 793 2263 +10c1d 7 805 2263 +10c24 d 806 2263 +FUNC 10c31 1e 4 TestDefaultCountry +10c31 0 826 2263 +10c31 2 830 2263 +10c33 15 832 2263 +10c48 3 835 2263 +10c4b 1 836 2263 +10c4c 2 833 2263 +10c4e 1 836 2263 +FUNC 10c4f 32 0 LcidFromHexString +10c4f 1 893 2263 +10c50 2 895 2263 +10c52 2 897 2263 +10c54 9 899 2263 +10c5d 5 900 2263 +10c62 8 901 2263 +10c6a 3 902 2263 +10c6d 10 903 2263 +10c7d 3 906 2263 +10c80 1 907 2263 +FUNC 10c81 1b 0 GetPrimaryLen +10c81 0 926 2263 +10c81 2 927 2263 +10c83 3 930 2263 +10c86 12 931 2263 +10c98 1 933 2263 +10c99 2 935 2263 +10c9b 1 938 2263 +FUNC 10c9c 96 4 CountryEnumProc +10c9c 15 717 2263 +10cb1 7 718 2263 +10cb8 f 719 2263 +10cc7 23 725 2263 +10cea 3 728 2263 +10ced 3 729 2263 +10cf0 12 731 2263 +10d02 b 734 2263 +10d0d a 738 2263 +10d17 b 741 2263 +10d22 10 742 2263 +FUNC 10d32 72 8 TestDefaultLanguage +10d32 11 858 2263 +10d43 22 864 2263 +10d65 4 865 2263 +10d69 d 867 2263 +10d76 1c 871 2263 +10d92 2 872 2263 +10d94 3 874 2263 +10d97 d 875 2263 +FUNC 10da4 1d0 4 LangCountryEnumProc +10da4 16 435 2263 +10dba 7 436 2263 +10dc1 d 437 2263 +10dce 27 444 2263 +10df5 4 447 2263 +10df9 8 448 2263 +10e01 16 450 2263 +10e17 1d 456 2263 +10e34 2 460 2263 +10e36 11 462 2263 +10e47 7 467 2263 +10e4e 5 468 2263 +10e53 6 472 2263 +10e59 1a 475 2263 +10e73 14 482 2263 +10e87 3 483 2263 +10e8a a 487 2263 +10e94 b 490 2263 +10e9f 6 493 2263 +10ea5 3 494 2263 +10ea8 12 501 2263 +10eba 1d 506 2263 +10ed7 6 510 2263 +10edd c 513 2263 +10ee9 16 518 2263 +10eff 8 522 2263 +10f07 14 528 2263 +10f1b 2 531 2263 +10f1d 2 540 2263 +10f1f 1b 550 2263 +10f3a f 553 2263 +10f49 7 557 2263 +10f50 5 558 2263 +10f55 3 559 2263 +10f58 b 566 2263 +10f63 11 567 2263 +FUNC 10f74 bf 4 LanguageEnumProc +10f74 15 624 2263 +10f89 7 625 2263 +10f90 f 626 2263 +10f9f 23 632 2263 +10fc2 3 635 2263 +10fc5 3 636 2263 +10fc8 11 639 2263 +10fd9 7 643 2263 +10fe0 2 650 2263 +10fe2 1d 651 2263 +10fff f 654 2263 +1100e a 658 2263 +11018 b 662 2263 +11023 10 663 2263 +FUNC 11033 2c 0 GetLcidFromCountry +11033 0 686 2263 +11033 10 687 2263 +11043 11 689 2263 +11054 6 693 2263 +1105a 4 694 2263 +1105e 1 695 2263 +FUNC 1105f 65 0 GetLcidFromLangCountry +1105f 0 386 2263 +1105f 7 388 2263 +11066 1a 389 2263 +11080 5 390 2263 +11085 17 392 2263 +1109c 10 394 2263 +110ac 13 402 2263 +110bf 4 403 2263 +110c3 1 404 2263 +FUNC 110c4 3c 0 GetLcidFromLanguage +110c4 0 591 2263 +110c4 13 593 2263 +110d7 e 594 2263 +110e5 10 596 2263 +110f5 6 600 2263 +110fb 4 601 2263 +110ff 1 602 2263 +FUNC 11100 1e3 c __get_qualified_locale +11100 4 205 2263 +11104 5 208 2263 +11109 12 212 2263 +1111b 7 215 2263 +11122 5 217 2263 +11127 3 222 2263 +1112a f 223 2263 +11139 10 226 2263 +11149 d 230 2263 +11156 a 232 2263 +11160 5 235 2263 +11165 2 237 2263 +11167 5 240 2263 +1116c 5 243 2263 +11171 14 248 2263 +11185 a 250 2263 +1118f 5 252 2263 +11194 2 254 2263 +11196 5 256 2263 +1119b 2 261 2263 +1119d a 263 2263 +111a7 28 266 2263 +111cf 2 268 2263 +111d1 13 271 2263 +111e4 3 277 2263 +111e7 6 278 2263 +111ed 17 281 2263 +11204 32 285 2263 +11236 d 289 2263 +11243 6 290 2263 +11249 8 293 2263 +11251 7 295 2263 +11258 8 296 2263 +11260 4 297 2263 +11264 8 301 2263 +1126c d 305 2263 +11279 23 306 2263 +1129c 2 307 2263 +1129e f 308 2263 +112ad 2 309 2263 +112af 12 311 2263 +112c1 2 312 2263 +112c3 14 313 2263 +112d7 5 315 2263 +112dc 6 286 2263 +112e2 1 316 2263 +FUNC 112e3 12 0 cmpResult +FUNC 112f5 18 0 cmpBYTE +FUNC 1130d 40 0 cmpWORD +FUNC 1134d 78 0 cmpDWORD +FUNC 113c5 1490 0 unaligned_memcmp +FUNC 12855 1680 c memcmp +FUNC 13ed5 be c strncmp +13ed5 4 42 543 +13ed9 5 43 543 +13ede 7 45 543 +13ee5 7 46 543 +13eec 6 48 543 +13ef2 d 51 543 +13eff 11 56 543 +13f10 c 61 543 +13f1c c 66 543 +13f28 15 71 543 +13f3d 2 81 543 +13f3f a 73 543 +13f49 a 68 543 +13f53 a 63 543 +13f5d 10 58 543 +13f6d 2 79 543 +13f6f a 81 543 +13f79 1 85 543 +13f7a 4 86 543 +13f7e 5 79 543 +13f83 4 89 543 +13f87 2 90 543 +13f89 a 83 543 +FUNC 13fa0 40 8 strpbrk +13fa0 4 191 536 +13fa4 2 198 536 +13fa6 1 199 536 +13fa7 1 200 536 +13fa8 1 201 536 +13fa9 1 202 536 +13faa 1 203 536 +13fab 1 204 536 +13fac 1 205 536 +13fad 1 206 536 +13fae 6 212 536 +13fb4 2 216 536 +13fb6 2 217 536 +13fb8 2 218 536 +13fba 3 219 536 +13fbd 4 220 536 +13fc1 2 221 536 +13fc3 5 227 536 +13fc8 2 236 536 +13fca 2 237 536 +13fcc 2 238 536 +13fce 3 239 536 +13fd1 4 240 536 +13fd5 2 247 536 +13fd7 3 248 536 +13fda 3 257 536 +13fdd 3 259 536 +FUNC 13fe0 104 0 __report_gsfailure +13fe0 9 140 2145 +13fe9 5 170 2145 +13fee 6 171 2145 +13ff4 6 172 2145 +13ffa 6 173 2145 +14000 6 174 2145 +14006 6 175 2145 +1400c 7 176 2145 +14013 7 177 2145 +1401a 7 178 2145 +14021 7 179 2145 +14028 7 180 2145 +1402f 7 181 2145 +14036 1 182 2145 +14037 6 183 2145 +1403d 3 190 2145 +14040 5 191 2145 +14045 3 192 2145 +14048 5 193 2145 +1404d 3 194 2145 +14050 5 195 2145 +14055 6 201 2145 +1405b a 204 2145 +14065 a 206 2145 +1406f a 285 2145 +14079 a 286 2145 +14083 b 293 2145 +1408e b 294 2145 +14099 b 297 2145 +140a4 8 298 2145 +140ac 8 302 2145 +140b4 b 304 2145 +140bf 9 313 2145 +140c8 8 315 2145 +140d0 12 319 2145 +140e2 2 320 2145 +FUNC 140e4 20 0 _global_unwind2 +FUNC 14104 45 0 __unwind_handler +FUNC 14149 84 0 _local_unwind2 +FUNC 141cd 23 0 _abnormal_termination +FUNC 141f0 9 0 _NLG_Notify1 +FUNC 141f9 1f 0 _NLG_Notify +PUBLIC 14210 0 _NLG_Dispatch +FUNC 14218 3 0 _NLG_Call +PUBLIC 1421a 0 _NLG_Return2 +FUNC 1421b 57 8 fastzero_I +FUNC 14272 8f c _VEC_memzero +FUNC 14301 22b 14 strtoxl +14301 8 80 4034 +14309 b 86 4034 +14314 3 89 4034 +14317 b 92 4034 +14322 30 94 4034 +14352 11 95 4034 +14363 c 100 4034 +1436f 34 101 4034 +143a3 5 102 4034 +143a8 5 104 4034 +143ad 4 105 4034 +143b1 2 106 4034 +143b3 5 108 4034 +143b8 3 109 4034 +143bb 1d 111 4034 +143d8 4 118 4034 +143dc 5 121 4034 +143e1 9 122 4034 +143ea a 123 4034 +143f4 9 126 4034 +143fd 7 124 4034 +14404 2 129 4034 +14406 5 140 4034 +1440b f 142 4034 +1441a 1 143 4034 +1441b 9 144 4034 +14424 8 149 4034 +1442c c 154 4034 +14438 8 155 4034 +14440 7 156 4034 +14447 13 157 4034 +1445a 5 160 4034 +1445f 4 164 4034 +14463 b 171 4034 +1446e 4 177 4034 +14472 6 178 4034 +14478 8 190 4034 +14480 6 193 4034 +14486 3 195 4034 +14489 4 196 4034 +1448d 2 198 4034 +1448f c 173 4034 +1449b 3 185 4034 +1449e 2 186 4034 +144a0 24 201 4034 +144c4 5 204 4034 +144c9 c 205 4034 +144d5 6 206 4034 +144db 10 207 4034 +144eb 7 213 4034 +144f2 2 215 4034 +144f4 6 217 4034 +144fa 3 219 4034 +144fd 12 221 4034 +1450f 7 113 4034 +14516 2 115 4034 +14518 12 116 4034 +1452a 2 222 4034 +FUNC 1452c 29 c strtol +1452c 3 229 4034 +1452f 8 230 4034 +14537 13 232 4034 +1454a 9 236 4034 +14553 2 238 4034 +FUNC 14555 1b 10 _strtol_l +14555 0 246 4034 +14555 1a 247 4034 +1456f 1 248 4034 +FUNC 14570 2a c strtoul +14570 3 255 4034 +14573 7 256 4034 +1457a 14 258 4034 +1458e a 262 4034 +14598 2 264 4034 +FUNC 1459a 1b 10 _strtoul_l +1459a 0 272 4034 +1459a 1a 273 4034 +145b4 1 274 4034 +FUNC 145b5 294 14 strtoxq +145b5 8 80 3989 +145bd b 86 3989 +145c8 3 89 3989 +145cb b 92 3989 +145d6 31 94 3989 +14607 12 95 3989 +14619 c 100 3989 +14625 37 102 3989 +1465c 2 103 3989 +1465e 9 105 3989 +14667 4 106 3989 +1466b 2 107 3989 +1466d 6 109 3989 +14673 9 110 3989 +1467c 8 112 3989 +14684 6 115 3989 +1468a 9 116 3989 +14693 a 117 3989 +1469d 9 120 3989 +146a6 3 118 3989 +146a9 5 123 3989 +146ae 10 125 3989 +146be 1 126 3989 +146bf 9 127 3989 +146c8 26 132 3989 +146ee e 137 3989 +146fc 8 138 3989 +14704 6 139 3989 +1470a 11 140 3989 +1471b 5 143 3989 +14720 31 154 3989 +14751 4 160 3989 +14755 6 161 3989 +1475b a 173 3989 +14765 7 176 3989 +1476c 6 178 3989 +14772 6 179 3989 +14778 5 181 3989 +1477d 19 156 3989 +14796 b 168 3989 +147a1 5 169 3989 +147a6 35 184 3989 +147db 5 187 3989 +147e0 c 188 3989 +147ec a 189 3989 +147f6 6 190 3989 +147fc 7 191 3989 +14803 2 192 3989 +14805 7 193 3989 +1480c 8 195 3989 +14814 5 197 3989 +14819 6 199 3989 +1481f 13 201 3989 +14832 15 203 3989 +14847 2 204 3989 +FUNC 14849 29 c _strtoi64 +14849 3 211 3989 +1484c 8 212 3989 +14854 13 214 3989 +14867 9 218 3989 +14870 2 220 3989 +FUNC 14872 1b 10 _strtoi64_l +14872 0 227 3989 +14872 1a 228 3989 +1488c 1 229 3989 +FUNC 1488d 2a c _strtoui64 +1488d 3 236 3989 +14890 7 237 3989 +14897 14 239 3989 +148ab a 243 3989 +148b5 2 245 3989 +FUNC 148b7 1b 10 _strtoui64_l +148b7 0 253 3989 +148b7 1a 254 3989 +148d1 1 255 3989 +FUNC 148d2 b6 c _isctype_l +148d2 7 114 4078 +148d9 b 118 4078 +148e4 d 121 4078 +148f1 f 122 4078 +14900 1f 124 4078 +1491f 3 126 4078 +14922 d 129 4078 +1492f 2 130 4078 +14931 a 133 4078 +1493b 26 144 4078 +14961 10 146 4078 +14971 15 149 4078 +14986 2 150 4078 +FUNC 14988 2f 8 _isctype +14988 0 156 4078 +14988 9 157 4078 +14991 12 159 4078 +149a3 1 165 4078 +149a4 12 163 4078 +149b6 1 165 4078 +FUNC 149c0 2c 0 _alloca_probe_16 +149c0 0 44 1046 +149c0 1 46 1046 +149c1 4 47 1046 +149c5 2 48 1046 +149c7 3 49 1046 +149ca 2 50 1046 +149cc 2 51 1046 +149ce 2 52 1046 +149d0 1 53 1046 +149d1 5 54 1046 +149d6 1 59 1046 +149d7 4 60 1046 +149db 2 61 1046 +149dd 3 62 1046 +149e0 2 63 1046 +149e2 2 64 1046 +149e4 2 65 1046 +149e6 1 66 1046 +149e7 5 67 1046 +PUBLIC 149d6 0 _alloca_probe_8 +FUNC 149ec 47 4 __ansicp +149ec 10 39 1348 +149fc 1c 44 1348 +14a18 3 45 1348 +14a1b 2 46 1348 +14a1d a 47 1348 +14a27 c 49 1348 +FUNC 14a33 1b2 18 __convertcp +14a33 16 79 1348 +14a49 10 83 1348 +14a59 18 85 1348 +14a71 17 90 1348 +14a88 13 92 1348 +14a9b 6 93 1348 +14aa1 d 99 1348 +14aae 2 101 1348 +14ab0 c 103 1348 +14abc 2a 115 1348 +14ae6 15 111 1348 +14afb 7 112 1348 +14b02 1c 115 1348 +14b1e 3 116 1348 +14b21 2 117 1348 +14b23 10 119 1348 +14b33 15 127 1348 +14b48 7 129 1348 +14b4f 18 138 1348 +14b67 3 139 1348 +14b6a 2 140 1348 +14b6c 1f 149 1348 +14b8b 11 151 1348 +14b9c 12 160 1348 +14bae 9 162 1348 +14bb7 3 163 1348 +14bba 2 164 1348 +14bbc 6 165 1348 +14bc2 5 166 1348 +14bc7 9 174 1348 +14bd0 3 177 1348 +14bd3 12 178 1348 +FUNC 14be5 50 0 has_osfxsr_set +FUNC 14c35 60 0 _get_sse2_info +FUNC 14c95 d 0 __sse2_available_init +FUNC 14ca2 34 4 _get_daylight +14ca2 0 35 161 +14ca2 27 36 161 +14cc9 1 41 161 +14cca 8 39 161 +14cd2 3 40 161 +14cd5 1 41 161 +FUNC 14cd6 34 4 _get_dstbias +14cd6 0 44 161 +14cd6 27 45 161 +14cfd 1 50 161 +14cfe 8 48 161 +14d06 3 49 161 +14d09 1 50 161 +FUNC 14d0a 34 4 _get_timezone +14d0a 0 53 161 +14d0a 27 54 161 +14d31 1 59 161 +14d32 8 57 161 +14d3a 3 58 161 +14d3d 1 59 161 +FUNC 14d3e a2 10 _get_tzname +14d3e 3 62 161 +14d41 10 63 161 +14d51 4 64 161 +14d55 3 66 161 +14d58 7 68 161 +14d5f 27 69 161 +14d86 20 63 161 +14da6 f 72 161 +14db5 8 73 161 +14dbd 4 76 161 +14dc1 5 78 161 +14dc6 5 80 161 +14dcb 13 82 161 +14dde 2 83 161 +FUNC 14de0 6 0 __daylight +14de0 0 118 161 +14de0 5 119 161 +14de5 1 120 161 +FUNC 14de6 6 0 __dstbias +14de6 0 123 161 +14de6 5 124 161 +14deb 1 125 161 +FUNC 14dec 6 0 __timezone +14dec 0 128 161 +14dec 5 129 161 +14df1 1 130 161 +FUNC 14df2 6 0 __tzname +14df2 0 133 161 +14df2 5 134 161 +14df7 1 135 161 +FUNC 14df8 c 4 _set_daylight +14df8 c 189 92 +FUNC 14e04 c 4 _set_dstbias +14e04 c 190 92 +FUNC 14e10 c 4 _set_timezone +14e10 c 191 92 +FUNC 14e1c 349 0 _tzset_nolock +14e1c c 124 114 +14e28 5 127 114 +14e2d 3 129 114 +14e30 3 130 114 +14e33 3 131 114 +14e36 3 132 114 +14e39 3 133 114 +14e3c 8 135 114 +14e44 3 136 114 +14e47 8 139 114 +14e4f 1b 142 114 +14e6a 1b 143 114 +14e85 1b 144 114 +14ea0 8 149 114 +14ea8 6 154 114 +14eae f 160 114 +14ebd 18 165 114 +14ed5 14 260 114 +14ee9 b 268 114 +14ef4 4 274 114 +14ef8 7 275 114 +14eff 16 277 114 +14f15 6 281 114 +14f1b 32 283 114 +14f4d 9 174 114 +14f56 7 175 114 +14f5d 6 176 114 +14f63 13 179 114 +14f76 9 183 114 +14f7f b 188 114 +14f8a 9 190 114 +14f93 e 191 114 +14fa1 12 199 114 +14fb3 3 201 114 +14fb6 c 203 114 +14fc2 2 205 114 +14fc4 3 206 114 +14fc7 3 214 114 +14fca 27 234 114 +14ff1 8 235 114 +14ff9 2 236 114 +14ffb 7 237 114 +15002 23 247 114 +15025 9 248 114 +1502e 2 249 114 +15030 8 250 114 +15038 7 256 114 +1503f a 288 114 +15049 a 289 114 +15053 a 290 114 +1505d c 292 114 +15069 9 296 114 +15072 23 301 114 +15095 8 310 114 +1509d 7 311 114 +150a4 1 312 114 +150a5 10 318 114 +150b5 11 320 114 +150c6 5 292 114 +150cb 9 293 114 +150d4 5 325 114 +150d9 e 329 114 +150e7 d 330 114 +150f4 5 335 114 +150f9 b 339 114 +15104 d 340 114 +15111 5 344 114 +15116 3 345 114 +15119 6 350 114 +1511f 4 351 114 +15123 21 352 114 +15144 2 354 114 +15146 5 355 114 +1514b a 357 114 +15155 a 358 114 +1515f 6 360 114 +FUNC 15165 1f5 24 cvtdate +15165 6 409 114 +1516b 4 412 114 +1516f c 414 114 +1517b 52 424 114 +151cd 4c 430 114 +15219 14 436 114 +1522d 2 437 114 +1522f 2 438 114 +15231 46 447 114 +15277 3 449 114 +1527a 2 452 114 +1527c 3c 457 114 +152b8 3 459 114 +152bb 27 467 114 +152e2 6 472 114 +152e8 2 474 114 +152ea 29 485 114 +15313 11 486 114 +15324 a 487 114 +1532e 8 488 114 +15336 d 490 114 +15343 6 491 114 +15349 6 492 114 +1534f 9 499 114 +15358 2 503 114 +FUNC 1535a 1ae 0 _isindst_nolock +1535a 5 554 114 +1535f 20 558 114 +1537f 5 560 114 +15384 7 561 114 +1538b 1b 568 114 +153a6 c 569 114 +153b2 7 573 114 +153b9 34 584 114 +153ed 2 585 114 +153ef 19 596 114 +15408 40 611 114 +15448 2 612 114 +1544a 1e 623 114 +15468 2 626 114 +1546a 14 641 114 +1547e 1a 653 114 +15498 d 660 114 +154a5 d 664 114 +154b2 8 666 114 +154ba 4 674 114 +154be 2 697 114 +154c0 8 673 114 +154c8 8 675 114 +154d0 4 676 114 +154d4 14 679 114 +154e8 4 681 114 +154ec b 682 114 +154f7 2 685 114 +154f9 d 691 114 +15506 2 694 114 +FUNC 15508 4f 0 __tzset +15508 c 85 114 +15514 a 88 114 +1551e 8 90 114 +15526 3 91 114 +15529 8 93 114 +15531 5 94 114 +15536 6 95 114 +1553c c 98 114 +15548 6 103 114 +1554e 9 99 114 +FUNC 15557 38 0 _tzset +15557 c 109 114 +15563 8 110 114 +1556b 4 111 114 +1556f 5 113 114 +15574 c 115 114 +15580 6 118 114 +15586 9 116 114 +FUNC 1558f 41 4 _isindst +1558f c 538 114 +1559b 8 541 114 +155a3 4 542 114 +155a7 b 543 114 +155b2 c 544 114 +155be 3 548 114 +155c1 6 549 114 +155c7 9 545 114 +FUNC 155d0 35 8 __ascii_stricmp +155d0 a 75 367 +155da c 80 367 +155e6 3 81 367 +155e9 c 82 367 +155f5 3 83 367 +155f8 9 85 367 +15601 3 87 367 +15604 1 88 367 +FUNC 15605 d3 c _stricmp_l +15605 7 47 367 +1560c b 49 367 +15617 36 52 367 +1564d 32 53 367 +1567f 8 55 367 +15687 e 57 367 +15695 15 63 367 +156aa 11 64 367 +156bb 8 65 367 +156c3 13 68 367 +156d6 2 69 367 +FUNC 156d8 50 8 _stricmp +156d8 4 94 367 +156dc a 95 367 +156e6 24 98 367 +1570a 6 99 367 +15710 1 107 367 +15711 5 101 367 +15716 10 105 367 +15726 2 107 367 +FUNC 15728 36 8 _isleadbyte_l +15728 6 55 4169 +1572e b 56 4169 +15739 23 57 4169 +1575c 2 58 4169 +FUNC 1575e e 4 isleadbyte +1575e 0 63 4169 +1575e d 64 4169 +1576b 1 65 4169 +FUNC 1576c 16 8 _iswalpha_l +1576c 0 71 4169 +1576c 15 72 4169 +15781 1 73 4169 +FUNC 15782 11 4 iswalpha +15782 0 78 4169 +15782 10 79 4169 +15792 1 80 4169 +FUNC 15793 13 8 _iswupper_l +15793 0 86 4169 +15793 12 87 4169 +157a5 1 88 4169 +FUNC 157a6 e 4 iswupper +157a6 0 93 4169 +157a6 d 94 4169 +157b3 1 95 4169 +FUNC 157b4 13 8 _iswlower_l +157b4 0 101 4169 +157b4 12 102 4169 +157c6 1 103 4169 +FUNC 157c7 e 4 iswlower +157c7 0 108 4169 +157c7 d 109 4169 +157d4 1 110 4169 +FUNC 157d5 13 8 _iswdigit_l +157d5 0 116 4169 +157d5 12 117 4169 +157e7 1 118 4169 +FUNC 157e8 e 4 iswdigit +157e8 0 123 4169 +157e8 d 124 4169 +157f5 1 125 4169 +FUNC 157f6 16 8 _iswxdigit_l +157f6 0 131 4169 +157f6 15 132 4169 +1580b 1 133 4169 +FUNC 1580c 11 4 iswxdigit +1580c 0 138 4169 +1580c 10 139 4169 +1581c 1 140 4169 +FUNC 1581d 13 8 _iswspace_l +1581d 0 146 4169 +1581d 12 147 4169 +1582f 1 148 4169 +FUNC 15830 e 4 iswspace +15830 0 153 4169 +15830 d 154 4169 +1583d 1 155 4169 +FUNC 1583e 13 8 _iswpunct_l +1583e 0 161 4169 +1583e 12 162 4169 +15850 1 163 4169 +FUNC 15851 e 4 iswpunct +15851 0 168 4169 +15851 d 169 4169 +1585e 1 170 4169 +FUNC 1585f 16 8 _iswalnum_l +1585f 0 176 4169 +1585f 15 177 4169 +15874 1 178 4169 +FUNC 15875 11 4 iswalnum +15875 0 183 4169 +15875 10 184 4169 +15885 1 185 4169 +FUNC 15886 16 8 _iswprint_l +15886 0 191 4169 +15886 15 192 4169 +1589b 1 193 4169 +FUNC 1589c 11 4 iswprint +1589c 0 198 4169 +1589c 10 199 4169 +158ac 1 200 4169 +FUNC 158ad 16 8 _iswgraph_l +158ad 0 206 4169 +158ad 15 207 4169 +158c2 1 208 4169 +FUNC 158c3 11 4 iswgraph +158c3 0 213 4169 +158c3 10 214 4169 +158d3 1 215 4169 +FUNC 158d4 13 8 _iswcntrl_l +158d4 0 221 4169 +158d4 12 222 4169 +158e6 1 223 4169 +FUNC 158e7 e 4 iswcntrl +158e7 0 228 4169 +158e7 d 229 4169 +158f4 1 230 4169 +FUNC 158f5 c 4 iswascii +158f5 0 235 4169 +158f5 b 236 4169 +15900 1 237 4169 +FUNC 15901 26 8 _iswcsym_l +15901 0 243 4169 +15901 21 244 4169 +15922 1 245 4169 +15923 3 244 4169 +15926 1 245 4169 +FUNC 15927 21 4 __iswcsym +15927 0 250 4169 +15927 1c 251 4169 +15943 1 252 4169 +15944 3 251 4169 +15947 1 252 4169 +FUNC 15948 26 8 _iswcsymf_l +15948 0 258 4169 +15948 21 259 4169 +15969 1 260 4169 +1596a 3 259 4169 +1596d 1 260 4169 +FUNC 1596e 21 4 __iswcsymf +1596e 0 265 4169 +1596e 1c 266 4169 +1598a 1 267 4169 +1598b 3 266 4169 +1598e 1 267 4169 +FUNC 1598f f0 10 _strnicmp_l +1598f 7 51 324 +15996 d 54 324 +159a3 b 56 324 +159ae 33 59 324 +159e1 7 60 324 +159e8 32 61 324 +15a1a 8 63 324 +15a22 1d 65 324 +15a3f 15 71 324 +15a54 11 72 324 +15a65 d 74 324 +15a72 6 76 324 +15a78 5 79 324 +15a7d 2 80 324 +FUNC 15a7f 5c c _strnicmp +15a7f 4 125 324 +15a83 a 127 324 +15a8d 24 130 324 +15ab1 5 131 324 +15ab6 a 132 324 +15ac0 1 141 324 +15ac1 5 134 324 +15ac6 13 138 324 +15ad9 2 141 324 +FUNC 15adb db c xtoa_s +15adb 8 93 4260 +15ae3 24 102 4260 +15b07 24 103 4260 +15b2b 19 105 4260 +15b44 b 106 4260 +15b4f a 112 4260 +15b59 6 114 4260 +15b5f 7 116 4260 +15b66 2 118 4260 +15b68 2 121 4260 +15b6a 5 124 4260 +15b6f 5 128 4260 +15b74 3 129 4260 +15b77 2 130 4260 +15b79 6 131 4260 +15b7f 3 135 4260 +15b82 e 136 4260 +15b90 8 139 4260 +15b98 2 141 4260 +15b9a 2 142 4260 +15b9c 3 148 4260 +15b9f 6 152 4260 +15ba5 3 154 4260 +15ba8 1 155 4260 +15ba9 4 156 4260 +15bad 5 158 4260 +15bb2 4 160 4260 +FUNC 15bb6 28 10 _itoa_s +15bb6 3 172 4260 +15bb9 d 175 4260 +15bc6 4 176 4260 +15bca 2 177 4260 +15bcc 10 178 4260 +15bdc 2 181 4260 +FUNC 15bde 25 10 _ltoa_s +15bde 3 189 4260 +15be1 20 190 4260 +15c01 2 191 4260 +FUNC 15c03 18 10 _ultoa_s +15c03 0 199 4260 +15c03 17 200 4260 +15c1a 1 201 4260 +FUNC 15c1b f6 14 x64toa_s +15c1b 7 309 4260 +15c22 25 318 4260 +15c47 5 319 4260 +15c4c 19 321 4260 +15c65 b 322 4260 +15c70 3 327 4260 +15c73 20 333 4260 +15c93 3 336 4260 +15c96 1e 352 4260 +15cb4 3 344 4260 +15cb7 2 345 4260 +15cb9 5 346 4260 +15cbe 5 351 4260 +15cc3 13 352 4260 +15cd6 5 355 4260 +15cdb 3 357 4260 +15cde 13 358 4260 +15cf1 4 364 4260 +15cf5 9 368 4260 +15cfe 3 370 4260 +15d01 1 371 4260 +15d02 7 372 4260 +15d09 4 375 4260 +15d0d 4 377 4260 +FUNC 15d11 33 14 _i64toa_s +15d11 3 390 4260 +15d14 2e 391 4260 +15d42 2 392 4260 +FUNC 15d44 1d 14 _ui64toa_s +15d44 4 400 4260 +15d48 17 401 4260 +15d5f 2 402 4260 +FUNC 15d70 2b 0 _chkstk +15d70 0 65 1048 +15d70 1 69 1048 +15d71 4 73 1048 +15d75 2 74 1048 +15d77 2 79 1048 +15d79 2 80 1048 +15d7b 2 81 1048 +15d7d 2 83 1048 +15d7f 5 84 1048 +15d84 2 87 1048 +15d86 2 88 1048 +15d88 2 89 1048 +15d8a 1 90 1048 +15d8b 1 91 1048 +15d8c 2 92 1048 +15d8e 3 93 1048 +15d91 1 94 1048 +15d92 5 98 1048 +15d97 2 99 1048 +15d99 2 100 1048 +FUNC 15d9b 81 4 _getenv_helper_nolock +15d9b 0 95 2318 +15d9b 10 103 2318 +15dab 3 104 2318 +15dae 1 169 2318 +15daf e 128 2318 +15dbd 7 131 2318 +15dc4 2 132 2318 +15dc6 6 135 2318 +15dcc c 140 2318 +15dd8 9 142 2318 +15de1 2 150 2318 +15de3 22 154 2318 +15e05 3 164 2318 +15e08 6 150 2318 +15e0e 5 168 2318 +15e13 9 169 2318 +FUNC 15e1c 93 c _getenv_s_helper +15e1c 7 220 2318 +15e23 21 224 2318 +15e44 15 226 2318 +15e59 4 227 2318 +15e5d 3 229 2318 +15e60 a 233 2318 +15e6a 3 234 2318 +15e6d 2 236 2318 +15e6f 7 239 2318 +15e76 6 240 2318 +15e7c 2 243 2318 +15e7e 5 246 2318 +15e83 5 251 2318 +15e88 20 254 2318 +15ea8 5 256 2318 +15ead 2 257 2318 +FUNC 15eaf a2 8 _dupenv_s_helper +15eaf 6 339 2318 +15eb5 21 344 2318 +15ed6 9 346 2318 +15edf 2 348 2318 +15ee1 5 350 2318 +15ee6 8 352 2318 +15eee 6 353 2318 +15ef4 2 355 2318 +15ef6 9 358 2318 +15eff b 362 2318 +15f0a 6 364 2318 +15f10 b 366 2318 +15f1b 9 367 2318 +15f24 1e 370 2318 +15f42 7 371 2318 +15f49 2 373 2318 +15f4b 4 375 2318 +15f4f 2 376 2318 +FUNC 15f51 83 4 getenv +15f51 c 75 2318 +15f5d 2a 78 2318 +15f87 18 79 2318 +15f9f 8 81 2318 +15fa7 3 82 2318 +15faa c 83 2318 +15fb6 c 85 2318 +15fc2 3 89 2318 +15fc5 6 90 2318 +15fcb 9 86 2318 +FUNC 15fd4 d8 10 getenv_s +15fd4 c 198 2318 +15fe0 8 201 2318 +15fe8 5 202 2318 +15fed a1 203 2318 +1608e c 205 2318 +1609a 3 209 2318 +1609d 6 210 2318 +160a3 9 206 2318 +FUNC 160ac e6 c _dupenv_s +160ac c 303 2318 +160b8 8 306 2318 +160c0 5 307 2318 +160c5 af 311 2318 +16174 c 314 2318 +16180 3 318 2318 +16183 6 319 2318 +16189 9 315 2318 +FUNC 16192 8 4 _tolower +16192 0 48 3943 +16192 7 49 3943 +16199 1 50 3943 +FUNC 1619a 117 8 _tolower_l +1619a 8 70 3943 +161a2 b 74 3943 +161ad c 77 3943 +161b9 31 79 3943 +161ea f 80 3943 +161f9 14 82 3943 +1620d 2b 86 3943 +16238 3 88 3943 +1623b d 91 3943 +16248 2 92 3943 +1624a b 94 3943 +16255 a 97 3943 +1625f 25 110 3943 +16284 6 112 3943 +1628a 5 116 3943 +1628f 6 117 3943 +16295 1a 119 3943 +162af 2 120 3943 +FUNC 162b1 27 4 tolower +162b1 0 143 3943 +162b1 9 145 3943 +162ba f 147 3943 +162c9 1 153 3943 +162ca d 151 3943 +162d7 1 153 3943 +FUNC 162d8 82 c _iswctype_l +162d8 6 66 4124 +162de 8 69 4124 +162e6 6 70 4124 +162ec 8 71 4124 +162f4 18 72 4124 +1630c 2 73 4124 +1630e b 75 4124 +16319 25 85 4124 +1633e 3 86 4124 +16341 d 87 4124 +1634e a 89 4124 +16358 2 90 4124 +FUNC 1635a 6e 8 iswctype +1635a 4 96 4124 +1635e 8 97 4124 +16366 2 99 4124 +16368 2 122 4124 +1636a 8 101 4124 +16372 14 103 4124 +16386 2 122 4124 +16388 9 106 4124 +16391 25 117 4124 +163b6 10 121 4124 +163c6 2 122 4124 +FUNC 163c8 5 8 is_wctype +163c8 0 148 4124 +163c8 5 149 4124 +FUNC 163d0 61 c __ascii_strnicmp +163d0 6 69 538 +163d6 3 75 538 +163d9 2 76 538 +163db 2 77 538 +163dd 3 79 538 +163e0 3 80 538 +163e3 2 82 538 +163e5 2 83 538 +163e7 5 84 538 +163ec 2 89 538 +163ee 2 91 538 +163f0 2 93 538 +163f2 2 95 538 +163f4 2 97 538 +163f6 2 98 538 +163f8 3 100 538 +163fb 3 101 538 +163fe 2 103 538 +16400 2 104 538 +16402 2 106 538 +16404 2 107 538 +16406 2 109 538 +16408 2 112 538 +1640a 2 113 538 +1640c 2 115 538 +1640e 2 116 538 +16410 2 118 538 +16412 2 121 538 +16414 2 122 538 +16416 3 124 538 +16419 2 125 538 +1641b 2 128 538 +1641d 2 129 538 +1641f 2 130 538 +16421 5 133 538 +16426 2 134 538 +16428 2 135 538 +1642a 2 138 538 +1642c 5 140 538 +FUNC 16431 ec 10 _mbsnbicoll_l +16431 7 53 2932 +16438 b 55 2932 +16443 9 57 2932 +1644c 13 58 2932 +1645f 33 61 2932 +16492 6 62 2932 +16498 23 63 2932 +164bb 8 65 2932 +164c3 14 66 2932 +164d7 23 74 2932 +164fa 10 75 2932 +1650a 11 77 2932 +1651b 2 79 2932 +FUNC 1651d 17 c _mbsnbicoll +1651d 0 85 2932 +1651d 16 86 2932 +16533 1 87 2932 +FUNC 16534 95 0 __wtomb_environ +16534 7 43 1113 +1653b 3 44 1113 +1653e 9 45 1113 +16547 c 52 1113 +16553 12 57 1113 +16565 11 61 1113 +16576 12 65 1113 +16588 10 72 1113 +16598 5 74 1113 +1659d 9 76 1113 +165a6 3 77 1113 +165a9 9 81 1113 +165b2 5 84 1113 +165b7 2 85 1113 +165b9 5 58 1113 +165be 9 67 1113 +165c7 2 68 1113 +FUNC 165c9 1a 8 strnlen +165c9 0 38 531 +165c9 19 45 531 +165e2 1 49 531 +FUNC 165e3 224 1c __crtGetStringTypeW_stat +165e3 10 64 1242 +165f3 9 72 1242 +165fc 7 73 1242 +16603 14 75 1242 +16617 11 79 1242 +16628 8 80 1242 +16630 b 82 1242 +1663b f 83 1242 +1664a 4 88 1242 +1664e 13 90 1242 +16661 7 95 1242 +16668 2 199 1242 +1666a 8 119 1242 +16672 b 120 1242 +1667d 5 121 1242 +16682 b 122 1242 +1668d e 128 1242 +1669b 5 130 1242 +166a0 3 131 1242 +166a3 1d 142 1242 +166c0 6 143 1242 +166c6 40 146 1242 +16706 3 147 1242 +16709 6 148 1242 +1670f d 150 1242 +1671c 1a 160 1242 +16736 4d 164 1242 +16783 4 165 1242 +16787 5 170 1242 +1678c b 171 1242 +16797 3 174 1242 +1679a 23 178 1242 +167bd 12 186 1242 +167cf f 189 1242 +167de 4 187 1242 +167e2 7 191 1242 +167e9 8 194 1242 +167f1 4 196 1242 +167f5 12 200 1242 +FUNC 16807 3e 1c __crtGetStringTypeW +16807 6 211 1242 +1680d b 212 1242 +16818 2b 222 1242 +16843 2 223 1242 +FUNC 16845 1a 4 strncnt +16845 0 50 2759 +16845 6 51 2759 +1684b 6 54 2759 +16851 1 55 2759 +16852 5 54 2759 +16857 7 57 2759 +1685e 1 58 2759 +FUNC 1685f 389 18 __crtCompareStringA_stat +1685f 10 96 2759 +1686f 31 280 2759 +168a0 c 107 2759 +168ac b 109 2759 +168b7 a 110 2759 +168c1 5 118 2759 +168c6 1b 119 2759 +168e1 7 122 2759 +168e8 1f 123 2759 +16907 6 120 2759 +1690d 7 121 2759 +16914 3 124 2759 +16917 2 125 2759 +16919 17 130 2759 +16930 7 189 2759 +16937 8 201 2759 +1693f 8 202 2759 +16947 d 208 2759 +16954 5 214 2759 +16959 8 215 2759 +16961 2 218 2759 +16963 6 219 2759 +16969 5 222 2759 +1696e 4 223 2759 +16972 f 231 2759 +16981 2 232 2759 +16983 5 237 2759 +16988 4 239 2759 +1698c 2 240 2759 +1698e 10 244 2759 +1699e a 246 2759 +169a8 7 244 2759 +169af 2 262 2759 +169b1 5 253 2759 +169b6 6 255 2759 +169bc 8 256 2759 +169c4 10 260 2759 +169d4 11 262 2759 +169e5 7 260 2759 +169ec 2 262 2759 +169ee 1a 280 2759 +16a08 6 281 2759 +16a0e 4d 284 2759 +16a5b 4 285 2759 +16a5f 6 286 2759 +16a65 19 295 2759 +16a7e 17 305 2759 +16a95 46 309 2759 +16adb 4 310 2759 +16adf 13 320 2759 +16af2 17 326 2759 +16b09 7 328 2759 +16b10 8 331 2759 +16b18 9 333 2759 +16b21 4 132 2759 +16b25 5 137 2759 +16b2a 8 138 2759 +16b32 5 139 2759 +16b37 8 140 2759 +16b3f e 142 2759 +16b4d 6 143 2759 +16b53 5 148 2759 +16b58 19 155 2759 +16b71 2 156 2759 +16b73 6 157 2759 +16b79 19 163 2759 +16b92 4 164 2759 +16b96 7 166 2759 +16b9d 5 167 2759 +16ba2 3 169 2759 +16ba5 3 170 2759 +16ba8 18 178 2759 +16bc0 6 179 2759 +16bc6 6 181 2759 +16bcc 8 182 2759 +16bd4 2 184 2759 +16bd6 12 337 2759 +FUNC 16be8 40 20 __crtCompareStringA +16be8 6 349 2759 +16bee b 350 2759 +16bf9 2d 361 2759 +16c26 2 362 2759 +FUNC 16c28 f8 10 _strnicoll_l +16c28 7 55 277 +16c2f b 57 277 +16c3a 9 59 277 +16c43 13 60 277 +16c56 33 63 277 +16c89 6 64 277 +16c8f 23 65 277 +16cb2 a 67 277 +16cbc 15 68 277 +16cd1 21 78 277 +16cf2 b 80 277 +16cfd 10 81 277 +16d0d 11 84 277 +16d1e 2 85 277 +FUNC 16d20 27 c _strnicoll +16d20 3 92 277 +16d23 9 93 277 +16d2c 1 101 277 +16d2d 5 95 277 +16d32 13 99 277 +16d45 2 101 277 +FUNC 16d47 4d 4 findenv +16d47 1 387 1450 +16d48 8 390 1450 +16d50 12 394 1450 +16d62 d 399 1450 +16d6f 9 390 1450 +16d78 e 407 1450 +16d86 1 408 1450 +16d87 c 400 1450 +16d93 1 408 1450 +FUNC 16d94 5d 0 copy_environ +16d94 4 428 1450 +16d98 2 429 1450 +16d9a 6 434 1450 +16da0 2 464 1450 +16da2 7 438 1450 +16da9 8 439 1450 +16db1 14 443 1450 +16dc5 8 444 1450 +16dcd 6 448 1450 +16dd3 11 458 1450 +16de4 4 448 1450 +16de8 2 461 1450 +16dea 5 463 1450 +16def 2 464 1450 +FUNC 16df1 24c 8 __crtsetenv +16df1 6 76 1450 +16df7 2c 89 1450 +16e23 2 91 1450 +16e25 1c 98 1450 +16e41 5 114 1450 +16e46 13 125 1450 +16e59 c 126 1450 +16e65 4 130 1450 +16e69 d 153 1450 +16e76 9 155 1450 +16e7f b 100 1450 +16e8a 6 101 1450 +16e90 2 356 1450 +16e92 3 164 1450 +16e95 6 165 1450 +16e9b f 171 1450 +16eaa 2 172 1450 +16eac 2 173 1450 +16eae 8 176 1450 +16eb6 f 178 1450 +16ec5 2 179 1450 +16ec7 2 180 1450 +16ec9 6 196 1450 +16ecf 5 197 1450 +16ed4 2 200 1450 +16ed6 10 207 1450 +16ee6 9 210 1450 +16eef a 216 1450 +16ef9 6 218 1450 +16eff 5 235 1450 +16f04 5 238 1450 +16f09 5 241 1450 +16f0e c 222 1450 +16f1a 4 221 1450 +16f1e 1d 230 1450 +16f3b 2 233 1450 +16f3d 9 245 1450 +16f46 4 250 1450 +16f4a 2 251 1450 +16f4c 2f 255 1450 +16f7b 8 258 1450 +16f83 3 259 1450 +16f86 5 262 1450 +16f8b 5 264 1450 +16f90 21 287 1450 +16fb1 25 289 1450 +16fd6 21 338 1450 +16ff7 4 339 1450 +16ffb b 343 1450 +17006 7 346 1450 +1700d 5 349 1450 +17012 8 351 1450 +1701a 6 352 1450 +17020 8 355 1450 +17028 8 271 1450 +17030 6 274 1450 +17036 7 276 1450 +FUNC 1703d 50 4 _strdup +1703d 1 66 568 +1703e b 70 568 +17049 6 71 568 +1704f 9 73 568 +17058 e 77 568 +17066 1c 80 568 +17082 4 81 568 +17086 6 84 568 +1708c 1 85 568 +FUNC 1708d ba c _mbschr_l +1708d 7 53 2982 +17094 b 55 2982 +1709f 32 58 2982 +170d1 8 60 2982 +170d9 d 61 2982 +170e6 a 65 2982 +170f0 7 67 2982 +170f7 10 69 2982 +17107 3 70 2982 +1710a 8 72 2982 +17112 d 63 2982 +1711f 8 76 2982 +17127 e 77 2982 +17135 10 79 2982 +17145 2 80 2982 +FUNC 17147 13 8 _mbschr +17147 0 86 2982 +17147 12 87 2982 +17159 1 88 2982 +FUNC 17170 be 8 strchr +17170 0 60 595 +17170 2 68 595 +17172 4 69 595 +17176 1 73 595 +17177 2 74 595 +17179 3 75 595 +1717c 4 76 595 +17180 6 77 595 +17186 2 78 595 +17188 2 81 595 +1718a 3 82 595 +1718d 2 83 595 +1718f 2 84 595 +17191 2 85 595 +17193 2 86 595 +17195 6 87 595 +1719b 2 88 595 +1719d 2 91 595 +1719f 1 92 595 +171a0 2 93 595 +171a2 3 94 595 +171a5 1 95 595 +171a6 2 96 595 +171a8 2 101 595 +171aa 5 102 595 +171af 2 104 595 +171b1 2 105 595 +171b3 2 107 595 +171b5 2 108 595 +171b7 2 110 595 +171b9 3 111 595 +171bc 3 113 595 +171bf 2 114 595 +171c1 2 116 595 +171c3 3 117 595 +171c6 6 119 595 +171cc 2 120 595 +171ce 5 124 595 +171d3 2 125 595 +171d5 5 127 595 +171da 2 128 595 +171dc 6 130 595 +171e2 2 131 595 +171e4 1 134 595 +171e5 1 135 595 +171e6 1 137 595 +171e7 2 138 595 +171e9 1 139 595 +171ea 3 142 595 +171ed 2 143 595 +171ef 2 144 595 +171f1 2 145 595 +171f3 2 146 595 +171f5 2 147 595 +171f7 2 148 595 +171f9 2 149 595 +171fb 2 150 595 +171fd 3 151 595 +17200 2 152 595 +17202 2 153 595 +17204 2 154 595 +17206 2 155 595 +17208 2 156 595 +1720a 2 157 595 +1720c 2 158 595 +1720e 2 159 595 +17210 2 160 595 +17212 1 163 595 +17213 1 164 595 +17214 3 165 595 +17217 1 166 595 +17218 1 167 595 +17219 3 170 595 +1721c 1 171 595 +1721d 1 172 595 +1721e 1 173 595 +1721f 1 174 595 +17220 3 177 595 +17223 1 178 595 +17224 1 179 595 +17225 1 180 595 +17226 1 181 595 +17227 3 184 595 +1722a 1 185 595 +1722b 1 186 595 +1722c 1 187 595 +1722d 1 188 595 +PUBLIC 17176 0 __from_strstr_to_strchr +STACK WIN 4 1060 54 6 0 8 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10c0 a 3 0 0 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10f0 21 7 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1120 14 7 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1140 16 7 0 4 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1160 1e 7 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1190 10 7 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 11b0 7 3 0 4 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 11c0 2c 7 0 4 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 11f7 f 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1206 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1214 1c 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1215 18 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1230 f 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 123f 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1247 1b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1262 1c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 127e 1f 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 129d 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12a1 b 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12ac 5 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12b1 5 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12b6 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12c0 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12ca a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12d4 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12de a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12e8 24 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 130c 41 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 134d 1b6 c 0 0 c 2c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14c5 14 0 0 0 c 2c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1503 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 150d 22 3 0 18 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 152f 70 c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1596 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 159f f5 c 0 8 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1688 b 0 0 8 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1694 70 c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16fb 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1704 31 3 0 10 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1735 eb c 0 8 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1814 b 0 0 8 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1820 53 c 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 186a 8 0 0 4 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1908 8e c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 195e 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1996 3d 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 19d3 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 19e1 24 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a05 26 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a2b 15 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a40 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a49 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a52 18 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a53 16 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a6a 20 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a6b 1e 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a8a 37 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1a8f 31 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1ac1 3c 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1ac6 36 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1afd 3c 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1b02 36 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1b39 3c 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1b3e 36 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1b75 3c 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1b7a 36 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1bb1 37 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1bb6 31 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1be8 37 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1bed 31 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1c1f 92 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1c5d 34 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1c5e 32 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1cb1 e2 c 0 c c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1d7b 11 0 0 c c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1d93 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1da4 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1db5 f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1dc4 f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1dd3 4c 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1dd4 4a 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1e1f 1a0 8 0 4 0 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1e21 19c 6 0 4 4 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 1e26 196 1 0 4 8 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 1e27 194 0 0 4 c 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 1e44 176 0 0 4 10 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 20 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 1fbf 20 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1fdf 39 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2018 1 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2019 32 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2024 1c 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 204b 15e 6 0 8 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2051 156 0 0 8 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2069 13d 0 0 8 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 206f 136 0 0 8 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 21a9 1b 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 21c4 db b 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 21c5 c3 a 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 21ce b9 1 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 21cf b7 0 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 221e 67 0 0 0 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 16 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 229f a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 22a9 198 e 0 c 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 22b1 187 6 0 c 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 22b7 180 0 0 c 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 2441 b9 11 0 0 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2448 b0 a 0 0 4 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 2451 a6 1 0 0 8 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 2452 a4 0 0 0 c c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 24fa 135 b 0 0 0 8 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2502 12a 3 0 0 4 8 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 12 - ^ = +STACK WIN 4 2503 128 2 0 0 8 8 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 16 - ^ = $ebx $T0 12 - ^ = +STACK WIN 4 2504 126 1 0 0 c 8 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 16 - ^ = $ebx $T0 12 - ^ = +STACK WIN 4 2505 124 0 0 0 10 8 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 16 - ^ = $ebx $T0 12 - ^ = +STACK WIN 4 262f 240 c 0 0 c 64 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2858 4 0 0 0 c 64 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 286f 4c 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2870 4a 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2871 48 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28bb 24 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28bc 22 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28bd 20 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28df 24 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28e0 22 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 28e1 20 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2903 6c 7 0 0 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2909 64 1 0 0 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 290a 62 0 0 0 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 292a 41 0 0 0 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 296f 6e 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2970 6c 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 29dd 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 29e6 6e 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 29e7 6c 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2a54 9 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2a5d 15 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2a72 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2a78 32 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2a79 30 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2aaa 19 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2ac3 3d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2b00 bf c 0 8 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2bb6 8 0 0 8 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 2bbf 77 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2bc0 75 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2bc1 71 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2c36 18 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2c37 16 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2c4e 121 c 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2d57 b 0 0 4 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 2d63 b 0 0 4 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 2d6f 69 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2d79 4b 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2d82 25 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2dd8 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2dde 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2de4 184 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2de5 182 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2e00 166 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 2f68 5b 6 0 0 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2f6e 43 0 0 0 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 2fc3 5a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 301d 74 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 301e 72 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +STACK WIN 4 302a 53 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 3031 4b 0 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 303c 30 0 0 0 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 3091 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3100 24 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3130 196 14 0 10 0 14 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3134 d3 10 0 10 4 14 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 24 - ^ = +STACK WIN 4 3139 cd b 0 10 8 14 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 28 - ^ = $ebx $T0 24 - ^ = +STACK WIN 4 313a cb a 0 10 c 14 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 28 - ^ = $ebx $T0 24 - ^ = +STACK WIN 4 3144 c0 0 0 10 10 14 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 28 - ^ = $ebx $T0 24 - ^ = +STACK WIN 4 32c6 94 15 0 0 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 32da 7e 1 0 0 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 32db 7c 0 0 0 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 32f7 5f 0 0 0 c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 335a a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3364 fc 1c 0 14 4 328 0 1 $T0 $ebp 680 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 3460 22 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3461 20 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3482 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 348f 9 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 3498 24 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 34bc 10 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 34cc 9 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 34d5 49 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 34d6 3b 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 34d7 39 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 351e 55 8 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 351f 53 7 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 3526 4b 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 352c 2a 0 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 3573 15 3 0 4 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 3588 18 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 35a0 c3 c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 365a 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 3663 31 7 0 4 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 366a 28 0 0 4 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 3694 65 b 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3699 5f 6 0 c 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 369e 59 1 0 c 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 369f 57 0 0 c c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 378b 6 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3791 1b 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 37ac 26 3 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 37ad 24 2 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 37d2 63 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3835 474 a 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 383c 42e 3 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 383d 42c 2 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 383e 42a 1 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 383f 428 0 0 0 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 3ca9 b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3cb4 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3cc1 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ccf e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3cdd e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ceb e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3cf9 12 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d0b e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d19 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d27 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d35 b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d40 b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d4b b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d56 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d64 b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d6f e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d7d 19 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d96 84 13 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d97 80 12 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3d98 7e 11 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3dbe 57 0 0 8 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 12 - ^ = +STACK WIN 4 3e1a d 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3e27 12 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3e39 9c 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3e4c 86 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ed5 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3edf 5 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ee4 7 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3eeb a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ef5 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3efd a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f07 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f11 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f19 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f23 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f2b a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f35 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f3d a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f47 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f4f 7b 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3f52 75 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3fca 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3fd3 25 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 3ff8 d 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4005 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4009 29 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 401b f 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4032 16 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4048 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 404c 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4050 1b 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 406b 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 406f 2f 6 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 409e 25 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 40c3 4 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 40c7 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 40d4 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 40e2 20 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4102 25 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4127 33 6 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 415a 34 6 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 418e 13 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 41a1 56 8 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 41a7 4d 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 41f7 61 b 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 41f8 5d a 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 41f9 59 9 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4258 17 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 426f 15 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4284 14 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4298 e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42a6 14 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42ba 25 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42bb 23 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42c7 14 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42df 38 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42e0 36 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 42e1 32 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4317 91 7 0 8 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 431b 89 3 0 8 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 431c 87 2 0 8 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4351 40 0 0 8 c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 43a8 35 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 43ab 2f 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 43dd 81 b 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 43de 7d a 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 43df 79 9 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 445e 1e 3 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 445f 1c 2 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 447c 47 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 447d 43 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 44c3 47 7 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 44c4 45 6 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 44c5 43 5 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 44c6 41 4 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 450a 65 11 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 450b 61 10 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 4510 5b b 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 4511 57 a 0 8 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 456f 12 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4581 31 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 45b2 f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 45c1 f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 45d0 1d 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 45ed 33 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4620 73 7 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4624 6b 3 0 14 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4625 5b 2 0 14 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4693 2f 3 0 8 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 46c2 f 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 46d1 79 4 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 46d2 75 3 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 46d3 71 2 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 474a 68 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 474b 64 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 47b2 a6 3 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 47b3 a2 2 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 47d3 81 0 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 47e5 6e 0 0 8 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 4858 26 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4859 22 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 487e 31 7 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4883 29 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 48af d0 7 0 8 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 48b3 b3 3 0 8 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 48b4 b1 2 0 8 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 48c3 9f 0 0 8 c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 497f 69 13 0 8 0 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4990 4f 2 0 8 4 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 4991 4b 1 0 8 8 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 4992 49 0 0 8 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 49e8 96 22 0 8 0 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 49fc 79 e 0 8 4 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4a0a 66 0 0 8 8 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4a2f 29 0 0 8 c 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 52 - ^ = +STACK WIN 4 4a7e 2e 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4a7f 2a 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4aac 62 8 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4aad 5e 7 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4aae 5a 6 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4b0e 8b a 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4b0f 87 9 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4b10 83 8 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4b99 1c 9 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4b9a 18 8 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4bb5 2a 7 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4bba 22 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4bdf a6 5 0 4 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4c85 37 3 0 4 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4cbc 51 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4cbd 4d 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4d0d 2e 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4d0e 2a 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4d3b 6a a 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4d3c 66 9 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 4d43 5e 2 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 4da5 6c a 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4da6 68 9 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4da7 64 8 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4e11 e0 e 0 4 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4e18 d7 7 0 4 4 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4e1f cd 0 0 4 8 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4e3a b1 0 0 4 c 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 32 - ^ = +STACK WIN 4 4ef1 4f 6 0 8 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4ef7 47 0 0 8 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4f40 22 5 0 c 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4f62 22 5 0 c 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4f84 22 5 0 c 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 4fa6 2e 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4fa7 2a 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4fd4 2e 1 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 4fd5 2a 0 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 5002 141 7 0 8 0 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5009 138 0 0 8 4 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 508a b3 0 0 8 8 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 508b b1 0 0 8 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 5143 d4 6 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5217 c4 e 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 52db 7e d 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5359 125 11 0 10 0 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 536a 112 0 0 10 4 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 547e 15f f 0 8 0 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 548d 4a 0 0 8 4 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 54e5 b3 0 0 8 8 28 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 55dd 31 6 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 560e 12 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 5620 12 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 5632 12 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 5644 150 7 0 8 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 564b 147 0 0 8 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5794 a0 6 0 c 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5834 50 5 0 4 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5884 2bb 2b 0 4 0 d0 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 589f 296 10 0 4 4 d0 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 58a8 28a 7 0 4 8 d0 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 58af 282 0 0 4 c d0 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 5b3f d9 b 0 c 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5bad 17 0 0 c 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5c18 14 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 5c2c 1b8 18 0 4 0 60 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5c3d 1a0 7 0 4 4 60 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5c44 18d 0 0 4 8 60 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5c65 168 0 0 4 c 60 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 108 - ^ = +STACK WIN 4 5de4 56f 22 0 c 0 a0 0 1 $T0 $ebp 108 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 5df8 97 e 0 c 4 a0 0 1 $T0 $ebp 108 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 164 - ^ = +STACK WIN 4 5e06 88 0 0 c 8 a0 0 1 $T0 $ebp 108 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 164 - ^ = +STACK WIN 4 6353 153 10 0 8 0 d0 0 1 $T0 $ebp 112 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 6377 11b 0 0 8 4 d0 0 1 $T0 $ebp 112 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 637e 113 0 0 8 8 d0 0 1 $T0 $ebp 112 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 6387 109 0 0 8 c d0 0 1 $T0 $ebp 112 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 212 - ^ = +STACK WIN 4 64a6 1ea 1b 0 8 0 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 64c1 1c8 0 0 8 4 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 6549 111 0 0 8 8 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 64 - ^ = +STACK WIN 4 654a 10f 0 0 8 c 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 64 - ^ = +STACK WIN 4 6690 e4 15 0 4 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 6697 db e 0 4 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 66a5 ca 0 0 4 8 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 6774 f 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 6783 100 19 0 4 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 678f f2 d 0 4 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 679c e4 0 0 4 8 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 6883 46 3 0 4 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 68c9 92 6 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 695b b42 14 0 8 0 6c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 6966 b35 9 0 8 4 6c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 696f b2b 0 0 8 8 6c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 69d8 abe 0 0 8 c 6c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 120 - ^ = +STACK WIN 4 749d 211 13 0 4 0 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 74a4 208 c 0 4 4 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 74b0 1fb 0 0 4 8 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 76ae 28b 1f 0 4 0 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 76ba 27a 13 0 4 4 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 76bb 278 12 0 4 8 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 76cd 263 0 0 4 c 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 7939 341 d 0 8 0 30 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 797e 2f7 0 0 8 4 30 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 52 - ^ = +STACK WIN 4 79e5 28f 0 0 8 8 30 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 52 - ^ = +STACK WIN 4 79e6 28d 0 0 8 c 30 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 52 - ^ = +STACK WIN 4 7c7a 4e4 18 0 14 0 54 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 7c88 4d4 a 0 14 4 54 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 88 - ^ = +STACK WIN 4 7c89 4d2 9 0 14 8 54 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 88 - ^ = +STACK WIN 4 7c92 4c8 0 0 14 c 54 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 88 - ^ = +STACK WIN 4 815e 14c 6 0 0 0 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 82aa 116 5 0 10 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 82cb 59 0 0 10 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 83c0 1b 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 83db 1b 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 83f6 1b 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8411 a3 f 0 18 c 94 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 84ab 8 0 0 18 c 94 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 84b4 a3 f 0 1c c 94 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 854e 8 0 0 1c c 94 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 8557 387 12 0 8 0 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8567 350 2 0 8 4 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 8568 34e 1 0 8 8 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 8569 34c 0 0 8 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 88de 13e 7 0 8 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 88e5 135 0 0 8 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8a1c b1 6 0 8 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8acd 64 7 0 8 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8ad4 5b 0 0 8 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8b31 4f c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8b77 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 8b80 75 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8bc8 2c 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8bf5 c3 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8bf6 c1 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +STACK WIN 4 8c04 9c 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 8c0b 94 0 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 8c0c 90 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 8cb8 3b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8cf3 13 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d06 13 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d19 1e 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d1a 1c 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d37 1b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d52 2a 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d53 28 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d7c 1b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d97 2a 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8d98 28 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8dc1 21 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8de2 46 b 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8ded 3a 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8e28 3c 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8e2d 36 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8e64 48 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8eac 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 8ed7 314 11 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8ee4 305 4 0 8 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8ee8 300 0 0 8 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 8f15 2d2 0 0 8 c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 91eb b0 d 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 91f1 a9 7 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 91f8 a1 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 929b 106 11 0 4 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 92a7 f8 5 0 4 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 92a8 f6 4 0 4 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 92ac f1 0 0 4 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 93a1 2df 12 0 c 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 93ae 2d0 5 0 c 4 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 93af 2ce 4 0 c 8 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 93b3 2c9 0 0 c c c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 9680 cd 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 974d 2e2 f 0 0 0 138 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 975c 294 0 0 0 4 138 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 316 - ^ = +STACK WIN 4 9771 27e 0 0 0 8 138 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 316 - ^ = +STACK WIN 4 9774 27a 0 0 0 c 138 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 316 - ^ = +STACK WIN 4 9a2f a8 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9a30 a6 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9a78 5d 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9ad7 2e3 2a 0 4 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 9afb 2bd 6 0 4 4 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 9b00 2b7 1 0 4 8 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 9b01 2b5 0 0 4 c 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 9dba 39 c 0 0 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 9dda 4 0 0 0 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 9df3 13 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9e06 37 c 0 0 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 9e2a 4 0 0 0 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 9e3d 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9e4e b9 5 0 4 0 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9e50 b5 3 0 4 4 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 9e51 b3 2 0 4 8 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 12 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 9e52 b1 1 0 4 c 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 12 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 9e53 af 0 0 4 10 4 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 12 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 9f07 2f 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9f08 2d 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9f36 3c c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 9f6c 5 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 9f72 12 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9f84 1f 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9f85 1d 1 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9f86 1b 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9fb0 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9fe0 42 18 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 9fee 33 a 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 9fef 31 9 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 9ff8 27 0 0 8 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 a030 bb 33 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a04a a1 19 0 4 10 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 a0b9 14 0 0 4 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 a0eb 19 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a104 9b c 0 4 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a17d 9 0 0 4 c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 a19f 34 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a1aa 1d 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a1d3 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a1e0 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a1e9 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a1f2 23d c 0 8 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a3e7 b 0 0 8 c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 a42f 1b0 c 0 4 c 30 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a59d 14 0 0 4 c 30 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 a5df a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a5e9 104 3 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a5ea 102 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +STACK WIN 4 a5eb 100 1 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +STACK WIN 4 a5ec fe 0 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +STACK WIN 4 a625 c4 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 16 - ^ = +STACK WIN 4 a6ed 15a 24 0 14 0 94 0 1 $T0 $ebp 100 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a706 bc b 0 14 4 94 0 1 $T0 $ebp 100 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 152 - ^ = +STACK WIN 4 a707 b8 a 0 14 8 94 0 1 $T0 $ebp 100 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 152 - ^ = +STACK WIN 4 a711 ad 0 0 14 c 94 0 1 $T0 $ebp 100 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 152 - ^ = +STACK WIN 4 a847 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a851 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a85b 10 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a86b c5 c 0 8 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a8f1 17 0 0 8 c 24 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 a930 a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a93a 31 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a93b 2f 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a96b 9 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a974 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a981 22 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 a9a3 1bd 9 0 c 0 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 a9aa 1b4 2 0 c 4 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 a9ab 1b2 1 0 c 8 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 a9ac 1b0 0 0 c c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 ab60 71 b 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ab65 6b 6 0 c 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 ab6a 65 1 0 c 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 ab6b 63 0 0 c c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 abd1 b3 e 0 10 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 abd5 1a a 0 10 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 abd6 2e 9 0 10 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 abdf e 0 0 10 c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 ac84 46 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ac89 40 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 acca a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 acd4 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 acda 21 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 acdb 1f 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 acfb 10 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad0b 40 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad0c 3e 1 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad0d 3c 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad4b 48 2 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad4c 46 1 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad4d 44 0 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad93 4b 2 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad94 49 1 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ad95 47 0 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 adde 50 2 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 addf 4e 1 0 c 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ade0 4c 0 0 c 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae2e 8 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae36 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae40 a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae4a e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae58 3 2 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae5b 2f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae8a 55 b 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ae8b 53 a 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 ae8c 51 9 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 ae8d 4f 8 0 0 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 ae8e 4d 7 0 0 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 aedf 18a 1d 0 0 0 51c 0 1 $T0 $ebp 1180 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 aefb 161 1 0 0 4 51c 0 1 $T0 $ebp 1180 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 1312 - ^ = +STACK WIN 4 aefc 15d 0 0 0 8 51c 0 1 $T0 $ebp 1180 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 1312 - ^ = +STACK WIN 4 b069 a4 c 0 0 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b101 b 0 0 0 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 b10d 82 9 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b114 78 2 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b18f 7a 7 0 0 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b196 71 0 0 0 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 b209 1d9 19 0 8 0 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b21a 1c1 8 0 8 4 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 b21e 1ba 4 0 8 8 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 b222 1b5 0 0 8 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 b3e2 3c 6 0 0 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b41e 19a c 0 4 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b57f 8 0 0 4 c 24 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 b5b8 1e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b5d6 51 6 0 10 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b627 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b63c 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b64f 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b664 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b677 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b68c 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b69f 18 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b6b7 16 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b6cd 18 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b6e5 16 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b6fb 18 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b713 16 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b729 18 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b741 16 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b757 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b76c 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b77f 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b794 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b7a7 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b7bc 13 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 b7cf 53 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 b822 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bb95 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bb9b 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bba1 140 12 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bba2 13e 11 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 bba3 13c 10 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bba4 13a f 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bbb3 12a 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bce1 86 8 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bce2 84 7 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 bce3 82 6 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bce4 80 5 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bce9 7a 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 bd67 8c 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bd68 8a 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bd71 7e 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 bd72 7c 0 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 12 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 bd73 7a 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 12 - ^ = $ebx $T0 8 - ^ = +STACK WIN 4 bdf3 24 3 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bdf4 22 2 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 be03 12 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 be17 3e 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 be20 31 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 be55 76 c 0 0 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 bebf 8 0 0 0 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 becb 66 2 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 becc 64 1 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 becd 62 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bf31 53 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 bf84 96 c 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c00e b 0 0 4 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 c01a 5 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 c01f 88 c 0 0 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c09b b 0 0 0 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 c0a7 5 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 c0ac 3 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 c0af 3e 2 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 c0b0 3c 1 0 c 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 c0b1 3a 0 0 c 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 c0bc 2e 0 0 c c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 c0ed 129 6 0 8 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c0f1 123 2 0 8 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 c0f2 121 1 0 8 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 c0f3 11f 0 0 8 c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 c216 6b 5 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c21a 4d 1 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 c21b 4b 0 0 c 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 c281 171 4 0 0 0 10 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 c285 169 0 0 0 4 10 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 20 - ^ = +STACK WIN 4 c2a4 149 0 0 0 8 10 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 24 - ^ = $ebx $T0 20 - ^ = +STACK WIN 4 c2a5 141 0 0 0 c 10 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 24 - ^ = $ebx $T0 20 - ^ = +STACK WIN 4 c3f2 1d4 1e 0 18 0 b4 0 1 $T0 $ebp 96 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c40b 1b1 5 0 18 4 b4 0 1 $T0 $ebp 96 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 184 - ^ = +STACK WIN 4 c40c 1ad 4 0 18 8 b4 0 1 $T0 $ebp 96 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 184 - ^ = +STACK WIN 4 c410 1a8 0 0 18 c b4 0 1 $T0 $ebp 96 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 184 - ^ = +STACK WIN 4 c5c6 2f6 17 0 4 0 1c4 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c5dc 2d6 1 0 4 4 1c4 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 456 - ^ = +STACK WIN 4 c5dd 2d2 0 0 4 8 1c4 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 456 - ^ = +STACK WIN 4 c8bc 1ce 18 0 4 0 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 c8d5 1ab 0 0 4 4 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 c8d6 1a7 0 0 4 8 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 c8dd 19f 0 0 4 c 98 0 1 $T0 $ebp 116 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 156 - ^ = +STACK WIN 4 ca8a f3 7 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ca90 2c 1 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ca91 2a 0 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 cb7d 5 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 cb82 170 c 0 8 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 cca8 10 0 0 8 c 24 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 ccb9 b 0 0 8 c 24 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 ccea 7 0 0 8 c 24 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 ccf2 f 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ce57 8 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ceda 2a 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 cf04 22 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 cf05 20 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 cf26 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d014 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d025 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d03a 5 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d03f 5 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d044 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d055 15 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d3d5 f3 23 0 0 4 328 0 1 $T0 $ebp 680 + = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d4c8 1e 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d4e6 a3 c 0 4 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d578 10 0 0 4 c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 d589 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d592 54 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d5e6 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d611 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d660 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d689 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d6d8 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d701 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d750 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d779 54 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d7cd 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d7f8 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d847 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d870 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d8bf 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d8e8 54 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d93c 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d967 54 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 d9bb 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 d9e6 54 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 da3a 2b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 da65 4f 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dab4 29 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 dadd d 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 daea 8 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 daf2 1f 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db11 1a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db2b 1f 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db4a 1c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db66 12 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db78 1b 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 db93 13b 1d 0 18 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dba8 126 8 0 18 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 dcce 3b 6 0 18 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dd09 13d 1d 0 18 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dd1e 128 8 0 18 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 de46 3b 6 0 18 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 de81 11e c 0 c c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 df78 d 0 0 c c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 df9f 3f 9 0 8 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dfa8 34 0 0 8 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dfc1 18 0 0 8 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 dfde 21b c 0 8 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e11c e 0 0 8 c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 e1f9 79 7 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e200 70 0 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 e236 39 0 0 c 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 e237 37 0 0 c c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 e272 1a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 e28c 3a2 1d 0 20 8 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e29d 391 c 0 20 c 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 e62e 43 6 0 24 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e671 1b8 1d 0 1c 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e686 1a3 8 0 1c c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 e829 40 6 0 20 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 e869 87 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 e8f0 e3 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 e9d3 14 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 e9e7 14 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 e9fb 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ea01 29 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ea2a 419 6 0 0 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 ea4c 3f5 0 0 0 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 ea4d 3ed 0 0 0 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 ee43 190 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ee44 18e 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 efd3 73 4 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 efd4 71 3 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 efd5 6f 2 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 efd6 6d 1 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 efd7 6b 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 f046 33 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f04d 16 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 f04e 14 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 f079 40 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f07a 3e 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f0b9 1c8 11 0 4 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 f0c0 1bf a 0 4 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 f0c4 1ba 6 0 4 8 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 f0ca 1b3 0 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 f281 33 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f288 16 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 f289 14 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 f2b4 89 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f2b5 87 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f33d 2c4 c 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 f344 2bb 5 0 4 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 f345 2b9 4 0 4 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 f349 2b4 0 0 4 c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 f601 395 1b 0 4 0 48 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 f612 37d a 0 4 4 48 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 76 - ^ = +STACK WIN 4 f615 377 7 0 4 8 48 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 76 - ^ = +STACK WIN 4 f61c 36f 0 0 4 c 48 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 76 - ^ = +STACK WIN 4 f996 29 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f9bf 16 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f9d5 26 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 f9fb 26 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 fa21 26 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 fa47 3 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 fa4a fe 9 0 4 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 fa51 e9 2 0 4 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 fa52 e7 1 0 4 8 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 fa53 e5 0 0 4 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 fb48 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 fb51 fe 9 0 4 0 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 fb58 e9 2 0 4 4 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 32 - ^ = +STACK WIN 4 fb59 e7 1 0 4 8 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 32 - ^ = +STACK WIN 4 fb5a e5 0 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 32 - ^ = +STACK WIN 4 fc4f 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 fc58 355 9 0 4 0 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 fc5f 34c 2 0 4 4 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 fc60 348 1 0 4 8 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 fc61 346 0 0 4 c 24 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 40 - ^ = +STACK WIN 4 ffad 9 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ffb6 20 6 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ffba 1b 2 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ffbf 15 0 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ffd6 36 6 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 ffdc 2f 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 1000c 79 8 0 4 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10011 72 3 0 4 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 10012 70 2 0 4 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 10085 3e6 11 0 10 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1008a 3df c 0 10 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 10091 3d7 5 0 10 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 10092 3d5 4 0 10 c 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 1046b 45d 1d 0 18 8 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1047f 449 9 0 18 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 108c8 1af a 0 18 0 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 108d2 1a3 0 0 18 4 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 10918 15c 0 0 18 8 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 1094b 128 0 0 18 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 36 - ^ = +STACK WIN 4 10a77 1e 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10a95 1d 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10ab2 1e 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10ad0 26 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10b46 60 6 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10b4c 56 0 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 10b55 45 0 0 c 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 10b56 43 0 0 c c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 10ba6 14 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10bba 77 11 0 0 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10bcb 5f 0 0 0 4 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10c31 1e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10c4f 32 1 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10c50 30 0 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10c81 1b 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 10c9c 96 12 0 4 0 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10cad 7c 1 0 4 4 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10cae 78 0 0 4 8 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10d32 72 11 0 8 0 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10d43 5a 0 0 8 4 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10d7f 13 0 0 8 8 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10da4 1d0 13 0 4 0 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10db5 1b6 2 0 4 4 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 128 - ^ = +STACK WIN 4 10db6 1b2 1 0 4 8 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 128 - ^ = +STACK WIN 4 10db7 1b0 0 0 4 c 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 128 - ^ = +STACK WIN 4 10f74 bf 12 0 4 0 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10f85 a5 1 0 4 4 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 10f86 a1 0 0 4 8 7c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 11033 2c 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1105f 65 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 110c4 3c 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 11100 1e3 4 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 11101 1e1 3 0 c 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 11102 1df 2 0 c 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 11103 1dd 1 0 c c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 11104 1db 0 0 c 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 112e3 12 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 112f5 18 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1130d 40 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1134d 78 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 113c5 1490 4 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 113c6 83f 3 0 0 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 113c7 83d 2 0 0 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 12855 1680 5 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 12859 15f8 1 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1285a 15f6 0 0 c 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1288b 86c 0 0 c c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 13ed5 be 9 0 c 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 13ede a9 0 0 c 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 13ef0 96 0 0 c 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 13fe0 104 9 0 0 0 328 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1421b 57 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14272 8f 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14301 22b 8 0 14 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14308 222 1 0 14 4 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14309 220 0 0 14 8 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14367 1c1 0 0 14 c 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 32 - ^ = +STACK WIN 4 1452c 29 3 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14555 1b 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14570 2a 3 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1459a 1b 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 145b5 294 8 0 14 0 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 145bc 28b 1 0 14 4 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 60 - ^ = +STACK WIN 4 145bd 289 0 0 14 8 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 60 - ^ = +STACK WIN 4 14619 1f9 0 0 14 c 38 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 60 - ^ = +STACK WIN 4 14849 29 3 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14872 1b 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1488d 2a 3 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 148b7 1b 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 148d2 b6 7 0 c 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 148d9 ad 0 0 c 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 14988 2f 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 149ec 47 10 0 4 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14a33 1b2 2a 0 18 8 34 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14a50 195 d 0 18 c 34 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 56 - ^ = +STACK WIN 4 14be5 50 c 0 0 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14c02 1c 0 0 0 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 14c35 60 9 0 0 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14c3e 57 0 0 0 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 14c95 d 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14ca2 34 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14ca7 2e 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14cd6 34 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14cdb 2e 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14d0a 34 5 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14d0f 2e 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14d3e a2 c 0 10 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 14d45 99 5 0 10 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 14d4a 93 0 0 10 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 14d58 84 0 0 10 c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 14de0 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14de6 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14dec 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14df2 6 0 0 0 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14df8 c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14e04 c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14e10 c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 14e1c 349 c 0 0 c 3c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 150c6 d 0 0 0 c 3c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 15165 1f5 14 0 24 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15174 1e4 5 0 24 4 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 15175 1e2 4 0 24 8 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 15176 1e0 3 0 24 c c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 1535a 1ae 5 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1535f 15f 0 0 0 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1538f 12e 0 0 0 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 15508 4f c 0 0 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1554e 8 0 0 0 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 15557 38 c 0 0 c 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15586 8 0 0 0 c 18 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 1558f 41 c 0 4 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 155c7 8 0 0 4 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 155d0 35 a 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 155d5 2f 5 0 8 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 155da 27 0 0 8 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15605 d3 7 0 c 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1560c ca 0 0 c 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 1564d 88 0 0 c 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 15695 33 0 0 c c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 156d8 50 4 0 8 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 156dc 4a 0 0 8 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15728 36 6 0 8 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1575e e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1576c 16 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15782 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15793 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157a6 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157b4 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157c7 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157d5 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157e8 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 157f6 16 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1580c 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1581d 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15830 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1583e 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15851 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1585f 16 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15875 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15886 16 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1589c 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 158ad 16 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 158c3 11 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 158d4 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 158e7 e 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 158f5 c 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15901 26 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15927 21 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15948 26 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1596e 21 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1598f f0 e 0 10 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15996 e7 7 0 10 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 1599c e0 1 0 10 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 1599d de 0 0 10 c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 15a7f 5c 4 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15a83 56 0 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15adb db 8 0 c 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15ae0 d2 3 0 c 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 15ae1 d0 2 0 c 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 15b0b a5 0 0 c c 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 15bb6 28 3 0 10 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15bde 25 3 0 10 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15c03 18 0 0 10 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15c1b f6 c 0 14 0 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15c22 eb 5 0 14 4 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 15c27 e5 0 0 14 8 c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 16 - ^ = +STACK WIN 4 15d11 33 3 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15d2c 16 0 0 14 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15d44 1d 4 0 14 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15d48 17 0 0 14 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15d9b 81 8 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15da3 70 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 15db2 60 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 15db3 5e 0 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 8 - ^ = +STACK WIN 4 15e1c 93 7 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15e20 8d 3 0 c 4 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 15e21 8b 2 0 c 8 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 15e60 4b 0 0 c c 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 4 - ^ = +STACK WIN 4 15eaf a2 6 0 8 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15eb4 9b 1 0 8 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15eb5 99 0 0 8 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15f51 83 c 0 4 c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 15fcb 8 0 0 4 c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 15fd4 d8 c 0 10 c 1c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 160a3 8 0 0 10 c 1c 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 160ac e6 c 0 c c 20 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16189 8 0 0 c c 20 0 1 $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = +STACK WIN 4 16192 8 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1619a 117 8 0 8 0 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 161a1 10e 1 0 8 4 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 161a2 10c 0 0 8 8 18 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ = +STACK WIN 4 162b1 27 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 162d8 82 6 0 c 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1635a 6e 4 0 8 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 163c8 5 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 16431 ec 7 0 10 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16438 e3 0 0 10 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 16498 82 0 0 10 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 1651d 17 0 0 c 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 16534 95 a 0 0 0 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 1653a 7d 4 0 0 4 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 1653b 7b 3 0 0 8 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 1653e 77 0 0 0 c 8 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 12 - ^ = +STACK WIN 4 165c9 1a 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 165e3 224 17 0 1c 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 165f8 20f 2 0 1c c 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 16807 3e 6 0 1c 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16845 1a 0 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1685f 389 16 0 18 8 2c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16873 375 2 0 18 c 2c 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 48 - ^ = +STACK WIN 4 16be8 40 6 0 20 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16c28 f8 7 0 10 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16c2f ef 0 0 10 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 16c8f 8e 0 0 10 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 16d20 27 3 0 c 0 0 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16d47 4d 1 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 16d48 48 0 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 16d94 5d 4 0 0 0 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16db0 3f 0 0 0 4 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 16db1 3d 0 0 0 8 4 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 8 - ^ = +STACK WIN 4 16df1 24c f 0 8 0 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 16dfb 95 5 0 8 4 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 16e00 8f 0 0 8 8 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 16e23 6b 0 0 8 c 14 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 24 - ^ = +STACK WIN 4 1703d 50 6 0 4 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 4 1703e 4e 5 0 4 4 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = +STACK WIN 4 17043 48 0 0 4 8 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 1704e 3c 0 0 4 c 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 1704f 3a 0 0 4 10 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 8 - ^ = $ebx $T0 4 - ^ = +STACK WIN 4 1708d ba 7 0 c 0 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = +STACK WIN 4 17094 b1 0 0 c 4 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 170d1 73 0 0 c 8 10 0 1 $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 20 - ^ = +STACK WIN 4 17147 13 0 0 8 0 0 0 1 $T2 $esp .cbLocals + .cbSavedRegs + = $T0 .raSearchStart = $eip $T0 ^ = $esp $T0 4 + = +STACK WIN 0 14c5 14 0 0 0 0 0 0 0 0 +STACK WIN 0 1596 9 0 0 0 0 0 0 0 0 +STACK WIN 0 1688 c 0 0 0 0 0 0 0 0 +STACK WIN 0 16fb 9 0 0 0 0 0 0 0 0 +STACK WIN 0 1814 c 0 0 0 0 0 0 0 0 +STACK WIN 0 186a 9 0 0 0 0 0 0 0 0 +STACK WIN 0 1880 88 0 0 8 0 0 0 0 0 +STACK WIN 0 195e 9 0 0 0 0 0 0 0 0 +STACK WIN 0 1d7b 12 0 0 0 0 0 0 0 0 +STACK WIN 0 2858 4 0 0 0 0 0 0 0 0 +STACK WIN 0 2bb6 9 0 0 0 0 0 0 0 0 +STACK WIN 0 2d57 c 0 0 0 0 0 0 0 0 +STACK WIN 0 2d63 c 0 0 0 0 0 0 0 0 +STACK WIN 0 365a 9 0 0 0 0 0 0 0 0 +STACK WIN 0 3700 8b 0 0 4 0 0 0 0 0 +STACK WIN 0 84ab 9 0 0 0 0 0 0 0 0 +STACK WIN 0 854e 9 0 0 0 0 0 0 0 0 +STACK WIN 0 8b77 9 0 0 0 0 0 0 0 0 +STACK WIN 0 9dda 4 0 0 0 0 0 0 0 0 +STACK WIN 0 9e2a 4 0 0 0 0 0 0 0 0 +STACK WIN 0 9f6c 6 0 0 0 0 0 0 0 0 +STACK WIN 0 a0b9 14 0 0 0 0 0 0 0 0 +STACK WIN 0 a17d a 0 0 0 0 0 0 0 0 +STACK WIN 0 a3e7 c 0 0 0 0 0 0 0 0 +STACK WIN 0 a59d 15 0 0 0 0 0 0 0 0 +STACK WIN 0 a8f1 17 0 0 0 0 0 0 0 0 +STACK WIN 0 b101 c 0 0 0 0 0 0 0 0 +STACK WIN 0 b57f 9 0 0 0 0 0 0 0 0 +STACK WIN 0 bebf 9 0 0 0 0 0 0 0 0 +STACK WIN 0 c00e c 0 0 0 0 0 0 0 0 +STACK WIN 0 c09b c 0 0 0 0 0 0 0 0 +STACK WIN 0 cca8 11 0 0 0 0 0 0 0 0 +STACK WIN 0 ccb9 c 0 0 0 0 0 0 0 0 +STACK WIN 0 ccea 8 0 0 0 0 0 0 0 0 +STACK WIN 0 cd04 90 3 0 c c 0 0 0 0 +STACK WIN 0 cd94 46 0 0 10 4 0 0 0 1 +STACK WIN 0 cdf6 17 4 0 0 10 0 0 0 1 +STACK WIN 0 ce0d 19 0 0 0 0 0 0 0 0 +STACK WIN 0 ce40 17 1 0 8 4 0 0 0 1 +STACK WIN 0 ce60 7a 0 0 c 0 0 0 0 0 +STACK WIN 0 d578 11 0 0 0 0 0 0 0 0 +STACK WIN 0 df78 e 0 0 0 0 0 0 0 0 +STACK WIN 0 e11c f 0 0 0 0 0 0 0 0 +STACK WIN 0 14149 84 3 0 8 c 0 0 0 0 +STACK WIN 0 141cd 23 0 0 0 0 0 0 0 0 +STACK WIN 0 14218 3 0 0 0 0 0 0 0 0 +STACK WIN 0 14c02 1c 0 0 0 0 0 0 0 0 +STACK WIN 0 150c6 e 0 0 0 0 0 0 0 0 +STACK WIN 0 1554e 9 0 0 0 0 0 0 0 0 +STACK WIN 0 15586 9 0 0 0 0 0 0 0 0 +STACK WIN 0 155c7 9 0 0 0 0 0 0 0 0 +STACK WIN 0 15fcb 9 0 0 0 0 0 0 0 0 +STACK WIN 0 160a3 9 0 0 0 0 0 0 0 0 +STACK WIN 0 16189 9 0 0 0 0 0 0 0 0 +STACK WIN 0 17170 be 0 0 8 0 0 0 0 0 diff --git a/thirdparty/google-breakpad/r318/src/tools/windows/symupload/symupload.cc b/thirdparty/google-breakpad/r318/src/tools/windows/symupload/symupload.cc new file mode 100644 index 00000000..e2ec640e --- /dev/null +++ b/thirdparty/google-breakpad/r318/src/tools/windows/symupload/symupload.cc @@ -0,0 +1,202 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Tool to upload an exe/dll and its associated symbols to an HTTP server. +// The PDB file is located automatically, using the path embedded in the +// executable. The upload is sent as a multipart/form-data POST request, +// with the following parameters: +// code_file: the basename of the module, e.g. "app.exe" +// debug_file: the basename of the debugging file, e.g. "app.pdb" +// debug_identifier: the debug file's identifier, usually consisting of +// the guid and age embedded in the pdb, e.g. +// "11111111BBBB3333DDDD555555555555F" +// version: the file version of the module, e.g. "1.2.3.4" +// os: the operating system that the module was built for, always +// "windows" in this implementation. +// cpu: the CPU that the module was built for, typically "x86". +// symbol_file: the contents of the breakpad-format symbol file + +#include +#include +#include + +#include +#include +#include +#include + +#include "common/windows/string_utils-inl.h" + +#include "common/windows/http_upload.h" +#include "common/windows/pdb_source_line_writer.h" + +using std::string; +using std::wstring; +using std::vector; +using std::map; +using google_breakpad::HTTPUpload; +using google_breakpad::PDBModuleInfo; +using google_breakpad::PDBSourceLineWriter; +using google_breakpad::WindowsStringUtils; + +// Extracts the file version information for the given filename, +// as a string, for example, "1.2.3.4". Returns true on success. +static bool GetFileVersionString(const wchar_t *filename, wstring *version) { + DWORD handle; + DWORD version_size = GetFileVersionInfoSize(filename, &handle); + if (version_size < sizeof(VS_FIXEDFILEINFO)) { + return false; + } + + vector version_info(version_size); + if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) { + return false; + } + + void *file_info_buffer = NULL; + unsigned int file_info_length; + if (!VerQueryValue(&version_info[0], L"\\", + &file_info_buffer, &file_info_length)) { + return false; + } + + // The maximum value of each version component is 65535 (0xffff), + // so the max length is 24, including the terminating null. + wchar_t ver_string[24]; + VS_FIXEDFILEINFO *file_info = + reinterpret_cast(file_info_buffer); + swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]), + L"%d.%d.%d.%d", + file_info->dwFileVersionMS >> 16, + file_info->dwFileVersionMS & 0xffff, + file_info->dwFileVersionLS >> 16, + file_info->dwFileVersionLS & 0xffff); + + // remove when VC++7.1 is no longer supported + ver_string[sizeof(ver_string) / sizeof(ver_string[0]) - 1] = L'\0'; + + *version = ver_string; + return true; +} + +// Creates a new temporary file and writes the symbol data from the given +// exe/dll file to it. Returns the path to the temp file in temp_file_path +// and information about the pdb in pdb_info. +static bool DumpSymbolsToTempFile(const wchar_t *file, + wstring *temp_file_path, + PDBModuleInfo *pdb_info) { + google_breakpad::PDBSourceLineWriter writer; + // Use EXE_FILE to get information out of the exe/dll in addition to the + // pdb. The name and version number of the exe/dll are of value, and + // there's no way to locate an exe/dll given a pdb. + if (!writer.Open(file, PDBSourceLineWriter::EXE_FILE)) { + return false; + } + + wchar_t temp_path[_MAX_PATH]; + if (GetTempPath(_MAX_PATH, temp_path) == 0) { + return false; + } + + wchar_t temp_filename[_MAX_PATH]; + if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) { + return false; + } + + FILE *temp_file = NULL; +#if _MSC_VER >= 1400 // MSVC 2005/8 + if (_wfopen_s(&temp_file, temp_filename, L"w") != 0) { +#else // _MSC_VER >= 1400 + // _wfopen_s was introduced in MSVC8. Use _wfopen for earlier environments. + // Don't use it with MSVC8 and later, because it's deprecated. + if (!(temp_file = _wfopen(temp_filename, L"w"))) { +#endif // _MSC_VER >= 1400 + return false; + } + + bool success = writer.WriteMap(temp_file); + fclose(temp_file); + if (!success) { + _wunlink(temp_filename); + return false; + } + + *temp_file_path = temp_filename; + + return writer.GetModuleInfo(pdb_info); +} + +int wmain(int argc, wchar_t *argv[]) { + if (argc < 3) { + wprintf(L"Usage: %s \n", argv[0]); + return 0; + } + const wchar_t *module = argv[1], *url = argv[2]; + + wstring symbol_file; + PDBModuleInfo pdb_info; + if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) { + fwprintf(stderr, L"Could not get symbol data from %s\n", module); + return 1; + } + + wstring code_file = WindowsStringUtils::GetBaseName(wstring(module)); + + map parameters; + parameters[L"code_file"] = code_file; + parameters[L"debug_file"] = pdb_info.debug_file; + parameters[L"debug_identifier"] = pdb_info.debug_identifier; + parameters[L"os"] = L"windows"; // This version of symupload is Windows-only + parameters[L"cpu"] = pdb_info.cpu; + + // Don't make a missing version a hard error. Issue a warning, and let the + // server decide whether to reject files without versions. + wstring file_version; + if (GetFileVersionString(module, &file_version)) { + parameters[L"version"] = file_version; + } else { + fwprintf(stderr, L"Warning: Could not get file version for %s\n", module); + } + + bool success = HTTPUpload::SendRequest(url, parameters, + symbol_file, L"symbol_file", + NULL, NULL); + _wunlink(symbol_file.c_str()); + + if (!success) { + fwprintf(stderr, L"Symbol file upload failed\n"); + return 1; + } + + wprintf(L"Uploaded symbols for windows-%s/%s/%s (%s %s)\n", + pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(), + pdb_info.debug_identifier.c_str(), code_file.c_str(), + file_version.c_str()); + return 0; +}