X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/390d58628f96731c7736302877e6c16d006d1a4f..5f63f9176d71d4404cc8760c840f186ad11792b7:/runtime/objc-errors.m?ds=sidebyside diff --git a/runtime/objc-errors.m b/runtime/objc-errors.m index 4a16111..7a9f677 100644 --- a/runtime/objc-errors.m +++ b/runtime/objc-errors.m @@ -1,9 +1,7 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ + * Copyright (c) 1999-2003, 2005-2007 Apple Inc. All Rights Reserved. * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License @@ -35,115 +33,204 @@ #import "objc-private.h" -static volatile void _objc_trap(void); +__private_extern__ char *__crashreporter_info__ = NULL; +OBJC_EXPORT void (*_error)(id, const char *, va_list); -static int hasTerminal() -{ - static char hasTerm = -1; - - if (hasTerm == -1) { - int fd = open("/dev/tty", O_RDWR, 0); - if (fd >= 0) { - (void)close(fd); - hasTerm = 1; - } else - hasTerm = 0; - } - return hasTerm; -} +static void _objc_trap(void) __attribute__((noreturn)); -void _objc_syslog(const char *format, ...) +// Add "message" to any forthcoming crash log. +static void _objc_crashlog(const char *message) { - va_list ap; - char bigBuffer[4*1024]; + char *newmsg; - va_start(ap, format); - vsnprintf(bigBuffer, sizeof(bigBuffer), format, ap); - va_end(ap); + if (!__crashreporter_info__) { + newmsg = strdup(message); + } else { + asprintf(&newmsg, "%s\n%s", __crashreporter_info__, message); + } + if (newmsg) { + // Strip trailing newline + char *c = &newmsg[strlen(newmsg)-1]; + if (*c == '\n') *c = '\0'; + + if (__crashreporter_info__) free(__crashreporter_info__); + __crashreporter_info__ = newmsg; + } +} - if (hasTerminal()) { - fwrite(bigBuffer, sizeof(char), strlen(bigBuffer), stderr); - if (bigBuffer[strlen(bigBuffer)-1] != '\n') - fputc('\n', stderr); +// Print "message" to the console. +static void _objc_syslog(const char *message) +{ + if (fcntl(STDERR_FILENO, F_GETFL, 0) != -1) { + // stderr is open - use it + write(STDERR_FILENO, message, strlen(message)); + if (message[strlen(message)-1] != '\n') { + write(STDERR_FILENO, "\n", 1); + } } else { - syslog(LOG_ERR, "%s", bigBuffer); + syslog(LOG_ERR, "%s", message); } } -/* - * this routine handles errors that involve an object (or class). +/* + * this routine handles errors that involve an object (or class). */ -volatile void __objc_error(id rcv, const char *fmt, ...) +__private_extern__ void __objc_error(id rcv, const char *fmt, ...) { - va_list vp; - - va_start(vp,fmt); - (*_error)(rcv, fmt, vp); - va_end(vp); - _objc_error (rcv, fmt, vp); /* In case (*_error)() returns. */ + va_list vp; + + va_start(vp,fmt); +#if !__OBJC2__ + (*_error)(rcv, fmt, vp); +#endif + _objc_error (rcv, fmt, vp); /* In case (*_error)() returns. */ + va_end(vp); } /* - * this routine is never called directly...it is only called indirectly - * through "_error", which can be overriden by an application. It is - * not declared static because it needs to be referenced in - * "objc-globaldata.m" (this file organization simplifies the shlib - * maintenance problem...oh well). It is, however, a "private extern". + * _objc_error is the default *_error handler. */ -volatile void _objc_error(id self, const char *fmt, va_list ap) +#if __OBJC2__ +__private_extern__ +#endif +void _objc_error(id self, const char *fmt, va_list ap) { - char bigBuffer[4*1024]; + char *buf1; + char *buf2; - vsnprintf (bigBuffer, sizeof(bigBuffer), fmt, ap); - _objc_syslog ("objc: %s: %s", object_getClassName (self), bigBuffer); + vasprintf(&buf1, fmt, ap); + asprintf(&buf2, "objc[%d]: %s: %s\n", + getpid(), object_getClassName(self), buf1); + _objc_syslog(buf2); + _objc_crashlog(buf2); _objc_trap(); } -/* - * this routine handles severe runtime errors...like not being able - * to read the mach headers, allocate space, etc...very uncommon. +/* + * this routine handles severe runtime errors...like not being able + * to read the mach headers, allocate space, etc...very uncommon. */ -volatile void _objc_fatal(const char *fmt, ...) +__private_extern__ void _objc_fatal(const char *fmt, ...) { va_list ap; - char bigBuffer[4*1024]; + char *buf1; + char *buf2; - va_start (ap,fmt); - vsnprintf (bigBuffer, sizeof(bigBuffer), fmt, ap); - _objc_syslog ("objc: %s", bigBuffer); + va_start(ap,fmt); + vasprintf(&buf1, fmt, ap); va_end (ap); + asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1); + _objc_syslog(buf2); + _objc_crashlog(buf2); + _objc_trap(); } /* - * this routine handles soft runtime errors...like not being able - * add a category to a class (because it wasn't linked in). + * this routine handles soft runtime errors...like not being able + * add a category to a class (because it wasn't linked in). + */ +__private_extern__ void _objc_inform(const char *fmt, ...) +{ + va_list ap; + char *buf1; + char *buf2; + + va_start (ap,fmt); + vasprintf(&buf1, fmt, ap); + va_end (ap); + + asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1); + _objc_syslog(buf2); + + free(buf2); + free(buf1); +} + + +/* + * Like _objc_inform(), but prints the message only in any + * forthcoming crash log, not to the console. */ -void _objc_inform(const char *fmt, ...) +__private_extern__ void _objc_inform_on_crash(const char *fmt, ...) { va_list ap; - char bigBuffer[4*1024]; + char *buf1; + char *buf2; va_start (ap,fmt); - vsnprintf (bigBuffer, sizeof(bigBuffer), fmt, ap); - _objc_syslog ("objc: %s", bigBuffer); + vasprintf(&buf1, fmt, ap); va_end (ap); + + asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1); + _objc_crashlog(buf2); + + free(buf2); + free(buf1); +} + + +/* + * Like calling both _objc_inform and _objc_inform_on_crash. + */ +__private_extern__ void _objc_inform_now_and_on_crash(const char *fmt, ...) +{ + va_list ap; + char *buf1; + char *buf2; + + va_start (ap,fmt); + vasprintf(&buf1, fmt, ap); + va_end (ap); + + asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1); + _objc_crashlog(buf2); + _objc_syslog(buf2); + + free(buf2); + free(buf1); } /* Kill the process in a way that generates a crash log. * This is better than calling exit(). */ -static volatile void _objc_trap(void) +static void _objc_trap(void) +{ + __builtin_trap(); +} + +/* Try to keep _objc_warn_deprecated out of crash logs + * caused by _objc_trap(). rdar://4546883 */ +__attribute__((used)) +static void _objc_trap2(void) { -#if defined(__ppc__) || defined(ppc) - asm("trap"); -#elif defined(__i386__) || defined(i386) - asm("int3"); -#else -#warning _objc_trap not specified for this architecture; using _exit instead - _exit(1); -#endif + __builtin_trap(); } + +__private_extern__ void _objc_warn_deprecated(const char *old, const char *new) +{ + if (PrintDeprecation) { + if (new) { + _objc_inform("The function %s is obsolete. Use %s instead. Set a breakpoint on _objc_warn_deprecated to find the culprit.", old, new); + } else { + _objc_inform("The function %s is obsolete. Do not use it. Set a breakpoint on _objc_warn_deprecated to find the culprit.", old); + } + } +} + + +/* Entry points for breakable errors. For some reason, can't inhibit the compiler's inlining aggression. + */ + +__private_extern__ void objc_assign_ivar_error(id base, ptrdiff_t offset) { +} + +__private_extern__ void objc_assign_global_error(id value, id *slot) { +} + +__private_extern__ void objc_exception_during_finalize_error(void) { +} +