]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-errors.m
objc4-437.1.tar.gz
[apple/objc4.git] / runtime / objc-errors.m
1 /*
2 * Copyright (c) 1999-2003, 2005-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * objc-errors.m
25 * Copyright 1988-2001, NeXT Software, Inc., Apple Computer, Inc.
26 */
27
28 #include "objc-private.h"
29
30 #if TARGET_OS_WIN32
31
32 #include <conio.h>
33
34 __private_extern__ void _objc_inform_on_crash(const char *fmt, ...)
35 {
36 }
37
38 __private_extern__ void _objc_inform(const char *fmt, ...)
39 {
40 va_list args;
41 va_start(args, fmt);
42 _vcprintf(fmt, args);
43 va_end(args);
44 _cprintf("\n");
45 }
46
47 __private_extern__ void _objc_fatal(const char *fmt, ...)
48 {
49 va_list args;
50 va_start(args, fmt);
51 _vcprintf(fmt, args);
52 va_end(args);
53 _cprintf("\n");
54
55 abort();
56 }
57
58 __private_extern__ void __objc_error(id rcv, const char *fmt, ...)
59 {
60 va_list args;
61 va_start(args, fmt);
62 _vcprintf(fmt, args);
63 va_end(args);
64 }
65
66 __private_extern__ void _objc_error(id rcv, const char *fmt, va_list args)
67 {
68 _vcprintf(fmt, args);
69 }
70
71 #else
72
73 __private_extern__ char *__crashreporter_info__ = NULL;
74
75 OBJC_EXPORT void (*_error)(id, const char *, va_list);
76
77 static void _objc_trap(void) __attribute__((noreturn));
78
79 // Add "message" to any forthcoming crash log.
80 static void _objc_crashlog(const char *message)
81 {
82 char *newmsg;
83
84 #if 0
85 {
86 // for debugging at BOOT time.
87 extern char **_NSGetProgname(void);
88 FILE *crashlog = fopen("/_objc_crash.log", "a");
89 setbuf(crashlog, NULL);
90 fprintf(crashlog, "[%s] %s\n", *_NSGetProgname(), message);
91 fclose(crashlog);
92 sync();
93 }
94 #endif
95
96 if (!__crashreporter_info__) {
97 newmsg = strdup(message);
98 } else {
99 asprintf(&newmsg, "%s\n%s", __crashreporter_info__, message);
100 }
101
102 if (newmsg) {
103 // Strip trailing newline
104 char *c = &newmsg[strlen(newmsg)-1];
105 if (*c == '\n') *c = '\0';
106
107 if (__crashreporter_info__) free(__crashreporter_info__);
108 __crashreporter_info__ = newmsg;
109 }
110 }
111
112 // Print "message" to the console.
113 static void _objc_syslog(const char *message)
114 {
115 if (fcntl(STDERR_FILENO, F_GETFL, 0) != -1) {
116 // stderr is open - use it
117 write(STDERR_FILENO, message, strlen(message));
118 if (message[strlen(message)-1] != '\n') {
119 write(STDERR_FILENO, "\n", 1);
120 }
121 } else {
122 syslog(LOG_ERR, "%s", message);
123 }
124 }
125 /*
126 * this routine handles errors that involve an object (or class).
127 */
128 __private_extern__ void __objc_error(id rcv, const char *fmt, ...)
129 {
130 va_list vp;
131
132 va_start(vp,fmt);
133 #if !__OBJC2__
134 (*_error)(rcv, fmt, vp);
135 #endif
136 _objc_error (rcv, fmt, vp); /* In case (*_error)() returns. */
137 va_end(vp);
138 }
139
140 /*
141 * _objc_error is the default *_error handler.
142 */
143 #if __OBJC2__
144 __private_extern__
145 #endif
146 void _objc_error(id self, const char *fmt, va_list ap)
147 {
148 char *buf1;
149 char *buf2;
150
151 vasprintf(&buf1, fmt, ap);
152 asprintf(&buf2, "objc[%d]: %s: %s\n",
153 getpid(), object_getClassName(self), buf1);
154 _objc_syslog(buf2);
155 _objc_crashlog(buf2);
156
157 _objc_trap();
158 }
159
160 /*
161 * this routine handles severe runtime errors...like not being able
162 * to read the mach headers, allocate space, etc...very uncommon.
163 */
164 __private_extern__ void _objc_fatal(const char *fmt, ...)
165 {
166 va_list ap;
167 char *buf1;
168 char *buf2;
169
170 va_start(ap,fmt);
171 vasprintf(&buf1, fmt, ap);
172 va_end (ap);
173
174 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
175 _objc_syslog(buf2);
176 _objc_crashlog(buf2);
177
178 _objc_trap();
179 }
180
181 /*
182 * this routine handles soft runtime errors...like not being able
183 * add a category to a class (because it wasn't linked in).
184 */
185 __private_extern__ void _objc_inform(const char *fmt, ...)
186 {
187 va_list ap;
188 char *buf1;
189 char *buf2;
190
191 va_start (ap,fmt);
192 vasprintf(&buf1, fmt, ap);
193 va_end (ap);
194
195 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
196 _objc_syslog(buf2);
197
198 free(buf2);
199 free(buf1);
200 }
201
202
203 /*
204 * Like _objc_inform(), but prints the message only in any
205 * forthcoming crash log, not to the console.
206 */
207 __private_extern__ void _objc_inform_on_crash(const char *fmt, ...)
208 {
209 va_list ap;
210 char *buf1;
211 char *buf2;
212
213 va_start (ap,fmt);
214 vasprintf(&buf1, fmt, ap);
215 va_end (ap);
216
217 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
218 _objc_crashlog(buf2);
219
220 free(buf2);
221 free(buf1);
222 }
223
224
225 /*
226 * Like calling both _objc_inform and _objc_inform_on_crash.
227 */
228 __private_extern__ void _objc_inform_now_and_on_crash(const char *fmt, ...)
229 {
230 va_list ap;
231 char *buf1;
232 char *buf2;
233
234 va_start (ap,fmt);
235 vasprintf(&buf1, fmt, ap);
236 va_end (ap);
237
238 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
239 _objc_crashlog(buf2);
240 _objc_syslog(buf2);
241
242 free(buf2);
243 free(buf1);
244 }
245
246
247 /* Kill the process in a way that generates a crash log.
248 * This is better than calling exit(). */
249 static void _objc_trap(void)
250 {
251 __builtin_trap();
252 }
253
254 /* Try to keep _objc_warn_deprecated out of crash logs
255 * caused by _objc_trap(). rdar://4546883 */
256 __attribute__((used))
257 static void _objc_trap2(void)
258 {
259 __builtin_trap();
260 }
261
262 #endif
263
264
265 __private_extern__ void _objc_warn_deprecated(const char *oldf, const char *newf)
266 {
267 if (PrintDeprecation) {
268 if (newf) {
269 _objc_inform("The function %s is obsolete. Use %s instead. Set a breakpoint on _objc_warn_deprecated to find the culprit.", oldf, newf);
270 } else {
271 _objc_inform("The function %s is obsolete. Do not use it. Set a breakpoint on _objc_warn_deprecated to find the culprit.", oldf);
272 }
273 }
274 }
275
276
277 /* Entry points for breakable errors. For some reason, can't inhibit the compiler's inlining aggression.
278 */
279
280 __private_extern__ void objc_assign_ivar_error(id base, ptrdiff_t offset) {
281 }
282
283 __private_extern__ void objc_assign_global_error(id value, id *slot) {
284 }
285
286 __private_extern__ void objc_exception_during_finalize_error(void) {
287 }
288