diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common/mac')
37 files changed, 0 insertions, 10117 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig deleted file mode 100644 index f091369081..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -GCC_C_LANGUAGE_STANDARD = c99 - -GCC_WARN_CHECK_SWITCH_STATEMENTS = YES -// TODO(nealsid): Get the code so we can turn on the 64_TO_32 warning. -GCC_WARN_64_TO_32_BIT_CONVERSION = NO -GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_MISSING_PARENTHESES = YES - -// Once https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697 -// is fixed this should be reenabled. -//GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES -GCC_WARN_ABOUT_MISSING_NEWLINE = YES -GCC_WARN_SIGN_COMPARE = YES -GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES -GCC_WARN_UNDECLARED_SELECTOR = YES -GCC_WARN_UNKNOWN_PRAGMAS = YES -GCC_WARN_UNUSED_VARIABLE = YES -GCC_TREAT_WARNINGS_AS_ERRORS = YES - -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym - -ALWAYS_SEARCH_USER_PATHS = NO diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig deleted file mode 100644 index 94cdd8cfca..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "Breakpad.xcconfig" - -GCC_OPTIMIZATION_LEVEL = 0 diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig deleted file mode 100644 index 920f277db8..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "Breakpad.xcconfig" - -GCC_OPTIMIZATION_LEVEL = s -GCC_WARN_UNINITIALIZED_AUTOS = YES -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) NDEBUG diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h deleted file mode 100644 index 14ffa7e13f..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h +++ /dev/null @@ -1,456 +0,0 @@ -// -// GTMDefines.h -// -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -// ============================================================================ - -#include <AvailabilityMacros.h> -#include <TargetConditionals.h> - -#ifdef __OBJC__ -#include <Foundation/NSObjCRuntime.h> -#endif // __OBJC__ - -#if TARGET_OS_IPHONE -#include <Availability.h> -#endif // TARGET_OS_IPHONE - -// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs -#ifndef MAC_OS_X_VERSION_10_5 - #define MAC_OS_X_VERSION_10_5 1050 -#endif -#ifndef MAC_OS_X_VERSION_10_6 - #define MAC_OS_X_VERSION_10_6 1060 -#endif -#ifndef MAC_OS_X_VERSION_10_7 - #define MAC_OS_X_VERSION_10_7 1070 -#endif - -// Not all __IPHONE_X macros defined in past SDKs -#ifndef __IPHONE_3_0 - #define __IPHONE_3_0 30000 -#endif -#ifndef __IPHONE_3_1 - #define __IPHONE_3_1 30100 -#endif -#ifndef __IPHONE_3_2 - #define __IPHONE_3_2 30200 -#endif -#ifndef __IPHONE_4_0 - #define __IPHONE_4_0 40000 -#endif -#ifndef __IPHONE_4_3 - #define __IPHONE_4_3 40300 -#endif -#ifndef __IPHONE_5_0 - #define __IPHONE_5_0 50000 -#endif - -// ---------------------------------------------------------------------------- -// CPP symbols that can be overridden in a prefix to control how the toolbox -// is compiled. -// ---------------------------------------------------------------------------- - - -// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and -// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens -// when a validation fails. If you implement your own validators, you may want -// to control their internals using the same macros for consistency. -#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT - #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 -#endif - -// Give ourselves a consistent way to do inlines. Apple's macros even use -// a few different actual definitions, so we're based off of the foundation -// one. -#if !defined(GTM_INLINE) - #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__) - #define GTM_INLINE static __inline__ __attribute__((always_inline)) - #else - #define GTM_INLINE static __inline__ - #endif -#endif - -// Give ourselves a consistent way of doing externs that links up nicely -// when mixing objc and objc++ -#if !defined (GTM_EXTERN) - #if defined __cplusplus - #define GTM_EXTERN extern "C" - #define GTM_EXTERN_C_BEGIN extern "C" { - #define GTM_EXTERN_C_END } - #else - #define GTM_EXTERN extern - #define GTM_EXTERN_C_BEGIN - #define GTM_EXTERN_C_END - #endif -#endif - -// Give ourselves a consistent way of exporting things if we have visibility -// set to hidden. -#if !defined (GTM_EXPORT) - #define GTM_EXPORT __attribute__((visibility("default"))) -#endif - -// Give ourselves a consistent way of declaring something as unused. This -// doesn't use __unused because that is only supported in gcc 4.2 and greater. -#if !defined (GTM_UNUSED) -#define GTM_UNUSED(x) ((void)(x)) -#endif - -// _GTMDevLog & _GTMDevAssert -// -// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for -// developer level errors. This implementation simply macros to NSLog/NSAssert. -// It is not intended to be a general logging/reporting system. -// -// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert -// for a little more background on the usage of these macros. -// -// _GTMDevLog log some error/problem in debug builds -// _GTMDevAssert assert if conditon isn't met w/in a method/function -// in all builds. -// -// To replace this system, just provide different macro definitions in your -// prefix header. Remember, any implementation you provide *must* be thread -// safe since this could be called by anything in what ever situtation it has -// been placed in. -// - -// We only define the simple macros if nothing else has defined this. -#ifndef _GTMDevLog - -#ifdef DEBUG - #define _GTMDevLog(...) NSLog(__VA_ARGS__) -#else - #define _GTMDevLog(...) do { } while (0) -#endif - -#endif // _GTMDevLog - -#ifndef _GTMDevAssert -// we directly invoke the NSAssert handler so we can pass on the varargs -// (NSAssert doesn't have a macro we can use that takes varargs) -#if !defined(NS_BLOCK_ASSERTIONS) - #define _GTMDevAssert(condition, ...) \ - do { \ - if (!(condition)) { \ - [[NSAssertionHandler currentHandler] \ - handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ - file:[NSString stringWithUTF8String:__FILE__] \ - lineNumber:__LINE__ \ - description:__VA_ARGS__]; \ - } \ - } while(0) -#else // !defined(NS_BLOCK_ASSERTIONS) - #define _GTMDevAssert(condition, ...) do { } while (0) -#endif // !defined(NS_BLOCK_ASSERTIONS) - -#endif // _GTMDevAssert - -// _GTMCompileAssert -// _GTMCompileAssert is an assert that is meant to fire at compile time if you -// want to check things at compile instead of runtime. For example if you -// want to check that a wchar is 4 bytes instead of 2 you would use -// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) -// Note that the second "arg" is not in quotes, and must be a valid processor -// symbol in it's own right (no spaces, punctuation etc). - -// Wrapping this in an #ifndef allows external groups to define their own -// compile time assert scheme. -#ifndef _GTMCompileAssert - // We got this technique from here: - // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html - - #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg - #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) - #define _GTMCompileAssert(test, msg) \ - typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] -#endif // _GTMCompileAssert - -// ---------------------------------------------------------------------------- -// CPP symbols defined based on the project settings so the GTM code has -// simple things to test against w/o scattering the knowledge of project -// setting through all the code. -// ---------------------------------------------------------------------------- - -// Provide a single constant CPP symbol that all of GTM uses for ifdefing -// iPhone code. -#if TARGET_OS_IPHONE // iPhone SDK - // For iPhone specific stuff - #define GTM_IPHONE_SDK 1 - #if TARGET_IPHONE_SIMULATOR - #define GTM_IPHONE_DEVICE 0 - #define GTM_IPHONE_SIMULATOR 1 - #else - #define GTM_IPHONE_DEVICE 1 - #define GTM_IPHONE_SIMULATOR 0 - #endif // TARGET_IPHONE_SIMULATOR - // By default, GTM has provided it's own unittesting support, define this - // to use the support provided by Xcode, especially for the Xcode4 support - // for unittesting. - #ifndef GTM_IPHONE_USE_SENTEST - #define GTM_IPHONE_USE_SENTEST 0 - #endif - #define GTM_MACOS_SDK 0 -#else - // For MacOS specific stuff - #define GTM_MACOS_SDK 1 - #define GTM_IPHONE_SDK 0 - #define GTM_IPHONE_SIMULATOR 0 - #define GTM_IPHONE_DEVICE 0 - #define GTM_IPHONE_USE_SENTEST 0 -#endif - -// Some of our own availability macros -#if GTM_MACOS_SDK -#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE -#define GTM_AVAILABLE_ONLY_ON_MACOS -#else -#define GTM_AVAILABLE_ONLY_ON_IPHONE -#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE -#endif - -// GC was dropped by Apple, define the old constant incase anyone still keys -// off of it. -#ifndef GTM_SUPPORT_GC - #define GTM_SUPPORT_GC 0 -#endif - -// To simplify support for 64bit (and Leopard in general), we provide the type -// defines for non Leopard SDKs -#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - // NSInteger/NSUInteger and Max/Mins - #ifndef NSINTEGER_DEFINED - #if (defined(__LP64__) && __LP64__) || NS_BUILD_32_LIKE_64 - typedef long NSInteger; - typedef unsigned long NSUInteger; - #else - typedef int NSInteger; - typedef unsigned int NSUInteger; - #endif - #define NSIntegerMax LONG_MAX - #define NSIntegerMin LONG_MIN - #define NSUIntegerMax ULONG_MAX - #define NSINTEGER_DEFINED 1 - #endif // NSINTEGER_DEFINED - // CGFloat - #ifndef CGFLOAT_DEFINED - #if defined(__LP64__) && __LP64__ - // This really is an untested path (64bit on Tiger?) - typedef double CGFloat; - #define CGFLOAT_MIN DBL_MIN - #define CGFLOAT_MAX DBL_MAX - #define CGFLOAT_IS_DOUBLE 1 - #else /* !defined(__LP64__) || !__LP64__ */ - typedef float CGFloat; - #define CGFLOAT_MIN FLT_MIN - #define CGFLOAT_MAX FLT_MAX - #define CGFLOAT_IS_DOUBLE 0 - #endif /* !defined(__LP64__) || !__LP64__ */ - #define CGFLOAT_DEFINED 1 - #endif // CGFLOAT_DEFINED -#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - -// Some support for advanced clang static analysis functionality -// See http://clang-analyzer.llvm.org/annotations.html -#ifndef __has_feature // Optional. - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_RETURNS_RETAINED - #if __has_feature(attribute_ns_returns_retained) - #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) - #else - #define NS_RETURNS_RETAINED - #endif -#endif - -#ifndef NS_RETURNS_NOT_RETAINED - #if __has_feature(attribute_ns_returns_not_retained) - #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) - #else - #define NS_RETURNS_NOT_RETAINED - #endif -#endif - -#ifndef CF_RETURNS_RETAINED - #if __has_feature(attribute_cf_returns_retained) - #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) - #else - #define CF_RETURNS_RETAINED - #endif -#endif - -#ifndef CF_RETURNS_NOT_RETAINED - #if __has_feature(attribute_cf_returns_not_retained) - #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) - #else - #define CF_RETURNS_NOT_RETAINED - #endif -#endif - -#ifndef NS_CONSUMED - #if __has_feature(attribute_ns_consumed) - #define NS_CONSUMED __attribute__((ns_consumed)) - #else - #define NS_CONSUMED - #endif -#endif - -#ifndef CF_CONSUMED - #if __has_feature(attribute_cf_consumed) - #define CF_CONSUMED __attribute__((cf_consumed)) - #else - #define CF_CONSUMED - #endif -#endif - -#ifndef NS_CONSUMES_SELF - #if __has_feature(attribute_ns_consumes_self) - #define NS_CONSUMES_SELF __attribute__((ns_consumes_self)) - #else - #define NS_CONSUMES_SELF - #endif -#endif - -// Defined on 10.6 and above. -#ifndef NS_FORMAT_ARGUMENT - #define NS_FORMAT_ARGUMENT(A) -#endif - -// Defined on 10.6 and above. -#ifndef NS_FORMAT_FUNCTION - #define NS_FORMAT_FUNCTION(F,A) -#endif - -// Defined on 10.6 and above. -#ifndef CF_FORMAT_ARGUMENT - #define CF_FORMAT_ARGUMENT(A) -#endif - -// Defined on 10.6 and above. -#ifndef CF_FORMAT_FUNCTION - #define CF_FORMAT_FUNCTION(F,A) -#endif - -#ifndef GTM_NONNULL - #if defined(__has_attribute) - #if __has_attribute(nonnull) - #define GTM_NONNULL(x) __attribute__((nonnull x)) - #else - #define GTM_NONNULL(x) - #endif - #else - #define GTM_NONNULL(x) - #endif -#endif - -// Invalidates the initializer from which it's called. -#ifndef GTMInvalidateInitializer - #if __has_feature(objc_arc) - #define GTMInvalidateInitializer() \ - do { \ - [self class]; /* Avoid warning of dead store to |self|. */ \ - _GTMDevAssert(NO, @"Invalid initializer."); \ - return nil; \ - } while (0) - #else - #define GTMInvalidateInitializer() \ - do { \ - [self release]; \ - _GTMDevAssert(NO, @"Invalid initializer."); \ - return nil; \ - } while (0) - #endif -#endif - -#ifndef GTMCFAutorelease - #if __has_feature(objc_arc) - #define GTMCFAutorelease(x) CFBridgingRelease(x) - #else - #define GTMCFAutorelease(x) ([(id)x autorelease]) - #endif -#endif - -#ifdef __OBJC__ - -// Declared here so that it can easily be used for logging tracking if -// necessary. See GTMUnitTestDevLog.h for details. -@class NSString; -GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); - -// Macro to allow you to create NSStrings out of other macros. -// #define FOO foo -// NSString *fooString = GTM_NSSTRINGIFY(FOO); -#if !defined (GTM_NSSTRINGIFY) - #define GTM_NSSTRINGIFY_INNER(x) @#x - #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x) -#endif - -// Macro to allow fast enumeration when building for 10.5 or later, and -// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration -// does keys, so pick the right thing, nothing is done on the FastEnumeration -// side to be sure you're getting what you wanted. -#ifndef GTM_FOREACH_OBJECT - #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) - #define GTM_FOREACH_ENUMEREE(element, enumeration) \ - for (element in enumeration) - #define GTM_FOREACH_OBJECT(element, collection) \ - for (element in collection) - #define GTM_FOREACH_KEY(element, collection) \ - for (element in collection) - #else - #define GTM_FOREACH_ENUMEREE(element, enumeration) \ - for (NSEnumerator *_ ## element ## _enum = enumeration; \ - (element = [_ ## element ## _enum nextObject]) != nil; ) - #define GTM_FOREACH_OBJECT(element, collection) \ - GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator]) - #define GTM_FOREACH_KEY(element, collection) \ - GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator]) - #endif -#endif - -// ============================================================================ - -// To simplify support for both Leopard and Snow Leopard we declare -// the Snow Leopard protocols that we need here. -#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) -#define GTM_10_6_PROTOCOLS_DEFINED 1 -@protocol NSConnectionDelegate -@end -@protocol NSAnimationDelegate -@end -@protocol NSImageDelegate -@end -@protocol NSTabViewDelegate -@end -#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) - -// GTM_SEL_STRING is for specifying selector (usually property) names to KVC -// or KVO methods. -// In debug it will generate warnings for undeclared selectors if -// -Wunknown-selector is turned on. -// In release it will have no runtime overhead. -#ifndef GTM_SEL_STRING - #ifdef DEBUG - #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName)) - #else - #define GTM_SEL_STRING(selName) @#selName - #endif // DEBUG -#endif // GTM_SEL_STRING - -#endif // __OBJC__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h deleted file mode 100644 index c4fd140290..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h +++ /dev/null @@ -1,504 +0,0 @@ -// -// GTMLogger.h -// -// Copyright 2007-2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -// Key Abstractions -// ---------------- -// -// This file declares multiple classes and protocols that are used by the -// GTMLogger logging system. The 4 main abstractions used in this file are the -// following: -// -// * logger (GTMLogger) - The main logging class that users interact with. It -// has methods for logging at different levels and uses a log writer, a log -// formatter, and a log filter to get the job done. -// -// * log writer (GTMLogWriter) - Writes a given string to some log file, where -// a "log file" can be a physical file on disk, a POST over HTTP to some URL, -// or even some in-memory structure (e.g., a ring buffer). -// -// * log formatter (GTMLogFormatter) - Given a format string and arguments as -// a va_list, returns a single formatted NSString. A "formatted string" could -// be a string with the date prepended, a string with values in a CSV format, -// or even a string of XML. -// -// * log filter (GTMLogFilter) - Given a formatted log message as an NSString -// and the level at which the message is to be logged, this class will decide -// whether the given message should be logged or not. This is a flexible way -// to filter out messages logged at a certain level, messages that contain -// certain text, or filter nothing out at all. This gives the caller the -// flexibility to dynamically enable debug logging in Release builds. -// -// This file also declares some classes to handle the common log writer, log -// formatter, and log filter cases. Callers can also create their own writers, -// formatters, and filters and they can even build them on top of the ones -// declared here. Keep in mind that your custom writer/formatter/filter may be -// called from multiple threads, so it must be thread-safe. - -#import <Foundation/Foundation.h> -#import "GTMDefines.h" - -// Predeclaration of used protocols that are declared later in this file. -@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter; - -// GTMLogger -// -// GTMLogger is the primary user-facing class for an object-oriented logging -// system. It is built on the concept of log formatters (GTMLogFormatter), log -// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is -// sent to a GTMLogger to log a message, the message is formatted using the log -// formatter, then the log filter is consulted to see if the message should be -// logged, and if so, the message is sent to the log writer to be written out. -// -// GTMLogger is intended to be a flexible and thread-safe logging solution. Its -// flexibility comes from the fact that GTMLogger instances can be customized -// with user defined formatters, filters, and writers. And these writers, -// filters, and formatters can be combined, stacked, and customized in arbitrary -// ways to suit the needs at hand. For example, multiple writers can be used at -// the same time, and a GTMLogger instance can even be used as another -// GTMLogger's writer. This allows for arbitrarily deep logging trees. -// -// A standard GTMLogger uses a writer that sends messages to standard out, a -// formatter that smacks a timestamp and a few other bits of interesting -// information on the message, and a filter that filters out debug messages from -// release builds. Using the standard log settings, a log message will look like -// the following: -// -// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123> -// -// The output contains the date and time of the log message, the name of the -// process followed by its process ID/thread ID, the log level at which the -// message was logged (in the previous example the level was 1: -// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in -// this case, the log message was @"foo=%@", foo). -// -// Multiple instances of GTMLogger can be created, each configured their own -// way. Though GTMLogger is not a singleton (in the GoF sense), it does provide -// access to a shared (i.e., globally accessible) GTMLogger instance. This makes -// it convenient for all code in a process to use the same GTMLogger instance. -// The shared GTMLogger instance can also be configured in an arbitrary, and -// these configuration changes will affect all code that logs through the shared -// instance. - -// -// Log Levels -// ---------- -// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger -// doesn't take any special action based on the log level; it simply forwards -// this information on to formatters, filters, and writers, each of which may -// optionally take action based on the level. Since log level filtering is -// performed at runtime, log messages are typically not filtered out at compile -// time. The exception to this rule is that calls to the GTMLoggerDebug() macro -// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible -// with behavior that many developers are currently used to. Note that this -// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but -// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out. -// -// Standard loggers are created with the GTMLogLevelFilter log filter, which -// filters out certain log messages based on log level, and some other settings. -// -// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on -// GTMLogger itself, there are also C macros that make usage of the shared -// GTMLogger instance very convenient. These macros are: -// -// GTMLoggerDebug(...) -// GTMLoggerInfo(...) -// GTMLoggerError(...) -// -// Again, a notable feature of these macros is that GTMLogDebug() calls *will be -// compiled out of non-DEBUG builds*. -// -// Standard Loggers -// ---------------- -// GTMLogger has the concept of "standard loggers". A standard logger is simply -// a logger that is pre-configured with some standard/common writer, formatter, -// and filter combination. Standard loggers are created using the creation -// methods beginning with "standard". The alternative to a standard logger is a -// regular logger, which will send messages to stdout, with no special -// formatting, and no filtering. -// -// How do I use GTMLogger? -// ---------------------- -// The typical way you will want to use GTMLogger is to simply use the -// GTMLogger*() macros for logging from code. That way we can easily make -// changes to the GTMLogger class and simply update the macros accordingly. Only -// your application startup code (perhaps, somewhere in main()) should use the -// GTMLogger class directly in order to configure the shared logger, which all -// of the code using the macros will be using. Again, this is just the typical -// situation. -// -// To be complete, there are cases where you may want to use GTMLogger directly, -// or even create separate GTMLogger instances for some reason. That's fine, -// too. -// -// Examples -// -------- -// The following show some common GTMLogger use cases. -// -// 1. You want to log something as simply as possible. Also, this call will only -// appear in debug builds. In non-DEBUG builds it will be completely removed. -// -// GTMLoggerDebug(@"foo = %@", foo); -// -// 2. The previous example is similar to the following. The major difference is -// that the previous call (example 1) will be compiled out of Release builds -// but this statement will not be compiled out. -// -// [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo]; -// -// 3. Send all logging output from the shared logger to a file. We do this by -// creating an NSFileHandle for writing associated with a file, and setting -// that file handle as the logger's writer. -// -// NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" -// create:YES]; -// [[GTMLogger sharedLogger] setWriter:f]; -// GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log -// -// 4. Create a new GTMLogger that will log to a file. This example differs from -// the previous one because here we create a new GTMLogger that is different -// from the shared logger. -// -// GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"]; -// [logger logInfo:@"hi temp log file"]; -// -// 5. Create a logger that writes to stdout and does NOT do any formatting to -// the log message. This might be useful, for example, when writing a help -// screen for a command-line tool to standard output. -// -// GTMLogger *logger = [GTMLogger logger]; -// [logger logInfo:@"%@ version 0.1 usage", progName]; -// -// 6. Send log output to stdout AND to a log file. The trick here is that -// NSArrays function as composite log writers, which means when an array is -// set as the log writer, it forwards all logging messages to all of its -// contained GTMLogWriters. -// -// // Create array of GTMLogWriters -// NSArray *writers = [NSArray arrayWithObjects: -// [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES], -// [NSFileHandle fileHandleWithStandardOutput], nil]; -// -// GTMLogger *logger = [GTMLogger standardLogger]; -// [logger setWriter:writers]; -// [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log -// -// For futher details on log writers, formatters, and filters, see the -// documentation below. -// -// NOTE: GTMLogger is application level logging. By default it does nothing -// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose -// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro -// definitions in its prefix header (see GTMDefines.h for how one would do -// that). -// -@interface GTMLogger : NSObject { - @private - id<GTMLogWriter> writer_; - id<GTMLogFormatter> formatter_; - id<GTMLogFilter> filter_; -} - -// -// Accessors for the shared logger instance -// - -// Returns a shared/global standard GTMLogger instance. Callers should typically -// use this method to get a GTMLogger instance, unless they explicitly want -// their own instance to configure for their own needs. This is the only method -// that returns a shared instance; all the rest return new GTMLogger instances. -+ (id)sharedLogger; - -// Sets the shared logger instance to |logger|. Future calls to +sharedLogger -// will return |logger| instead. -+ (void)setSharedLogger:(GTMLogger *)logger; - -// -// Creation methods -// - -// Returns a new autoreleased GTMLogger instance that will log to stdout, using -// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter. -+ (id)standardLogger; - -// Same as +standardLogger, but logs to stderr. -+ (id)standardLoggerWithStderr; - -// Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to -// stderr, everything else goes to stdout. -+ (id)standardLoggerWithStdoutAndStderr; - -// Returns a new standard GTMLogger instance with a log writer that will -// write to the file at |path|, and will use the GTMLogStandardFormatter and -// GTMLogLevelFilter classes. If |path| does not exist, it will be created. -+ (id)standardLoggerWithPath:(NSString *)path; - -// Returns an autoreleased GTMLogger instance that will use the specified -// |writer|, |formatter|, and |filter|. -+ (id)loggerWithWriter:(id<GTMLogWriter>)writer - formatter:(id<GTMLogFormatter>)formatter - filter:(id<GTMLogFilter>)filter; - -// Returns an autoreleased GTMLogger instance that logs to stdout, with the -// basic formatter, and no filter. The returned logger differs from the logger -// returned by +standardLogger because this one does not do any filtering and -// does not do any special log formatting; this is the difference between a -// "regular" logger and a "standard" logger. -+ (id)logger; - -// Designated initializer. This method returns a GTMLogger initialized with the -// specified |writer|, |formatter|, and |filter|. See the setter methods below -// for what values will be used if nil is passed for a parameter. -- (id)initWithWriter:(id<GTMLogWriter>)writer - formatter:(id<GTMLogFormatter>)formatter - filter:(id<GTMLogFilter>)filter; - -// -// Logging methods -// - -// Logs a message at the debug level (kGTMLoggerLevelDebug). -- (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); -// Logs a message at the info level (kGTMLoggerLevelInfo). -- (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); -// Logs a message at the error level (kGTMLoggerLevelError). -- (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); -// Logs a message at the assert level (kGTMLoggerLevelAssert). -- (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); - - -// -// Accessors -// - -// Accessor methods for the log writer. If the log writer is set to nil, -// [NSFileHandle fileHandleWithStandardOutput] is used. -- (id<GTMLogWriter>)writer; -- (void)setWriter:(id<GTMLogWriter>)writer; - -// Accessor methods for the log formatter. If the log formatter is set to nil, -// GTMLogBasicFormatter is used. This formatter will format log messages in a -// plain printf style. -- (id<GTMLogFormatter>)formatter; -- (void)setFormatter:(id<GTMLogFormatter>)formatter; - -// Accessor methods for the log filter. If the log filter is set to nil, -// GTMLogNoFilter is used, which allows all log messages through. -- (id<GTMLogFilter>)filter; -- (void)setFilter:(id<GTMLogFilter>)filter; - -@end // GTMLogger - - -// Helper functions that are used by the convenience GTMLogger*() macros that -// enable the logging of function names. -@interface GTMLogger (GTMLoggerMacroHelpers) -- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... - NS_FORMAT_FUNCTION(2, 3); -- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... - NS_FORMAT_FUNCTION(2, 3); -- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... - NS_FORMAT_FUNCTION(2, 3); -- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... - NS_FORMAT_FUNCTION(2, 3); -@end // GTMLoggerMacroHelpers - - -// The convenience macros are only defined if they haven't already been defined. -#ifndef GTMLoggerInfo - -// Convenience macros that log to the shared GTMLogger instance. These macros -// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug() -// calls will be compiled out of non-Debug builds. -#define GTMLoggerDebug(...) \ - [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__] -#define GTMLoggerInfo(...) \ - [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__] -#define GTMLoggerError(...) \ - [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__] -#define GTMLoggerAssert(...) \ - [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__] - -// If we're not in a debug build, remove the GTMLoggerDebug statements. This -// makes calls to GTMLoggerDebug "compile out" of Release builds -#ifndef DEBUG -#undef GTMLoggerDebug -#define GTMLoggerDebug(...) do {} while(0) -#endif - -#endif // !defined(GTMLoggerInfo) - -// Log levels. -typedef enum { - kGTMLoggerLevelUnknown, - kGTMLoggerLevelDebug, - kGTMLoggerLevelInfo, - kGTMLoggerLevelError, - kGTMLoggerLevelAssert, -} GTMLoggerLevel; - - -// -// Log Writers -// - -// Protocol to be implemented by a GTMLogWriter instance. -@protocol GTMLogWriter <NSObject> -// Writes the given log message to where the log writer is configured to write. -- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level; -@end // GTMLogWriter - - -// Simple category on NSFileHandle that makes NSFileHandles valid log writers. -// This is convenient because something like, say, +fileHandleWithStandardError -// now becomes a valid log writer. Log messages are written to the file handle -// with a newline appended. -@interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter> -// Opens the file at |path| in append mode, and creates the file with |mode| -// if it didn't previously exist. -+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode; -@end // NSFileHandle - - -// This category makes NSArray a GTMLogWriter that can be composed of other -// GTMLogWriters. This is the classic Composite GoF design pattern. When the -// GTMLogWriter -logMessage:level: message is sent to the array, the array -// forwards the message to all of its elements that implement the GTMLogWriter -// protocol. -// -// This is useful in situations where you would like to send log output to -// multiple log writers at the same time. Simply create an NSArray of the log -// writers you wish to use, then set the array as the "writer" for your -// GTMLogger instance. -@interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter> -@end // GTMArrayCompositeLogWriter - - -// This category adapts the GTMLogger interface so that it can be used as a log -// writer; it's an "adapter" in the GoF Adapter pattern sense. -// -// This is useful when you want to configure a logger to log to a specific -// writer with a specific formatter and/or filter. But you want to also compose -// that with a different log writer that may have its own formatter and/or -// filter. -@interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter> -@end // GTMLoggerLogWriter - - -// -// Log Formatters -// - -// Protocol to be implemented by a GTMLogFormatter instance. -@protocol GTMLogFormatter <NSObject> -// Returns a formatted string using the format specified in |fmt| and the va -// args specified in |args|. -- (NSString *)stringForFunc:(NSString *)func - withFormat:(NSString *)fmt - valist:(va_list)args - level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); -@end // GTMLogFormatter - - -// A basic log formatter that formats a string the same way that NSLog (or -// printf) would. It does not do anything fancy, nor does it add any data of its -// own. -@interface GTMLogBasicFormatter : NSObject <GTMLogFormatter> - -// Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__ -- (NSString *)prettyNameForFunc:(NSString *)func; - -@end // GTMLogBasicFormatter - - -// A log formatter that formats the log string like the basic formatter, but -// also prepends a timestamp and some basic process info to the message, as -// shown in the following sample output. -// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here -@interface GTMLogStandardFormatter : GTMLogBasicFormatter { - @private - NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS - NSString *pname_; - pid_t pid_; -} -@end // GTMLogStandardFormatter - - -// -// Log Filters -// - -// Protocol to be imlemented by a GTMLogFilter instance. -@protocol GTMLogFilter <NSObject> -// Returns YES if |msg| at |level| should be filtered out; NO otherwise. -- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level; -@end // GTMLogFilter - - -// A log filter that filters messages at the kGTMLoggerLevelDebug level out of -// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered -// out of non-debug builds unless GTMVerboseLogging is set in the environment or -// the processes's defaults. Messages at the kGTMLoggerLevelError level are -// never filtered. -@interface GTMLogLevelFilter : NSObject <GTMLogFilter> -@end // GTMLogLevelFilter - -// A simple log filter that does NOT filter anything out; -// -filterAllowsMessage:level will always return YES. This can be a convenient -// way to enable debug-level logging in release builds (if you so desire). -@interface GTMLogNoFilter : NSObject <GTMLogFilter> -@end // GTMLogNoFilter - - -// Base class for custom level filters. Not for direct use, use the minimum -// or maximum level subclasses below. -@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> { - @private - NSIndexSet *allowedLevels_; -} -@end - -// A log filter that allows you to set a minimum log level. Messages below this -// level will be filtered. -@interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter - -// Designated initializer, logs at levels < |level| will be filtered. -- (id)initWithMinimumLevel:(GTMLoggerLevel)level; - -@end - -// A log filter that allows you to set a maximum log level. Messages whose level -// exceeds this level will be filtered. This is really only useful if you have -// a composite GTMLogger that is sending the other messages elsewhere. -@interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter - -// Designated initializer, logs at levels > |level| will be filtered. -- (id)initWithMaximumLevel:(GTMLoggerLevel)level; - -@end - - -// For subclasses only -@interface GTMLogger (PrivateMethods) - -- (void)logInternalFunc:(const char *)func - format:(NSString *)fmt - valist:(va_list)args - level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); - -@end - diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m deleted file mode 100644 index ebc5836a25..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m +++ /dev/null @@ -1,611 +0,0 @@ -// -// GTMLogger.m -// -// Copyright 2007-2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -#import "GTMLogger.h" -#import <fcntl.h> -#import <unistd.h> -#import <stdlib.h> -#import <pthread.h> - - -#if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42) -// Some versions of GCC (4.2 and below AFAIK) aren't great about supporting -// -Wmissing-format-attribute -// when the function is anything more complex than foo(NSString *fmt, ...). -// You see the error inside the function when you turn ... into va_args and -// attempt to call another function (like vsprintf for example). -// So we just shut off the warning for this file. We reenable it at the end. -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" -#endif // !__clang__ - -// Reference to the shared GTMLogger instance. This is not a singleton, it's -// just an easy reference to one shared instance. -static GTMLogger *gSharedLogger = nil; - - -@implementation GTMLogger - -// Returns a pointer to the shared logger instance. If none exists, a standard -// logger is created and returned. -+ (id)sharedLogger { - @synchronized(self) { - if (gSharedLogger == nil) { - gSharedLogger = [[self standardLogger] retain]; - } - } - return [[gSharedLogger retain] autorelease]; -} - -+ (void)setSharedLogger:(GTMLogger *)logger { - @synchronized(self) { - [gSharedLogger autorelease]; - gSharedLogger = [logger retain]; - } -} - -+ (id)standardLogger { - // Don't trust NSFileHandle not to throw - @try { - id<GTMLogWriter> writer = [NSFileHandle fileHandleWithStandardOutput]; - id<GTMLogFormatter> fr = [[[GTMLogStandardFormatter alloc] init] - autorelease]; - id<GTMLogFilter> filter = [[[GTMLogLevelFilter alloc] init] autorelease]; - return [[[self alloc] initWithWriter:writer - formatter:fr - filter:filter] autorelease]; - } - @catch (id e) { - // Ignored - } - return nil; -} - -+ (id)standardLoggerWithStderr { - // Don't trust NSFileHandle not to throw - @try { - id me = [self standardLogger]; - [me setWriter:[NSFileHandle fileHandleWithStandardError]]; - return me; - } - @catch (id e) { - // Ignored - } - return nil; -} - -+ (id)standardLoggerWithStdoutAndStderr { - // We're going to take advantage of the GTMLogger to GTMLogWriter adaptor - // and create a composite logger that an outer "standard" logger can use - // as a writer. Our inner loggers should apply no formatting since the main - // logger does that and we want the caller to be able to change formatters - // or add writers without knowing the inner structure of our composite. - - // Don't trust NSFileHandle not to throw - @try { - GTMLogBasicFormatter *formatter = [[[GTMLogBasicFormatter alloc] init] - autorelease]; - GTMLogger *stdoutLogger = - [self loggerWithWriter:[NSFileHandle fileHandleWithStandardOutput] - formatter:formatter - filter:[[[GTMLogMaximumLevelFilter alloc] - initWithMaximumLevel:kGTMLoggerLevelInfo] - autorelease]]; - GTMLogger *stderrLogger = - [self loggerWithWriter:[NSFileHandle fileHandleWithStandardError] - formatter:formatter - filter:[[[GTMLogMininumLevelFilter alloc] - initWithMinimumLevel:kGTMLoggerLevelError] - autorelease]]; - GTMLogger *compositeWriter = - [self loggerWithWriter:[NSArray arrayWithObjects: - stdoutLogger, stderrLogger, nil] - formatter:formatter - filter:[[[GTMLogNoFilter alloc] init] autorelease]]; - GTMLogger *outerLogger = [self standardLogger]; - [outerLogger setWriter:compositeWriter]; - return outerLogger; - } - @catch (id e) { - // Ignored - } - return nil; -} - -+ (id)standardLoggerWithPath:(NSString *)path { - @try { - NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644]; - if (fh == nil) return nil; - id me = [self standardLogger]; - [me setWriter:fh]; - return me; - } - @catch (id e) { - // Ignored - } - return nil; -} - -+ (id)loggerWithWriter:(id<GTMLogWriter>)writer - formatter:(id<GTMLogFormatter>)formatter - filter:(id<GTMLogFilter>)filter { - return [[[self alloc] initWithWriter:writer - formatter:formatter - filter:filter] autorelease]; -} - -+ (id)logger { - return [[[self alloc] init] autorelease]; -} - -- (id)init { - return [self initWithWriter:nil formatter:nil filter:nil]; -} - -- (id)initWithWriter:(id<GTMLogWriter>)writer - formatter:(id<GTMLogFormatter>)formatter - filter:(id<GTMLogFilter>)filter { - if ((self = [super init])) { - [self setWriter:writer]; - [self setFormatter:formatter]; - [self setFilter:filter]; - } - return self; -} - -- (void)dealloc { - // Unlikely, but |writer_| may be an NSFileHandle, which can throw - @try { - [formatter_ release]; - [filter_ release]; - [writer_ release]; - } - @catch (id e) { - // Ignored - } - [super dealloc]; -} - -- (id<GTMLogWriter>)writer { - return [[writer_ retain] autorelease]; -} - -- (void)setWriter:(id<GTMLogWriter>)writer { - @synchronized(self) { - [writer_ autorelease]; - writer_ = nil; - if (writer == nil) { - // Try to use stdout, but don't trust NSFileHandle - @try { - writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain]; - } - @catch (id e) { - // Leave |writer_| nil - } - } else { - writer_ = [writer retain]; - } - } -} - -- (id<GTMLogFormatter>)formatter { - return [[formatter_ retain] autorelease]; -} - -- (void)setFormatter:(id<GTMLogFormatter>)formatter { - @synchronized(self) { - [formatter_ autorelease]; - formatter_ = nil; - if (formatter == nil) { - @try { - formatter_ = [[GTMLogBasicFormatter alloc] init]; - } - @catch (id e) { - // Leave |formatter_| nil - } - } else { - formatter_ = [formatter retain]; - } - } -} - -- (id<GTMLogFilter>)filter { - return [[filter_ retain] autorelease]; -} - -- (void)setFilter:(id<GTMLogFilter>)filter { - @synchronized(self) { - [filter_ autorelease]; - filter_ = nil; - if (filter == nil) { - @try { - filter_ = [[GTMLogNoFilter alloc] init]; - } - @catch (id e) { - // Leave |filter_| nil - } - } else { - filter_ = [filter retain]; - } - } -} - -- (void)logDebug:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug]; - va_end(args); -} - -- (void)logInfo:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo]; - va_end(args); -} - -- (void)logError:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError]; - va_end(args); -} - -- (void)logAssert:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert]; - va_end(args); -} - -@end // GTMLogger - -@implementation GTMLogger (GTMLoggerMacroHelpers) - -- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug]; - va_end(args); -} - -- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo]; - va_end(args); -} - -- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError]; - va_end(args); -} - -- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... { - va_list args; - va_start(args, fmt); - [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert]; - va_end(args); -} - -@end // GTMLoggerMacroHelpers - -@implementation GTMLogger (PrivateMethods) - -- (void)logInternalFunc:(const char *)func - format:(NSString *)fmt - valist:(va_list)args - level:(GTMLoggerLevel)level { - // Primary point where logging happens, logging should never throw, catch - // everything. - @try { - NSString *fname = func ? [NSString stringWithUTF8String:func] : nil; - NSString *msg = [formatter_ stringForFunc:fname - withFormat:fmt - valist:args - level:level]; - if (msg && [filter_ filterAllowsMessage:msg level:level]) - [writer_ logMessage:msg level:level]; - } - @catch (id e) { - // Ignored - } -} - -@end // PrivateMethods - - -@implementation NSFileHandle (GTMFileHandleLogWriter) - -+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode { - int fd = -1; - if (path) { - int flags = O_WRONLY | O_APPEND | O_CREAT; - fd = open([path fileSystemRepresentation], flags, mode); - } - if (fd == -1) return nil; - return [[[self alloc] initWithFileDescriptor:fd - closeOnDealloc:YES] autorelease]; -} - -- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { - @synchronized(self) { - // Closed pipes should not generate exceptions in our caller. Catch here - // as well [GTMLogger logInternalFunc:...] so that an exception in this - // writer does not prevent other writers from having a chance. - @try { - NSString *line = [NSString stringWithFormat:@"%@\n", msg]; - [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]]; - } - @catch (id e) { - // Ignored - } - } -} - -@end // GTMFileHandleLogWriter - - -@implementation NSArray (GTMArrayCompositeLogWriter) - -- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { - @synchronized(self) { - id<GTMLogWriter> child = nil; - GTM_FOREACH_OBJECT(child, self) { - if ([child conformsToProtocol:@protocol(GTMLogWriter)]) - [child logMessage:msg level:level]; - } - } -} - -@end // GTMArrayCompositeLogWriter - - -@implementation GTMLogger (GTMLoggerLogWriter) - -- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { - switch (level) { - case kGTMLoggerLevelDebug: - [self logDebug:@"%@", msg]; - break; - case kGTMLoggerLevelInfo: - [self logInfo:@"%@", msg]; - break; - case kGTMLoggerLevelError: - [self logError:@"%@", msg]; - break; - case kGTMLoggerLevelAssert: - [self logAssert:@"%@", msg]; - break; - default: - // Ignore the message. - break; - } -} - -@end // GTMLoggerLogWriter - - -@implementation GTMLogBasicFormatter - -- (NSString *)prettyNameForFunc:(NSString *)func { - NSString *name = [func stringByTrimmingCharactersInSet: - [NSCharacterSet whitespaceAndNewlineCharacterSet]]; - NSString *function = @"(unknown)"; - if ([name length]) { - if (// Objective C __func__ and __PRETTY_FUNCTION__ - [name hasPrefix:@"-["] || [name hasPrefix:@"+["] || - // C++ __PRETTY_FUNCTION__ and other preadorned formats - [name hasSuffix:@")"]) { - function = name; - } else { - // Assume C99 __func__ - function = [NSString stringWithFormat:@"%@()", name]; - } - } - return function; -} - -- (NSString *)stringForFunc:(NSString *)func - withFormat:(NSString *)fmt - valist:(va_list)args - level:(GTMLoggerLevel)level { - // Performance note: We may want to do a quick check here to see if |fmt| - // contains a '%', and if not, simply return 'fmt'. - if (!(fmt && args)) return nil; - return [[[NSString alloc] initWithFormat:fmt arguments:args] autorelease]; -} - -@end // GTMLogBasicFormatter - - -@implementation GTMLogStandardFormatter - -- (id)init { - if ((self = [super init])) { - dateFormatter_ = [[NSDateFormatter alloc] init]; - [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4]; - [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; - pname_ = [[[NSProcessInfo processInfo] processName] copy]; - pid_ = [[NSProcessInfo processInfo] processIdentifier]; - if (!(dateFormatter_ && pname_)) { - [self release]; - return nil; - } - } - return self; -} - -- (void)dealloc { - [dateFormatter_ release]; - [pname_ release]; - [super dealloc]; -} - -- (NSString *)stringForFunc:(NSString *)func - withFormat:(NSString *)fmt - valist:(va_list)args - level:(GTMLoggerLevel)level { - NSString *tstamp = nil; - @synchronized (dateFormatter_) { - tstamp = [dateFormatter_ stringFromDate:[NSDate date]]; - } - return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@", - tstamp, pname_, pid_, pthread_self(), - level, [self prettyNameForFunc:func], - // |super| has guard for nil |fmt| and |args| - [super stringForFunc:func withFormat:fmt valist:args level:level]]; -} - -@end // GTMLogStandardFormatter - - -@implementation GTMLogLevelFilter - -// Check the environment and the user preferences for the GTMVerboseLogging key -// to see if verbose logging has been enabled. The environment variable will -// override the defaults setting, so check the environment first. -// COV_NF_START -static BOOL IsVerboseLoggingEnabled(void) { - static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging"; - NSString *value = [[[NSProcessInfo processInfo] environment] - objectForKey:kVerboseLoggingKey]; - if (value) { - // Emulate [NSString boolValue] for pre-10.5 - value = [value stringByTrimmingCharactersInSet: - [NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if ([[value uppercaseString] hasPrefix:@"Y"] || - [[value uppercaseString] hasPrefix:@"T"] || - [value intValue]) { - return YES; - } else { - return NO; - } - } - return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey]; -} -// COV_NF_END - -// In DEBUG builds, log everything. If we're not in a debug build we'll assume -// that we're in a Release build. -- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { -#if defined(DEBUG) && DEBUG - return YES; -#endif - - BOOL allow = YES; - - switch (level) { - case kGTMLoggerLevelDebug: - allow = NO; - break; - case kGTMLoggerLevelInfo: - allow = IsVerboseLoggingEnabled(); - break; - case kGTMLoggerLevelError: - allow = YES; - break; - case kGTMLoggerLevelAssert: - allow = YES; - break; - default: - allow = YES; - break; - } - - return allow; -} - -@end // GTMLogLevelFilter - - -@implementation GTMLogNoFilter - -- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { - return YES; // Allow everything through -} - -@end // GTMLogNoFilter - - -@implementation GTMLogAllowedLevelFilter - -// Private designated initializer -- (id)initWithAllowedLevels:(NSIndexSet *)levels { - self = [super init]; - if (self != nil) { - allowedLevels_ = [levels retain]; - // Cap min/max level - if (!allowedLevels_ || - // NSIndexSet is unsigned so only check the high bound, but need to - // check both first and last index because NSIndexSet appears to allow - // wraparound. - ([allowedLevels_ firstIndex] > kGTMLoggerLevelAssert) || - ([allowedLevels_ lastIndex] > kGTMLoggerLevelAssert)) { - [self release]; - return nil; - } - } - return self; -} - -- (id)init { - // Allow all levels in default init - return [self initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: - NSMakeRange(kGTMLoggerLevelUnknown, - (kGTMLoggerLevelAssert - kGTMLoggerLevelUnknown + 1))]]; -} - -- (void)dealloc { - [allowedLevels_ release]; - [super dealloc]; -} - -- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { - return [allowedLevels_ containsIndex:level]; -} - -@end // GTMLogAllowedLevelFilter - - -@implementation GTMLogMininumLevelFilter - -- (id)initWithMinimumLevel:(GTMLoggerLevel)level { - return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: - NSMakeRange(level, - (kGTMLoggerLevelAssert - level + 1))]]; -} - -@end // GTMLogMininumLevelFilter - - -@implementation GTMLogMaximumLevelFilter - -- (id)initWithMaximumLevel:(GTMLoggerLevel)level { - return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: - NSMakeRange(kGTMLoggerLevelUnknown, level + 1)]]; -} - -@end // GTMLogMaximumLevelFilter - -#if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42) -// See comment at top of file. -#pragma GCC diagnostic error "-Wmissing-format-attribute" -#endif // !__clang__ - diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h deleted file mode 100644 index 42e8fed390..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// HTTPMultipartUpload: A multipart/form-data HTTP uploader. -// Each parameter pair is sent as a boundary -// Each file is sent with a name field in addition to the filename and data -// The data will be sent synchronously. - -#import <Foundation/Foundation.h> - -@interface HTTPMultipartUpload : NSObject { - @protected - NSURL *url_; // The destination URL (STRONG) - NSDictionary *parameters_; // The key/value pairs for sending data (STRONG) - NSMutableDictionary *files_; // Dictionary of name/file-path (STRONG) - NSString *boundary_; // The boundary string (STRONG) - NSHTTPURLResponse *response_; // The response from the send (STRONG) -} - -- (id)initWithURL:(NSURL *)url; - -- (NSURL *)URL; - -- (void)setParameters:(NSDictionary *)parameters; -- (NSDictionary *)parameters; - -- (void)addFileAtPath:(NSString *)path name:(NSString *)name; -- (void)addFileContents:(NSData *)data name:(NSString *)name; -- (NSDictionary *)files; - -// Set the data and return the response -- (NSData *)send:(NSError **)error; -- (NSHTTPURLResponse *)response; - -@end diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m deleted file mode 100644 index 9ac886d53e..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#import "HTTPMultipartUpload.h" -#import "GTMDefines.h" - -// As -[NSString stringByAddingPercentEscapesUsingEncoding:] has been -// deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements it -// using -[NSString stringByAddingPercentEncodingWithAllowedCharacters:] when -// using those SDKs. -static NSString *PercentEncodeNSString(NSString *key) { -#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \ - __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \ - (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ - defined(MAC_OS_X_VERSION_10_11) && \ - MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11) - return [key stringByAddingPercentEncodingWithAllowedCharacters: - [NSCharacterSet URLQueryAllowedCharacterSet]]; -#else - return [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; -#endif -} - -// As -[NSURLConnection sendSynchronousRequest:returningResponse:error:] has -// been deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements -// it using -[NSURLSession dataTaskWithRequest:completionHandler:] when using -// those SDKs. -static NSData *SendSynchronousNSURLRequest(NSURLRequest *req, - NSURLResponse **out_response, - NSError **out_error) { -#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \ - __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \ - (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ - defined(MAC_OS_X_VERSION_10_11) && \ - MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11) - __block NSData* result = nil; - __block NSError* error = nil; - __block NSURLResponse* response = nil; - dispatch_semaphore_t wait_semaphone = dispatch_semaphore_create(0); - [[[NSURLSession sharedSession] - dataTaskWithRequest:req - completionHandler:^(NSData *data, - NSURLResponse *resp, - NSError *err) { - if (out_error) - error = [err retain]; - if (out_response) - response = [resp retain]; - if (err == nil) - result = [data retain]; - dispatch_semaphore_signal(wait_semaphone); - }] resume]; - dispatch_semaphore_wait(wait_semaphone, DISPATCH_TIME_FOREVER); - dispatch_release(wait_semaphone); - if (out_error) - *out_error = [error autorelease]; - if (out_response) - *out_response = [response autorelease]; - return [result autorelease]; -#else - return [NSURLConnection sendSynchronousRequest:req - returningResponse:out_response - error:out_error]; -#endif -} -@interface HTTPMultipartUpload(PrivateMethods) -- (NSString *)multipartBoundary; -// Each of the following methods will append the starting multipart boundary, -// but not the ending one. -- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value; -- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name; -- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name; -@end - -@implementation HTTPMultipartUpload -//============================================================================= -#pragma mark - -#pragma mark || Private || -//============================================================================= -- (NSString *)multipartBoundary { - // The boundary has 27 '-' characters followed by 16 hex digits - return [NSString stringWithFormat:@"---------------------------%08X%08X", - rand(), rand()]; -} - -//============================================================================= -- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value { - NSString *escaped = PercentEncodeNSString(key); - NSString *fmt = - @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n"; - NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value]; - - return [form dataUsingEncoding:NSUTF8StringEncoding]; -} - -//============================================================================= -- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name { - NSMutableData *data = [NSMutableData data]; - NSString *escaped = PercentEncodeNSString(name); - NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; " - "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n"; - NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped]; - - [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]]; - [data appendData:contents]; - - return data; -} - -//============================================================================= -- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name { - NSData *contents = [NSData dataWithContentsOfFile:file]; - - return [self formDataForFileContents:contents name:name]; -} - -//============================================================================= -#pragma mark - -#pragma mark || Public || -//============================================================================= -- (id)initWithURL:(NSURL *)url { - if ((self = [super init])) { - url_ = [url copy]; - boundary_ = [[self multipartBoundary] retain]; - files_ = [[NSMutableDictionary alloc] init]; - } - - return self; -} - -//============================================================================= -- (void)dealloc { - [url_ release]; - [parameters_ release]; - [files_ release]; - [boundary_ release]; - [response_ release]; - - [super dealloc]; -} - -//============================================================================= -- (NSURL *)URL { - return url_; -} - -//============================================================================= -- (void)setParameters:(NSDictionary *)parameters { - if (parameters != parameters_) { - [parameters_ release]; - parameters_ = [parameters copy]; - } -} - -//============================================================================= -- (NSDictionary *)parameters { - return parameters_; -} - -//============================================================================= -- (void)addFileAtPath:(NSString *)path name:(NSString *)name { - [files_ setObject:path forKey:name]; -} - -//============================================================================= -- (void)addFileContents:(NSData *)data name:(NSString *)name { - [files_ setObject:data forKey:name]; -} - -//============================================================================= -- (NSDictionary *)files { - return files_; -} - -//============================================================================= -- (NSData *)send:(NSError **)error { - NSMutableURLRequest *req = - [[NSMutableURLRequest alloc] - initWithURL:url_ cachePolicy:NSURLRequestUseProtocolCachePolicy - timeoutInterval:10.0 ]; - - NSMutableData *postBody = [NSMutableData data]; - - [req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", - boundary_] forHTTPHeaderField:@"Content-type"]; - - // Add any parameters to the message - NSArray *parameterKeys = [parameters_ allKeys]; - NSString *key; - - NSInteger count = [parameterKeys count]; - for (NSInteger i = 0; i < count; ++i) { - key = [parameterKeys objectAtIndex:i]; - [postBody appendData:[self formDataForKey:key - value:[parameters_ objectForKey:key]]]; - } - - // Add any files to the message - NSArray *fileNames = [files_ allKeys]; - count = [fileNames count]; - for (NSInteger i = 0; i < count; ++i) { - NSString *name = [fileNames objectAtIndex:i]; - id fileOrData = [files_ objectForKey:name]; - NSData *fileData; - - // The object can be either the path to a file (NSString) or the contents - // of the file (NSData). - if ([fileOrData isKindOfClass:[NSData class]]) - fileData = [self formDataForFileContents:fileOrData name:name]; - else - fileData = [self formDataForFile:fileOrData name:name]; - - [postBody appendData:fileData]; - } - - NSString *epilogue = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_]; - [postBody appendData:[epilogue dataUsingEncoding:NSUTF8StringEncoding]]; - - [req setHTTPBody:postBody]; - [req setHTTPMethod:@"POST"]; - - [response_ release]; - response_ = nil; - - NSData *data = nil; - if ([[req URL] isFileURL]) { - [[req HTTPBody] writeToURL:[req URL] options:0 error:error]; - } else { - NSURLResponse *response = nil; - data = SendSynchronousNSURLRequest(req, &response, error); - response_ = (NSHTTPURLResponse *)[response retain]; - } - [req release]; - - return data; -} - -//============================================================================= -- (NSHTTPURLResponse *)response { - return response_; -} - -@end diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h deleted file mode 100644 index 8df9165bb3..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// MachIPC.h -// -// Some helpful wrappers for using Mach IPC calls - -#ifndef MACH_IPC_H__ -#define MACH_IPC_H__ - -#import <mach/mach.h> -#import <mach/message.h> -#import <servers/bootstrap.h> -#import <sys/types.h> - -#import <CoreServices/CoreServices.h> - -//============================================================================== -// DISCUSSION: -// -// The three main classes of interest are -// -// MachMessage: a wrapper for a mach message of the following form -// mach_msg_header_t -// mach_msg_body_t -// optional descriptors -// optional extra message data -// -// MachReceiveMessage and MachSendMessage subclass MachMessage -// and are used instead of MachMessage which is an abstract base class -// -// ReceivePort: -// Represents a mach port for which we have receive rights -// -// MachPortSender: -// Represents a mach port for which we have send rights -// -// Here's an example to receive a message on a server port: -// -// // This creates our named server port -// ReceivePort receivePort("com.Google.MyService"); -// -// MachReceiveMessage message; -// kern_return_t result = receivePort.WaitForMessage(&message, 0); -// -// if (result == KERN_SUCCESS && message.GetMessageID() == 57) { -// mach_port_t task = message.GetTranslatedPort(0); -// mach_port_t thread = message.GetTranslatedPort(1); -// -// char *messageString = message.GetData(); -// -// printf("message string = %s\n", messageString); -// } -// -// Here is an example of using these classes to send a message to this port: -// -// // send to already named port -// MachPortSender sender("com.Google.MyService"); -// MachSendMessage message(57); // our message ID is 57 -// -// // add some ports to be translated for us -// message.AddDescriptor(mach_task_self()); // our task -// message.AddDescriptor(mach_thread_self()); // this thread -// -// char messageString[] = "Hello server!\n"; -// message.SetData(messageString, strlen(messageString)+1); -// -// kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms -// - -namespace google_breakpad { -#define PRINT_MACH_RESULT(result_, message_) \ - printf(message_" %s (%d)\n", mach_error_string(result_), result_ ); - -//============================================================================== -// A wrapper class for mach_msg_port_descriptor_t (with same memory layout) -// with convenient constructors and accessors -class MachMsgPortDescriptor : public mach_msg_port_descriptor_t { - public: - // General-purpose constructor - MachMsgPortDescriptor(mach_port_t in_name, - mach_msg_type_name_t in_disposition) { - name = in_name; - pad1 = 0; - pad2 = 0; - disposition = in_disposition; - type = MACH_MSG_PORT_DESCRIPTOR; - } - - // For passing send rights to a port - MachMsgPortDescriptor(mach_port_t in_name) { - name = in_name; - pad1 = 0; - pad2 = 0; - disposition = MACH_MSG_TYPE_COPY_SEND; - type = MACH_MSG_PORT_DESCRIPTOR; - } - - // Copy constructor - MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) { - name = desc.name; - pad1 = desc.pad1; - pad2 = desc.pad2; - disposition = desc.disposition; - type = desc.type; - } - - mach_port_t GetMachPort() const { - return name; - } - - mach_msg_type_name_t GetDisposition() const { - return disposition; - } - - // For convenience - operator mach_port_t() const { - return GetMachPort(); - } -}; - -//============================================================================== -// MachMessage: a wrapper for a mach message -// (mach_msg_header_t, mach_msg_body_t, extra data) -// -// This considerably simplifies the construction of a message for sending -// and the getting at relevant data and descriptors for the receiver. -// -// Currently the combined size of the descriptors plus data must be -// less than 1024. But as a benefit no memory allocation is necessary. -// -// TODO: could consider adding malloc() support for very large messages -// -// A MachMessage object is used by ReceivePort::WaitForMessage -// and MachPortSender::SendMessage -// -class MachMessage { - public: - - // The receiver of the message can retrieve the raw data this way - uint8_t *GetData() { - return GetDataLength() > 0 ? GetDataPacket()->data : NULL; - } - - uint32_t GetDataLength() { - return EndianU32_LtoN(GetDataPacket()->data_length); - } - - // The message ID may be used as a code identifying the type of message - void SetMessageID(int32_t message_id) { - GetDataPacket()->id = EndianU32_NtoL(message_id); - } - - int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); } - - // Adds a descriptor (typically a mach port) to be translated - // returns true if successful, otherwise not enough space - bool AddDescriptor(const MachMsgPortDescriptor &desc); - - int GetDescriptorCount() const { return body.msgh_descriptor_count; } - MachMsgPortDescriptor *GetDescriptor(int n); - - // Convenience method which gets the mach port described by the descriptor - mach_port_t GetTranslatedPort(int n); - - // A simple message is one with no descriptors - bool IsSimpleMessage() const { return GetDescriptorCount() == 0; } - - // Sets raw data for the message (returns false if not enough space) - bool SetData(void *data, int32_t data_length); - - protected: - // Consider this an abstract base class - must create an actual instance - // of MachReceiveMessage or MachSendMessage - - MachMessage() { - memset(this, 0, sizeof(MachMessage)); - } - - friend class ReceivePort; - friend class MachPortSender; - - // Represents raw data in our message - struct MessageDataPacket { - int32_t id; // little-endian - int32_t data_length; // little-endian - uint8_t data[1]; // actual size limited by sizeof(MachMessage) - }; - - MessageDataPacket* GetDataPacket(); - - void SetDescriptorCount(int n); - void SetDescriptor(int n, const MachMsgPortDescriptor &desc); - - // Returns total message size setting msgh_size in the header to this value - mach_msg_size_t CalculateSize(); - - mach_msg_header_t head; - mach_msg_body_t body; - uint8_t padding[1024]; // descriptors and data may be embedded here -}; - -//============================================================================== -// MachReceiveMessage and MachSendMessage are useful to separate the idea -// of a mach message being sent and being received, and adds increased type -// safety: -// ReceivePort::WaitForMessage() only accepts a MachReceiveMessage -// MachPortSender::SendMessage() only accepts a MachSendMessage - -//============================================================================== -class MachReceiveMessage : public MachMessage { - public: - MachReceiveMessage() : MachMessage() {}; -}; - -//============================================================================== -class MachSendMessage : public MachMessage { - public: - MachSendMessage(int32_t message_id); -}; - -//============================================================================== -// Represents a mach port for which we have receive rights -class ReceivePort { - public: - // Creates a new mach port for receiving messages and registers a name for it - explicit ReceivePort(const char *receive_port_name); - - // Given an already existing mach port, use it. We take ownership of the - // port and deallocate it in our destructor. - explicit ReceivePort(mach_port_t receive_port); - - // Create a new mach port for receiving messages - ReceivePort(); - - ~ReceivePort(); - - // Waits on the mach port until message received or timeout - kern_return_t WaitForMessage(MachReceiveMessage *out_message, - mach_msg_timeout_t timeout); - - // The underlying mach port that we wrap - mach_port_t GetPort() const { return port_; } - - private: - ReceivePort(const ReceivePort&); // disable copy c-tor - - mach_port_t port_; - kern_return_t init_result_; -}; - -//============================================================================== -// Represents a mach port for which we have send rights -class MachPortSender { - public: - // get a port with send rights corresponding to a named registered service - explicit MachPortSender(const char *receive_port_name); - - - // Given an already existing mach port, use it. - explicit MachPortSender(mach_port_t send_port); - - kern_return_t SendMessage(MachSendMessage &message, - mach_msg_timeout_t timeout); - - private: - MachPortSender(const MachPortSender&); // disable copy c-tor - - mach_port_t send_port_; - kern_return_t init_result_; -}; - -} // namespace google_breakpad - -#endif // MACH_IPC_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm deleted file mode 100644 index dc9773f77a..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// MachIPC.mm -// Wrapper for mach IPC calls - -#import <stdio.h> -#import "MachIPC.h" -#include "common/mac/bootstrap_compat.h" - -namespace google_breakpad { -//============================================================================== -MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() { - head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); - - // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage() - head.msgh_local_port = MACH_PORT_NULL; - head.msgh_reserved = 0; - head.msgh_id = 0; - - SetDescriptorCount(0); // start out with no descriptors - - SetMessageID(message_id); - SetData(NULL, 0); // client may add data later -} - -//============================================================================== -// returns true if successful -bool MachMessage::SetData(void *data, - int32_t data_length) { - // first check to make sure we have enough space - size_t size = CalculateSize(); - size_t new_size = size + data_length; - - if (new_size > sizeof(MachMessage)) { - return false; // not enough space - } - - GetDataPacket()->data_length = EndianU32_NtoL(data_length); - if (data) memcpy(GetDataPacket()->data, data, data_length); - - CalculateSize(); - - return true; -} - -//============================================================================== -// calculates and returns the total size of the message -// Currently, the entire message MUST fit inside of the MachMessage -// messsage size <= sizeof(MachMessage) -mach_msg_size_t MachMessage::CalculateSize() { - size_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t); - - // add space for MessageDataPacket - int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3; - size += 2*sizeof(int32_t) + alignedDataLength; - - // add space for descriptors - size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor); - - head.msgh_size = static_cast<mach_msg_size_t>(size); - - return head.msgh_size; -} - -//============================================================================== -MachMessage::MessageDataPacket *MachMessage::GetDataPacket() { - size_t desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount(); - MessageDataPacket *packet = - reinterpret_cast<MessageDataPacket*>(padding + desc_size); - - return packet; -} - -//============================================================================== -void MachMessage::SetDescriptor(int n, - const MachMsgPortDescriptor &desc) { - MachMsgPortDescriptor *desc_array = - reinterpret_cast<MachMsgPortDescriptor*>(padding); - desc_array[n] = desc; -} - -//============================================================================== -// returns true if successful otherwise there was not enough space -bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) { - // first check to make sure we have enough space - int size = CalculateSize(); - size_t new_size = size + sizeof(MachMsgPortDescriptor); - - if (new_size > sizeof(MachMessage)) { - return false; // not enough space - } - - // unfortunately, we need to move the data to allow space for the - // new descriptor - u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket()); - bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t)); - - SetDescriptor(GetDescriptorCount(), desc); - SetDescriptorCount(GetDescriptorCount() + 1); - - CalculateSize(); - - return true; -} - -//============================================================================== -void MachMessage::SetDescriptorCount(int n) { - body.msgh_descriptor_count = n; - - if (n > 0) { - head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; - } else { - head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX; - } -} - -//============================================================================== -MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) { - if (n < GetDescriptorCount()) { - MachMsgPortDescriptor *desc = - reinterpret_cast<MachMsgPortDescriptor*>(padding); - return desc + n; - } - - return nil; -} - -//============================================================================== -mach_port_t MachMessage::GetTranslatedPort(int n) { - if (n < GetDescriptorCount()) { - return GetDescriptor(n)->GetMachPort(); - } - return MACH_PORT_NULL; -} - -#pragma mark - - -//============================================================================== -// create a new mach port for receiving messages and register a name for it -ReceivePort::ReceivePort(const char *receive_port_name) { - mach_port_t current_task = mach_task_self(); - - init_result_ = mach_port_allocate(current_task, - MACH_PORT_RIGHT_RECEIVE, - &port_); - - if (init_result_ != KERN_SUCCESS) - return; - - init_result_ = mach_port_insert_right(current_task, - port_, - port_, - MACH_MSG_TYPE_MAKE_SEND); - - if (init_result_ != KERN_SUCCESS) - return; - - mach_port_t task_bootstrap_port = 0; - init_result_ = task_get_bootstrap_port(current_task, &task_bootstrap_port); - - if (init_result_ != KERN_SUCCESS) - return; - - init_result_ = breakpad::BootstrapRegister( - bootstrap_port, - const_cast<char*>(receive_port_name), - port_); -} - -//============================================================================== -// create a new mach port for receiving messages -ReceivePort::ReceivePort() { - mach_port_t current_task = mach_task_self(); - - init_result_ = mach_port_allocate(current_task, - MACH_PORT_RIGHT_RECEIVE, - &port_); - - if (init_result_ != KERN_SUCCESS) - return; - - init_result_ = mach_port_insert_right(current_task, - port_, - port_, - MACH_MSG_TYPE_MAKE_SEND); -} - -//============================================================================== -// Given an already existing mach port, use it. We take ownership of the -// port and deallocate it in our destructor. -ReceivePort::ReceivePort(mach_port_t receive_port) - : port_(receive_port), - init_result_(KERN_SUCCESS) { -} - -//============================================================================== -ReceivePort::~ReceivePort() { - if (init_result_ == KERN_SUCCESS) - mach_port_deallocate(mach_task_self(), port_); -} - -//============================================================================== -kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message, - mach_msg_timeout_t timeout) { - if (!out_message) { - return KERN_INVALID_ARGUMENT; - } - - // return any error condition encountered in constructor - if (init_result_ != KERN_SUCCESS) - return init_result_; - - out_message->head.msgh_bits = 0; - out_message->head.msgh_local_port = port_; - out_message->head.msgh_remote_port = MACH_PORT_NULL; - out_message->head.msgh_reserved = 0; - out_message->head.msgh_id = 0; - - mach_msg_option_t options = MACH_RCV_MSG; - if (timeout != MACH_MSG_TIMEOUT_NONE) - options |= MACH_RCV_TIMEOUT; - kern_return_t result = mach_msg(&out_message->head, - options, - 0, - sizeof(MachMessage), - port_, - timeout, // timeout in ms - MACH_PORT_NULL); - - return result; -} - -#pragma mark - - -//============================================================================== -// get a port with send rights corresponding to a named registered service -MachPortSender::MachPortSender(const char *receive_port_name) { - mach_port_t task_bootstrap_port = 0; - init_result_ = task_get_bootstrap_port(mach_task_self(), - &task_bootstrap_port); - - if (init_result_ != KERN_SUCCESS) - return; - - init_result_ = bootstrap_look_up(task_bootstrap_port, - const_cast<char*>(receive_port_name), - &send_port_); -} - -//============================================================================== -MachPortSender::MachPortSender(mach_port_t send_port) - : send_port_(send_port), - init_result_(KERN_SUCCESS) { -} - -//============================================================================== -kern_return_t MachPortSender::SendMessage(MachSendMessage &message, - mach_msg_timeout_t timeout) { - if (message.head.msgh_size == 0) { - return KERN_INVALID_VALUE; // just for safety -- never should occur - }; - - if (init_result_ != KERN_SUCCESS) - return init_result_; - - message.head.msgh_remote_port = send_port_; - - kern_return_t result = mach_msg(&message.head, - MACH_SEND_MSG | MACH_SEND_TIMEOUT, - message.head.msgh_size, - 0, - MACH_PORT_NULL, - timeout, // timeout in ms - MACH_PORT_NULL); - - return result; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc deleted file mode 100644 index 4e5f5534a5..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/mac/arch_utilities.h" - -#include <mach-o/arch.h> -#include <mach-o/fat.h> -#include <stdio.h> -#include <string.h> - -#ifndef CPU_SUBTYPE_ARM_V7S -#define CPU_SUBTYPE_ARM_V7S (static_cast<cpu_subtype_t>(11)) -#endif // CPU_SUBTYPE_ARM_V7S - -#ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) -#endif // CPU_TYPE_ARM64 - -#ifndef CPU_SUBTYPE_ARM64_ALL -#define CPU_SUBTYPE_ARM64_ALL (static_cast<cpu_subtype_t>(0)) -#endif // CPU_SUBTYPE_ARM64_ALL - -namespace { - -const NXArchInfo* ArchInfo_arm64() { - NXArchInfo* arm64 = new NXArchInfo; - *arm64 = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM, - CPU_SUBTYPE_ARM_V7); - arm64->name = "arm64"; - arm64->cputype = CPU_TYPE_ARM64; - arm64->cpusubtype = CPU_SUBTYPE_ARM64_ALL; - arm64->description = "arm 64"; - return arm64; -} - -const NXArchInfo* ArchInfo_armv7s() { - NXArchInfo* armv7s = new NXArchInfo; - *armv7s = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM, - CPU_SUBTYPE_ARM_V7); - armv7s->name = "armv7s"; - armv7s->cpusubtype = CPU_SUBTYPE_ARM_V7S; - armv7s->description = "arm v7s"; - return armv7s; -} - -} // namespace - -namespace google_breakpad { - -const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name) { - // TODO: Remove this when the OS knows about arm64. - if (!strcmp("arm64", arch_name)) - return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64, - CPU_SUBTYPE_ARM64_ALL); - - // TODO: Remove this when the OS knows about armv7s. - if (!strcmp("armv7s", arch_name)) - return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S); - - return NXGetArchInfoFromName(arch_name); -} - -const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype) { - // TODO: Remove this when the OS knows about arm64. - if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_ALL) { - static const NXArchInfo* arm64 = ArchInfo_arm64(); - return arm64; - } - - // TODO: Remove this when the OS knows about armv7s. - if (cpu_type == CPU_TYPE_ARM && cpu_subtype == CPU_SUBTYPE_ARM_V7S) { - static const NXArchInfo* armv7s = ArchInfo_armv7s(); - return armv7s; - } - - return NXGetArchInfoFromCpuType(cpu_type, cpu_subtype); -} - -} // namespace google_breakpad - -#ifndef __APPLE__ -namespace { - -enum Architecture { - kArch_i386 = 0, - kArch_x86_64, - kArch_arm, - kArch_arm64, - kArch_ppc, - // This must be last. - kNumArchitectures -}; - -// enum Architecture above and kKnownArchitectures below -// must be kept in sync. -const NXArchInfo kKnownArchitectures[] = { - { - "i386", - CPU_TYPE_I386, - CPU_SUBTYPE_I386_ALL, - NX_LittleEndian, - "Intel 80x86" - }, - { - "x86_64", - CPU_TYPE_X86_64, - CPU_SUBTYPE_X86_64_ALL, - NX_LittleEndian, - "Intel x86-64" - }, - { - "arm", - CPU_TYPE_ARM, - CPU_SUBTYPE_ARM_ALL, - NX_LittleEndian, - "ARM" - }, - { - "arm64", - CPU_TYPE_ARM64, - CPU_SUBTYPE_ARM64_ALL, - NX_LittleEndian, - "ARM64" - }, - { - "ppc", - CPU_TYPE_POWERPC, - CPU_SUBTYPE_POWERPC_ALL, - NX_BigEndian, - "PowerPC" - } -}; - -} // namespace - -const NXArchInfo *NXGetLocalArchInfo(void) { - Architecture arch; -#if defined(__i386__) - arch = kArch_i386; -#elif defined(__x86_64__) - arch = kArch_x86_64; -#elif defined(__arm64) - arch = kArch_arm64; -#elif defined(__arm__) - arch = kArch_arm; -#elif defined(__powerpc__) - arch = kArch_ppc; -#else - #error "Unsupported CPU architecture" -#endif - return &kKnownArchitectures[arch]; -} - -const NXArchInfo *NXGetArchInfoFromName(const char *name) { - for (int arch = 0; arch < kNumArchitectures; ++arch) { - if (!strcmp(name, kKnownArchitectures[arch].name)) { - return &kKnownArchitectures[arch]; - } - } - return NULL; -} - -const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype, - cpu_subtype_t cpusubtype) { - for (int arch = 0; arch < kNumArchitectures; ++arch) { - if (kKnownArchitectures[arch].cputype == cputype) { - return &kKnownArchitectures[arch]; - } - } - return NULL; -} - -struct fat_arch *NXFindBestFatArch(cpu_type_t cputype, - cpu_subtype_t cpusubtype, - struct fat_arch *fat_archs, - uint32_t nfat_archs) { - for (uint32_t f = 0; f < nfat_archs; ++f) { - if (fat_archs[f].cputype == cputype) { - return &fat_archs[f]; - } - } - return NULL; -} -#endif // !__APPLE__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h deleted file mode 100644 index 397c1f5873..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// arch_utilities.h: Utilities for architecture introspection for Mac platform. - -#ifndef COMMON_MAC_ARCH_UTILITIES_H__ -#define COMMON_MAC_ARCH_UTILITIES_H__ - -#include <mach-o/arch.h> - -namespace google_breakpad { - -// Custom implementation of |NXGetArchInfoFromName| and -// |NXGetArchInfoFromCpuType| that handle newer CPU on older OSes. -const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name); -const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype); - -} // namespace google_breakpad - -#endif // COMMON_MAC_ARCH_UTILITIES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc deleted file mode 100644 index d875d95b5f..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/mac/bootstrap_compat.h" - -namespace breakpad { - -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -kern_return_t BootstrapRegister(mach_port_t bp, - name_t service_name, - mach_port_t sp) { - return bootstrap_register(bp, service_name, sp); -} -#pragma GCC diagnostic warning "-Wdeprecated-declarations" - -} // namesapce breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h deleted file mode 100644 index 8ca7357c34..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef COMMON_MAC_BOOTSTRAP_COMPAT_H_ -#define COMMON_MAC_BOOTSTRAP_COMPAT_H_ - -#include <servers/bootstrap.h> - -namespace breakpad { - -// Wrapper for bootstrap_register to avoid deprecation warnings. -// -// In 10.6, it's possible to call bootstrap_check_in as the one-stop-shop for -// handling what bootstrap_register is used for. In 10.5, bootstrap_check_in -// can't check in a service whose name has not yet been registered, despite -// bootstrap_register being marked as deprecated in that OS release. Breakpad -// needs to register new service names, and in 10.5, calling -// bootstrap_register is the only way to achieve that. Attempts to call -// bootstrap_check_in for a new service name on 10.5 will result in -// BOOTSTRAP_UNKNOWN_SERVICE being returned rather than registration of the -// new service name. -kern_return_t BootstrapRegister(mach_port_t bp, - name_t service_name, - mach_port_t sp); - -} // namespace breakpad - -#endif // COMMON_MAC_BOOTSTRAP_COMPAT_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h b/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h deleted file mode 100644 index b7bbc0b95b..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h +++ /dev/null @@ -1,73 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jim@mozilla.com> <jimb@red-bean.com> - -// byteswap.h: Overloaded functions for conveniently byteswapping values. - -#ifndef COMMON_MAC_BYTESWAP_H_ -#define COMMON_MAC_BYTESWAP_H_ - -#ifdef __APPLE__ -#include <libkern/OSByteOrder.h> - -static inline uint16_t ByteSwap(uint16_t v) { return OSSwapInt16(v); } -static inline uint32_t ByteSwap(uint32_t v) { return OSSwapInt32(v); } -static inline uint64_t ByteSwap(uint64_t v) { return OSSwapInt64(v); } -static inline int16_t ByteSwap(int16_t v) { return OSSwapInt16(v); } -static inline int32_t ByteSwap(int32_t v) { return OSSwapInt32(v); } -static inline int64_t ByteSwap(int64_t v) { return OSSwapInt64(v); } - -#elif defined(__linux__) -// For NXByteOrder -#include <architecture/byte_order.h> -#include <stdint.h> -#include <endian.h> -#include_next <byteswap.h> - -static inline uint16_t ByteSwap(uint16_t v) { return bswap_16(v); } -static inline uint32_t ByteSwap(uint32_t v) { return bswap_32(v); } -static inline uint64_t ByteSwap(uint64_t v) { return bswap_64(v); } -static inline int16_t ByteSwap(int16_t v) { return bswap_16(v); } -static inline int32_t ByteSwap(int32_t v) { return bswap_32(v); } -static inline int64_t ByteSwap(int64_t v) { return bswap_64(v); } - -static inline NXByteOrder NXHostByteOrder() { -#ifdef __LITTLE_ENDIAN - return NX_LittleEndian; -#else - return NX_BigEndian; -#endif -} - -#endif // __APPLE__ - -#endif // COMMON_MAC_BYTESWAP_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc deleted file mode 100644 index b20a055868..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc +++ /dev/null @@ -1,646 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2011, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// dump_syms.mm: Create a symbol file for use with minidumps - -#include "common/mac/dump_syms.h" - -#include <assert.h> -#include <dirent.h> -#include <errno.h> -#include <libgen.h> -#include <mach-o/arch.h> -#include <mach-o/fat.h> -#include <stdint.h> -#include <stdio.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <ostream> -#include <string> -#include <vector> - -#include "common/dwarf/bytereader-inl.h" -#include "common/dwarf/dwarf2reader.h" -#include "common/dwarf_cfi_to_module.h" -#include "common/dwarf_cu_to_module.h" -#include "common/dwarf_line_to_module.h" -#include "common/mac/file_id.h" -#include "common/mac/arch_utilities.h" -#include "common/mac/macho_reader.h" -#include "common/module.h" -#include "common/scoped_ptr.h" -#include "common/stabs_reader.h" -#include "common/stabs_to_module.h" -#include "common/symbol_data.h" - -#ifndef CPU_TYPE_ARM -#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12)) -#endif // CPU_TYPE_ARM - -#ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 (static_cast<cpu_type_t>(16777228)) -#endif // CPU_TYPE_ARM64 - -using dwarf2reader::ByteReader; -using google_breakpad::DwarfCUToModule; -using google_breakpad::DwarfLineToModule; -using google_breakpad::FileID; -using google_breakpad::mach_o::FatReader; -using google_breakpad::mach_o::Section; -using google_breakpad::mach_o::Segment; -using google_breakpad::Module; -using google_breakpad::StabsReader; -using google_breakpad::StabsToModule; -using google_breakpad::scoped_ptr; -using std::make_pair; -using std::pair; -using std::string; -using std::vector; - -namespace { -// Return a vector<string> with absolute paths to all the entries -// in directory (excluding . and ..). -vector<string> list_directory(const string& directory) { - vector<string> entries; - DIR* dir = opendir(directory.c_str()); - if (!dir) { - return entries; - } - - string path = directory; - if (path[path.length() - 1] != '/') { - path += '/'; - } - - struct dirent* entry = NULL; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { - entries.push_back(path + entry->d_name); - } - } - - closedir(dir); - return entries; -} -} - -namespace google_breakpad { - -bool DumpSymbols::Read(const string &filename) { - struct stat st; - if (stat(filename.c_str(), &st) == -1) { - fprintf(stderr, "Could not access object file %s: %s\n", - filename.c_str(), strerror(errno)); - return false; - } - - input_pathname_ = filename; - - // Does this filename refer to a dSYM bundle? - string contents_path = input_pathname_ + "/Contents/Resources/DWARF"; - if (S_ISDIR(st.st_mode) && - access(contents_path.c_str(), F_OK) == 0) { - // If there's one file under Contents/Resources/DWARF then use that, - // otherwise bail out. - const vector<string> entries = list_directory(contents_path); - if (entries.size() == 0) { - fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n", - input_pathname_.c_str()); - return false; - } - if (entries.size() > 1) { - fprintf(stderr, "Too many DWARF files in bundle: %s\n", - input_pathname_.c_str()); - return false; - } - - object_filename_ = entries[0]; - } else { - object_filename_ = input_pathname_; - } - - // Read the file's contents into memory. - bool read_ok = true; - string error; - if (stat(object_filename_.c_str(), &st) != -1) { - FILE* f = fopen(object_filename_.c_str(), "rb"); - if (f) { - contents_.reset(new uint8_t[st.st_size]); - off_t total = 0; - while (total < st.st_size && !feof(f)) { - size_t read = fread(&contents_[0] + total, 1, st.st_size - total, f); - if (read == 0) { - if (ferror(f)) { - read_ok = false; - error = strerror(errno); - } - break; - } - total += read; - } - fclose(f); - } else { - error = strerror(errno); - } - } - - if (!read_ok) { - fprintf(stderr, "Error reading object file: %s: %s\n", - object_filename_.c_str(), - error.c_str()); - return false; - } - - // Get the list of object files present in the file. - FatReader::Reporter fat_reporter(object_filename_); - FatReader fat_reader(&fat_reporter); - if (!fat_reader.Read(&contents_[0], - st.st_size)) { - return false; - } - - // Get our own copy of fat_reader's object file list. - size_t object_files_count; - const SuperFatArch *object_files = - fat_reader.object_files(&object_files_count); - if (object_files_count == 0) { - fprintf(stderr, "Fat binary file contains *no* architectures: %s\n", - object_filename_.c_str()); - return false; - } - object_files_.resize(object_files_count); - memcpy(&object_files_[0], object_files, - sizeof(SuperFatArch) * object_files_count); - - return true; -} - -bool DumpSymbols::SetArchitecture(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype) { - // Find the best match for the architecture the user requested. - const SuperFatArch *best_match = FindBestMatchForArchitecture( - cpu_type, cpu_subtype); - if (!best_match) return false; - - // Record the selected object file. - selected_object_file_ = best_match; - return true; -} - -bool DumpSymbols::SetArchitecture(const std::string &arch_name) { - bool arch_set = false; - const NXArchInfo *arch_info = - google_breakpad::BreakpadGetArchInfoFromName(arch_name.c_str()); - if (arch_info) { - arch_set = SetArchitecture(arch_info->cputype, arch_info->cpusubtype); - } - return arch_set; -} - -SuperFatArch* DumpSymbols::FindBestMatchForArchitecture( - cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { - // Check if all the object files can be converted to struct fat_arch. - bool can_convert_to_fat_arch = true; - vector<struct fat_arch> fat_arch_vector; - for (vector<SuperFatArch>::const_iterator it = object_files_.begin(); - it != object_files_.end(); - ++it) { - struct fat_arch arch; - bool success = it->ConvertToFatArch(&arch); - if (!success) { - can_convert_to_fat_arch = false; - break; - } - fat_arch_vector.push_back(arch); - } - - // If all the object files can be converted to struct fat_arch, use - // NXFindBestFatArch. - if (can_convert_to_fat_arch) { - const struct fat_arch *best_match - = NXFindBestFatArch(cpu_type, cpu_subtype, &fat_arch_vector[0], - static_cast<uint32_t>(fat_arch_vector.size())); - - for (size_t i = 0; i < fat_arch_vector.size(); ++i) { - if (best_match == &fat_arch_vector[i]) - return &object_files_[i]; - } - assert(best_match == NULL); - return NULL; - } - - // Check for an exact match with cpu_type and cpu_subtype. - for (vector<SuperFatArch>::iterator it = object_files_.begin(); - it != object_files_.end(); - ++it) { - if (static_cast<cpu_type_t>(it->cputype) == cpu_type && - static_cast<cpu_subtype_t>(it->cpusubtype) == cpu_subtype) - return &*it; - } - - // No exact match found. - // TODO(erikchen): If it becomes necessary, we can copy the implementation of - // NXFindBestFatArch, located at - // http://web.mit.edu/darwin/src/modules/cctools/libmacho/arch.c. - fprintf(stderr, "Failed to find an exact match for an object file with cpu " - "type: %d and cpu subtype: %d. Furthermore, at least one object file is " - "larger than 2**32.\n", cpu_type, cpu_subtype); - return NULL; -} - -string DumpSymbols::Identifier() { - FileID file_id(object_filename_.c_str()); - unsigned char identifier_bytes[16]; - cpu_type_t cpu_type = selected_object_file_->cputype; - cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype; - if (!file_id.MachoIdentifier(cpu_type, cpu_subtype, identifier_bytes)) { - fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n", - object_filename_.c_str()); - return ""; - } - - char identifier_string[40]; - FileID::ConvertIdentifierToString(identifier_bytes, identifier_string, - sizeof(identifier_string)); - - string compacted(identifier_string); - for(size_t i = compacted.find('-'); i != string::npos; - i = compacted.find('-', i)) - compacted.erase(i, 1); - - return compacted; -} - -// A line-to-module loader that accepts line number info parsed by -// dwarf2reader::LineInfo and populates a Module and a line vector -// with the results. -class DumpSymbols::DumperLineToModule: - public DwarfCUToModule::LineToModuleHandler { - public: - // Create a line-to-module converter using BYTE_READER. - DumperLineToModule(dwarf2reader::ByteReader *byte_reader) - : byte_reader_(byte_reader) { } - - void StartCompilationUnit(const string& compilation_dir) { - compilation_dir_ = compilation_dir; - } - - void ReadProgram(const uint8_t *program, uint64 length, - Module *module, vector<Module::Line> *lines) { - DwarfLineToModule handler(module, compilation_dir_, lines); - dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); - parser.Start(); - } - private: - string compilation_dir_; - dwarf2reader::ByteReader *byte_reader_; // WEAK -}; - -bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) { - // Select an object file, if SetArchitecture hasn't been called to set one - // explicitly. - if (!selected_object_file_) { - // If there's only one architecture, that's the one. - if (object_files_.size() == 1) - selected_object_file_ = &object_files_[0]; - else { - // Look for an object file whose architecture matches our own. - const NXArchInfo *local_arch = NXGetLocalArchInfo(); - if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) { - fprintf(stderr, "%s: object file contains more than one" - " architecture, none of which match the current" - " architecture; specify an architecture explicitly" - " with '-a ARCH' to resolve the ambiguity\n", - object_filename_.c_str()); - return false; - } - } - } - - assert(selected_object_file_); - - // Find the name of the selected file's architecture, to appear in - // the MODULE record and in error messages. - const NXArchInfo *selected_arch_info = - google_breakpad::BreakpadGetArchInfoFromCpuType( - selected_object_file_->cputype, selected_object_file_->cpusubtype); - - const char *selected_arch_name = selected_arch_info->name; - if (strcmp(selected_arch_name, "i386") == 0) - selected_arch_name = "x86"; - - // Produce a name to use in error messages that includes the - // filename, and the architecture, if there is more than one. - selected_object_name_ = object_filename_; - if (object_files_.size() > 1) { - selected_object_name_ += ", architecture "; - selected_object_name_ + selected_arch_name; - } - - // Compute a module name, to appear in the MODULE record. - string module_name = object_filename_; - module_name = basename(&module_name[0]); - - // Choose an identifier string, to appear in the MODULE record. - string identifier = Identifier(); - if (identifier.empty()) - return false; - identifier += "0"; - - // Create a module to hold the debugging information. - module.reset(new Module(module_name, - "mac", - selected_arch_name, - identifier)); - return true; -} - -bool DumpSymbols::ReadDwarf(google_breakpad::Module *module, - const mach_o::Reader &macho_reader, - const mach_o::SectionMap &dwarf_sections, - bool handle_inter_cu_refs) const { - // Build a byte reader of the appropriate endianness. - ByteReader byte_reader(macho_reader.big_endian() - ? dwarf2reader::ENDIANNESS_BIG - : dwarf2reader::ENDIANNESS_LITTLE); - - // Construct a context for this file. - DwarfCUToModule::FileContext file_context(selected_object_name_, - module, - handle_inter_cu_refs); - - // Build a dwarf2reader::SectionMap from our mach_o::SectionMap. - for (mach_o::SectionMap::const_iterator it = dwarf_sections.begin(); - it != dwarf_sections.end(); ++it) { - file_context.AddSectionToSectionMap( - it->first, - it->second.contents.start, - it->second.contents.Size()); - } - - // Find the __debug_info section. - dwarf2reader::SectionMap::const_iterator debug_info_entry = - file_context.section_map().find("__debug_info"); - assert(debug_info_entry != file_context.section_map().end()); - const std::pair<const uint8_t *, uint64>& debug_info_section = - debug_info_entry->second; - // There had better be a __debug_info section! - if (!debug_info_section.first) { - fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n", - selected_object_name_.c_str()); - return false; - } - - // Build a line-to-module loader for the root handler to use. - DumperLineToModule line_to_module(&byte_reader); - - // Walk the __debug_info section, one compilation unit at a time. - uint64 debug_info_length = debug_info_section.second; - for (uint64 offset = 0; offset < debug_info_length;) { - // Make a handler for the root DIE that populates MODULE with the - // debug info. - DwarfCUToModule::WarningReporter reporter(selected_object_name_, - offset); - DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); - // Make a Dwarf2Handler that drives our DIEHandler. - dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); - // Make a DWARF parser for the compilation unit at OFFSET. - dwarf2reader::CompilationUnit dwarf_reader(selected_object_name_, - file_context.section_map(), - offset, - &byte_reader, - &die_dispatcher); - // Process the entire compilation unit; get the offset of the next. - offset += dwarf_reader.Start(); - } - - return true; -} - -bool DumpSymbols::ReadCFI(google_breakpad::Module *module, - const mach_o::Reader &macho_reader, - const mach_o::Section §ion, - bool eh_frame) const { - // Find the appropriate set of register names for this file's - // architecture. - vector<string> register_names; - switch (macho_reader.cpu_type()) { - case CPU_TYPE_X86: - register_names = DwarfCFIToModule::RegisterNames::I386(); - break; - case CPU_TYPE_X86_64: - register_names = DwarfCFIToModule::RegisterNames::X86_64(); - break; - case CPU_TYPE_ARM: - register_names = DwarfCFIToModule::RegisterNames::ARM(); - break; - case CPU_TYPE_ARM64: - register_names = DwarfCFIToModule::RegisterNames::ARM64(); - break; - default: { - const NXArchInfo *arch = google_breakpad::BreakpadGetArchInfoFromCpuType( - macho_reader.cpu_type(), macho_reader.cpu_subtype()); - fprintf(stderr, "%s: cannot convert DWARF call frame information for ", - selected_object_name_.c_str()); - if (arch) - fprintf(stderr, "architecture '%s'", arch->name); - else - fprintf(stderr, "architecture %d,%d", - macho_reader.cpu_type(), macho_reader.cpu_subtype()); - fprintf(stderr, " to Breakpad symbol file: no register name table\n"); - return false; - } - } - - // Find the call frame information and its size. - const uint8_t *cfi = section.contents.start; - size_t cfi_size = section.contents.Size(); - - // Plug together the parser, handler, and their entourages. - DwarfCFIToModule::Reporter module_reporter(selected_object_name_, - section.section_name); - DwarfCFIToModule handler(module, register_names, &module_reporter); - dwarf2reader::ByteReader byte_reader(macho_reader.big_endian() ? - dwarf2reader::ENDIANNESS_BIG : - dwarf2reader::ENDIANNESS_LITTLE); - byte_reader.SetAddressSize(macho_reader.bits_64() ? 8 : 4); - // At the moment, according to folks at Apple and some cursory - // investigation, Mac OS X only uses DW_EH_PE_pcrel-based pointers, so - // this is the only base address the CFI parser will need. - byte_reader.SetCFIDataBase(section.address, cfi); - - dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(selected_object_name_, - section.section_name); - dwarf2reader::CallFrameInfo parser(cfi, cfi_size, - &byte_reader, &handler, &dwarf_reporter, - eh_frame); - parser.Start(); - return true; -} - -// A LoadCommandHandler that loads whatever debugging data it finds into a -// Module. -class DumpSymbols::LoadCommandDumper: - public mach_o::Reader::LoadCommandHandler { - public: - // Create a load command dumper handling load commands from READER's - // file, and adding data to MODULE. - LoadCommandDumper(const DumpSymbols &dumper, - google_breakpad::Module *module, - const mach_o::Reader &reader, - SymbolData symbol_data, - bool handle_inter_cu_refs) - : dumper_(dumper), - module_(module), - reader_(reader), - symbol_data_(symbol_data), - handle_inter_cu_refs_(handle_inter_cu_refs) { } - - bool SegmentCommand(const mach_o::Segment &segment); - bool SymtabCommand(const ByteBuffer &entries, const ByteBuffer &strings); - - private: - const DumpSymbols &dumper_; - google_breakpad::Module *module_; // WEAK - const mach_o::Reader &reader_; - const SymbolData symbol_data_; - const bool handle_inter_cu_refs_; -}; - -bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) { - mach_o::SectionMap section_map; - if (!reader_.MapSegmentSections(segment, §ion_map)) - return false; - - if (segment.name == "__TEXT") { - module_->SetLoadAddress(segment.vmaddr); - if (symbol_data_ != NO_CFI) { - mach_o::SectionMap::const_iterator eh_frame = - section_map.find("__eh_frame"); - if (eh_frame != section_map.end()) { - // If there is a problem reading this, don't treat it as a fatal error. - dumper_.ReadCFI(module_, reader_, eh_frame->second, true); - } - } - return true; - } - - if (segment.name == "__DWARF") { - if (symbol_data_ != ONLY_CFI) { - if (!dumper_.ReadDwarf(module_, reader_, section_map, - handle_inter_cu_refs_)) { - return false; - } - } - if (symbol_data_ != NO_CFI) { - mach_o::SectionMap::const_iterator debug_frame - = section_map.find("__debug_frame"); - if (debug_frame != section_map.end()) { - // If there is a problem reading this, don't treat it as a fatal error. - dumper_.ReadCFI(module_, reader_, debug_frame->second, false); - } - } - } - - return true; -} - -bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries, - const ByteBuffer &strings) { - StabsToModule stabs_to_module(module_); - // Mac OS X STABS are never "unitized", and the size of the 'value' field - // matches the address size of the executable. - StabsReader stabs_reader(entries.start, entries.Size(), - strings.start, strings.Size(), - reader_.big_endian(), - reader_.bits_64() ? 8 : 4, - true, - &stabs_to_module); - if (!stabs_reader.Process()) - return false; - stabs_to_module.Finalize(); - return true; -} - -bool DumpSymbols::ReadSymbolData(Module** out_module) { - scoped_ptr<Module> module; - if (!CreateEmptyModule(module)) - return false; - - // Parse the selected object file. - mach_o::Reader::Reporter reporter(selected_object_name_); - mach_o::Reader reader(&reporter); - if (!reader.Read(&contents_[0] - + selected_object_file_->offset, - selected_object_file_->size, - selected_object_file_->cputype, - selected_object_file_->cpusubtype)) - return false; - - // Walk its load commands, and deal with whatever is there. - LoadCommandDumper load_command_dumper(*this, module.get(), reader, - symbol_data_, handle_inter_cu_refs_); - if (!reader.WalkLoadCommands(&load_command_dumper)) - return false; - - *out_module = module.release(); - - return true; -} - -bool DumpSymbols::WriteSymbolFile(std::ostream &stream) { - Module* module = NULL; - - if (ReadSymbolData(&module) && module) { - bool res = module->Write(stream, symbol_data_); - delete module; - return res; - } - - return false; -} - -// Read the selected object file's debugging information, and write out the -// header only to |stream|. Return true on success; if an error occurs, report -// it and return false. -bool DumpSymbols::WriteSymbolFileHeader(std::ostream &stream) { - scoped_ptr<Module> module; - if (!CreateEmptyModule(module)) - return false; - - return module->Write(stream, symbol_data_); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h deleted file mode 100644 index 9463f7dc0c..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h +++ /dev/null @@ -1,196 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2011, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for -// reading debugging information from Mach-O files and writing it out as a -// Breakpad symbol file. - -#include <mach-o/loader.h> -#include <stdio.h> -#include <stdlib.h> - -#include <ostream> -#include <string> -#include <vector> - -#include "common/byte_cursor.h" -#include "common/mac/macho_reader.h" -#include "common/mac/super_fat_arch.h" -#include "common/module.h" -#include "common/scoped_ptr.h" -#include "common/symbol_data.h" - -namespace google_breakpad { - -class DumpSymbols { - public: - DumpSymbols(SymbolData symbol_data, bool handle_inter_cu_refs) - : symbol_data_(symbol_data), - handle_inter_cu_refs_(handle_inter_cu_refs), - input_pathname_(), - object_filename_(), - contents_(), - object_files_(), - selected_object_file_(), - selected_object_name_() { } - ~DumpSymbols() { - } - - // Prepare to read debugging information from |filename|. |filename| may be - // the name of a universal binary, a Mach-O file, or a dSYM bundle - // containing either of the above. On success, return true; if there is a - // problem reading |filename|, report it and return false. - bool Read(const std::string &filename); - - // If this dumper's file includes an object file for |cpu_type| and - // |cpu_subtype|, then select that object file for dumping, and return - // true. Otherwise, return false, and leave this dumper's selected - // architecture unchanged. - // - // By default, if this dumper's file contains only one object file, then - // the dumper will dump those symbols; and if it contains more than one - // object file, then the dumper will dump the object file whose - // architecture matches that of this dumper program. - bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); - - // If this dumper's file includes an object file for |arch_name|, then select - // that object file for dumping, and return true. Otherwise, return false, - // and leave this dumper's selected architecture unchanged. - // - // By default, if this dumper's file contains only one object file, then - // the dumper will dump those symbols; and if it contains more than one - // object file, then the dumper will dump the object file whose - // architecture matches that of this dumper program. - bool SetArchitecture(const std::string &arch_name); - - // Return a pointer to an array of SuperFatArch structures describing the - // object files contained in this dumper's file. Set *|count| to the number - // of elements in the array. The returned array is owned by this DumpSymbols - // instance. - // - // If there are no available architectures, this function - // may return NULL. - const SuperFatArch* AvailableArchitectures(size_t *count) { - *count = object_files_.size(); - if (object_files_.size() > 0) - return &object_files_[0]; - return NULL; - } - - // Read the selected object file's debugging information, and write it out to - // |stream|. Return true on success; if an error occurs, report it and - // return false. - bool WriteSymbolFile(std::ostream &stream); - - // Read the selected object file's debugging information, and write out the - // header only to |stream|. Return true on success; if an error occurs, report - // it and return false. - bool WriteSymbolFileHeader(std::ostream &stream); - - // As above, but simply return the debugging information in module - // instead of writing it to a stream. The caller owns the resulting - // module object and must delete it when finished. - bool ReadSymbolData(Module** module); - - private: - // Used internally. - class DumperLineToModule; - class LoadCommandDumper; - - // This method behaves similarly to NXFindBestFatArch, but it supports - // SuperFatArch. - SuperFatArch* FindBestMatchForArchitecture( - cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); - - // Return an identifier string for the file this DumpSymbols is dumping. - std::string Identifier(); - - - // Creates an empty module object. - bool CreateEmptyModule(scoped_ptr<Module>& module); - - // Read debugging information from |dwarf_sections|, which was taken from - // |macho_reader|, and add it to |module|. On success, return true; - // on failure, report the problem and return false. - bool ReadDwarf(google_breakpad::Module *module, - const mach_o::Reader &macho_reader, - const mach_o::SectionMap &dwarf_sections, - bool handle_inter_cu_refs) const; - - // Read DWARF CFI or .eh_frame data from |section|, belonging to - // |macho_reader|, and record it in |module|. If |eh_frame| is true, - // then the data is .eh_frame-format data; otherwise, it is standard DWARF - // .debug_frame data. On success, return true; on failure, report - // the problem and return false. - bool ReadCFI(google_breakpad::Module *module, - const mach_o::Reader &macho_reader, - const mach_o::Section §ion, - bool eh_frame) const; - - // The selection of what type of symbol data to read/write. - const SymbolData symbol_data_; - - // Whether to handle references between compilation units. - const bool handle_inter_cu_refs_; - - // The name of the file or bundle whose symbols this will dump. - // This is the path given to Read, for use in error messages. - std::string input_pathname_; - - // The name of the file this DumpSymbols will actually read debugging - // information from. Normally, this is the same as input_pathname_, but if - // filename refers to a dSYM bundle, then this is the resource file - // within that bundle. - std::string object_filename_; - - // The complete contents of object_filename_, mapped into memory. - scoped_array<uint8_t> contents_; - - // A vector of SuperFatArch structures describing the object files - // object_filename_ contains. If object_filename_ refers to a fat binary, - // this may have more than one element; if it refers to a Mach-O file, this - // has exactly one element. - vector<SuperFatArch> object_files_; - - // The object file in object_files_ selected to dump, or NULL if - // SetArchitecture hasn't been called yet. - const SuperFatArch *selected_object_file_; - - // A string that identifies the selected object file, for use in error - // messages. This is usually object_filename_, but if that refers to a - // fat binary, it includes an indication of the particular architecture - // within that binary. - string selected_object_name_; -}; - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc deleted file mode 100644 index 4661d5d625..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// file_id.cc: Return a unique identifier for a file -// -// See file_id.h for documentation -// -// Author: Dan Waylonis - -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "common/mac/file_id.h" -#include "common/mac/macho_id.h" - -using MacFileUtilities::MachoID; - -namespace google_breakpad { - -FileID::FileID(const char *path) { - snprintf(path_, sizeof(path_), "%s", path); -} - -bool FileID::FileIdentifier(unsigned char identifier[16]) { - int fd = open(path_, O_RDONLY); - if (fd == -1) - return false; - - MD5Context md5; - MD5Init(&md5); - - // Read 4k x 2 bytes at a time. This is faster than just 4k bytes, but - // doesn't seem to be an unreasonable size for the stack. - unsigned char buffer[4096 * 2]; - size_t buffer_size = sizeof(buffer); - while ((buffer_size = read(fd, buffer, buffer_size) > 0)) { - MD5Update(&md5, buffer, static_cast<unsigned>(buffer_size)); - } - - close(fd); - MD5Final(identifier, &md5); - - return true; -} - -bool FileID::MachoIdentifier(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]) { - MachoID macho(path_); - - if (macho.UUIDCommand(cpu_type, cpu_subtype, identifier)) - return true; - - return macho.MD5(cpu_type, cpu_subtype, identifier); -} - -// static -void FileID::ConvertIdentifierToString(const unsigned char identifier[16], - char *buffer, int buffer_length) { - int buffer_idx = 0; - for (int idx = 0; (buffer_idx < buffer_length) && (idx < 16); ++idx) { - int hi = (identifier[idx] >> 4) & 0x0F; - int lo = (identifier[idx]) & 0x0F; - - if (idx == 4 || idx == 6 || idx == 8 || idx == 10) - buffer[buffer_idx++] = '-'; - - buffer[buffer_idx++] = - static_cast<char>((hi >= 10) ? ('A' + hi - 10) : ('0' + hi)); - buffer[buffer_idx++] = - static_cast<char>((lo >= 10) ? ('A' + lo - 10) : ('0' + lo)); - } - - // NULL terminate - buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h deleted file mode 100644 index 1d6dfde1b0..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// file_id.h: Return a unique identifier for a file -// -// Author: Dan Waylonis - -#ifndef COMMON_MAC_FILE_ID_H__ -#define COMMON_MAC_FILE_ID_H__ - -#include <limits.h> -#include <mach/machine.h> - -namespace google_breakpad { - -class FileID { - public: - FileID(const char *path); - ~FileID() {}; - - // Load the identifier for the file path specified in the constructor into - // |identifier|. Return false if the identifier could not be created for the - // file. - // The current implementation will return the MD5 hash of the file's bytes. - bool FileIdentifier(unsigned char identifier[16]); - - // Treat the file as a mach-o file that will contain one or more archicture. - // Accepted values for |cpu_type| and |cpu_subtype| (e.g., CPU_TYPE_X86 or - // CPU_TYPE_POWERPC) are listed in /usr/include/mach/machine.h. - // If |cpu_type| is 0, then the native cpu type is used. If |cpu_subtype| is - // CPU_SUBTYPE_MULTIPLE, the match is only done on |cpu_type|. - // Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype| - // is not present in the file. - // Return the unique identifier in |identifier|. - // The current implementation will look for the (in order of priority): - // LC_UUID, LC_ID_DYLIB, or MD5 hash of the given |cpu_type|. - bool MachoIdentifier(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]); - - // Convert the |identifier| data to a NULL terminated string. The string will - // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE). - // The |buffer| should be at least 37 bytes long to receive all of the data - // and termination. Shorter buffers will contain truncated data. - static void ConvertIdentifierToString(const unsigned char identifier[16], - char *buffer, int buffer_length); - - private: - // Storage for the path specified - char path_[PATH_MAX]; -}; - -} // namespace google_breakpad - -#endif // COMMON_MAC_FILE_ID_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc deleted file mode 100644 index 245be82659..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <stdio.h> -#include <sys/wait.h> -#include <unistd.h> - -namespace google_breakpad { - -void LaunchReporter(const char *reporter_executable_path, - const char *config_file_path) { - const char* argv[] = { reporter_executable_path, config_file_path, NULL }; - - // Launch the reporter - pid_t pid = fork(); - - if (pid == -1) { - perror("fork"); - fprintf(stderr, "Failed to fork reporter process\n"); - return; - } - - // If we're in the child, load in our new executable and run. - // The parent will not wait for the child to complete. - if (pid == 0) { - execv(argv[0], (char* const*)argv); - perror("exec"); - fprintf(stderr, - "Failed to launch reporter process from path %s\n", - reporter_executable_path); - unlink(config_file_path); // launch failed - get rid of config file - _exit(1); - } - - // Wait until the Reporter child process exits. - // - - // We'll use a timeout of one minute. - int timeout_count = 60; // 60 seconds - - while (timeout_count-- > 0) { - int status; - pid_t result = waitpid(pid, &status, WNOHANG); - - if (result == 0) { - // The child has not yet finished. - sleep(1); - } else if (result == -1) { - // error occurred. - break; - } else { - // child has finished - break; - } - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h deleted file mode 100644 index 4531123c2d..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef COMMON_MAC_LAUNCH_REPORTER_H__ -#define COMMON_MAC_LAUNCH_REPORTER_H__ - -namespace google_breakpad { - -// Launch the crash dump sender app. -// |reporter_executable_path| is the path to the sender executable. -// |config_file_path| is the path to the config file. -void LaunchReporter(const char *reporter_executable_path, - const char *config_file_path); - -} // namespace google_breakpad - -#endif // COMMON_MAC_LAUNCH_REPORTER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc deleted file mode 100644 index c396ad888d..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_id.cc: Functions to gather identifying information from a macho file -// -// See macho_id.h for documentation -// -// Author: Dan Waylonis - - -#include <fcntl.h> -#include <mach-o/loader.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> - -#include "common/mac/macho_id.h" -#include "common/mac/macho_walker.h" -#include "common/mac/macho_utilities.h" - -namespace MacFileUtilities { - -using google_breakpad::MD5Init; -using google_breakpad::MD5Update; -using google_breakpad::MD5Final; - -MachoID::MachoID(const char *path) - : memory_(0), - memory_size_(0), - crc_(0), - md5_context_(), - update_function_(NULL) { - snprintf(path_, sizeof(path_), "%s", path); -} - -MachoID::MachoID(const char *path, void *memory, size_t size) - : memory_(memory), - memory_size_(size), - crc_(0), - md5_context_(), - update_function_(NULL) { - snprintf(path_, sizeof(path_), "%s", path); -} - -MachoID::~MachoID() { -} - -// The CRC info is from http://en.wikipedia.org/wiki/Adler-32 -// With optimizations from http://www.zlib.net/ - -// The largest prime smaller than 65536 -#define MOD_ADLER 65521 -// MAX_BLOCK is the largest n such that 255n(n+1)/2 + (n+1)(MAX_BLOCK-1) <= 2^32-1 -#define MAX_BLOCK 5552 - -void MachoID::UpdateCRC(unsigned char *bytes, size_t size) { -// Unrolled loops for summing -#define DO1(buf,i) {sum1 += (buf)[i]; sum2 += sum1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - // Split up the crc - uint32_t sum1 = crc_ & 0xFFFF; - uint32_t sum2 = (crc_ >> 16) & 0xFFFF; - - // Do large blocks - while (size >= MAX_BLOCK) { - size -= MAX_BLOCK; - int block_count = MAX_BLOCK / 16; - do { - DO16(bytes); - bytes += 16; - } while (--block_count); - sum1 %= MOD_ADLER; - sum2 %= MOD_ADLER; - } - - // Do remaining bytes - if (size) { - while (size >= 16) { - size -= 16; - DO16(bytes); - bytes += 16; - } - while (size--) { - sum1 += *bytes++; - sum2 += sum1; - } - sum1 %= MOD_ADLER; - sum2 %= MOD_ADLER; - crc_ = (sum2 << 16) | sum1; - } -} - -void MachoID::UpdateMD5(unsigned char *bytes, size_t size) { - MD5Update(&md5_context_, bytes, static_cast<unsigned>(size)); -} - -void MachoID::Update(MachoWalker *walker, off_t offset, size_t size) { - if (!update_function_ || !size) - return; - - // Read up to 4k bytes at a time - unsigned char buffer[4096]; - size_t buffer_size; - off_t file_offset = offset; - while (size > 0) { - if (size > sizeof(buffer)) { - buffer_size = sizeof(buffer); - size -= buffer_size; - } else { - buffer_size = size; - size = 0; - } - - if (!walker->ReadBytes(buffer, buffer_size, file_offset)) - return; - - (this->*update_function_)(buffer, buffer_size); - file_offset += buffer_size; - } -} - -bool MachoID::UUIDCommand(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char bytes[16]) { - struct breakpad_uuid_command uuid_cmd; - uuid_cmd.cmd = 0; - if (!WalkHeader(cpu_type, cpu_subtype, UUIDWalkerCB, &uuid_cmd)) - return false; - - // If we found the command, we'll have initialized the uuid_command - // structure - if (uuid_cmd.cmd == LC_UUID) { - memcpy(bytes, uuid_cmd.uuid, sizeof(uuid_cmd.uuid)); - return true; - } - - return false; -} - -bool MachoID::IDCommand(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]) { - struct dylib_command dylib_cmd; - dylib_cmd.cmd = 0; - if (!WalkHeader(cpu_type, cpu_subtype, IDWalkerCB, &dylib_cmd)) - return false; - - // If we found the command, we'll have initialized the dylib_command - // structure - if (dylib_cmd.cmd == LC_ID_DYLIB) { - // Take the hashed filename, version, and compatability version bytes - // to form the first 12 bytes, pad the rest with zeros - - // create a crude hash of the filename to generate the first 4 bytes - identifier[0] = 0; - identifier[1] = 0; - identifier[2] = 0; - identifier[3] = 0; - - for (int j = 0, i = (int)strlen(path_)-1; i>=0 && path_[i]!='/'; ++j, --i) { - identifier[j%4] += path_[i]; - } - - identifier[4] = (dylib_cmd.dylib.current_version >> 24) & 0xFF; - identifier[5] = (dylib_cmd.dylib.current_version >> 16) & 0xFF; - identifier[6] = (dylib_cmd.dylib.current_version >> 8) & 0xFF; - identifier[7] = dylib_cmd.dylib.current_version & 0xFF; - identifier[8] = (dylib_cmd.dylib.compatibility_version >> 24) & 0xFF; - identifier[9] = (dylib_cmd.dylib.compatibility_version >> 16) & 0xFF; - identifier[10] = (dylib_cmd.dylib.compatibility_version >> 8) & 0xFF; - identifier[11] = dylib_cmd.dylib.compatibility_version & 0xFF; - identifier[12] = (cpu_type >> 24) & 0xFF; - identifier[13] = (cpu_type >> 16) & 0xFF; - identifier[14] = (cpu_type >> 8) & 0xFF; - identifier[15] = cpu_type & 0xFF; - - return true; - } - - return false; -} - -uint32_t MachoID::Adler32(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { - update_function_ = &MachoID::UpdateCRC; - crc_ = 0; - - if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this)) - return 0; - - return crc_; -} - -bool MachoID::MD5(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, unsigned char identifier[16]) { - update_function_ = &MachoID::UpdateMD5; - - MD5Init(&md5_context_); - - if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this)) - return false; - - MD5Final(identifier, &md5_context_); - return true; -} - -bool MachoID::WalkHeader(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - MachoWalker::LoadCommandCallback callback, - void *context) { - if (memory_) { - MachoWalker walker(memory_, memory_size_, callback, context); - return walker.WalkHeader(cpu_type, cpu_subtype); - } else { - MachoWalker walker(path_, callback, context); - return walker.WalkHeader(cpu_type, cpu_subtype); - } -} - -// static -bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context) { - MachoID *macho_id = (MachoID *)context; - - if (cmd->cmd == LC_SEGMENT) { - struct segment_command seg; - - if (!walker->ReadBytes(&seg, sizeof(seg), offset)) - return false; - - if (swap) - breakpad_swap_segment_command(&seg); - - struct mach_header_64 header; - off_t header_offset; - - if (!walker->CurrentHeader(&header, &header_offset)) - return false; - - // Process segments that have sections: - // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) - offset += sizeof(struct segment_command); - struct section sec; - for (unsigned long i = 0; i < seg.nsects; ++i) { - if (!walker->ReadBytes(&sec, sizeof(sec), offset)) - return false; - - if (swap) - breakpad_swap_section(&sec, 1); - - // sections of type S_ZEROFILL are "virtual" and contain no data - // in the file itself - if ((sec.flags & SECTION_TYPE) != S_ZEROFILL && sec.offset != 0) - macho_id->Update(walker, header_offset + sec.offset, sec.size); - - offset += sizeof(struct section); - } - } else if (cmd->cmd == LC_SEGMENT_64) { - struct segment_command_64 seg64; - - if (!walker->ReadBytes(&seg64, sizeof(seg64), offset)) - return false; - - if (swap) - breakpad_swap_segment_command_64(&seg64); - - struct mach_header_64 header; - off_t header_offset; - - if (!walker->CurrentHeader(&header, &header_offset)) - return false; - - // Process segments that have sections: - // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) - offset += sizeof(struct segment_command_64); - struct section_64 sec64; - for (unsigned long i = 0; i < seg64.nsects; ++i) { - if (!walker->ReadBytes(&sec64, sizeof(sec64), offset)) - return false; - - if (swap) - breakpad_swap_section_64(&sec64, 1); - - // sections of type S_ZEROFILL are "virtual" and contain no data - // in the file itself - if ((sec64.flags & SECTION_TYPE) != S_ZEROFILL && sec64.offset != 0) - macho_id->Update(walker, - header_offset + sec64.offset, - (size_t)sec64.size); - - offset += sizeof(struct section_64); - } - } - - // Continue processing - return true; -} - -// static -bool MachoID::UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context) { - if (cmd->cmd == LC_UUID) { - struct breakpad_uuid_command *uuid_cmd = - (struct breakpad_uuid_command *)context; - - if (!walker->ReadBytes(uuid_cmd, sizeof(struct breakpad_uuid_command), - offset)) - return false; - - if (swap) - breakpad_swap_uuid_command(uuid_cmd); - - return false; - } - - // Continue processing - return true; -} - -// static -bool MachoID::IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context) { - if (cmd->cmd == LC_ID_DYLIB) { - struct dylib_command *dylib_cmd = (struct dylib_command *)context; - - if (!walker->ReadBytes(dylib_cmd, sizeof(struct dylib_command), offset)) - return false; - - if (swap) - breakpad_swap_dylib_command(dylib_cmd); - - return false; - } - - // Continue processing - return true; -} - -} // namespace MacFileUtilities diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h deleted file mode 100644 index 1037549124..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_id.h: Functions to gather identifying information from a macho file -// -// Author: Dan Waylonis - -#ifndef COMMON_MAC_MACHO_ID_H__ -#define COMMON_MAC_MACHO_ID_H__ - -#include <limits.h> -#include <mach/machine.h> -#include <mach-o/loader.h> - -#include "common/mac/macho_walker.h" -#include "common/md5.h" - -namespace MacFileUtilities { - -class MachoID { - public: - MachoID(const char *path); - MachoID(const char *path, void *memory, size_t size); - ~MachoID(); - - // For the given |cpu_type| and |cpu_subtype|, return a UUID from the LC_UUID - // command. - // Return false if there isn't a LC_UUID command. - bool UUIDCommand(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]); - - // For the given |cpu_type| and |cpu_subtype|, return a UUID from the - // LC_ID_DYLIB command. - // Return false if there isn't a LC_ID_DYLIB command. - bool IDCommand(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]); - - // For the given |cpu_type| and |cpu_subtype|, return the Adler32 CRC for the - // mach-o data segment(s). - // Return 0 on error (e.g., if the file is not a mach-o file) - uint32_t Adler32(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype); - - // For the given |cpu_type|, and |cpu_subtype| return the MD5 for the mach-o - // data segment(s). - // Return true on success, false otherwise - bool MD5(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - unsigned char identifier[16]); - - private: - // Signature of class member function to be called with data read from file - typedef void (MachoID::*UpdateFunction)(unsigned char *bytes, size_t size); - - // Update the CRC value by examining |size| |bytes| and applying the algorithm - // to each byte. - void UpdateCRC(unsigned char *bytes, size_t size); - - // Update the MD5 value by examining |size| |bytes| and applying the algorithm - // to each byte. - void UpdateMD5(unsigned char *bytes, size_t size); - - // Bottleneck for update routines - void Update(MachoWalker *walker, off_t offset, size_t size); - - // Factory for the MachoWalker - bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, - MachoWalker::LoadCommandCallback callback, void *context); - - // The callback from the MachoWalker for CRC and MD5 - static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context); - - // The callback from the MachoWalker for LC_UUID - static bool UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context); - - // The callback from the MachoWalker for LC_ID_DYLIB - static bool IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, - bool swap, void *context); - - // File path - char path_[PATH_MAX]; - - // Memory region to read from - void *memory_; - - // Size of the memory region - size_t memory_size_; - - // The current crc value - uint32_t crc_; - - // The MD5 context - google_breakpad::MD5Context md5_context_; - - // The current update to call from the Update callback - UpdateFunction update_function_; -}; - -} // namespace MacFileUtilities - -#endif // COMMON_MAC_MACHO_ID_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc deleted file mode 100644 index 52f3c411be..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc +++ /dev/null @@ -1,539 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// macho_reader.cc: Implementation of google_breakpad::Mach_O::FatReader and -// google_breakpad::Mach_O::Reader. See macho_reader.h for details. - -#include "common/mac/macho_reader.h" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -// Unfortunately, CPU_TYPE_ARM is not define for 10.4. -#if !defined(CPU_TYPE_ARM) -#define CPU_TYPE_ARM 12 -#endif - -#if !defined(CPU_TYPE_ARM_64) -#define CPU_TYPE_ARM_64 16777228 -#endif - -namespace google_breakpad { -namespace mach_o { - -// If NDEBUG is #defined, then the 'assert' macro doesn't evaluate its -// arguments, so you can't place expressions that do necessary work in -// the argument of an assert. Nor can you assign the result of the -// expression to a variable and assert that the variable's value is -// true: you'll get unused variable warnings when NDEBUG is #defined. -// -// ASSERT_ALWAYS_EVAL always evaluates its argument, and asserts that -// the result is true if NDEBUG is not #defined. -#if defined(NDEBUG) -#define ASSERT_ALWAYS_EVAL(x) (x) -#else -#define ASSERT_ALWAYS_EVAL(x) assert(x) -#endif - -void FatReader::Reporter::BadHeader() { - fprintf(stderr, "%s: file is neither a fat binary file" - " nor a Mach-O object file\n", filename_.c_str()); -} - -void FatReader::Reporter::TooShort() { - fprintf(stderr, "%s: file too short for the data it claims to contain\n", - filename_.c_str()); -} - -void FatReader::Reporter::MisplacedObjectFile() { - fprintf(stderr, "%s: file too short for the object files it claims" - " to contain\n", filename_.c_str()); -} - -bool FatReader::Read(const uint8_t *buffer, size_t size) { - buffer_.start = buffer; - buffer_.end = buffer + size; - ByteCursor cursor(&buffer_); - - // Fat binaries always use big-endian, so read the magic number in - // that endianness. To recognize Mach-O magic numbers, which can use - // either endianness, check for both the proper and reversed forms - // of the magic numbers. - cursor.set_big_endian(true); - if (cursor >> magic_) { - if (magic_ == FAT_MAGIC) { - // How many object files does this fat binary contain? - uint32_t object_files_count; - if (!(cursor >> object_files_count)) { // nfat_arch - reporter_->TooShort(); - return false; - } - - // Read the list of object files. - object_files_.resize(object_files_count); - for (size_t i = 0; i < object_files_count; i++) { - struct fat_arch objfile; - - // Read this object file entry, byte-swapping as appropriate. - cursor >> objfile.cputype - >> objfile.cpusubtype - >> objfile.offset - >> objfile.size - >> objfile.align; - - SuperFatArch super_fat_arch(objfile); - object_files_[i] = super_fat_arch; - - if (!cursor) { - reporter_->TooShort(); - return false; - } - // Does the file actually have the bytes this entry refers to? - size_t fat_size = buffer_.Size(); - if (objfile.offset > fat_size || - objfile.size > fat_size - objfile.offset) { - reporter_->MisplacedObjectFile(); - return false; - } - } - - return true; - } else if (magic_ == MH_MAGIC || magic_ == MH_MAGIC_64 || - magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) { - // If this is a little-endian Mach-O file, fix the cursor's endianness. - if (magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) - cursor.set_big_endian(false); - // Record the entire file as a single entry in the object file list. - object_files_.resize(1); - - // Get the cpu type and subtype from the Mach-O header. - if (!(cursor >> object_files_[0].cputype - >> object_files_[0].cpusubtype)) { - reporter_->TooShort(); - return false; - } - - object_files_[0].offset = 0; - object_files_[0].size = static_cast<uint64_t>(buffer_.Size()); - // This alignment is correct for 32 and 64-bit x86 and ppc. - // See get_align in the lipo source for other architectures: - // http://www.opensource.apple.com/source/cctools/cctools-773/misc/lipo.c - object_files_[0].align = 12; // 2^12 == 4096 - return true; - } - } - reporter_->BadHeader(); - return false; -} - -void Reader::Reporter::BadHeader() { - fprintf(stderr, "%s: file is not a Mach-O object file\n", filename_.c_str()); -} - -void Reader::Reporter::CPUTypeMismatch(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype) { - fprintf(stderr, "%s: CPU type %d, subtype %d does not match expected" - " type %d, subtype %d\n", - filename_.c_str(), cpu_type, cpu_subtype, - expected_cpu_type, expected_cpu_subtype); -} - -void Reader::Reporter::HeaderTruncated() { - fprintf(stderr, "%s: file does not contain a complete Mach-O header\n", - filename_.c_str()); -} - -void Reader::Reporter::LoadCommandRegionTruncated() { - fprintf(stderr, "%s: file too short to hold load command region" - " given in Mach-O header\n", filename_.c_str()); -} - -void Reader::Reporter::LoadCommandsOverrun(size_t claimed, size_t i, - LoadCommandType type) { - fprintf(stderr, "%s: file's header claims there are %zu" - " load commands, but load command #%zu", - filename_.c_str(), claimed, i); - if (type) fprintf(stderr, ", of type %d,", type); - fprintf(stderr, " extends beyond the end of the load command region\n"); -} - -void Reader::Reporter::LoadCommandTooShort(size_t i, LoadCommandType type) { - fprintf(stderr, "%s: the contents of load command #%zu, of type %d," - " extend beyond the size given in the load command's header\n", - filename_.c_str(), i, type); -} - -void Reader::Reporter::SectionsMissing(const string &name) { - fprintf(stderr, "%s: the load command for segment '%s'" - " is too short to hold the section headers it claims to have\n", - filename_.c_str(), name.c_str()); -} - -void Reader::Reporter::MisplacedSegmentData(const string &name) { - fprintf(stderr, "%s: the segment '%s' claims its contents lie beyond" - " the end of the file\n", filename_.c_str(), name.c_str()); -} - -void Reader::Reporter::MisplacedSectionData(const string §ion, - const string &segment) { - fprintf(stderr, "%s: the section '%s' in segment '%s'" - " claims its contents lie outside the segment's contents\n", - filename_.c_str(), section.c_str(), segment.c_str()); -} - -void Reader::Reporter::MisplacedSymbolTable() { - fprintf(stderr, "%s: the LC_SYMTAB load command claims that the symbol" - " table's contents are located beyond the end of the file\n", - filename_.c_str()); -} - -void Reader::Reporter::UnsupportedCPUType(cpu_type_t cpu_type) { - fprintf(stderr, "%s: CPU type %d is not supported\n", - filename_.c_str(), cpu_type); -} - -bool Reader::Read(const uint8_t *buffer, - size_t size, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype) { - assert(!buffer_.start); - buffer_.start = buffer; - buffer_.end = buffer + size; - ByteCursor cursor(&buffer_, true); - uint32_t magic; - if (!(cursor >> magic)) { - reporter_->HeaderTruncated(); - return false; - } - - if (expected_cpu_type != CPU_TYPE_ANY) { - uint32_t expected_magic; - // validate that magic matches the expected cpu type - switch (expected_cpu_type) { - case CPU_TYPE_ARM: - case CPU_TYPE_I386: - expected_magic = MH_CIGAM; - break; - case CPU_TYPE_POWERPC: - expected_magic = MH_MAGIC; - break; - case CPU_TYPE_ARM_64: - case CPU_TYPE_X86_64: - expected_magic = MH_CIGAM_64; - break; - case CPU_TYPE_POWERPC64: - expected_magic = MH_MAGIC_64; - break; - default: - reporter_->UnsupportedCPUType(expected_cpu_type); - return false; - } - - if (expected_magic != magic) { - reporter_->BadHeader(); - return false; - } - } - - // Since the byte cursor is in big-endian mode, a reversed magic number - // always indicates a little-endian file, regardless of our own endianness. - switch (magic) { - case MH_MAGIC: big_endian_ = true; bits_64_ = false; break; - case MH_CIGAM: big_endian_ = false; bits_64_ = false; break; - case MH_MAGIC_64: big_endian_ = true; bits_64_ = true; break; - case MH_CIGAM_64: big_endian_ = false; bits_64_ = true; break; - default: - reporter_->BadHeader(); - return false; - } - cursor.set_big_endian(big_endian_); - uint32_t commands_size, reserved; - cursor >> cpu_type_ >> cpu_subtype_ >> file_type_ >> load_command_count_ - >> commands_size >> flags_; - if (bits_64_) - cursor >> reserved; - if (!cursor) { - reporter_->HeaderTruncated(); - return false; - } - - if (expected_cpu_type != CPU_TYPE_ANY && - (expected_cpu_type != cpu_type_ || - expected_cpu_subtype != cpu_subtype_)) { - reporter_->CPUTypeMismatch(cpu_type_, cpu_subtype_, - expected_cpu_type, expected_cpu_subtype); - return false; - } - - cursor - .PointTo(&load_commands_.start, commands_size) - .PointTo(&load_commands_.end, 0); - if (!cursor) { - reporter_->LoadCommandRegionTruncated(); - return false; - } - - return true; -} - -bool Reader::WalkLoadCommands(Reader::LoadCommandHandler *handler) const { - ByteCursor list_cursor(&load_commands_, big_endian_); - - for (size_t index = 0; index < load_command_count_; ++index) { - // command refers to this load command alone, so that cursor will - // refuse to read past the load command's end. But since we haven't - // read the size yet, let command initially refer to the entire - // remainder of the load command series. - ByteBuffer command(list_cursor.here(), list_cursor.Available()); - ByteCursor cursor(&command, big_endian_); - - // Read the command type and size --- fields common to all commands. - uint32_t type, size; - if (!(cursor >> type)) { - reporter_->LoadCommandsOverrun(load_command_count_, index, 0); - return false; - } - if (!(cursor >> size) || size > command.Size()) { - reporter_->LoadCommandsOverrun(load_command_count_, index, type); - return false; - } - - // Now that we've read the length, restrict command's range to this - // load command only. - command.end = command.start + size; - - switch (type) { - case LC_SEGMENT: - case LC_SEGMENT_64: { - Segment segment; - segment.bits_64 = (type == LC_SEGMENT_64); - size_t word_size = segment.bits_64 ? 8 : 4; - cursor.CString(&segment.name, 16); - size_t file_offset, file_size; - cursor - .Read(word_size, false, &segment.vmaddr) - .Read(word_size, false, &segment.vmsize) - .Read(word_size, false, &file_offset) - .Read(word_size, false, &file_size); - cursor >> segment.maxprot - >> segment.initprot - >> segment.nsects - >> segment.flags; - if (!cursor) { - reporter_->LoadCommandTooShort(index, type); - return false; - } - if (file_offset > buffer_.Size() || - file_size > buffer_.Size() - file_offset) { - reporter_->MisplacedSegmentData(segment.name); - return false; - } - // Mach-O files in .dSYM bundles have the contents of the loaded - // segments removed, and their file offsets and file sizes zeroed - // out. To help us handle this special case properly, give such - // segments' contents NULL starting and ending pointers. - if (file_offset == 0 && file_size == 0) { - segment.contents.start = segment.contents.end = NULL; - } else { - segment.contents.start = buffer_.start + file_offset; - segment.contents.end = segment.contents.start + file_size; - } - // The section list occupies the remainder of this load command's space. - segment.section_list.start = cursor.here(); - segment.section_list.end = command.end; - - if (!handler->SegmentCommand(segment)) - return false; - break; - } - - case LC_SYMTAB: { - uint32_t symoff, nsyms, stroff, strsize; - cursor >> symoff >> nsyms >> stroff >> strsize; - if (!cursor) { - reporter_->LoadCommandTooShort(index, type); - return false; - } - // How big are the entries in the symbol table? - // sizeof(struct nlist_64) : sizeof(struct nlist), - // but be paranoid about alignment vs. target architecture. - size_t symbol_size = bits_64_ ? 16 : 12; - // How big is the entire symbol array? - size_t symbols_size = nsyms * symbol_size; - if (symoff > buffer_.Size() || symbols_size > buffer_.Size() - symoff || - stroff > buffer_.Size() || strsize > buffer_.Size() - stroff) { - reporter_->MisplacedSymbolTable(); - return false; - } - ByteBuffer entries(buffer_.start + symoff, symbols_size); - ByteBuffer names(buffer_.start + stroff, strsize); - if (!handler->SymtabCommand(entries, names)) - return false; - break; - } - - default: { - if (!handler->UnknownCommand(type, command)) - return false; - break; - } - } - - list_cursor.set_here(command.end); - } - - return true; -} - -// A load command handler that looks for a segment of a given name. -class Reader::SegmentFinder : public LoadCommandHandler { - public: - // Create a load command handler that looks for a segment named NAME, - // and sets SEGMENT to describe it if found. - SegmentFinder(const string &name, Segment *segment) - : name_(name), segment_(segment), found_() { } - - // Return true if the traversal found the segment, false otherwise. - bool found() const { return found_; } - - bool SegmentCommand(const Segment &segment) { - if (segment.name == name_) { - *segment_ = segment; - found_ = true; - return false; - } - return true; - } - - private: - // The name of the segment our creator is looking for. - const string &name_; - - // Where we should store the segment if found. (WEAK) - Segment *segment_; - - // True if we found the segment. - bool found_; -}; - -bool Reader::FindSegment(const string &name, Segment *segment) const { - SegmentFinder finder(name, segment); - WalkLoadCommands(&finder); - return finder.found(); -} - -bool Reader::WalkSegmentSections(const Segment &segment, - SectionHandler *handler) const { - size_t word_size = segment.bits_64 ? 8 : 4; - ByteCursor cursor(&segment.section_list, big_endian_); - - for (size_t i = 0; i < segment.nsects; i++) { - Section section; - section.bits_64 = segment.bits_64; - uint64_t size; - uint32_t offset, dummy32; - cursor - .CString(§ion.section_name, 16) - .CString(§ion.segment_name, 16) - .Read(word_size, false, §ion.address) - .Read(word_size, false, &size) - >> offset - >> section.align - >> dummy32 - >> dummy32 - >> section.flags - >> dummy32 - >> dummy32; - if (section.bits_64) - cursor >> dummy32; - if (!cursor) { - reporter_->SectionsMissing(segment.name); - return false; - } - const uint32_t section_type = section.flags & SECTION_TYPE; - if (section_type == S_ZEROFILL || section_type == S_THREAD_LOCAL_ZEROFILL || - section_type == S_GB_ZEROFILL) { - // Zero-fill sections have a size, but no contents. - section.contents.start = section.contents.end = NULL; - } else if (segment.contents.start == NULL && - segment.contents.end == NULL) { - // Mach-O files in .dSYM bundles have the contents of the loaded - // segments removed, and their file offsets and file sizes zeroed - // out. However, the sections within those segments still have - // non-zero sizes. There's no reason to call MisplacedSectionData in - // this case; the caller may just need the section's load - // address. But do set the contents' limits to NULL, for safety. - section.contents.start = section.contents.end = NULL; - } else { - if (offset < size_t(segment.contents.start - buffer_.start) || - offset > size_t(segment.contents.end - buffer_.start) || - size > size_t(segment.contents.end - buffer_.start - offset)) { - reporter_->MisplacedSectionData(section.section_name, - section.segment_name); - return false; - } - section.contents.start = buffer_.start + offset; - section.contents.end = section.contents.start + size; - } - if (!handler->HandleSection(section)) - return false; - } - return true; -} - -// A SectionHandler that builds a SectionMap for the sections within a -// given segment. -class Reader::SectionMapper: public SectionHandler { - public: - // Create a SectionHandler that populates MAP with an entry for - // each section it is given. - SectionMapper(SectionMap *map) : map_(map) { } - bool HandleSection(const Section §ion) { - (*map_)[section.section_name] = section; - return true; - } - private: - // The map under construction. (WEAK) - SectionMap *map_; -}; - -bool Reader::MapSegmentSections(const Segment &segment, - SectionMap *section_map) const { - section_map->clear(); - SectionMapper mapper(section_map); - return WalkSegmentSections(segment, &mapper); -} - -} // namespace mach_o -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h deleted file mode 100644 index 30db742db5..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h +++ /dev/null @@ -1,460 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// macho_reader.h: A class for parsing Mach-O files. - -#ifndef BREAKPAD_COMMON_MAC_MACHO_READER_H_ -#define BREAKPAD_COMMON_MAC_MACHO_READER_H_ - -#include <mach-o/loader.h> -#include <mach-o/fat.h> -#include <stdint.h> -#include <stdlib.h> -#include <unistd.h> - -#include <map> -#include <string> -#include <vector> - -#include "common/byte_cursor.h" -#include "common/mac/super_fat_arch.h" - -namespace google_breakpad { -namespace mach_o { - -using std::map; -using std::string; -using std::vector; - -// The Mac headers don't specify particular types for these groups of -// constants, but defining them here provides some documentation -// value. We also give them the same width as the fields in which -// they appear, which makes them a bit easier to use with ByteCursors. -typedef uint32_t Magic; -typedef uint32_t FileType; -typedef uint32_t FileFlags; -typedef uint32_t LoadCommandType; -typedef uint32_t SegmentFlags; -typedef uint32_t SectionFlags; - -// A parser for fat binary files, used to store universal binaries. -// When applied to a (non-fat) Mach-O file, this behaves as if the -// file were a fat file containing a single object file. -class FatReader { - public: - - // A class for reporting errors found while parsing fat binary files. The - // default definitions of these methods print messages to stderr. - class Reporter { - public: - // Create a reporter that attributes problems to |filename|. - explicit Reporter(const string &filename) : filename_(filename) { } - - virtual ~Reporter() { } - - // The data does not begin with a fat binary or Mach-O magic number. - // This is a fatal error. - virtual void BadHeader(); - - // The Mach-O fat binary file ends abruptly, without enough space - // to contain an object file it claims is present. - virtual void MisplacedObjectFile(); - - // The file ends abruptly: either it is not large enough to hold a - // complete header, or the header implies that contents are present - // beyond the actual end of the file. - virtual void TooShort(); - - private: - // The filename to which the reader should attribute problems. - string filename_; - }; - - // Create a fat binary file reader that uses |reporter| to report problems. - explicit FatReader(Reporter *reporter) : reporter_(reporter) { } - - // Read the |size| bytes at |buffer| as a fat binary file. On success, - // return true; on failure, report the problem to reporter_ and return - // false. - // - // If the data is a plain Mach-O file, rather than a fat binary file, - // then the reader behaves as if it had found a fat binary file whose - // single object file is the Mach-O file. - bool Read(const uint8_t *buffer, size_t size); - - // Return an array of 'SuperFatArch' structures describing the - // object files present in this fat binary file. Set |size| to the - // number of elements in the array. - // - // Assuming Read returned true, the entries are validated: it is safe to - // assume that the offsets and sizes in each SuperFatArch refer to subranges - // of the bytes passed to Read. - // - // If there are no object files in this fat binary, then this - // function can return NULL. - // - // The array is owned by this FatReader instance; it will be freed when - // this FatReader is destroyed. - // - // This function returns a C-style array instead of a vector to make it - // possible to use the result with OS X functions like NXFindBestFatArch, - // so that the symbol dumper will behave consistently with other OS X - // utilities that work with fat binaries. - const SuperFatArch* object_files(size_t *count) const { - *count = object_files_.size(); - if (object_files_.size() > 0) - return &object_files_[0]; - return NULL; - } - - private: - // We use this to report problems parsing the file's contents. (WEAK) - Reporter *reporter_; - - // The contents of the fat binary or Mach-O file we're parsing. We do not - // own the storage it refers to. - ByteBuffer buffer_; - - // The magic number of this binary, in host byte order. - Magic magic_; - - // The list of object files in this binary. - // object_files_.size() == fat_header.nfat_arch - vector<SuperFatArch> object_files_; -}; - -// A segment in a Mach-O file. All these fields have been byte-swapped as -// appropriate for use by the executing architecture. -struct Segment { - // The ByteBuffers below point into the bytes passed to the Reader that - // created this Segment. - - ByteBuffer section_list; // This segment's section list. - ByteBuffer contents; // This segment's contents. - - // This segment's name. - string name; - - // The address at which this segment should be loaded in memory. If - // bits_64 is false, only the bottom 32 bits of this value are valid. - uint64_t vmaddr; - - // The size of this segment when loaded into memory. This may be larger - // than contents.Size(), in which case the extra area will be - // initialized with zeros. If bits_64 is false, only the bottom 32 bits - // of this value are valid. - uint64_t vmsize; - - // The maximum and initial VM protection of this segment's contents. - uint32_t maxprot; - uint32_t initprot; - - // The number of sections in section_list. - uint32_t nsects; - - // Flags describing this segment, from SegmentFlags. - uint32_t flags; - - // True if this is a 64-bit section; false if it is a 32-bit section. - bool bits_64; -}; - -// A section in a Mach-O file. All these fields have been byte-swapped as -// appropriate for use by the executing architecture. -struct Section { - // This section's contents. This points into the bytes passed to the - // Reader that created this Section. - ByteBuffer contents; - - // This section's name. - string section_name; // section[_64].sectname - // The name of the segment this section belongs to. - string segment_name; // section[_64].segname - - // The address at which this section's contents should be loaded in - // memory. If bits_64 is false, only the bottom 32 bits of this value - // are valid. - uint64_t address; - - // The contents of this section should be loaded into memory at an - // address which is a multiple of (two raised to this power). - uint32_t align; - - // Flags from SectionFlags describing the section's contents. - uint32_t flags; - - // We don't support reading relocations yet. - - // True if this is a 64-bit section; false if it is a 32-bit section. - bool bits_64; -}; - -// A map from section names to Sections. -typedef map<string, Section> SectionMap; - -// A reader for a Mach-O file. -// -// This does not handle fat binaries; see FatReader above. FatReader -// provides a friendly interface for parsing data that could be either a -// fat binary or a Mach-O file. -class Reader { - public: - - // A class for reporting errors found while parsing Mach-O files. The - // default definitions of these member functions print messages to - // stderr. - class Reporter { - public: - // Create a reporter that attributes problems to |filename|. - explicit Reporter(const string &filename) : filename_(filename) { } - virtual ~Reporter() { } - - // Reporter functions for fatal errors return void; the reader will - // definitely return an error to its caller after calling them - - // The data does not begin with a Mach-O magic number, or the magic - // number does not match the expected value for the cpu architecture. - // This is a fatal error. - virtual void BadHeader(); - - // The data contained in a Mach-O fat binary (|cpu_type|, |cpu_subtype|) - // does not match the expected CPU architecture - // (|expected_cpu_type|, |expected_cpu_subtype|). - virtual void CPUTypeMismatch(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype); - - // The file ends abruptly: either it is not large enough to hold a - // complete header, or the header implies that contents are present - // beyond the actual end of the file. - virtual void HeaderTruncated(); - - // The file's load command region, as given in the Mach-O header, is - // too large for the file. - virtual void LoadCommandRegionTruncated(); - - // The file's Mach-O header claims the file contains |claimed| load - // commands, but the I'th load command, of type |type|, extends beyond - // the end of the load command region, as given by the Mach-O header. - // If |type| is zero, the command's type was unreadable. - virtual void LoadCommandsOverrun(size_t claimed, size_t i, - LoadCommandType type); - - // The contents of the |i|'th load command, of type |type|, extend beyond - // the size given in the load command's header. - virtual void LoadCommandTooShort(size_t i, LoadCommandType type); - - // The LC_SEGMENT or LC_SEGMENT_64 load command for the segment named - // |name| is too short to hold the sections that its header says it does. - // (This more specific than LoadCommandTooShort.) - virtual void SectionsMissing(const string &name); - - // The segment named |name| claims that its contents lie beyond the end - // of the file. - virtual void MisplacedSegmentData(const string &name); - - // The section named |section| in the segment named |segment| claims that - // its contents do not lie entirely within the segment. - virtual void MisplacedSectionData(const string §ion, - const string &segment); - - // The LC_SYMTAB command claims that symbol table contents are located - // beyond the end of the file. - virtual void MisplacedSymbolTable(); - - // An attempt was made to read a Mach-O file of the unsupported - // CPU architecture |cpu_type|. - virtual void UnsupportedCPUType(cpu_type_t cpu_type); - - private: - string filename_; - }; - - // A handler for sections parsed from a segment. The WalkSegmentSections - // member function accepts an instance of this class, and applies it to - // each section defined in a given segment. - class SectionHandler { - public: - virtual ~SectionHandler() { } - - // Called to report that the segment's section list contains |section|. - // This should return true if the iteration should continue, or false - // if it should stop. - virtual bool HandleSection(const Section §ion) = 0; - }; - - // A handler for the load commands in a Mach-O file. - class LoadCommandHandler { - public: - LoadCommandHandler() { } - virtual ~LoadCommandHandler() { } - - // When called from WalkLoadCommands, the following handler functions - // should return true if they wish to continue iterating over the load - // command list, or false if they wish to stop iterating. - // - // When called from LoadCommandIterator::Handle or Reader::Handle, - // these functions' return values are simply passed through to Handle's - // caller. - // - // The definitions provided by this base class simply return true; the - // default is to silently ignore sections whose member functions the - // subclass doesn't override. - - // COMMAND is load command we don't recognize. We provide only the - // command type and a ByteBuffer enclosing the command's data (If we - // cannot parse the command type or its size, we call - // reporter_->IncompleteLoadCommand instead.) - virtual bool UnknownCommand(LoadCommandType type, - const ByteBuffer &contents) { - return true; - } - - // The load command is LC_SEGMENT or LC_SEGMENT_64, defining a segment - // with the properties given in |segment|. - virtual bool SegmentCommand(const Segment &segment) { - return true; - } - - // The load command is LC_SYMTAB. |entries| holds the array of nlist - // entries, and |names| holds the strings the entries refer to. - virtual bool SymtabCommand(const ByteBuffer &entries, - const ByteBuffer &names) { - return true; - } - - // Add handler functions for more load commands here as needed. - }; - - // Create a Mach-O file reader that reports problems to |reporter|. - explicit Reader(Reporter *reporter) - : reporter_(reporter) { } - - // Read the given data as a Mach-O file. The reader retains pointers - // into the data passed, so the data should live as long as the reader - // does. On success, return true; on failure, return false. - // - // At most one of these functions should be invoked once on each Reader - // instance. - bool Read(const uint8_t *buffer, - size_t size, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype); - bool Read(const ByteBuffer &buffer, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype) { - return Read(buffer.start, - buffer.Size(), - expected_cpu_type, - expected_cpu_subtype); - } - - // Return this file's characteristics, as found in the Mach-O header. - cpu_type_t cpu_type() const { return cpu_type_; } - cpu_subtype_t cpu_subtype() const { return cpu_subtype_; } - FileType file_type() const { return file_type_; } - FileFlags flags() const { return flags_; } - - // Return true if this is a 64-bit Mach-O file, false if it is a 32-bit - // Mach-O file. - bool bits_64() const { return bits_64_; } - - // Return true if this is a big-endian Mach-O file, false if it is - // little-endian. - bool big_endian() const { return big_endian_; } - - // Apply |handler| to each load command in this Mach-O file, stopping when - // a handler function returns false. If we encounter a malformed load - // command, report it via reporter_ and return false. Return true if all - // load commands were parseable and all handlers returned true. - bool WalkLoadCommands(LoadCommandHandler *handler) const; - - // Set |segment| to describe the segment named |name|, if present. If - // found, |segment|'s byte buffers refer to a subregion of the bytes - // passed to Read. If we find the section, return true; otherwise, - // return false. - bool FindSegment(const string &name, Segment *segment) const; - - // Apply |handler| to each section defined in |segment|. If |handler| returns - // false, stop iterating and return false. If all calls to |handler| return - // true and we reach the end of the section list, return true. - bool WalkSegmentSections(const Segment &segment, SectionHandler *handler) - const; - - // Clear |section_map| and then populate it with a map of the sections - // in |segment|, from section names to Section structures. - // Each Section's contents refer to bytes in |segment|'s contents. - // On success, return true; if a problem occurs, report it and return false. - bool MapSegmentSections(const Segment &segment, SectionMap *section_map) - const; - - private: - // Used internally. - class SegmentFinder; - class SectionMapper; - - // We use this to report problems parsing the file's contents. (WEAK) - Reporter *reporter_; - - // The contents of the Mach-O file we're parsing. We do not own the - // storage it refers to. - ByteBuffer buffer_; - - // True if this file is big-endian. - bool big_endian_; - - // True if this file is a 64-bit Mach-O file. - bool bits_64_; - - // This file's cpu type and subtype. - cpu_type_t cpu_type_; // mach_header[_64].cputype - cpu_subtype_t cpu_subtype_; // mach_header[_64].cpusubtype - - // This file's type. - FileType file_type_; // mach_header[_64].filetype - - // The region of buffer_ occupied by load commands. - ByteBuffer load_commands_; - - // The number of load commands in load_commands_. - uint32_t load_command_count_; // mach_header[_64].ncmds - - // This file's header flags. - FileFlags flags_; -}; - -} // namespace mach_o -} // namespace google_breakpad - -#endif // BREAKPAD_COMMON_MAC_MACHO_READER_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc deleted file mode 100644 index 8ceab14bf2..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc +++ /dev/null @@ -1,1902 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// macho_reader_unittest.cc: Unit tests for google_breakpad::Mach_O::FatReader -// and google_breakpad::Mach_O::Reader. - -#include <map> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/mac/macho_reader.h" -#include "common/test_assembler.h" - -namespace mach_o = google_breakpad::mach_o; -namespace test_assembler = google_breakpad::test_assembler; - -using mach_o::FatReader; -using mach_o::FileFlags; -using mach_o::FileType; -using mach_o::LoadCommandType; -using mach_o::Reader; -using mach_o::Section; -using mach_o::SectionMap; -using mach_o::Segment; -using test_assembler::Endianness; -using test_assembler::Label; -using test_assembler::kBigEndian; -using test_assembler::kLittleEndian; -using test_assembler::kUnsetEndian; -using google_breakpad::ByteBuffer; -using std::map; -using std::string; -using std::vector; -using testing::AllOf; -using testing::DoAll; -using testing::Field; -using testing::InSequence; -using testing::Matcher; -using testing::Return; -using testing::SaveArg; -using testing::Test; -using testing::_; - - -// Mock classes for the reader's various reporters and handlers. - -class MockFatReaderReporter: public FatReader::Reporter { - public: - MockFatReaderReporter(const string &filename) - : FatReader::Reporter(filename) { } - MOCK_METHOD0(BadHeader, void()); - MOCK_METHOD0(MisplacedObjectFile, void()); - MOCK_METHOD0(TooShort, void()); -}; - -class MockReaderReporter: public Reader::Reporter { - public: - MockReaderReporter(const string &filename) : Reader::Reporter(filename) { } - MOCK_METHOD0(BadHeader, void()); - MOCK_METHOD4(CPUTypeMismatch, void(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype)); - MOCK_METHOD0(HeaderTruncated, void()); - MOCK_METHOD0(LoadCommandRegionTruncated, void()); - MOCK_METHOD3(LoadCommandsOverrun, void(size_t claimed, size_t i, - LoadCommandType type)); - MOCK_METHOD2(LoadCommandTooShort, void(size_t i, LoadCommandType type)); - MOCK_METHOD1(SectionsMissing, void(const string &name)); - MOCK_METHOD1(MisplacedSegmentData, void(const string &name)); - MOCK_METHOD2(MisplacedSectionData, void(const string §ion, - const string &segment)); - MOCK_METHOD0(MisplacedSymbolTable, void()); - MOCK_METHOD1(UnsupportedCPUType, void(cpu_type_t cpu_type)); -}; - -class MockLoadCommandHandler: public Reader::LoadCommandHandler { - public: - MOCK_METHOD2(UnknownCommand, bool(LoadCommandType, const ByteBuffer &)); - MOCK_METHOD1(SegmentCommand, bool(const Segment &)); - MOCK_METHOD2(SymtabCommand, bool(const ByteBuffer &, const ByteBuffer &)); -}; - -class MockSectionHandler: public Reader::SectionHandler { - public: - MOCK_METHOD1(HandleSection, bool(const Section §ion)); -}; - - -// Tests for mach_o::FatReader. - -// Since the effect of these functions is to write to stderr, the -// results of these tests must be inspected by hand. -TEST(FatReaderReporter, BadHeader) { - FatReader::Reporter reporter("filename"); - reporter.BadHeader(); -} - -TEST(FatReaderReporter, MisplacedObjectFile) { - FatReader::Reporter reporter("filename"); - reporter.MisplacedObjectFile(); -} - -TEST(FatReaderReporter, TooShort) { - FatReader::Reporter reporter("filename"); - reporter.TooShort(); -} - -TEST(MachOReaderReporter, BadHeader) { - Reader::Reporter reporter("filename"); - reporter.BadHeader(); -} - -TEST(MachOReaderReporter, CPUTypeMismatch) { - Reader::Reporter reporter("filename"); - reporter.CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL, - CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL); -} - -TEST(MachOReaderReporter, HeaderTruncated) { - Reader::Reporter reporter("filename"); - reporter.HeaderTruncated(); -} - -TEST(MachOReaderReporter, LoadCommandRegionTruncated) { - Reader::Reporter reporter("filename"); - reporter.LoadCommandRegionTruncated(); -} - -TEST(MachOReaderReporter, LoadCommandsOverrun) { - Reader::Reporter reporter("filename"); - reporter.LoadCommandsOverrun(10, 9, LC_DYSYMTAB); - reporter.LoadCommandsOverrun(10, 9, 0); -} - -TEST(MachOReaderReporter, LoadCommandTooShort) { - Reader::Reporter reporter("filename"); - reporter.LoadCommandTooShort(11, LC_SYMTAB); -} - -TEST(MachOReaderReporter, SectionsMissing) { - Reader::Reporter reporter("filename"); - reporter.SectionsMissing("segment name"); -} - -TEST(MachOReaderReporter, MisplacedSegmentData) { - Reader::Reporter reporter("filename"); - reporter.MisplacedSegmentData("segment name"); -} - -TEST(MachOReaderReporter, MisplacedSectionData) { - Reader::Reporter reporter("filename"); - reporter.MisplacedSectionData("section name", "segment name"); -} - -TEST(MachOReaderReporter, MisplacedSymbolTable) { - Reader::Reporter reporter("filename"); - reporter.MisplacedSymbolTable(); -} - -TEST(MachOReaderReporter, UnsupportedCPUType) { - Reader::Reporter reporter("filename"); - reporter.UnsupportedCPUType(CPU_TYPE_HPPA); -} - -struct FatReaderFixture { - FatReaderFixture() - : fat(kBigEndian), - reporter("reporter filename"), - reader(&reporter), object_files() { - EXPECT_CALL(reporter, BadHeader()).Times(0); - EXPECT_CALL(reporter, TooShort()).Times(0); - - // here, start, and Mark are file offsets in 'fat'. - fat.start() = 0; - } - // Append a 'fat_arch' entry to 'fat', with the given field values. - void AppendFatArch(cpu_type_t type, cpu_subtype_t subtype, - Label offset, Label size, uint32_t align) { - fat - .B32(type) - .B32(subtype) - .B32(offset) - .B32(size) - .B32(align); - } - // Append |n| dummy 'fat_arch' entries to 'fat'. The cpu type and - // subtype have unrealistic values. - void AppendDummyArchEntries(int n) { - for (int i = 0; i < n; i++) - AppendFatArch(0xb68ad617, 0x715a0840, 0, 0, 1); - } - void ReadFat(bool expect_parse_success = true) { - ASSERT_TRUE(fat.GetContents(&contents)); - fat_bytes = reinterpret_cast<const uint8_t *>(contents.data()); - if (expect_parse_success) { - EXPECT_TRUE(reader.Read(fat_bytes, contents.size())); - size_t fat_files_count; - const SuperFatArch* fat_files = reader.object_files(&fat_files_count); - object_files.resize(fat_files_count); - for (size_t i = 0; i < fat_files_count; ++i) { - EXPECT_TRUE(fat_files[i].ConvertToFatArch(&object_files[i])); - } - } - else - EXPECT_FALSE(reader.Read(fat_bytes, contents.size())); - } - test_assembler::Section fat; - MockFatReaderReporter reporter; - FatReader reader; - string contents; - const uint8_t *fat_bytes; - vector<struct fat_arch> object_files; -}; - -class FatReaderTest: public FatReaderFixture, public Test { }; - -TEST_F(FatReaderTest, BadMagic) { - EXPECT_CALL(reporter, BadHeader()).Times(1); - fat - .B32(0xcafed00d) // magic number (incorrect) - .B32(10); // number of architectures - AppendDummyArchEntries(10); - ReadFat(false); -} - -TEST_F(FatReaderTest, HeaderTooShort) { - EXPECT_CALL(reporter, TooShort()).Times(1); - fat - .B32(0xcafebabe); // magic number - ReadFat(false); -} - -TEST_F(FatReaderTest, ObjectListTooShort) { - EXPECT_CALL(reporter, TooShort()).Times(1); - fat - .B32(0xcafebabe) // magic number - .B32(10); // number of architectures - AppendDummyArchEntries(9); // nine dummy architecture entries... - fat // and a tenth, missing a byte at the end - .B32(0x3d46c8fc) // cpu type - .B32(0x8a7bfb01) // cpu subtype - .B32(0) // offset - .B32(0) // size - .Append(3, '*'); // one byte short of a four-byte alignment - ReadFat(false); -} - -TEST_F(FatReaderTest, DataTooShort) { - EXPECT_CALL(reporter, MisplacedObjectFile()).Times(1); - Label arch_data; - fat - .B32(0xcafebabe) // magic number - .B32(1); // number of architectures - AppendFatArch(0xb4d4a366, 0x4ba4f525, arch_data, 40, 0); - fat - .Mark(&arch_data) // file data begins here - .Append(30, '*'); // only 30 bytes, not 40 as header claims - ReadFat(false); -} - -TEST_F(FatReaderTest, NoObjectFiles) { - fat - .B32(0xcafebabe) // magic number - .B32(0); // number of architectures - ReadFat(); - EXPECT_EQ(0U, object_files.size()); -} - -TEST_F(FatReaderTest, OneObjectFile) { - Label obj1_offset; - fat - .B32(0xcafebabe) // magic number - .B32(1); // number of architectures - // First object file list entry - AppendFatArch(0x5e3a6e91, 0x52ccd852, obj1_offset, 0x42, 0x355b15b2); - // First object file data - fat - .Mark(&obj1_offset) - .Append(0x42, '*'); // dummy contents - ReadFat(); - ASSERT_EQ(1U, object_files.size()); - EXPECT_EQ(0x5e3a6e91, object_files[0].cputype); - EXPECT_EQ(0x52ccd852, object_files[0].cpusubtype); - EXPECT_EQ(obj1_offset.Value(), object_files[0].offset); - EXPECT_EQ(0x42U, object_files[0].size); - EXPECT_EQ(0x355b15b2U, object_files[0].align); -} - -TEST_F(FatReaderTest, ThreeObjectFiles) { - Label obj1, obj2, obj3; - fat - .B32(0xcafebabe) // magic number - .B32(3); // number of architectures - // Three object file list entries. - AppendFatArch(0x0cb92c30, 0x6a159a71, obj1, 0xfb4, 0x2615dbe8); - AppendFatArch(0x0f3f1cbb, 0x6c55e90f, obj2, 0xc31, 0x83af6ffd); - AppendFatArch(0x3717276d, 0x10ecdc84, obj3, 0x4b3, 0x035267d7); - fat - // First object file data - .Mark(&obj1) - .Append(0xfb4, '*') // dummy contents - // Second object file data - .Mark(&obj2) - .Append(0xc31, '%') // dummy contents - // Third object file data - .Mark(&obj3) - .Append(0x4b3, '^'); // dummy contents - - ReadFat(); - - ASSERT_EQ(3U, object_files.size()); - - // First object file. - EXPECT_EQ(0x0cb92c30, object_files[0].cputype); - EXPECT_EQ(0x6a159a71, object_files[0].cpusubtype); - EXPECT_EQ(obj1.Value(), object_files[0].offset); - EXPECT_EQ(0xfb4U, object_files[0].size); - EXPECT_EQ(0x2615dbe8U, object_files[0].align); - - // Second object file. - EXPECT_EQ(0x0f3f1cbb, object_files[1].cputype); - EXPECT_EQ(0x6c55e90f, object_files[1].cpusubtype); - EXPECT_EQ(obj2.Value(), object_files[1].offset); - EXPECT_EQ(0xc31U, object_files[1].size); - EXPECT_EQ(0x83af6ffdU, object_files[1].align); - - // Third object file. - EXPECT_EQ(0x3717276d, object_files[2].cputype); - EXPECT_EQ(0x10ecdc84, object_files[2].cpusubtype); - EXPECT_EQ(obj3.Value(), object_files[2].offset); - EXPECT_EQ(0x4b3U, object_files[2].size); - EXPECT_EQ(0x035267d7U, object_files[2].align); -} - -TEST_F(FatReaderTest, BigEndianMachO32) { - fat.set_endianness(kBigEndian); - fat - .D32(0xfeedface) // Mach-O file magic number - .D32(0x1a9d0518) // cpu type - .D32(0x1b779357) // cpu subtype - .D32(0x009df67e) // file type - .D32(0) // no load commands - .D32(0) // the load commands occupy no bytes - .D32(0x21987a99); // flags - - ReadFat(); - - // FatReader should treat a Mach-O file as if it were a fat binary file - // containing one object file --- the whole thing. - ASSERT_EQ(1U, object_files.size()); - EXPECT_EQ(0x1a9d0518, object_files[0].cputype); - EXPECT_EQ(0x1b779357, object_files[0].cpusubtype); - EXPECT_EQ(0U, object_files[0].offset); - EXPECT_EQ(contents.size(), object_files[0].size); -} - -TEST_F(FatReaderTest, BigEndianMachO64) { - fat.set_endianness(kBigEndian); - fat - .D32(0xfeedfacf) // Mach-O 64-bit file magic number - .D32(0x5aff8487) // cpu type - .D32(0x4c6a57f7) // cpu subtype - .D32(0x4392d2c8) // file type - .D32(0) // no load commands - .D32(0) // the load commands occupy no bytes - .D32(0x1b033eea); // flags - - ReadFat(); - - // FatReader should treat a Mach-O file as if it were a fat binary file - // containing one object file --- the whole thing. - ASSERT_EQ(1U, object_files.size()); - EXPECT_EQ(0x5aff8487, object_files[0].cputype); - EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype); - EXPECT_EQ(0U, object_files[0].offset); - EXPECT_EQ(contents.size(), object_files[0].size); -} - -TEST_F(FatReaderTest, LittleEndianMachO32) { - fat.set_endianness(kLittleEndian); - fat - .D32(0xfeedface) // Mach-O file magic number - .D32(0x1a9d0518) // cpu type - .D32(0x1b779357) // cpu subtype - .D32(0x009df67e) // file type - .D32(0) // no load commands - .D32(0) // the load commands occupy no bytes - .D32(0x21987a99); // flags - - ReadFat(); - - // FatReader should treat a Mach-O file as if it were a fat binary file - // containing one object file --- the whole thing. - ASSERT_EQ(1U, object_files.size()); - EXPECT_EQ(0x1a9d0518, object_files[0].cputype); - EXPECT_EQ(0x1b779357, object_files[0].cpusubtype); - EXPECT_EQ(0U, object_files[0].offset); - EXPECT_EQ(contents.size(), object_files[0].size); -} - -TEST_F(FatReaderTest, LittleEndianMachO64) { - fat.set_endianness(kLittleEndian); - fat - .D32(0xfeedfacf) // Mach-O 64-bit file magic number - .D32(0x5aff8487) // cpu type - .D32(0x4c6a57f7) // cpu subtype - .D32(0x4392d2c8) // file type - .D32(0) // no load commands - .D32(0) // the load commands occupy no bytes - .D32(0x1b033eea); // flags - - ReadFat(); - - // FatReader should treat a Mach-O file as if it were a fat binary file - // containing one object file --- the whole thing. - ASSERT_EQ(1U, object_files.size()); - EXPECT_EQ(0x5aff8487, object_files[0].cputype); - EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype); - EXPECT_EQ(0U, object_files[0].offset); - EXPECT_EQ(contents.size(), object_files[0].size); -} - -TEST_F(FatReaderTest, IncompleteMach) { - fat.set_endianness(kLittleEndian); - fat - .D32(0xfeedfacf) // Mach-O 64-bit file magic number - .D32(0x5aff8487); // cpu type - // Truncated! - - EXPECT_CALL(reporter, TooShort()).WillOnce(Return()); - - ReadFat(false); -} - - -// General mach_o::Reader tests. - -// Dynamically scoped configuration data. -class WithConfiguration { - public: - // Establish the given parameters as the default for SizedSections - // created within the dynamic scope of this instance. - WithConfiguration(Endianness endianness, size_t word_size) - : endianness_(endianness), word_size_(word_size), saved_(current_) { - current_ = this; - } - ~WithConfiguration() { current_ = saved_; } - static Endianness endianness() { - assert(current_); - return current_->endianness_; - } - static size_t word_size() { - assert(current_); - return current_->word_size_; - } - - private: - // The innermost WithConfiguration in whose dynamic scope we are - // currently executing. - static WithConfiguration *current_; - - // The innermost WithConfiguration whose dynamic scope encloses this - // WithConfiguration. - Endianness endianness_; - size_t word_size_; - WithConfiguration *saved_; -}; - -WithConfiguration *WithConfiguration::current_ = NULL; - -// A test_assembler::Section with a size that we can cite. The start(), -// Here() and Mark() member functions of a SizedSection always represent -// offsets within the overall file. -class SizedSection: public test_assembler::Section { - public: - // Construct a section of the given endianness and word size. - explicit SizedSection(Endianness endianness, size_t word_size) - : test_assembler::Section(endianness), word_size_(word_size) { - assert(word_size_ == 32 || word_size_ == 64); - } - SizedSection() - : test_assembler::Section(WithConfiguration::endianness()), - word_size_(WithConfiguration::word_size()) { - assert(word_size_ == 32 || word_size_ == 64); - } - - // Access/set this section's word size. - size_t word_size() const { return word_size_; } - void set_word_size(size_t word_size) { - assert(word_size_ == 32 || word_size_ == 64); - word_size_ = word_size; - } - - // Return a label representing the size this section will have when it - // is Placed in some containing section. - Label final_size() const { return final_size_; } - - // Append SECTION to the end of this section, and call its Finish member. - // Return a reference to this section. - SizedSection &Place(SizedSection *section) { - assert(section->endianness() == endianness()); - section->Finish(); - section->start() = Here(); - test_assembler::Section::Append(*section); - return *this; - } - - protected: - // Mark this section's contents as complete. For plain SizedSections, we - // set SECTION's start to its position in this section, and its final_size - // label to its current size. Derived classes can extend this as needed - // for their additional semantics. - virtual void Finish() { - final_size_ = Size(); - } - - // The word size for this data: either 32 or 64. - size_t word_size_; - - private: - // This section's final size, set when we are placed in some other - // SizedSection. - Label final_size_; -}; - -// A SizedSection that is loaded into memory at a particular address. -class LoadedSection: public SizedSection { - public: - explicit LoadedSection(Label address = Label()) : address_(address) { } - - // Return a label representing this section's address. - Label address() const { return address_; } - - // Placing a loaded section within a loaded section sets the relationship - // between their addresses. - LoadedSection &Place(LoadedSection *section) { - section->address() = address() + Size(); - SizedSection::Place(section); - return *this; - } - - protected: - // The address at which this section's contents will be loaded. - Label address_; -}; - -// A SizedSection representing a segment load command. -class SegmentLoadCommand: public SizedSection { - public: - SegmentLoadCommand() : section_count_(0) { } - - // Append a segment load command header with the given characteristics. - // The load command will refer to CONTENTS, which must be Placed in the - // file separately, at the desired position. Return a reference to this - // section. - SegmentLoadCommand &Header(const string &name, const LoadedSection &contents, - uint32_t maxprot, uint32_t initprot, - uint32_t flags) { - assert(contents.word_size() == word_size()); - D32(word_size() == 32 ? LC_SEGMENT : LC_SEGMENT_64); - D32(final_size()); - AppendCString(name, 16); - Append(endianness(), word_size() / 8, contents.address()); - Append(endianness(), word_size() / 8, vmsize_); - Append(endianness(), word_size() / 8, contents.start()); - Append(endianness(), word_size() / 8, contents.final_size()); - D32(maxprot); - D32(initprot); - D32(final_section_count_); - D32(flags); - - content_final_size_ = contents.final_size(); - - return *this; - } - - // Return a label representing the size of this segment when loaded into - // memory. If this label is still undefined by the time we place this - // segment, it defaults to the final size of the segment's in-file - // contents. Return a reference to this load command. - Label &vmsize() { return vmsize_; } - - // Add a section entry with the given characteristics to this segment - // load command. Return a reference to this. The section entry will refer - // to CONTENTS, which must be Placed in the segment's contents - // separately, at the desired position. - SegmentLoadCommand &AppendSectionEntry(const string §ion_name, - const string &segment_name, - uint32_t alignment, uint32_t flags, - const LoadedSection &contents) { - AppendCString(section_name, 16); - AppendCString(segment_name, 16); - Append(endianness(), word_size() / 8, contents.address()); - Append(endianness(), word_size() / 8, contents.final_size()); - D32(contents.start()); - D32(alignment); - D32(0); // relocations start - D32(0); // relocations size - D32(flags); - D32(0x93656b95); // reserved1 - D32(0xc35a2473); // reserved2 - if (word_size() == 64) - D32(0x70284b95); // reserved3 - - section_count_++; - - return *this; - } - - protected: - void Finish() { - final_section_count_ = section_count_; - if (!vmsize_.IsKnownConstant()) - vmsize_ = content_final_size_; - SizedSection::Finish(); - } - - private: - // The number of sections that have been added to this segment so far. - size_t section_count_; - - // A label representing the final number of sections this segment will hold. - Label final_section_count_; - - // The size of the contents for this segment present in the file. - Label content_final_size_; - - // A label representing the size of this segment when loaded; this can be - // larger than the size of its file contents, the difference being - // zero-filled. If not set explicitly by calling set_vmsize, this is set - // equal to the size of the contents. - Label vmsize_; -}; - -// A SizedSection holding a list of Mach-O load commands. -class LoadCommands: public SizedSection { - public: - LoadCommands() : command_count_(0) { } - - // Return a label representing the final load command count. - Label final_command_count() const { return final_command_count_; } - - // Increment the command count; return a reference to this section. - LoadCommands &CountCommand() { - command_count_++; - return *this; - } - - // Place COMMAND, containing a load command, at the end of this section. - // Return a reference to this section. - LoadCommands &Place(SizedSection *section) { - SizedSection::Place(section); - CountCommand(); - return *this; - } - - protected: - // Mark this load command list as complete. - void Finish() { - SizedSection::Finish(); - final_command_count_ = command_count_; - } - - private: - // The number of load commands we have added to this file so far. - size_t command_count_; - - // A label representing the final command count. - Label final_command_count_; -}; - -// A SizedSection holding the contents of a Mach-O file. Within a -// MachOFile, the start, Here, and Mark members refer to file offsets. -class MachOFile: public SizedSection { - public: - MachOFile() { - start() = 0; - } - - // Create a Mach-O file header using the given characteristics and load - // command list. This Places COMMANDS immediately after the header. - // Return a reference to this section. - MachOFile &Header(LoadCommands *commands, - cpu_type_t cpu_type = CPU_TYPE_X86, - cpu_subtype_t cpu_subtype = CPU_SUBTYPE_I386_ALL, - FileType file_type = MH_EXECUTE, - uint32_t file_flags = (MH_TWOLEVEL | - MH_DYLDLINK | - MH_NOUNDEFS)) { - D32(word_size() == 32 ? 0xfeedface : 0xfeedfacf); // magic number - D32(cpu_type); // cpu type - D32(cpu_subtype); // cpu subtype - D32(file_type); // file type - D32(commands->final_command_count()); // number of load commands - D32(commands->final_size()); // their size in bytes - D32(file_flags); // flags - if (word_size() == 64) - D32(0x55638b90); // reserved - Place(commands); - return *this; - } -}; - - -struct ReaderFixture { - ReaderFixture() - : reporter("reporter filename"), - reader(&reporter) { - EXPECT_CALL(reporter, BadHeader()).Times(0); - EXPECT_CALL(reporter, CPUTypeMismatch(_, _, _, _)).Times(0); - EXPECT_CALL(reporter, HeaderTruncated()).Times(0); - EXPECT_CALL(reporter, LoadCommandRegionTruncated()).Times(0); - EXPECT_CALL(reporter, LoadCommandsOverrun(_, _, _)).Times(0); - EXPECT_CALL(reporter, LoadCommandTooShort(_, _)).Times(0); - EXPECT_CALL(reporter, SectionsMissing(_)).Times(0); - EXPECT_CALL(reporter, MisplacedSegmentData(_)).Times(0); - EXPECT_CALL(reporter, MisplacedSectionData(_, _)).Times(0); - EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(0); - EXPECT_CALL(reporter, UnsupportedCPUType(_)).Times(0); - - EXPECT_CALL(load_command_handler, UnknownCommand(_, _)).Times(0); - EXPECT_CALL(load_command_handler, SegmentCommand(_)).Times(0); - } - - void ReadFile(MachOFile *file, - bool expect_parse_success, - cpu_type_t expected_cpu_type, - cpu_subtype_t expected_cpu_subtype) { - ASSERT_TRUE(file->GetContents(&file_contents)); - file_bytes = reinterpret_cast<const uint8_t *>(file_contents.data()); - if (expect_parse_success) { - EXPECT_TRUE(reader.Read(file_bytes, - file_contents.size(), - expected_cpu_type, - expected_cpu_subtype)); - } else { - EXPECT_FALSE(reader.Read(file_bytes, - file_contents.size(), - expected_cpu_type, - expected_cpu_subtype)); - } - } - - string file_contents; - const uint8_t *file_bytes; - MockReaderReporter reporter; - Reader reader; - MockLoadCommandHandler load_command_handler; - MockSectionHandler section_handler; -}; - -class ReaderTest: public ReaderFixture, public Test { }; - -TEST_F(ReaderTest, BadMagic) { - WithConfiguration config(kLittleEndian, 32); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0x67bdebe1) // Not a proper magic number. - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - EXPECT_CALL(reporter, BadHeader()).WillOnce(Return()); - ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType); -} - -TEST_F(ReaderTest, MismatchedMagic) { - WithConfiguration config(kLittleEndian, 32); - const cpu_type_t kCPUType = CPU_TYPE_I386; - const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL; - MachOFile file; - file - .D32(MH_CIGAM) // Right magic, but winds up wrong - // due to bitswapping - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - EXPECT_CALL(reporter, BadHeader()).WillOnce(Return()); - ReadFile(&file, false, kCPUType, kCPUSubType); -} - -TEST_F(ReaderTest, ShortMagic) { - WithConfiguration config(kBigEndian, 32); - MachOFile file; - file - .D16(0xfeed); // magic number - // truncated! - EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return()); - ReadFile(&file, false, CPU_TYPE_ANY, 0); -} - -TEST_F(ReaderTest, ShortHeader) { - WithConfiguration config(kBigEndian, 32); - const cpu_type_t kCPUType = CPU_TYPE_ANY; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedface) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0); // they occupy no bytes - EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return()); - ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType); -} - -TEST_F(ReaderTest, MismatchedCPU) { - WithConfiguration config(kBigEndian, 32); - const cpu_type_t kCPUType = CPU_TYPE_I386; - const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL; - MachOFile file; - file - .D32(MH_MAGIC) // Right magic for PPC (once bitswapped) - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - EXPECT_CALL(reporter, - CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL, - CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL)) - .WillOnce(Return()); - ReadFile(&file, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL); -} - -TEST_F(ReaderTest, LittleEndian32Bit) { - WithConfiguration config(kLittleEndian, 32); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedface) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType); - EXPECT_FALSE(reader.bits_64()); - EXPECT_FALSE(reader.big_endian()); - EXPECT_EQ(kCPUType, reader.cpu_type()); - EXPECT_EQ(kCPUSubType, reader.cpu_subtype()); - EXPECT_EQ(FileType(0x149fc717), reader.file_type()); - EXPECT_EQ(FileFlags(0x80e71d64), reader.flags()); -} - -TEST_F(ReaderTest, LittleEndian64Bit) { - WithConfiguration config(kLittleEndian, 64); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedfacf) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType); - EXPECT_TRUE(reader.bits_64()); - EXPECT_FALSE(reader.big_endian()); - EXPECT_EQ(kCPUType, reader.cpu_type()); - EXPECT_EQ(kCPUSubType, reader.cpu_subtype()); - EXPECT_EQ(FileType(0x149fc717), reader.file_type()); - EXPECT_EQ(FileFlags(0x80e71d64), reader.flags()); -} - -TEST_F(ReaderTest, BigEndian32Bit) { - WithConfiguration config(kBigEndian, 32); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedface) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType); - EXPECT_FALSE(reader.bits_64()); - EXPECT_TRUE(reader.big_endian()); - EXPECT_EQ(kCPUType, reader.cpu_type()); - EXPECT_EQ(kCPUSubType, reader.cpu_subtype()); - EXPECT_EQ(FileType(0x149fc717), reader.file_type()); - EXPECT_EQ(FileFlags(0x80e71d64), reader.flags()); -} - -TEST_F(ReaderTest, BigEndian64Bit) { - WithConfiguration config(kBigEndian, 64); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedfacf) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(0) // no load commands - .D32(0) // they occupy no bytes - .D32(0x80e71d64) // flags - .D32(0); // reserved - ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType); - EXPECT_TRUE(reader.bits_64()); - EXPECT_TRUE(reader.big_endian()); - EXPECT_EQ(kCPUType, reader.cpu_type()); - EXPECT_EQ(kCPUSubType, reader.cpu_subtype()); - EXPECT_EQ(FileType(0x149fc717), reader.file_type()); - EXPECT_EQ(FileFlags(0x80e71d64), reader.flags()); -} - - -// Load command tests. - -class LoadCommand: public ReaderFixture, public Test { }; - -TEST_F(LoadCommand, RegionTruncated) { - WithConfiguration config(kBigEndian, 64); - const cpu_type_t kCPUType = 0x46b760df; - const cpu_subtype_t kCPUSubType = 0x76a0e7f7; - MachOFile file; - file - .D32(0xfeedfacf) // magic number - .D32(kCPUType) // cpu type - .D32(kCPUSubType) // cpu subtype - .D32(0x149fc717) // file type - .D32(1) // one load command - .D32(40) // occupying 40 bytes - .D32(0x80e71d64) // flags - .D32(0) // reserved - .Append(20, 0); // load command region, not as long as - // Mach-O header promised - - EXPECT_CALL(reporter, LoadCommandRegionTruncated()).WillOnce(Return()); - - ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType); -} - -TEST_F(LoadCommand, None) { - WithConfiguration config(kLittleEndian, 32); - LoadCommands load_commands; - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_X86, CPU_SUBTYPE_I386_ALL); - - EXPECT_FALSE(reader.bits_64()); - EXPECT_FALSE(reader.big_endian()); - EXPECT_EQ(CPU_TYPE_X86, reader.cpu_type()); - EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype()); - EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type()); - EXPECT_EQ(FileFlags(MH_TWOLEVEL | - MH_DYLDLINK | - MH_NOUNDEFS), - FileFlags(reader.flags())); - - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, Unknown) { - WithConfiguration config(kBigEndian, 32); - LoadCommands load_commands; - load_commands - .CountCommand() - .D32(0x33293d4a) // unknown load command - .D32(40) // total size in bytes - .Append(32, '*'); // dummy data - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_FALSE(reader.bits_64()); - EXPECT_TRUE(reader.big_endian()); - EXPECT_EQ(CPU_TYPE_X86, reader.cpu_type()); - EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype()); - EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type()); - EXPECT_EQ(FileFlags(MH_TWOLEVEL | - MH_DYLDLINK | - MH_NOUNDEFS), - reader.flags()); - - ByteBuffer expected; - expected.start = file_bytes + load_commands.start().Value(); - expected.end = expected.start + load_commands.final_size().Value(); - EXPECT_CALL(load_command_handler, UnknownCommand(0x33293d4a, - expected)) - .WillOnce(Return(true)); - - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, TypeIncomplete) { - WithConfiguration config(kLittleEndian, 32); - LoadCommands load_commands; - load_commands - .CountCommand() - .Append(3, 0); // load command type, incomplete - - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, 0)) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, LengthIncomplete) { - WithConfiguration config(kBigEndian, 64); - LoadCommands load_commands; - load_commands - .CountCommand() - .D32(LC_SEGMENT); // load command - // no length - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT)) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, ContentIncomplete) { - WithConfiguration config(kLittleEndian, 64); - LoadCommands load_commands; - load_commands - .CountCommand() - .D32(LC_SEGMENT) // load command - .D32(40) // total size in bytes - .Append(28, '*'); // not enough dummy data - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT)) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, SegmentBE32) { - WithConfiguration config(kBigEndian, 32); - LoadedSection segment; - segment.address() = 0x1891139c; - segment.Append(42, '*'); // segment contents - SegmentLoadCommand segment_command; - segment_command - .Header("froon", segment, 0x94d6dd22, 0x8bdbc319, 0x990a16dd); - segment_command.vmsize() = 0xcb76584fU; - LoadCommands load_commands; - load_commands.Place(&segment_command); - MachOFile file; - file - .Header(&load_commands) - .Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_CALL(load_command_handler, SegmentCommand(_)) - .WillOnce(DoAll(SaveArg<0>(&actual_segment), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(false, actual_segment.bits_64); - EXPECT_EQ("froon", actual_segment.name); - EXPECT_EQ(0x1891139cU, actual_segment.vmaddr); - EXPECT_EQ(0xcb76584fU, actual_segment.vmsize); - EXPECT_EQ(0x94d6dd22U, actual_segment.maxprot); - EXPECT_EQ(0x8bdbc319U, actual_segment.initprot); - EXPECT_EQ(0x990a16ddU, actual_segment.flags); - EXPECT_EQ(0U, actual_segment.nsects); - EXPECT_EQ(0U, actual_segment.section_list.Size()); - EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size()); -} - -TEST_F(LoadCommand, SegmentLE32) { - WithConfiguration config(kLittleEndian, 32); - LoadedSection segment; - segment.address() = 0x4b877866; - segment.Append(42, '*'); // segment contents - SegmentLoadCommand segment_command; - segment_command - .Header("sixteenprecisely", segment, - 0x350759ed, 0x6cf5a62e, 0x990a16dd); - segment_command.vmsize() = 0xcb76584fU; - LoadCommands load_commands; - load_commands.Place(&segment_command); - MachOFile file; - file - .Header(&load_commands) - .Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_CALL(load_command_handler, SegmentCommand(_)) - .WillOnce(DoAll(SaveArg<0>(&actual_segment), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(false, actual_segment.bits_64); - EXPECT_EQ("sixteenprecisely", actual_segment.name); - EXPECT_EQ(0x4b877866U, actual_segment.vmaddr); - EXPECT_EQ(0xcb76584fU, actual_segment.vmsize); - EXPECT_EQ(0x350759edU, actual_segment.maxprot); - EXPECT_EQ(0x6cf5a62eU, actual_segment.initprot); - EXPECT_EQ(0x990a16ddU, actual_segment.flags); - EXPECT_EQ(0U, actual_segment.nsects); - EXPECT_EQ(0U, actual_segment.section_list.Size()); - EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size()); -} - -TEST_F(LoadCommand, SegmentBE64) { - WithConfiguration config(kBigEndian, 64); - LoadedSection segment; - segment.address() = 0x79f484f77009e511ULL; - segment.Append(42, '*'); // segment contents - SegmentLoadCommand segment_command; - segment_command - .Header("froon", segment, 0x42b45da5, 0x8bdbc319, 0xb2335220); - segment_command.vmsize() = 0x8d92397ce6248abaULL; - LoadCommands load_commands; - load_commands.Place(&segment_command); - MachOFile file; - file - .Header(&load_commands) - .Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_CALL(load_command_handler, SegmentCommand(_)) - .WillOnce(DoAll(SaveArg<0>(&actual_segment), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(true, actual_segment.bits_64); - EXPECT_EQ("froon", actual_segment.name); - EXPECT_EQ(0x79f484f77009e511ULL, actual_segment.vmaddr); - EXPECT_EQ(0x8d92397ce6248abaULL, actual_segment.vmsize); - EXPECT_EQ(0x42b45da5U, actual_segment.maxprot); - EXPECT_EQ(0x8bdbc319U, actual_segment.initprot); - EXPECT_EQ(0xb2335220U, actual_segment.flags); - EXPECT_EQ(0U, actual_segment.nsects); - EXPECT_EQ(0U, actual_segment.section_list.Size()); - EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size()); -} - -TEST_F(LoadCommand, SegmentLE64) { - WithConfiguration config(kLittleEndian, 64); - LoadedSection segment; - segment.address() = 0x50c0501dc5922d35ULL; - segment.Append(42, '*'); // segment contents - SegmentLoadCommand segment_command; - segment_command - .Header("sixteenprecisely", segment, - 0x917c339d, 0xdbc446fa, 0xb650b563); - segment_command.vmsize() = 0x84ae73e7c75469bfULL; - LoadCommands load_commands; - load_commands.Place(&segment_command); - MachOFile file; - file - .Header(&load_commands) - .Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_CALL(load_command_handler, SegmentCommand(_)) - .WillOnce(DoAll(SaveArg<0>(&actual_segment), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(true, actual_segment.bits_64); - EXPECT_EQ("sixteenprecisely", actual_segment.name); - EXPECT_EQ(0x50c0501dc5922d35ULL, actual_segment.vmaddr); - EXPECT_EQ(0x84ae73e7c75469bfULL, actual_segment.vmsize); - EXPECT_EQ(0x917c339dU, actual_segment.maxprot); - EXPECT_EQ(0xdbc446faU, actual_segment.initprot); - EXPECT_EQ(0xb650b563U, actual_segment.flags); - EXPECT_EQ(0U, actual_segment.nsects); - EXPECT_EQ(0U, actual_segment.section_list.Size()); - EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size()); -} - -TEST_F(LoadCommand, SegmentCommandTruncated) { - WithConfiguration config(kBigEndian, 32); - LoadedSection segment_contents; - segment_contents.Append(20, '*'); // lah di dah - SizedSection command; - command - .D32(LC_SEGMENT) // command type - .D32(command.final_size()) // command size - .AppendCString("too-short", 16) // segment name - .D32(0x9c759211) // vmaddr - .D32(segment_contents.final_size()) // vmsize - .D32(segment_contents.start()) // file offset - .D32(segment_contents.final_size()) // file size - .D32(0x56f28446) // max protection - .D32(0xe7910dcb) // initial protection - .D32(0) // no sections - .Append(3, 0); // flags (one byte short!) - LoadCommands load_commands; - load_commands.Place(&command); - MachOFile file; - file - .Header(&load_commands) - .Place(&segment_contents); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, LoadCommandTooShort(0, LC_SEGMENT)) - .WillOnce(Return()); - - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, SegmentBadContentOffset) { - WithConfiguration config(kLittleEndian, 32); - // Instead of letting a Place call set the segment's file offset and size, - // set them ourselves, to check that the parser catches invalid offsets - // instead of handing us bogus pointers. - LoadedSection segment; - segment.address() = 0x4db5489c; - segment.start() = 0x7e189e76; // beyond end of file - segment.final_size() = 0x98b9c3ab; - SegmentLoadCommand segment_command; - segment_command - .Header("notmerelyfifteen", segment, 0xcbab25ee, 0x359a20db, 0x68a3933f); - LoadCommands load_commands; - load_commands.Place(&segment_command); - MachOFile file; - file.Header(&load_commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, MisplacedSegmentData("notmerelyfifteen")) - .WillOnce(Return()); - - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(LoadCommand, ThreeLoadCommands) { - WithConfiguration config(kBigEndian, 32); - LoadedSection seg1, seg2, seg3; - SegmentLoadCommand cmd1, cmd2, cmd3; - - seg1.Append(128, '@'); - seg1.address() = 0xa7f61ef6; - cmd1.Header("head", seg1, 0x88bf1cc7, 0x889a26a4, 0xe9b80d87); - // Include some dummy data at the end of the load command. Since we - // didn't claim to have any sections, the reader should ignore this. But - // making sure the commands have different lengths ensures that we're - // using the right command's length to advance the LoadCommandIterator. - cmd1.Append(128, '!'); - - seg2.Append(42, '*'); - seg2.address() = 0xc70fc909; - cmd2.Header("thorax", seg2, 0xde7327f4, 0xfdaf771d, 0x65e74b30); - // More dummy data at the end of the load command. - cmd2.Append(32, '^'); - - seg3.Append(42, '%'); - seg3.address() = 0x46b3ab05; - cmd3.Header("abdomen", seg3, 0x7098b70d, 0x8d8d7728, 0x5131419b); - // More dummy data at the end of the load command. - cmd3.Append(64, '&'); - - LoadCommands load_commands; - load_commands.Place(&cmd1).Place(&cmd2).Place(&cmd3); - - MachOFile file; - file.Header(&load_commands).Place(&seg1).Place(&seg2).Place(&seg3); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - { - InSequence s; - EXPECT_CALL(load_command_handler, - SegmentCommand(Field(&Segment::name, "head"))) - .WillOnce(Return(true)); - EXPECT_CALL(load_command_handler, - SegmentCommand(Field(&Segment::name, "thorax"))) - .WillOnce(Return(true)); - EXPECT_CALL(load_command_handler, - SegmentCommand(Field(&Segment::name, "abdomen"))) - .WillOnce(Return(true)); - } - - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); -} - -static inline Matcher<const Section &> MatchSection( - Matcher<bool> bits_64, - Matcher<const string &> section_name, - Matcher<const string &> segment_name, - Matcher<uint64_t> address, - Matcher<uint32_t> alignment, - Matcher<uint32_t> flags, - Matcher<const ByteBuffer &> contents) { - return AllOf(AllOf(Field(&Section::bits_64, bits_64), - Field(&Section::section_name, section_name), - Field(&Section::segment_name, segment_name), - Field(&Section::address, address)), - AllOf(Field(&Section::align, alignment), - Field(&Section::flags, flags), - Field(&Section::contents, contents))); -} - -static inline Matcher<const Section &> MatchSection( - Matcher<bool> bits_64, - Matcher<const string &> section_name, - Matcher<const string &> segment_name, - Matcher<uint64_t> address) { - return AllOf(Field(&Section::bits_64, bits_64), - Field(&Section::section_name, section_name), - Field(&Section::segment_name, segment_name), - Field(&Section::address, address)); -} - -TEST_F(LoadCommand, OneSegmentTwoSections) { - WithConfiguration config(kBigEndian, 64); - - // Create some sections with some data. - LoadedSection section1, section2; - section1.Append("buddha's hand"); - section2.Append("kumquat"); - - // Create a segment to hold them. - LoadedSection segment; - segment.address() = 0xe1d0eeec; - segment.Place(§ion2).Place(§ion1); - - SegmentLoadCommand segment_command; - segment_command - .Header("head", segment, 0x92c9568c, 0xa89f2627, 0x4dc7a1e2) - .AppendSectionEntry("mandarin", "kishu", 12, 0x8cd4604bU, section1) - .AppendSectionEntry("bergamot", "cara cara", 12, 0x98746efaU, section2); - - LoadCommands commands; - commands.Place(&segment_command); - - MachOFile file; - file.Header(&commands).Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_CALL(load_command_handler, SegmentCommand(_)) - .WillOnce(DoAll(SaveArg<0>(&actual_segment), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - { - InSequence s; - ByteBuffer contents1; - contents1.start = file_bytes + section1.start().Value(); - contents1.end = contents1.start + section1.final_size().Value(); - EXPECT_EQ("buddha's hand", - string(reinterpret_cast<const char *>(contents1.start), - contents1.Size())); - EXPECT_CALL(section_handler, - HandleSection(MatchSection(true, "mandarin", "kishu", - section1.address().Value(), 12, - 0x8cd4604bU, contents1))) - .WillOnce(Return(true)); - - ByteBuffer contents2; - contents2.start = file_bytes + section2.start().Value(); - contents2.end = contents2.start + section2.final_size().Value(); - EXPECT_EQ("kumquat", - string(reinterpret_cast<const char *>(contents2.start), - contents2.Size())); - EXPECT_CALL(section_handler, - HandleSection(MatchSection(true, "bergamot", "cara cara", - section2.address().Value(), 12, - 0x98746efaU, contents2))) - .WillOnce(Return(true)); - } - - EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, §ion_handler)); -} - -TEST_F(LoadCommand, MisplacedSectionBefore) { - WithConfiguration config(kLittleEndian, 64); - - // The segment. - LoadedSection segment; - segment.address() = 0x696d83cc; - segment.Append(10, '0'); - - // The contents of the following sections don't matter, because - // we're not really going to Place them in segment; we're just going - // to set all their labels by hand to get the (impossible) - // configurations we want. - - // A section whose starting offset is before that of its section. - LoadedSection before; - before.Append(10, '1'); - before.start() = segment.start() - 1; - before.address() = segment.address() - 1; - before.final_size() = before.Size(); - - SegmentLoadCommand command; - command - .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057) - .AppendSectionEntry("before", "segment", 0, 0x686c6921, before); - - LoadCommands commands; - commands.Place(&command); - - MachOFile file; - file.Header(&commands).Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_TRUE(reader.FindSegment("segment", &actual_segment)); - - EXPECT_CALL(reporter, MisplacedSectionData("before", "segment")) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, §ion_handler)); -} - -TEST_F(LoadCommand, MisplacedSectionAfter) { - WithConfiguration config(kLittleEndian, 64); - - // The segment. - LoadedSection segment; - segment.address() = 0x696d83cc; - segment.Append(10, '0'); - - // The contents of the following sections don't matter, because - // we're not really going to Place them in segment; we're just going - // to set all their labels by hand to get the (impossible) - // configurations we want. - - // A section whose starting offset is after the end of its section. - LoadedSection after; - after.Append(10, '2'); - after.start() = segment.start() + 11; - after.address() = segment.address() + 11; - after.final_size() = after.Size(); - - SegmentLoadCommand command; - command - .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057) - .AppendSectionEntry("after", "segment", 0, 0x2ee50124, after); - - LoadCommands commands; - commands.Place(&command); - - MachOFile file; - file.Header(&commands).Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_TRUE(reader.FindSegment("segment", &actual_segment)); - - EXPECT_CALL(reporter, MisplacedSectionData("after", "segment")) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, §ion_handler)); -} - -TEST_F(LoadCommand, MisplacedSectionTooBig) { - WithConfiguration config(kLittleEndian, 64); - - // The segment. - LoadedSection segment; - segment.address() = 0x696d83cc; - segment.Append(10, '0'); - - // The contents of the following sections don't matter, because - // we're not really going to Place them in segment; we're just going - // to set all their labels by hand to get the (impossible) - // configurations we want. - - // A section that extends beyond the end of its section. - LoadedSection too_big; - too_big.Append(10, '3'); - too_big.start() = segment.start() + 1; - too_big.address() = segment.address() + 1; - too_big.final_size() = too_big.Size(); - - SegmentLoadCommand command; - command - .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057) - .AppendSectionEntry("too big", "segment", 0, 0x8b53ae5c, too_big); - - LoadCommands commands; - commands.Place(&command); - - MachOFile file; - file.Header(&commands).Place(&segment); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_TRUE(reader.FindSegment("segment", &actual_segment)); - - EXPECT_CALL(reporter, MisplacedSectionData("too big", "segment")) - .WillOnce(Return()); - EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, §ion_handler)); -} - - -// The segments in a .dSYM bundle's Mach-O file have their file offset -// and size set to zero, but the sections don't. The reader shouldn't -// report an error in this case. -TEST_F(LoadCommand, ZappedSegment) { - WithConfiguration config(kBigEndian, 32); - - // The segment. - LoadedSection segment; - segment.address() = 0x696d83cc; - segment.start() = 0; - segment.final_size() = 0; - - // The section. - LoadedSection section; - section.address() = segment.address(); - section.start() = 0; - section.final_size() = 1000; // extends beyond its segment - - SegmentLoadCommand command; - command - .Header("zapped", segment, 0x0861a5cb, 0x68ccff67, 0x0b66255c) - .AppendSectionEntry("twitching", "zapped", 0, 0x93b3bd42, section); - - LoadCommands commands; - commands.Place(&command); - - MachOFile file; - file.Header(&commands); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - EXPECT_TRUE(reader.FindSegment("zapped", &actual_segment)); - - ByteBuffer zapped_extent(NULL, 0); - EXPECT_CALL(section_handler, - HandleSection(MatchSection(false, "twitching", "zapped", - 0x696d83cc, 0, 0x93b3bd42, - zapped_extent))) - .WillOnce(Return(true)); - - EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, §ion_handler)); -} - -TEST_F(LoadCommand, MapSegmentSections) { - WithConfiguration config(kLittleEndian, 32); - - // Create some sections with some data. - LoadedSection section1, section2, section3, section4; - section1.Append("buddha's hand"); - section2.start() = 0; // Section 2 is an S_ZEROFILL section. - section2.final_size() = 0; - section3.Append("shasta gold"); - section4.Append("satsuma"); - - // Create two segments to hold them. - LoadedSection segment1, segment2; - segment1.address() = 0x13e6c8a9; - segment1.Place(§ion3).Place(§ion1); - segment2.set_word_size(64); - segment2.address() = 0x04d462e2; - segment2.Place(§ion4); - section2.address() = segment2.address() + segment2.Size(); - - SegmentLoadCommand segment_command1, segment_command2; - segment_command1 - .Header("head", segment1, 0x67d955a6, 0x7a61c13e, 0xe3e50c64) - .AppendSectionEntry("mandarin", "head", 12, 0x5bb565d7, section1) - .AppendSectionEntry("bergamot", "head", 12, 0x8620de73, section3); - segment_command2.set_word_size(64); - segment_command2 - .Header("thorax", segment2, 0x7aab2419, 0xe908007f, 0x17961d33) - .AppendSectionEntry("sixteenprecisely", "thorax", - 12, S_ZEROFILL, section2) - .AppendSectionEntry("cara cara", "thorax", 12, 0xb6c5dd8a, section4); - - LoadCommands commands; - commands.Place(&segment_command1).Place(&segment_command2); - - MachOFile file; - file.Header(&commands).Place(&segment1).Place(&segment2); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment segment; - SectionMap section_map; - - EXPECT_FALSE(reader.FindSegment("smoot", &segment)); - - ASSERT_TRUE(reader.FindSegment("thorax", &segment)); - ASSERT_TRUE(reader.MapSegmentSections(segment, §ion_map)); - - EXPECT_FALSE(section_map.find("sixteenpreciselyandthensome") - != section_map.end()); - EXPECT_FALSE(section_map.find("mandarin") != section_map.end()); - ASSERT_TRUE(section_map.find("cara cara") != section_map.end()); - EXPECT_THAT(section_map["cara cara"], - MatchSection(true, "cara cara", "thorax", 0x04d462e2)); - ASSERT_TRUE(section_map.find("sixteenprecisely") - != section_map.end()); - ByteBuffer sixteenprecisely_contents(NULL, 0); - EXPECT_THAT(section_map["sixteenprecisely"], - MatchSection(true, "sixteenprecisely", "thorax", - 0x04d462e2 + 7, 12, S_ZEROFILL, - sixteenprecisely_contents)); - - ASSERT_TRUE(reader.FindSegment("head", &segment)); - ASSERT_TRUE(reader.MapSegmentSections(segment, §ion_map)); - - ASSERT_TRUE(section_map.find("mandarin") != section_map.end()); - EXPECT_THAT(section_map["mandarin"], - MatchSection(false, "mandarin", "head", 0x13e6c8a9 + 11)); - ASSERT_TRUE(section_map.find("bergamot") != section_map.end()); - EXPECT_THAT(section_map["bergamot"], - MatchSection(false, "bergamot", "head", 0x13e6c8a9)); -} - -TEST_F(LoadCommand, FindSegment) { - WithConfiguration config(kBigEndian, 32); - - LoadedSection segment1, segment2, segment3; - segment1.address() = 0xb8ae5752; - segment1.Append("Some contents!"); - segment2.address() = 0xd6b0ce83; - segment2.Append("Different stuff."); - segment3.address() = 0x7374fd2a; - segment3.Append("Further materials."); - - SegmentLoadCommand cmd1, cmd2, cmd3; - cmd1.Header("first", segment1, 0xfadb6932, 0x175bf529, 0x0de790ad); - cmd2.Header("second", segment2, 0xeef716e0, 0xe103a9d7, 0x7d38a8ef); - cmd3.Header("third", segment3, 0xe172b39e, 0x86012f07, 0x080ac94d); - - LoadCommands commands; - commands.Place(&cmd1).Place(&cmd2).Place(&cmd3); - - MachOFile file; - file.Header(&commands).Place(&segment1).Place(&segment2).Place(&segment3); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - Segment actual_segment; - - EXPECT_FALSE(reader.FindSegment("murphy", &actual_segment)); - - EXPECT_TRUE(reader.FindSegment("second", &actual_segment)); - EXPECT_EQ(0xd6b0ce83, actual_segment.vmaddr); -} - - -// Symtab tests. - -// A StringAssembler is a class for generating .stabstr sections to present -// as input to the STABS parser. -class StringAssembler: public SizedSection { - public: - // Add the string S to this StringAssembler, and return the string's - // offset within this compilation unit's strings. - size_t Add(const string &s) { - size_t offset = Size(); - AppendCString(s); - return offset; - } -}; - -// A SymbolAssembler is a class for generating .stab sections to present as -// test input for the STABS parser. -class SymbolAssembler: public SizedSection { - public: - // Create a SymbolAssembler that uses StringAssembler for its strings. - explicit SymbolAssembler(StringAssembler *string_assembler) - : string_assembler_(string_assembler), - entry_count_(0) { } - - // Append a STAB entry to the end of this section with the given - // characteristics. NAME is the offset of this entry's name string within - // its compilation unit's portion of the .stabstr section; this can be a - // value generated by a StringAssembler. Return a reference to this - // SymbolAssembler. - SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor, - Label value, Label name) { - D32(name); - D8(type); - D8(other); - D16(descriptor); - Append(endianness(), word_size_ / 8, value); - entry_count_++; - return *this; - } - - // As above, but automatically add NAME to our StringAssembler. - SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor, - Label value, const string &name) { - return Symbol(type, other, descriptor, value, string_assembler_->Add(name)); - } - - private: - // The strings for our STABS entries. - StringAssembler *string_assembler_; - - // The number of entries in this compilation unit so far. - size_t entry_count_; -}; - -class Symtab: public ReaderFixture, public Test { }; - -TEST_F(Symtab, Symtab32) { - WithConfiguration config(kLittleEndian, 32); - - StringAssembler strings; - SymbolAssembler symbols(&strings); - symbols - .Symbol(0x52, 0x7c, 0x3470, 0x9bb02e7c, "hrududu") - .Symbol(0x50, 0x90, 0x7520, 0x1122525d, "Frith"); - - SizedSection symtab_command; - symtab_command - .D32(LC_SYMTAB) // command - .D32(symtab_command.final_size()) // size - .D32(symbols.start()) // file offset of symbols - .D32(2) // symbol count - .D32(strings.start()) // file offset of strings - .D32(strings.final_size()); // strings size - - LoadCommands load_commands; - load_commands.Place(&symtab_command); - - MachOFile file; - file.Header(&load_commands).Place(&symbols).Place(&strings); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - ByteBuffer symbols_found, strings_found; - EXPECT_CALL(load_command_handler, SymtabCommand(_, _)) - .WillOnce(DoAll(SaveArg<0>(&symbols_found), - SaveArg<1>(&strings_found), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(24U, symbols_found.Size()); - EXPECT_EQ(14U, strings_found.Size()); -} - -TEST_F(Symtab, Symtab64) { - WithConfiguration config(kBigEndian, 64); - - StringAssembler strings; - SymbolAssembler symbols(&strings); - symbols - .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo") - .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar"); - - SizedSection symtab_command; - symtab_command - .D32(LC_SYMTAB) // command - .D32(symtab_command.final_size()) // size - .D32(symbols.start()) // file offset of symbols - .D32(2) // symbol count - .D32(strings.start()) // file offset of strings - .D32(strings.final_size()); // strings size - - LoadCommands load_commands; - load_commands.Place(&symtab_command); - - MachOFile file; - file.Header(&load_commands).Place(&symbols).Place(&strings); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - ByteBuffer symbols_found, strings_found; - EXPECT_CALL(load_command_handler, SymtabCommand(_, _)) - .WillOnce(DoAll(SaveArg<0>(&symbols_found), - SaveArg<1>(&strings_found), - Return(true))); - EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler)); - - EXPECT_EQ(32U, symbols_found.Size()); - EXPECT_EQ(8U, strings_found.Size()); -} - -TEST_F(Symtab, SymtabMisplacedSymbols) { - WithConfiguration config(kBigEndian, 32); - - StringAssembler strings; - SymbolAssembler symbols(&strings); - symbols - .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo") - .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar"); - - SizedSection symtab_command; - symtab_command - .D32(LC_SYMTAB) // command - .D32(symtab_command.final_size()) // size - .D32(symbols.start()) // file offset of symbols - .D32(3) // symbol count (too many) - .D32(strings.start()) // file offset of strings - .D32(strings.final_size()); // strings size - - LoadCommands load_commands; - load_commands.Place(&symtab_command); - - MachOFile file; - // Put symbols at end, so the excessive length will be noticed. - file.Header(&load_commands).Place(&strings).Place(&symbols); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1); - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - -TEST_F(Symtab, SymtabMisplacedStrings) { - WithConfiguration config(kLittleEndian, 32); - - StringAssembler strings; - SymbolAssembler symbols(&strings); - symbols - .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo") - .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar"); - - SizedSection symtab_command; - symtab_command - .D32(LC_SYMTAB) // command - .D32(symtab_command.final_size()) // size - .D32(symbols.start()) // file offset of symbols - .D32(2) // symbol count - .D32(strings.start()) // file offset of strings - .D32(strings.final_size() + 1); // strings size (too long) - - LoadCommands load_commands; - load_commands.Place(&symtab_command); - - MachOFile file; - // Put strings at end, so the excessive length will be noticed. - file.Header(&load_commands).Place(&symbols).Place(&strings); - - ReadFile(&file, true, CPU_TYPE_ANY, 0); - - EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1); - EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler)); -} - diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc deleted file mode 100644 index f56fe768c1..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_utilties.cc: Utilities for dealing with mach-o files -// -// Author: Dave Camp - -#include "common/mac/byteswap.h" -#include "common/mac/macho_utilities.h" - -#include <mach-o/fat.h> -#include <mach-o/loader.h> - -void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc) { - uc->cmd = ByteSwap(uc->cmd); - uc->cmdsize = ByteSwap(uc->cmdsize); -} - -void breakpad_swap_load_command(struct load_command *lc) { - lc->cmd = ByteSwap(lc->cmd); - lc->cmdsize = ByteSwap(lc->cmdsize); -} - -void breakpad_swap_dylib_command(struct dylib_command *dc) { - dc->cmd = ByteSwap(dc->cmd); - dc->cmdsize = ByteSwap(dc->cmdsize); - - dc->dylib.name.offset = ByteSwap(dc->dylib.name.offset); - dc->dylib.timestamp = ByteSwap(dc->dylib.timestamp); - dc->dylib.current_version = ByteSwap(dc->dylib.current_version); - dc->dylib.compatibility_version = ByteSwap(dc->dylib.compatibility_version); -} - -void breakpad_swap_segment_command(struct segment_command *sc) { - sc->cmd = ByteSwap(sc->cmd); - sc->cmdsize = ByteSwap(sc->cmdsize); - - sc->vmaddr = ByteSwap(sc->vmaddr); - sc->vmsize = ByteSwap(sc->vmsize); - sc->fileoff = ByteSwap(sc->fileoff); - sc->filesize = ByteSwap(sc->filesize); - sc->maxprot = ByteSwap(sc->maxprot); - sc->initprot = ByteSwap(sc->initprot); - sc->nsects = ByteSwap(sc->nsects); - sc->flags = ByteSwap(sc->flags); -} - -void breakpad_swap_segment_command_64(struct segment_command_64 *sg) { - sg->cmd = ByteSwap(sg->cmd); - sg->cmdsize = ByteSwap(sg->cmdsize); - - sg->vmaddr = ByteSwap(sg->vmaddr); - sg->vmsize = ByteSwap(sg->vmsize); - sg->fileoff = ByteSwap(sg->fileoff); - sg->filesize = ByteSwap(sg->filesize); - - sg->maxprot = ByteSwap(sg->maxprot); - sg->initprot = ByteSwap(sg->initprot); - sg->nsects = ByteSwap(sg->nsects); - sg->flags = ByteSwap(sg->flags); -} - -void breakpad_swap_fat_header(struct fat_header *fh) { - fh->magic = ByteSwap(fh->magic); - fh->nfat_arch = ByteSwap(fh->nfat_arch); -} - -void breakpad_swap_fat_arch(struct fat_arch *fa, uint32_t narchs) { - for (uint32_t i = 0; i < narchs; ++i) { - fa[i].cputype = ByteSwap(fa[i].cputype); - fa[i].cpusubtype = ByteSwap(fa[i].cpusubtype); - fa[i].offset = ByteSwap(fa[i].offset); - fa[i].size = ByteSwap(fa[i].size); - fa[i].align = ByteSwap(fa[i].align); - } -} - -void breakpad_swap_mach_header(struct mach_header *mh) { - mh->magic = ByteSwap(mh->magic); - mh->cputype = ByteSwap(mh->cputype); - mh->cpusubtype = ByteSwap(mh->cpusubtype); - mh->filetype = ByteSwap(mh->filetype); - mh->ncmds = ByteSwap(mh->ncmds); - mh->sizeofcmds = ByteSwap(mh->sizeofcmds); - mh->flags = ByteSwap(mh->flags); -} - -void breakpad_swap_mach_header_64(struct mach_header_64 *mh) { - mh->magic = ByteSwap(mh->magic); - mh->cputype = ByteSwap(mh->cputype); - mh->cpusubtype = ByteSwap(mh->cpusubtype); - mh->filetype = ByteSwap(mh->filetype); - mh->ncmds = ByteSwap(mh->ncmds); - mh->sizeofcmds = ByteSwap(mh->sizeofcmds); - mh->flags = ByteSwap(mh->flags); - mh->reserved = ByteSwap(mh->reserved); -} - -void breakpad_swap_section(struct section *s, - uint32_t nsects) { - for (uint32_t i = 0; i < nsects; i++) { - s[i].addr = ByteSwap(s[i].addr); - s[i].size = ByteSwap(s[i].size); - - s[i].offset = ByteSwap(s[i].offset); - s[i].align = ByteSwap(s[i].align); - s[i].reloff = ByteSwap(s[i].reloff); - s[i].nreloc = ByteSwap(s[i].nreloc); - s[i].flags = ByteSwap(s[i].flags); - s[i].reserved1 = ByteSwap(s[i].reserved1); - s[i].reserved2 = ByteSwap(s[i].reserved2); - } -} - -void breakpad_swap_section_64(struct section_64 *s, - uint32_t nsects) { - for (uint32_t i = 0; i < nsects; i++) { - s[i].addr = ByteSwap(s[i].addr); - s[i].size = ByteSwap(s[i].size); - - s[i].offset = ByteSwap(s[i].offset); - s[i].align = ByteSwap(s[i].align); - s[i].reloff = ByteSwap(s[i].reloff); - s[i].nreloc = ByteSwap(s[i].nreloc); - s[i].flags = ByteSwap(s[i].flags); - s[i].reserved1 = ByteSwap(s[i].reserved1); - s[i].reserved2 = ByteSwap(s[i].reserved2); - } -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h deleted file mode 100644 index 00563a77c8..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_utilities.h: Utilities for dealing with mach-o files -// -// Author: Dave Camp - -#ifndef COMMON_MAC_MACHO_UTILITIES_H__ -#define COMMON_MAC_MACHO_UTILITIES_H__ - -#include <mach-o/loader.h> -#include <mach/thread_status.h> - -/* Some #defines and structs that aren't defined in older SDKs */ -#ifndef CPU_ARCH_ABI64 -# define CPU_ARCH_ABI64 0x01000000 -#endif - -#ifndef CPU_TYPE_X86 -# define CPU_TYPE_X86 CPU_TYPE_I386 -#endif - -#ifndef CPU_TYPE_POWERPC64 -# define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) -#endif - -#ifndef LC_UUID -# define LC_UUID 0x1b /* the uuid */ -#endif - -// The uuid_command struct/swap routines were added during the 10.4 series. -// Their presence isn't guaranteed. -struct breakpad_uuid_command { - uint32_t cmd; /* LC_UUID */ - uint32_t cmdsize; /* sizeof(struct uuid_command) */ - uint8_t uuid[16]; /* the 128-bit uuid */ -}; - -void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc); - -void breakpad_swap_load_command(struct load_command *lc); - -void breakpad_swap_dylib_command(struct dylib_command *dc); - -// Older SDKs defines thread_state_data_t as an int[] instead -// of the natural_t[] it should be. -typedef natural_t breakpad_thread_state_data_t[THREAD_STATE_MAX]; - -void breakpad_swap_segment_command(struct segment_command *sc); - -// The 64-bit swap routines were added during the 10.4 series, their -// presence isn't guaranteed. -void breakpad_swap_segment_command_64(struct segment_command_64 *sg); - -void breakpad_swap_fat_header(struct fat_header *fh); - -void breakpad_swap_fat_arch(struct fat_arch *fa, uint32_t narchs); - -void breakpad_swap_mach_header(struct mach_header *mh); - -void breakpad_swap_mach_header_64(struct mach_header_64 *mh); - -void breakpad_swap_section(struct section *s, - uint32_t nsects); - -void breakpad_swap_section_64(struct section_64 *s, - uint32_t nsects); - -#endif diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc deleted file mode 100644 index 1acd86656b..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_walker.cc: Iterate over the load commands in a mach-o file -// -// See macho_walker.h for documentation -// -// Author: Dan Waylonis - -#include <assert.h> -#include <fcntl.h> -#include <mach-o/arch.h> -#include <mach-o/fat.h> -#include <mach-o/loader.h> -#include <string.h> -#include <unistd.h> - -#include "common/mac/byteswap.h" -#include "common/mac/macho_walker.h" -#include "common/mac/macho_utilities.h" - -namespace MacFileUtilities { - -MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback, - void *context) - : file_(-1), - memory_(NULL), - memory_size_(0), - callback_(callback), - callback_context_(context), - current_header_(NULL), - current_header_size_(0), - current_header_offset_(0) { - file_ = open(path, O_RDONLY); -} - -MachoWalker::MachoWalker(void *memory, size_t size, - LoadCommandCallback callback, void *context) - : file_(-1), - memory_(memory), - memory_size_(size), - callback_(callback), - callback_context_(context), - current_header_(NULL), - current_header_size_(0), - current_header_offset_(0) { -} - -MachoWalker::~MachoWalker() { - if (file_ != -1) - close(file_); -} - -bool MachoWalker::WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { - cpu_type_t valid_cpu_type = cpu_type; - cpu_subtype_t valid_cpu_subtype = cpu_subtype; - // if |cpu_type| is 0, use the native cpu type. - if (cpu_type == 0) { - const NXArchInfo *arch = NXGetLocalArchInfo(); - assert(arch); - valid_cpu_type = arch->cputype; - valid_cpu_subtype = CPU_SUBTYPE_MULTIPLE; - } - off_t offset; - if (FindHeader(valid_cpu_type, valid_cpu_subtype, offset)) { - if (cpu_type & CPU_ARCH_ABI64) - return WalkHeader64AtOffset(offset); - - return WalkHeaderAtOffset(offset); - } - - return false; -} - -bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) { - if (memory_) { - if (offset < 0) - return false; - bool result = true; - if (offset + size > memory_size_) { - if (static_cast<size_t>(offset) >= memory_size_) - return false; - size = memory_size_ - static_cast<size_t>(offset); - result = false; - } - memcpy(buffer, static_cast<char *>(memory_) + offset, size); - return result; - } else { - return pread(file_, buffer, size, offset) == (ssize_t)size; - } -} - -bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) { - if (current_header_) { - memcpy(header, current_header_, sizeof(mach_header_64)); - *offset = current_header_offset_; - return true; - } - - return false; -} - -bool MachoWalker::FindHeader(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - off_t &offset) { - // Read the magic bytes that's common amongst all mach-o files - uint32_t magic; - if (!ReadBytes(&magic, sizeof(magic), 0)) - return false; - - offset = sizeof(magic); - - // Figure out what type of file we've got - bool is_fat = false; - if (magic == FAT_MAGIC || magic == FAT_CIGAM) { - is_fat = true; - } - else if (magic != MH_MAGIC && magic != MH_CIGAM && magic != MH_MAGIC_64 && - magic != MH_CIGAM_64) { - return false; - } - - if (!is_fat) { - // If we don't have a fat header, check if the cpu type matches the single - // header - struct mach_header header; - if (!ReadBytes(&header, sizeof(header), 0)) - return false; - - if (magic == MH_CIGAM || magic == MH_CIGAM_64) - breakpad_swap_mach_header(&header); - - if (cpu_type != header.cputype || - (cpu_subtype != CPU_SUBTYPE_MULTIPLE && - cpu_subtype != header.cpusubtype)) { - return false; - } - - offset = 0; - return true; - } else { - // Read the fat header and find an appropriate architecture - offset = 0; - struct fat_header fat; - if (!ReadBytes(&fat, sizeof(fat), offset)) - return false; - - if (NXHostByteOrder() != NX_BigEndian) - breakpad_swap_fat_header(&fat); - - offset += sizeof(fat); - - // Search each architecture for the desired one - struct fat_arch arch; - for (uint32_t i = 0; i < fat.nfat_arch; ++i) { - if (!ReadBytes(&arch, sizeof(arch), offset)) - return false; - - if (NXHostByteOrder() != NX_BigEndian) - breakpad_swap_fat_arch(&arch, 1); - - if (arch.cputype == cpu_type && - (cpu_subtype == CPU_SUBTYPE_MULTIPLE || - arch.cpusubtype == cpu_subtype)) { - offset = arch.offset; - return true; - } - - offset += sizeof(arch); - } - } - - return false; -} - -bool MachoWalker::WalkHeaderAtOffset(off_t offset) { - struct mach_header header; - if (!ReadBytes(&header, sizeof(header), offset)) - return false; - - bool swap = (header.magic == MH_CIGAM); - if (swap) - breakpad_swap_mach_header(&header); - - // Copy the data into the mach_header_64 structure. Since the 32-bit and - // 64-bit only differ in the last field (reserved), this is safe to do. - struct mach_header_64 header64; - memcpy((void *)&header64, (const void *)&header, sizeof(header)); - header64.reserved = 0; - - current_header_ = &header64; - current_header_size_ = sizeof(header); // 32-bit, not 64-bit - current_header_offset_ = offset; - offset += current_header_size_; - bool result = WalkHeaderCore(offset, header.ncmds, swap); - current_header_ = NULL; - current_header_size_ = 0; - current_header_offset_ = 0; - return result; -} - -bool MachoWalker::WalkHeader64AtOffset(off_t offset) { - struct mach_header_64 header; - if (!ReadBytes(&header, sizeof(header), offset)) - return false; - - bool swap = (header.magic == MH_CIGAM_64); - if (swap) - breakpad_swap_mach_header_64(&header); - - current_header_ = &header; - current_header_size_ = sizeof(header); - current_header_offset_ = offset; - offset += current_header_size_; - bool result = WalkHeaderCore(offset, header.ncmds, swap); - current_header_ = NULL; - current_header_size_ = 0; - current_header_offset_ = 0; - return result; -} - -bool MachoWalker::WalkHeaderCore(off_t offset, uint32_t number_of_commands, - bool swap) { - for (uint32_t i = 0; i < number_of_commands; ++i) { - struct load_command cmd; - if (!ReadBytes(&cmd, sizeof(cmd), offset)) - return false; - - if (swap) - breakpad_swap_load_command(&cmd); - - // Call the user callback - if (callback_ && !callback_(this, &cmd, offset, swap, callback_context_)) - break; - - offset += cmd.cmdsize; - } - - return true; -} - -} // namespace MacFileUtilities diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h deleted file mode 100644 index dd535814a1..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// macho_walker.h: Iterate over the load commands in a mach-o file -// -// Author: Dan Waylonis - -#ifndef COMMON_MAC_MACHO_WALKER_H__ -#define COMMON_MAC_MACHO_WALKER_H__ - -#include <mach/machine.h> -#include <mach-o/loader.h> -#include <sys/types.h> - -namespace MacFileUtilities { - -class MachoWalker { - public: - // A callback function executed when a new load command is read. If no - // further processing of load commands is desired, return false. Otherwise, - // return true. - // |cmd| is the current command, and |offset| is the location relative to the - // beginning of the file (not header) where the command was read. If |swap| - // is set, then any command data (other than the returned load_command) should - // be swapped when read - typedef bool (*LoadCommandCallback)(MachoWalker *walker, load_command *cmd, - off_t offset, bool swap, void *context); - - MachoWalker(const char *path, LoadCommandCallback callback, void *context); - MachoWalker(void *memory, size_t size, LoadCommandCallback callback, - void *context); - ~MachoWalker(); - - // Begin walking the header for |cpu_type| and |cpu_subtype|. If |cpu_type| - // is 0, then the native cpu type is used. Otherwise, accepted values are - // listed in /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or - // CPU_TYPE_POWERPC). If |cpu_subtype| is CPU_SUBTYPE_MULTIPLE, the match is - // only done on |cpu_type|. - // Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype| - // is not present in the file. - bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); - - // Read |size| bytes from the opened file at |offset| into |buffer| - bool ReadBytes(void *buffer, size_t size, off_t offset); - - // Return the current header and header offset - bool CurrentHeader(struct mach_header_64 *header, off_t *offset); - - private: - // Locate (if any) the header offset for |cpu_type| and return in |offset|. - // Return true if found, false otherwise. - bool FindHeader(cpu_type_t cpu_type, - cpu_subtype_t cpu_subtype, - off_t &offset); - - // Process an individual header starting at |offset| from the start of the - // file. Return true if successful, false otherwise. - bool WalkHeaderAtOffset(off_t offset); - bool WalkHeader64AtOffset(off_t offset); - - // Bottleneck for walking the load commands - bool WalkHeaderCore(off_t offset, uint32_t number_of_commands, bool swap); - - // File descriptor to the opened file - int file_; - - // Memory location to read from. - void *memory_; - - // Size of the memory segment we can read from. - size_t memory_size_; - - // User specified callback & context - LoadCommandCallback callback_; - void *callback_context_; - - // Current header, size, and offset. The mach_header_64 is used for both - // 32-bit and 64-bit headers because they only differ in their last field - // (reserved). By adding the |current_header_size_| and the - // |current_header_offset_|, you can determine the offset in the file just - // after the header. - struct mach_header_64 *current_header_; - unsigned long current_header_size_; - off_t current_header_offset_; - - private: - MachoWalker(const MachoWalker &); - MachoWalker &operator=(const MachoWalker &); -}; - -} // namespace MacFileUtilities - -#endif // COMMON_MAC_MACHO_WALKER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build b/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build deleted file mode 100644 index 6d6df28e21..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build +++ /dev/null @@ -1,52 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -UNIFIED_SOURCES += [ - 'arch_utilities.cc', - 'file_id.cc', - 'macho_id.cc', - 'macho_reader.cc', - 'macho_utilities.cc', - 'macho_walker.cc', -] - -if CONFIG['HOST_OS_ARCH'] != 'Darwin': - HOST_CXXFLAGS += [ - '-I%s/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/' % TOPSRCDIR, - ] - -# This is a little weird, but we're building a host and a target lib here. -# The host lib is used for dump_syms, and the target lib for the -# crash reporter client. Therefore, we don't need all the srcs in both. -if CONFIG['MOZ_CRASHREPORTER']: - HOST_SOURCES += UNIFIED_SOURCES - HOST_SOURCES += [ - 'dump_syms.cc', - ] - HOST_CXXFLAGS += [ - '-O2', - '-g', - '-stdlib=libc++', - ] - HostLibrary('host_breakpad_mac_common_s') - -SOURCES += [ - 'bootstrap_compat.cc', - 'HTTPMultipartUpload.m', - 'MachIPC.mm', - 'string_utilities.cc', -] - -Library('breakpad_mac_common_s') - -# We allow warnings for third-party code that can be updated from upstream. -ALLOW_COMPILER_WARNINGS = True - -FINAL_LIBRARY = 'xul' - -CMFLAGS += ['-std=c99'] - -include('/toolkit/crashreporter/crashreporter.mozbuild') diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h b/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h deleted file mode 100644 index d6d1bef971..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Inline implementation of ScopedTaskSuspend, which suspends a Mach -// task for the duration of its scope. - -#ifndef GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_ -#define GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_ - -#include <mach/mach.h> - -namespace google_breakpad { - -class ScopedTaskSuspend { - public: - explicit ScopedTaskSuspend(mach_port_t target) : target_(target) { - task_suspend(target_); - } - - ~ScopedTaskSuspend() { - task_resume(target_); - } - - private: - mach_port_t target_; -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc deleted file mode 100644 index 07c0f42680..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/scoped_ptr.h" -#include "common/mac/string_utilities.h" - -namespace MacStringUtils { - -using google_breakpad::scoped_array; - -std::string ConvertToString(CFStringRef str) { - CFIndex length = CFStringGetLength(str); - std::string result; - - if (!length) - return result; - - CFIndex maxUTF8Length = - CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); - scoped_array<UInt8> buffer(new UInt8[maxUTF8Length + 1]); - CFIndex actualUTF8Length; - CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingUTF8, 0, - false, buffer.get(), maxUTF8Length, &actualUTF8Length); - buffer[actualUTF8Length] = 0; - result.assign((const char *)buffer.get()); - - return result; -} - -unsigned int IntegerValueAtIndex(string &str, unsigned int idx) { - string digits("0123456789"), temp; - size_t start = 0; - size_t end; - size_t found = 0; - unsigned int result = 0; - - for (; found <= idx; ++found) { - end = str.find_first_not_of(digits, start); - - if (end == string::npos) - end = str.size(); - - temp = str.substr(start, end - start); - - if (found == idx) { - result = atoi(temp.c_str()); - } - - start = str.find_first_of(digits, end + 1); - - if (start == string::npos) - break; - } - - return result; -} - -} // namespace MacStringUtils diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h deleted file mode 100644 index 6d89c834e7..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// string_utilities.h: Utilities for strings for Mac platform - -#ifndef COMMON_MAC_STRING_UTILITIES_H__ -#define COMMON_MAC_STRING_UTILITIES_H__ - -#include <CoreFoundation/CoreFoundation.h> - -#include <string> - -namespace MacStringUtils { - -using std::string; - -// Convert a CoreFoundation string into a std::string -string ConvertToString(CFStringRef str); - -// Return the idx'th decimal integer in str, separated by non-decimal-digits -// E.g., str = 10.4.8, idx = 1 -> 4 -unsigned int IntegerValueAtIndex(string &str, unsigned int idx); - -} // namespace MacStringUtils - -#endif // COMMON_MAC_STRING_UTILITIES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h b/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h deleted file mode 100644 index 501c8652a1..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2015, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Erik Chen <erikchen@chromium.org> - -// super_fat_arch.h: A class to handle 64-bit object files. Has conversions to -// and from struct fat_arch. - -#ifndef BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_ -#define BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_ - -#include <limits> -#include <mach-o/fat.h> -#include <stdint.h> - -// Similar to struct fat_arch, except size-related parameters support -// 64-bits. -class SuperFatArch { - public: - uint32_t cputype; - uint32_t cpusubtype; - uint64_t offset; - uint64_t size; - uint64_t align; - - SuperFatArch() : - cputype(0), - cpusubtype(0), - offset(0), - size(0), - align(0) { - } - - explicit SuperFatArch(const struct fat_arch &arch) : - cputype(arch.cputype), - cpusubtype(arch.cpusubtype), - offset(arch.offset), - size(arch.size), - align(arch.align) { - } - - // Returns false if the conversion cannot be made. - // If the conversion succeeds, the result is placed in |output_arch|. - bool ConvertToFatArch(struct fat_arch* output_arch) const { - if (offset > std::numeric_limits<uint32_t>::max()) - return false; - if (size > std::numeric_limits<uint32_t>::max()) - return false; - if (align > std::numeric_limits<uint32_t>::max()) - return false; - struct fat_arch arch; - arch.cputype = cputype; - arch.cpusubtype = cpusubtype; - arch.offset = offset; - arch.size = size; - arch.align = align; - *output_arch = arch; - return true; - } -}; - -#endif // BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h deleted file mode 100644 index ce3d9022cd..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h +++ /dev/null @@ -1,1110 +0,0 @@ -// -// GTMSenTestCase.h -// -// Copyright 2007-2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -// Portions of this file fall under the following license, marked with -// SENTE_BEGIN - SENTE_END -// -// Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. -// -// Use of this source code is governed by the following license: -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// (1) Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// (2) Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Note: this license is equivalent to the FreeBSD license. -// -// This notice may not be removed from this file. - -// Some extra test case macros that would have been convenient for SenTestingKit -// to provide. I didn't stick GTM in front of the Macro names, so that they would -// be easy to remember. - -#import "GTMDefines.h" - -#if (!GTM_IPHONE_SDK) || (GTM_IPHONE_USE_SENTEST) -#import <SenTestingKit/SenTestingKit.h> -#else -#import <Foundation/Foundation.h> -#ifdef __cplusplus -extern "C" { -#endif - -#if defined __clang__ -// gcc and gcc-llvm do not allow you to use STAssert(blah, nil) with nil -// as a description if you have the NS_FORMAT_FUNCTION on. -// clang however will not compile without warnings if you don't have it. -NSString *STComposeString(NSString *, ...) NS_FORMAT_FUNCTION(1, 2); -#else -NSString *STComposeString(NSString *, ...); -#endif // __clang__ - -#ifdef __cplusplus -} -#endif - -#endif // !GTM_IPHONE_SDK || GTM_IPHONE_USE_SENTEST - -// Generates a failure when a1 != noErr -// Args: -// a1: should be either an OSErr or an OSStatus -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNoErr(a1, description, ...) \ -do { \ - @try { \ - OSStatus a1value = (a1); \ - if (a1value != noErr) { \ - NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", (long)a1value, #a1]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when a1 != a2 -// Args: -// a1: received value. Should be either an OSErr or an OSStatus -// a2: expected value. Should be either an OSErr or an OSStatus -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertErr(a1, a2, description, ...) \ -do { \ - @try { \ - OSStatus a1value = (a1); \ - OSStatus a2value = (a2); \ - if (a1value != a2value) { \ - NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, (long)a2value, (long)a1value, #a1]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - - -// Generates a failure when a1 is NULL -// Args: -// a1: should be a pointer (use STAssertNotNil for an object) -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNotNULL(a1, description, ...) \ -do { \ - @try { \ - __typeof__(a1) a1value = (a1); \ - if (a1value == (__typeof__(a1))NULL) { \ - NSString *_expression = [NSString stringWithFormat:@"((%s) != NULL)", #a1]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when a1 is not NULL -// Args: -// a1: should be a pointer (use STAssertNil for an object) -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNULL(a1, description, ...) \ -do { \ - @try { \ - __typeof__(a1) a1value = (a1); \ - if (a1value != (__typeof__(a1))NULL) { \ - NSString *_expression = [NSString stringWithFormat:@"((%s) == NULL)", #a1]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when a1 is equal to a2. This test is for C scalars, -// structs and unions. -// Args: -// a1: argument 1 -// a2: argument 2 -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNotEquals(a1, a2, description, ...) \ -do { \ - @try { \ - if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ - } else { \ - __typeof__(a1) a1value = (a1); \ - __typeof__(a2) a2value = (a2); \ - NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ - NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ - if ([a1encoded isEqualToValue:a2encoded]) { \ - NSString *_expression = [NSString stringWithFormat:@"((%s) != (%s))", #a1, #a2]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - }\ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when a1 is equal to a2. This test is for objects. -// Args: -// a1: argument 1. object. -// a2: argument 2. object. -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNotEqualObjects(a1, a2, description, ...) \ -do { \ - @try {\ - id a1value = (a1); \ - id a2value = (a2); \ - if ( (strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ - (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ - (![(id)a1value isEqual:(id)a2value]) ) continue; \ - [self failWithException:([NSException failureInEqualityBetweenObject:a1value \ - andObject:a2value \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - }\ - @catch (id anException) {\ - [self failWithException:([NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - }\ -} while(0) - -// Generates a failure when a1 is not 'op' to a2. This test is for C scalars. -// Args: -// a1: argument 1 -// a2: argument 2 -// op: operation -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertOperation(a1, a2, op, description, ...) \ -do { \ - @try { \ - if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ - } else { \ - __typeof__(a1) a1value = (a1); \ - __typeof__(a2) a2value = (a2); \ - if (!(a1value op a2value)) { \ - double a1DoubleValue = a1value; \ - double a2DoubleValue = a2value; \ - NSString *_expression = [NSString stringWithFormat:@"(%s (%lg) %s %s (%lg))", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ - [self failWithException:([NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ - } \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException \ - failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when a1 is not > a2. This test is for C scalars. -// Args: -// a1: argument 1 -// a2: argument 2 -// op: operation -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertGreaterThan(a1, a2, description, ...) \ - STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) - -// Generates a failure when a1 is not >= a2. This test is for C scalars. -// Args: -// a1: argument 1 -// a2: argument 2 -// op: operation -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ - STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) - -// Generates a failure when a1 is not < a2. This test is for C scalars. -// Args: -// a1: argument 1 -// a2: argument 2 -// op: operation -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertLessThan(a1, a2, description, ...) \ - STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) - -// Generates a failure when a1 is not <= a2. This test is for C scalars. -// Args: -// a1: argument 1 -// a2: argument 2 -// op: operation -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertLessThanOrEqual(a1, a2, description, ...) \ - STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) - -// Generates a failure when string a1 is not equal to string a2. This call -// differs from STAssertEqualObjects in that strings that are different in -// composition (precomposed vs decomposed) will compare equal if their final -// representation is equal. -// ex O + umlaut decomposed is the same as O + umlaut composed. -// Args: -// a1: string 1 -// a2: string 2 -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertEqualStrings(a1, a2, description, ...) \ -do { \ - @try { \ - id a1value = (a1); \ - id a2value = (a2); \ - if (a1value == a2value) continue; \ - if ([a1value isKindOfClass:[NSString class]] && \ - [a2value isKindOfClass:[NSString class]] && \ - [a1value compare:a2value options:0] == NSOrderedSame) continue; \ - [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ - andObject:a2value \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when string a1 is equal to string a2. This call -// differs from STAssertEqualObjects in that strings that are different in -// composition (precomposed vs decomposed) will compare equal if their final -// representation is equal. -// ex O + umlaut decomposed is the same as O + umlaut composed. -// Args: -// a1: string 1 -// a2: string 2 -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNotEqualStrings(a1, a2, description, ...) \ -do { \ - @try { \ - id a1value = (a1); \ - id a2value = (a2); \ - if ([a1value isKindOfClass:[NSString class]] && \ - [a2value isKindOfClass:[NSString class]] && \ - [a1value compare:a2value options:0] != NSOrderedSame) continue; \ - [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ - andObject:a2value \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when c-string a1 is not equal to c-string a2. -// Args: -// a1: string 1 -// a2: string 2 -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertEqualCStrings(a1, a2, description, ...) \ -do { \ - @try { \ - const char* a1value = (a1); \ - const char* a2value = (a2); \ - if (a1value == a2value) continue; \ - if (strcmp(a1value, a2value) == 0) continue; \ - [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \ - andObject:[NSString stringWithUTF8String:a2value] \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -// Generates a failure when c-string a1 is equal to c-string a2. -// Args: -// a1: string 1 -// a2: string 2 -// description: A format string as in the printf() function. Can be nil or -// an empty string but must be present. -// ...: A variable number of arguments to the format string. Can be absent. -#define STAssertNotEqualCStrings(a1, a2, description, ...) \ -do { \ - @try { \ - const char* a1value = (a1); \ - const char* a2value = (a2); \ - if (strcmp(a1value, a2value) != 0) continue; \ - [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \ - andObject:[NSString stringWithUTF8String:a2value] \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. - This test is for GLKit types (GLKVector, GLKMatrix) where small differences - could make these items not exactly equal. Do not use this version directly. - Use the explicit STAssertEqualGLKVectors and STAssertEqualGLKMatrices defined - below. - _{a1 The GLKType on the left.} - _{a2 The GLKType on the right.} - _{accuracy The maximum difference between a1 and a2 for these values to be - considered equal.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ - -#define STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ...) \ -do { \ - @try { \ - if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ - } else { \ - __typeof__(a1) a1GLKValue = (a1); \ - __typeof__(a2) a2GLKValue = (a2); \ - __typeof__(accuracy) accuracyvalue = (accuracy); \ - float *a1FloatValue = ((float*)&a1GLKValue); \ - float *a2FloatValue = ((float*)&a2GLKValue); \ - for (size_t i = 0; i < sizeof(__typeof__(a1)) / sizeof(float); ++i) { \ - float a1value = a1FloatValue[i]; \ - float a2value = a2FloatValue[i]; \ - if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ - NSMutableArray *strings = [NSMutableArray arrayWithCapacity:sizeof(a1) / sizeof(float)]; \ - NSString *string; \ - for (size_t j = 0; j < sizeof(__typeof__(a1)) / sizeof(float); ++j) { \ - string = [NSString stringWithFormat:@"(%0.3f == %0.3f)", a1FloatValue[j], a2FloatValue[j]]; \ - [strings addObject:string]; \ - } \ - string = [strings componentsJoinedByString:@", "]; \ - NSString *desc = STComposeString(description, ##__VA_ARGS__); \ - desc = [NSString stringWithFormat:@"%@ With Accuracy %0.3f: %@", string, (float)accuracyvalue, desc]; \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", desc]]; \ - break; \ - } \ - } \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -#define STAssertEqualGLKVectors(a1, a2, accuracy, description, ...) \ - STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) - -#define STAssertEqualGLKMatrices(a1, a2, accuracy, description, ...) \ - STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) - -#define STAssertEqualGLKQuaternions(a1, a2, accuracy, description, ...) \ - STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) - -#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST -// When not using the Xcode provided version, define everything ourselves. - -// SENTE_BEGIN -/*" Generates a failure when !{ [a1 isEqualTo:a2] } is false - (or one is nil and the other is not). - _{a1 The object on the left.} - _{a2 The object on the right.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertEqualObjects(a1, a2, description, ...) \ -do { \ - @try { \ - id a1value = (a1); \ - id a2value = (a2); \ - if (a1value == a2value) continue; \ - if ((strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ - (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ - [(id)a1value isEqual:(id)a2value]) continue; \ - [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ - andObject:a2value \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - - -/*" Generates a failure when a1 is not equal to a2. This test is for - C scalars, structs and unions. - _{a1 The argument on the left.} - _{a2 The argument on the right.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertEquals(a1, a2, description, ...) \ -do { \ - @try { \ - if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ - } else { \ - __typeof__(a1) a1value = (a1); \ - __typeof__(a2) a2value = (a2); \ - NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ - NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ - if (![a1encoded isEqualToValue:a2encoded]) { \ - [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \ - andValue:a2encoded \ - withAccuracy:nil \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - -#define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) - - -/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. - This test is for scalars such as floats and doubles where small differences - could make these items not exactly equal, but also works for all scalars. - _{a1 The scalar on the left.} - _{a2 The scalar on the right.} - _{accuracy The maximum difference between a1 and a2 for these values to be - considered equal.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ - -#define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ -do { \ - @try { \ - if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ - [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ - } else { \ - __typeof__(a1) a1value = (a1); \ - __typeof__(a2) a2value = (a2); \ - __typeof__(accuracy) accuracyvalue = (accuracy); \ - if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ - NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ - NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ - NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ - [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \ - andValue:a2encoded \ - withAccuracy:accuracyencoded \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - - - -/*" Generates a failure unconditionally. - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STFail(description, ...) \ -[self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]] - - - -/*" Generates a failure when a1 is not nil. - _{a1 An object.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertNil(a1, description, ...) \ -do { \ - @try { \ - id a1value = (a1); \ - if (a1value != nil) { \ - NSString *_a1 = [NSString stringWithUTF8String:#a1]; \ - NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == nil fails", #a1] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - - -/*" Generates a failure when a1 is nil. - _{a1 An object.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertNotNil(a1, description, ...) \ -do { \ - @try { \ - id a1value = (a1); \ - if (a1value == nil) { \ - NSString *_a1 = [NSString stringWithUTF8String:#a1]; \ - NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != nil fails", #a1] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while(0) - - -/*" Generates a failure when expression evaluates to false. - _{expr The expression that is tested.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertTrue(expr, description, ...) \ -do { \ - BOOL _evaluatedExpression = (expr); \ - if (!_evaluatedExpression) { \ - NSString *_expression = [NSString stringWithUTF8String:#expr]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while (0) - - -/*" Generates a failure when expression evaluates to false and in addition will - generate error messages if an exception is encountered. - _{expr The expression that is tested.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertTrueNoThrow(expr, description, ...) \ -do { \ - @try { \ - BOOL _evaluatedExpression = (expr); \ - if (!_evaluatedExpression) { \ - NSString *_expression = [NSString stringWithUTF8String:#expr]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:NO \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) ", #expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while (0) - - -/*" Generates a failure when the expression evaluates to true. - _{expr The expression that is tested.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertFalse(expr, description, ...) \ -do { \ - BOOL _evaluatedExpression = (expr); \ - if (_evaluatedExpression) { \ - NSString *_expression = [NSString stringWithUTF8String:#expr]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:YES \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while (0) - - -/*" Generates a failure when the expression evaluates to true and in addition - will generate error messages if an exception is encountered. - _{expr The expression that is tested.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertFalseNoThrow(expr, description, ...) \ -do { \ - @try { \ - BOOL _evaluatedExpression = (expr); \ - if (_evaluatedExpression) { \ - NSString *_expression = [NSString stringWithUTF8String:#expr]; \ - [self failWithException:[NSException failureInCondition:_expression \ - isTrue:YES \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"!(%s) ", #expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while (0) - - -/*" Generates a failure when expression does not throw an exception. - _{expression The expression that is evaluated.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent. -"*/ -#define STAssertThrows(expr, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (id anException) { \ - continue; \ - } \ - [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:nil \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ -} while (0) - - -/*" Generates a failure when expression does not throw an exception of a - specific class. - _{expression The expression that is evaluated.} - _{specificException The specified class of the exception.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertThrowsSpecific(expr, specificException, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (specificException *anException) { \ - continue; \ - } \ - @catch (id anException) { \ - NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ - [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ - continue; \ - } \ - NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ - [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:nil \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ -} while (0) - - -/*" Generates a failure when expression does not throw an exception of a - specific class with a specific name. Useful for those frameworks like - AppKit or Foundation that throw generic NSException w/specific names - (NSInvalidArgumentException, etc). - _{expression The expression that is evaluated.} - _{specificException The specified class of the exception.} - _{aName The name of the specified exception.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} - -"*/ -#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (specificException *anException) { \ - if ([aName isEqualToString:[anException name]]) continue; \ - NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \ - [self failWithException: \ - [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ - continue; \ - } \ - @catch (id anException) { \ - NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ - [self failWithException: \ - [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ - continue; \ - } \ - NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ - [self failWithException: \ - [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:nil \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ -} while (0) - - -/*" Generates a failure when expression does throw an exception. - _{expression The expression that is evaluated.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertNoThrow(expr, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (id anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ -} while (0) - - -/*" Generates a failure when expression does throw an exception of the specitied - class. Any other exception is okay (i.e. does not generate a failure). - _{expression The expression that is evaluated.} - _{specificException The specified class of the exception.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} -"*/ -#define STAssertNoThrowSpecific(expr, specificException, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (specificException *anException) { \ - [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ - } \ - @catch (id anythingElse) { \ - ; \ - } \ -} while (0) - - -/*" Generates a failure when expression does throw an exception of a - specific class with a specific name. Useful for those frameworks like - AppKit or Foundation that throw generic NSException w/specific names - (NSInvalidArgumentException, etc). - _{expression The expression that is evaluated.} - _{specificException The specified class of the exception.} - _{aName The name of the specified exception.} - _{description A format string as in the printf() function. Can be nil or - an empty string but must be present.} - _{... A variable number of arguments to the format string. Can be absent.} - -"*/ -#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ -do { \ - @try { \ - (expr); \ - } \ - @catch (specificException *anException) { \ - if ([aName isEqualToString:[anException name]]) { \ - NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \ - [self failWithException: \ - [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ - exception:anException \ - inFile:[NSString stringWithUTF8String:__FILE__] \ - atLine:__LINE__ \ - withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ - } \ - continue; \ - } \ - @catch (id anythingElse) { \ - ; \ - } \ -} while (0) - - - -@interface NSException (GTMSenTestAdditions) -+ (NSException *)failureInFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(3, 4); -+ (NSException *)failureInCondition:(NSString *)condition - isTrue:(BOOL)isTrue - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); -+ (NSException *)failureInEqualityBetweenObject:(id)left - andObject:(id)right - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); -+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left - andValue:(NSValue *)right - withAccuracy:(NSValue *)accuracy - inFile:(NSString *)filename - atLine:(int) ineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(6, 7); -+ (NSException *)failureInRaise:(NSString *)expression - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(4, 5); -+ (NSException *)failureInRaise:(NSString *)expression - exception:(NSException *)exception - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); -@end - -// SENTE_END - -@protocol SenTestCase -+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation; -- (id)initWithInvocation:(NSInvocation *)anInvocation; -- (void)setUp; -- (void)invokeTest; -- (void)tearDown; -- (void)performTest; -- (void)failWithException:(NSException*)exception; -- (NSInvocation *)invocation; -- (SEL)selector; -+ (NSArray *)testInvocations; -@end - -@interface SenTestCase : NSObject<SenTestCase> { - @private - NSInvocation *invocation_; -} -@end - -GTM_EXTERN NSString *const SenTestFailureException; - -GTM_EXTERN NSString *const SenTestFilenameKey; -GTM_EXTERN NSString *const SenTestLineNumberKey; - -#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST - -// All unittest cases in GTM should inherit from GTMTestCase. It makes sure -// to set up our logging system correctly to verify logging calls. -// See GTMUnitTestDevLog.h for details -@interface GTMTestCase : SenTestCase - -// Returns YES if this is an abstract testCase class as opposed to a concrete -// testCase class that you want tests run against. SenTestCase is not designed -// out of the box to handle an abstract class hierarchy descending from it with -// some concrete subclasses. In some cases we want all the "concrete" -// subclasses of an abstract subclass of SenTestCase to run a test, but we don't -// want that test to be run against an instance of an abstract subclass itself. -// By returning "YES" here, the tests defined by this class won't be run against -// an instance of this class. As an example class hierarchy: -// -// FooExtensionTestCase -// GTMTestCase <- ExtensionAbstractTestCase < -// BarExtensionTestCase -// -// So FooExtensionTestCase and BarExtensionTestCase inherit from -// ExtensionAbstractTestCase (and probably FooExtension and BarExtension inherit -// from a class named Extension). We want the tests in ExtensionAbstractTestCase -// to be run as part of FooExtensionTestCase and BarExtensionTestCase, but we -// don't want them run against ExtensionAbstractTestCase. The default -// implementation checks to see if the name of the class contains the word -// "AbstractTest" (case sensitive). -+ (BOOL)isAbstractTestCase; - -@end diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m deleted file mode 100644 index 162f01e97c..0000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m +++ /dev/null @@ -1,428 +0,0 @@ -// -// GTMSenTestCase.m -// -// Copyright 2007-2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -#import "GTMSenTestCase.h" - -#import <unistd.h> -#if GTM_IPHONE_SIMULATOR -#import <objc/message.h> -#endif - -#import "GTMObjC2Runtime.h" -#import "GTMUnitTestDevLog.h" - -#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST -#import <stdarg.h> - -@interface NSException (GTMSenTestPrivateAdditions) -+ (NSException *)failureInFile:(NSString *)filename - atLine:(int)lineNumber - reason:(NSString *)reason; -@end - -@implementation NSException (GTMSenTestPrivateAdditions) -+ (NSException *)failureInFile:(NSString *)filename - atLine:(int)lineNumber - reason:(NSString *)reason { - NSDictionary *userInfo = - [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey, - filename, SenTestFilenameKey, - nil]; - - return [self exceptionWithName:SenTestFailureException - reason:reason - userInfo:userInfo]; -} -@end - -@implementation NSException (GTMSenTestAdditions) - -+ (NSException *)failureInFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason = testDescription; - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -+ (NSException *)failureInCondition:(NSString *)condition - isTrue:(BOOL)isTrue - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@", - condition, isTrue ? "false" : "true", testDescription]; - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -+ (NSException *)failureInEqualityBetweenObject:(id)left - andObject:(id)right - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason = - [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", - [left description], [right description], testDescription]; - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left - andValue:(NSValue *)right - withAccuracy:(NSValue *)accuracy - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason; - if (accuracy) { - reason = - [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", - left, right, testDescription]; - } else { - reason = - [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@", - left, right, accuracy, testDescription]; - } - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -+ (NSException *)failureInRaise:(NSString *)expression - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@", - expression, testDescription]; - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -+ (NSException *)failureInRaise:(NSString *)expression - exception:(NSException *)exception - inFile:(NSString *)filename - atLine:(int)lineNumber - withDescription:(NSString *)formatString, ... { - - NSString *testDescription = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - testDescription = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - - NSString *reason; - if ([[exception name] isEqualToString:SenTestFailureException]) { - // it's our exception, assume it has the right description on it. - reason = [exception reason]; - } else { - // not one of our exception, use the exceptions reason and our description - reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@", - expression, [exception reason], testDescription]; - } - - return [self failureInFile:filename atLine:lineNumber reason:reason]; -} - -@end - -NSString *STComposeString(NSString *formatString, ...) { - NSString *reason = @""; - if (formatString) { - va_list vl; - va_start(vl, formatString); - reason = - [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; - va_end(vl); - } - return reason; -} - -NSString *const SenTestFailureException = @"SenTestFailureException"; -NSString *const SenTestFilenameKey = @"SenTestFilenameKey"; -NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey"; - -@interface SenTestCase (SenTestCasePrivate) -// our method of logging errors -+ (void)printException:(NSException *)exception fromTestName:(NSString *)name; -@end - -@implementation SenTestCase -+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation { - return [[[self alloc] initWithInvocation:anInvocation] autorelease]; -} - -- (id)initWithInvocation:(NSInvocation *)anInvocation { - if ((self = [super init])) { - invocation_ = [anInvocation retain]; - } - return self; -} - -- (void)dealloc { - [invocation_ release]; - [super dealloc]; -} - -- (void)failWithException:(NSException*)exception { - [exception raise]; -} - -- (void)setUp { -} - -- (void)performTest { - @try { - [self invokeTest]; - } @catch (NSException *exception) { - [[self class] printException:exception - fromTestName:NSStringFromSelector([self selector])]; - [exception raise]; - } -} - -- (NSInvocation *)invocation { - return invocation_; -} - -- (SEL)selector { - return [invocation_ selector]; -} - -+ (void)printException:(NSException *)exception fromTestName:(NSString *)name { - NSDictionary *userInfo = [exception userInfo]; - NSString *filename = [userInfo objectForKey:SenTestFilenameKey]; - NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey]; - NSString *className = NSStringFromClass([self class]); - if ([filename length] == 0) { - filename = @"Unknown.m"; - } - fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n", - [filename UTF8String], - (long)[lineNumber integerValue], - [className UTF8String], - [name UTF8String], - [[exception reason] UTF8String]); - fflush(stderr); -} - -- (void)invokeTest { - NSException *e = nil; - @try { - // Wrap things in autorelease pools because they may - // have an STMacro in their dealloc which may get called - // when the pool is cleaned up - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - // We don't log exceptions here, instead we let the person that called - // this log the exception. This ensures they are only logged once but the - // outer layers get the exceptions to report counts, etc. - @try { - [self setUp]; - @try { - NSInvocation *invocation = [self invocation]; -#if GTM_IPHONE_SIMULATOR - // We don't call [invocation invokeWithTarget:self]; because of - // Radar 8081169: NSInvalidArgumentException can't be caught - // It turns out that on iOS4 (and 3.2) exceptions thrown inside an - // [invocation invoke] on the simulator cannot be caught. - // http://openradar.appspot.com/8081169 - objc_msgSend(self, [invocation selector]); -#else - [invocation invokeWithTarget:self]; -#endif - } @catch (NSException *exception) { - e = [exception retain]; - } - [self tearDown]; - } @catch (NSException *exception) { - e = [exception retain]; - } - [pool release]; - } @catch (NSException *exception) { - e = [exception retain]; - } - if (e) { - [e autorelease]; - [e raise]; - } -} - -- (void)tearDown { -} - -- (NSString *)description { - // This matches the description OCUnit would return to you - return [NSString stringWithFormat:@"-[%@ %@]", [self class], - NSStringFromSelector([self selector])]; -} - -// Used for sorting methods below -static int MethodSort(id a, id b, void *context) { - NSInvocation *invocationA = a; - NSInvocation *invocationB = b; - const char *nameA = sel_getName([invocationA selector]); - const char *nameB = sel_getName([invocationB selector]); - return strcmp(nameA, nameB); -} - - -+ (NSArray *)testInvocations { - NSMutableArray *invocations = nil; - // Need to walk all the way up the parent classes collecting methods (in case - // a test is a subclass of another test). - Class senTestCaseClass = [SenTestCase class]; - for (Class currentClass = self; - currentClass && (currentClass != senTestCaseClass); - currentClass = class_getSuperclass(currentClass)) { - unsigned int methodCount; - Method *methods = class_copyMethodList(currentClass, &methodCount); - if (methods) { - // This handles disposing of methods for us even if an exception should fly. - [NSData dataWithBytesNoCopy:methods - length:sizeof(Method) * methodCount]; - if (!invocations) { - invocations = [NSMutableArray arrayWithCapacity:methodCount]; - } - for (size_t i = 0; i < methodCount; ++i) { - Method currMethod = methods[i]; - SEL sel = method_getName(currMethod); - char *returnType = NULL; - const char *name = sel_getName(sel); - // If it starts with test, takes 2 args (target and sel) and returns - // void run it. - if (strstr(name, "test") == name) { - returnType = method_copyReturnType(currMethod); - if (returnType) { - // This handles disposing of returnType for us even if an - // exception should fly. Length +1 for the terminator, not that - // the length really matters here, as we never reference inside - // the data block. - [NSData dataWithBytesNoCopy:returnType - length:strlen(returnType) + 1]; - } - } - // TODO: If a test class is a subclass of another, and they reuse the - // same selector name (ie-subclass overrides it), this current loop - // and test here will cause cause it to get invoked twice. To fix this - // the selector would have to be checked against all the ones already - // added, so it only gets done once. - if (returnType // True if name starts with "test" - && strcmp(returnType, @encode(void)) == 0 - && method_getNumberOfArguments(currMethod) == 2) { - NSMethodSignature *sig = [self instanceMethodSignatureForSelector:sel]; - NSInvocation *invocation - = [NSInvocation invocationWithMethodSignature:sig]; - [invocation setSelector:sel]; - [invocations addObject:invocation]; - } - } - } - } - // Match SenTestKit and run everything in alphbetical order. - [invocations sortUsingFunction:MethodSort context:nil]; - return invocations; -} - -@end - -#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST - -@implementation GTMTestCase : SenTestCase -- (void)invokeTest { - NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; - Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog"); - if (devLogClass) { - [devLogClass performSelector:@selector(enableTracking)]; - [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; - - } - [super invokeTest]; - if (devLogClass) { - [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; - [devLogClass performSelector:@selector(disableTracking)]; - } - [localPool drain]; -} - -+ (BOOL)isAbstractTestCase { - NSString *name = NSStringFromClass(self); - return [name rangeOfString:@"AbstractTest"].location != NSNotFound; -} - -+ (NSArray *)testInvocations { - NSArray *invocations = nil; - if (![self isAbstractTestCase]) { - invocations = [super testInvocations]; - } - return invocations; -} - -@end |