/src/mozilla-central/xpcom/base/nsDebugImpl.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | // Chromium headers must come before Mozilla headers. |
8 | | #include "base/process_util.h" |
9 | | |
10 | | #include "mozilla/Atomics.h" |
11 | | #include "mozilla/Printf.h" |
12 | | |
13 | | #include "MainThreadUtils.h" |
14 | | #include "nsDebugImpl.h" |
15 | | #include "nsDebug.h" |
16 | | #include "nsExceptionHandler.h" |
17 | | #include "nsString.h" |
18 | | #include "nsXULAppAPI.h" |
19 | | #include "prprf.h" |
20 | | #include "nsError.h" |
21 | | #include "prerror.h" |
22 | | #include "prerr.h" |
23 | | #include "prenv.h" |
24 | | |
25 | | #ifdef ANDROID |
26 | | #include <android/log.h> |
27 | | #endif |
28 | | |
29 | | #ifdef _WIN32 |
30 | | /* for getenv() */ |
31 | | #include <stdlib.h> |
32 | | #endif |
33 | | |
34 | | #include "nsTraceRefcnt.h" |
35 | | |
36 | | #if defined(XP_UNIX) |
37 | | #include <signal.h> |
38 | | #endif |
39 | | |
40 | | #if defined(XP_WIN) |
41 | | #include <tchar.h> |
42 | | #include "nsString.h" |
43 | | #endif |
44 | | |
45 | | #if defined(XP_MACOSX) || defined(__DragonFly__) || defined(__FreeBSD__) \ |
46 | | || defined(__NetBSD__) || defined(__OpenBSD__) |
47 | | #include <stdbool.h> |
48 | | #include <unistd.h> |
49 | | #include <sys/param.h> |
50 | | #include <sys/sysctl.h> |
51 | | #endif |
52 | | |
53 | | #if defined(__OpenBSD__) |
54 | | #include <sys/proc.h> |
55 | | #endif |
56 | | |
57 | | #if defined(__DragonFly__) || defined(__FreeBSD__) |
58 | | #include <sys/user.h> |
59 | | #endif |
60 | | |
61 | | #if defined(__NetBSD__) |
62 | | #undef KERN_PROC |
63 | | #define KERN_PROC KERN_PROC2 |
64 | | #define KINFO_PROC struct kinfo_proc2 |
65 | | #else |
66 | | #define KINFO_PROC struct kinfo_proc |
67 | | #endif |
68 | | |
69 | | #if defined(XP_MACOSX) |
70 | | #define KP_FLAGS kp_proc.p_flag |
71 | | #elif defined(__DragonFly__) |
72 | | #define KP_FLAGS kp_flags |
73 | | #elif defined(__FreeBSD__) |
74 | | #define KP_FLAGS ki_flag |
75 | | #elif defined(__OpenBSD__) && !defined(_P_TRACED) |
76 | | #define KP_FLAGS p_psflags |
77 | | #define P_TRACED PS_TRACED |
78 | | #else |
79 | | #define KP_FLAGS p_flag |
80 | | #endif |
81 | | |
82 | | #include "mozilla/mozalloc_abort.h" |
83 | | |
84 | | static void |
85 | | Abort(const char* aMsg); |
86 | | |
87 | | static void |
88 | | RealBreak(); |
89 | | |
90 | | static void |
91 | | Break(const char* aMsg); |
92 | | |
93 | | #if defined(_WIN32) |
94 | | #include <windows.h> |
95 | | #include <signal.h> |
96 | | #include <malloc.h> // for _alloca |
97 | | #elif defined(XP_UNIX) |
98 | | #include <stdlib.h> |
99 | | #endif |
100 | | |
101 | | using namespace mozilla; |
102 | | |
103 | | static const char* sMultiprocessDescription = nullptr; |
104 | | |
105 | | static Atomic<int32_t> gAssertionCount; |
106 | | |
107 | | NS_IMPL_QUERY_INTERFACE(nsDebugImpl, nsIDebug2) |
108 | | |
109 | | NS_IMETHODIMP_(MozExternalRefCountType) |
110 | | nsDebugImpl::AddRef() |
111 | 513 | { |
112 | 513 | return 2; |
113 | 513 | } |
114 | | |
115 | | NS_IMETHODIMP_(MozExternalRefCountType) |
116 | | nsDebugImpl::Release() |
117 | 512 | { |
118 | 512 | return 1; |
119 | 512 | } |
120 | | |
121 | | NS_IMETHODIMP |
122 | | nsDebugImpl::Assertion(const char* aStr, const char* aExpr, |
123 | | const char* aFile, int32_t aLine) |
124 | 0 | { |
125 | 0 | NS_DebugBreak(NS_DEBUG_ASSERTION, aStr, aExpr, aFile, aLine); |
126 | 0 | return NS_OK; |
127 | 0 | } |
128 | | |
129 | | NS_IMETHODIMP |
130 | | nsDebugImpl::Warning(const char* aStr, const char* aFile, int32_t aLine) |
131 | 0 | { |
132 | 0 | NS_DebugBreak(NS_DEBUG_WARNING, aStr, nullptr, aFile, aLine); |
133 | 0 | return NS_OK; |
134 | 0 | } |
135 | | |
136 | | NS_IMETHODIMP |
137 | | nsDebugImpl::Break(const char* aFile, int32_t aLine) |
138 | 0 | { |
139 | 0 | NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, aFile, aLine); |
140 | 0 | return NS_OK; |
141 | 0 | } |
142 | | |
143 | | NS_IMETHODIMP |
144 | | nsDebugImpl::Abort(const char* aFile, int32_t aLine) |
145 | 0 | { |
146 | 0 | NS_DebugBreak(NS_DEBUG_ABORT, nullptr, nullptr, aFile, aLine); |
147 | 0 | return NS_OK; |
148 | 0 | } |
149 | | |
150 | | // From toolkit/library/rust/lib.rs |
151 | | extern "C" void intentional_panic(const char* message); |
152 | | |
153 | | NS_IMETHODIMP |
154 | | nsDebugImpl::RustPanic(const char* aMessage) |
155 | 0 | { |
156 | 0 | intentional_panic(aMessage); |
157 | 0 | return NS_OK; |
158 | 0 | } |
159 | | |
160 | | NS_IMETHODIMP |
161 | | nsDebugImpl::GetIsDebugBuild(bool* aResult) |
162 | 0 | { |
163 | | #ifdef DEBUG |
164 | | *aResult = true; |
165 | | #else |
166 | | *aResult = false; |
167 | 0 | #endif |
168 | 0 | return NS_OK; |
169 | 0 | } |
170 | | |
171 | | NS_IMETHODIMP |
172 | | nsDebugImpl::GetAssertionCount(int32_t* aResult) |
173 | 0 | { |
174 | 0 | *aResult = gAssertionCount; |
175 | 0 | return NS_OK; |
176 | 0 | } |
177 | | |
178 | | NS_IMETHODIMP |
179 | | nsDebugImpl::GetIsDebuggerAttached(bool* aResult) |
180 | 512 | { |
181 | 512 | *aResult = false; |
182 | 512 | |
183 | | #if defined(__OpenBSD__) && defined(MOZ_SANDBOX) |
184 | | // no access to KERN_PROC_PID sysctl when pledge'd |
185 | | return NS_OK; |
186 | | #endif |
187 | | #if defined(XP_WIN) |
188 | | *aResult = ::IsDebuggerPresent(); |
189 | | #elif defined(XP_MACOSX) || defined(__DragonFly__) || defined(__FreeBSD__) \ |
190 | | || defined(__NetBSD__) || defined(__OpenBSD__) |
191 | | // Specify the info we're looking for |
192 | | int mib[] = { |
193 | | CTL_KERN, |
194 | | KERN_PROC, |
195 | | KERN_PROC_PID, |
196 | | getpid(), |
197 | | #if defined(__NetBSD__) || defined(__OpenBSD__) |
198 | | sizeof(KINFO_PROC), |
199 | | 1, |
200 | | #endif |
201 | | }; |
202 | | u_int mibSize = sizeof(mib) / sizeof(int); |
203 | | |
204 | | KINFO_PROC info; |
205 | | size_t infoSize = sizeof(info); |
206 | | memset(&info, 0, infoSize); |
207 | | |
208 | | if (sysctl(mib, mibSize, &info, &infoSize, nullptr, 0)) { |
209 | | // if the call fails, default to false |
210 | | *aResult = false; |
211 | | return NS_OK; |
212 | | } |
213 | | |
214 | | if (info.KP_FLAGS & P_TRACED) { |
215 | | *aResult = true; |
216 | | } |
217 | | #endif |
218 | | |
219 | 512 | return NS_OK; |
220 | 512 | } |
221 | | |
222 | | /* static */ void |
223 | | nsDebugImpl::SetMultiprocessMode(const char* aDesc) |
224 | 0 | { |
225 | 0 | sMultiprocessDescription = aDesc; |
226 | 0 | } |
227 | | |
228 | | /* static */ const char * |
229 | | nsDebugImpl::GetMultiprocessMode() |
230 | 0 | { |
231 | 0 | return sMultiprocessDescription; |
232 | 0 | } |
233 | | |
234 | | /** |
235 | | * Implementation of the nsDebug methods. Note that this code is |
236 | | * always compiled in, in case some other module that uses it is |
237 | | * compiled with debugging even if this library is not. |
238 | | */ |
239 | | enum nsAssertBehavior |
240 | | { |
241 | | NS_ASSERT_UNINITIALIZED, |
242 | | NS_ASSERT_WARN, |
243 | | NS_ASSERT_SUSPEND, |
244 | | NS_ASSERT_STACK, |
245 | | NS_ASSERT_TRAP, |
246 | | NS_ASSERT_ABORT, |
247 | | NS_ASSERT_STACK_AND_ABORT |
248 | | }; |
249 | | |
250 | | static nsAssertBehavior |
251 | | GetAssertBehavior() |
252 | 0 | { |
253 | 0 | static nsAssertBehavior gAssertBehavior = NS_ASSERT_UNINITIALIZED; |
254 | 0 | if (gAssertBehavior != NS_ASSERT_UNINITIALIZED) { |
255 | 0 | return gAssertBehavior; |
256 | 0 | } |
257 | 0 | |
258 | 0 | gAssertBehavior = NS_ASSERT_WARN; |
259 | 0 |
|
260 | 0 | const char* assertString = PR_GetEnv("XPCOM_DEBUG_BREAK"); |
261 | 0 | if (!assertString || !*assertString) { |
262 | 0 | return gAssertBehavior; |
263 | 0 | } |
264 | 0 | if (!strcmp(assertString, "warn")) { |
265 | 0 | return gAssertBehavior = NS_ASSERT_WARN; |
266 | 0 | } |
267 | 0 | if (!strcmp(assertString, "suspend")) { |
268 | 0 | return gAssertBehavior = NS_ASSERT_SUSPEND; |
269 | 0 | } |
270 | 0 | if (!strcmp(assertString, "stack")) { |
271 | 0 | return gAssertBehavior = NS_ASSERT_STACK; |
272 | 0 | } |
273 | 0 | if (!strcmp(assertString, "abort")) { |
274 | 0 | return gAssertBehavior = NS_ASSERT_ABORT; |
275 | 0 | } |
276 | 0 | if (!strcmp(assertString, "trap") || !strcmp(assertString, "break")) { |
277 | 0 | return gAssertBehavior = NS_ASSERT_TRAP; |
278 | 0 | } |
279 | 0 | if (!strcmp(assertString, "stack-and-abort")) { |
280 | 0 | return gAssertBehavior = NS_ASSERT_STACK_AND_ABORT; |
281 | 0 | } |
282 | 0 | |
283 | 0 | fprintf(stderr, "Unrecognized value of XPCOM_DEBUG_BREAK\n"); |
284 | 0 | return gAssertBehavior; |
285 | 0 | } |
286 | | |
287 | | struct FixedBuffer final : public mozilla::PrintfTarget |
288 | | { |
289 | | FixedBuffer() : curlen(0) |
290 | 0 | { |
291 | 0 | buffer[0] = '\0'; |
292 | 0 | } |
293 | | |
294 | | char buffer[500]; |
295 | | uint32_t curlen; |
296 | | |
297 | | bool append(const char* sp, size_t len) override; |
298 | | }; |
299 | | |
300 | | bool |
301 | | FixedBuffer::append(const char* aBuf, size_t aLen) |
302 | 0 | { |
303 | 0 | if (!aLen) { |
304 | 0 | return true; |
305 | 0 | } |
306 | 0 | |
307 | 0 | if (curlen + aLen >= sizeof(buffer)) { |
308 | 0 | aLen = sizeof(buffer) - curlen - 1; |
309 | 0 | } |
310 | 0 |
|
311 | 0 | if (aLen) { |
312 | 0 | memcpy(buffer + curlen, aBuf, aLen); |
313 | 0 | curlen += aLen; |
314 | 0 | buffer[curlen] = '\0'; |
315 | 0 | } |
316 | 0 |
|
317 | 0 | return true; |
318 | 0 | } |
319 | | |
320 | | EXPORT_XPCOM_API(void) |
321 | | NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr, |
322 | | const char* aFile, int32_t aLine) |
323 | 0 | { |
324 | 0 | // Allow messages to be printed during GC if we are recording or replaying. |
325 | 0 | recordreplay::AutoEnsurePassThroughThreadEvents pt; |
326 | 0 |
|
327 | 0 | FixedBuffer nonPIDBuf; |
328 | 0 | FixedBuffer buf; |
329 | 0 | const char* sevString = "WARNING"; |
330 | 0 |
|
331 | 0 | switch (aSeverity) { |
332 | 0 | case NS_DEBUG_ASSERTION: |
333 | 0 | sevString = "###!!! ASSERTION"; |
334 | 0 | break; |
335 | 0 |
|
336 | 0 | case NS_DEBUG_BREAK: |
337 | 0 | sevString = "###!!! BREAK"; |
338 | 0 | break; |
339 | 0 |
|
340 | 0 | case NS_DEBUG_ABORT: |
341 | 0 | sevString = "###!!! ABORT"; |
342 | 0 | break; |
343 | 0 |
|
344 | 0 | default: |
345 | 0 | aSeverity = NS_DEBUG_WARNING; |
346 | 0 | } |
347 | 0 |
|
348 | 0 | nonPIDBuf.print("%s: ", sevString); |
349 | 0 | if (aStr) { |
350 | 0 | nonPIDBuf.print("%s: ", aStr); |
351 | 0 | } |
352 | 0 | if (aExpr) { |
353 | 0 | nonPIDBuf.print("'%s', ", aExpr); |
354 | 0 | } |
355 | 0 | if (aFile) { |
356 | 0 | nonPIDBuf.print("file %s, ", aFile); |
357 | 0 | } |
358 | 0 | if (aLine != -1) { |
359 | 0 | nonPIDBuf.print("line %d", aLine); |
360 | 0 | } |
361 | 0 |
|
362 | 0 | // Print "[PID]" or "[Desc PID]" at the beginning of the message. |
363 | 0 | buf.print("["); |
364 | 0 | if (sMultiprocessDescription) { |
365 | 0 | buf.print("%s ", sMultiprocessDescription); |
366 | 0 | } |
367 | 0 |
|
368 | 0 | bool isMainthread = (NS_IsMainThreadTLSInitialized() && NS_IsMainThread()); |
369 | 0 | PRThread *currentThread = PR_GetCurrentThread(); |
370 | 0 | const char *currentThreadName = isMainthread |
371 | 0 | ? "Main Thread" |
372 | 0 | : PR_GetThreadName(currentThread); |
373 | 0 | if(currentThreadName) { |
374 | 0 | buf.print("%d, %s] %s", base::GetCurrentProcId(), currentThreadName , nonPIDBuf.buffer); |
375 | 0 | } else { |
376 | 0 | buf.print("%d, Unnamed thread %p] %s", base::GetCurrentProcId(), currentThread, nonPIDBuf.buffer); |
377 | 0 | } |
378 | 0 |
|
379 | 0 | // errors on platforms without a debugdlg ring a bell on stderr |
380 | 0 | #if !defined(XP_WIN) |
381 | 0 | if (aSeverity != NS_DEBUG_WARNING) { |
382 | 0 | fprintf(stderr, "\07"); |
383 | 0 | } |
384 | 0 | #endif |
385 | 0 |
|
386 | | #ifdef ANDROID |
387 | | __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", buf.buffer); |
388 | | #endif |
389 | |
|
390 | 0 | // Write the message to stderr unless it's a warning and MOZ_IGNORE_WARNINGS |
391 | 0 | // is set. |
392 | 0 | if (!(PR_GetEnv("MOZ_IGNORE_WARNINGS") && aSeverity == NS_DEBUG_WARNING)) { |
393 | 0 | fprintf(stderr, "%s\n", buf.buffer); |
394 | 0 | fflush(stderr); |
395 | 0 | } |
396 | 0 |
|
397 | 0 | switch (aSeverity) { |
398 | 0 | case NS_DEBUG_WARNING: |
399 | 0 | return; |
400 | 0 |
|
401 | 0 | case NS_DEBUG_BREAK: |
402 | 0 | Break(buf.buffer); |
403 | 0 | return; |
404 | 0 |
|
405 | 0 | case NS_DEBUG_ABORT: { |
406 | 0 | // Updating crash annotations in the child causes us to do IPC. This can |
407 | 0 | // really cause trouble if we're asserting from within IPC code. So we |
408 | 0 | // have to do without the annotations in that case. |
409 | 0 | if (XRE_IsParentProcess()) { |
410 | 0 | // Don't include the PID in the crash report annotation to |
411 | 0 | // allow faceting on crash-stats.mozilla.org. |
412 | 0 | nsCString note("xpcom_runtime_abort("); |
413 | 0 | note += nonPIDBuf.buffer; |
414 | 0 | note += ")"; |
415 | 0 | CrashReporter::AppendAppNotesToCrashReport(note); |
416 | 0 | CrashReporter::AnnotateCrashReport( |
417 | 0 | CrashReporter::Annotation::AbortMessage, |
418 | 0 | nsDependentCString(nonPIDBuf.buffer)); |
419 | 0 | } |
420 | 0 |
|
421 | | #if defined(DEBUG) && defined(_WIN32) |
422 | | RealBreak(); |
423 | | #endif |
424 | | #if defined(DEBUG) |
425 | | nsTraceRefcnt::WalkTheStack(stderr); |
426 | | #endif |
427 | | Abort(buf.buffer); |
428 | 0 | return; |
429 | 0 | } |
430 | 0 | } |
431 | 0 |
|
432 | 0 | // Now we deal with assertions |
433 | 0 | gAssertionCount++; |
434 | 0 |
|
435 | 0 | switch (GetAssertBehavior()) { |
436 | 0 | case NS_ASSERT_WARN: |
437 | 0 | return; |
438 | 0 |
|
439 | 0 | case NS_ASSERT_SUSPEND: |
440 | 0 | #ifdef XP_UNIX |
441 | 0 | fprintf(stderr, "Suspending process; attach with the debugger.\n"); |
442 | 0 | kill(0, SIGSTOP); |
443 | | #else |
444 | | Break(buf.buffer); |
445 | | #endif |
446 | | return; |
447 | 0 |
|
448 | 0 | case NS_ASSERT_STACK: |
449 | 0 | nsTraceRefcnt::WalkTheStack(stderr); |
450 | 0 | return; |
451 | 0 |
|
452 | 0 | case NS_ASSERT_STACK_AND_ABORT: |
453 | 0 | nsTraceRefcnt::WalkTheStack(stderr); |
454 | 0 | // Fall through to abort |
455 | 0 | MOZ_FALLTHROUGH; |
456 | 0 |
|
457 | 0 | case NS_ASSERT_ABORT: |
458 | 0 | Abort(buf.buffer); |
459 | 0 | return; |
460 | 0 |
|
461 | 0 | case NS_ASSERT_TRAP: |
462 | 0 | case NS_ASSERT_UNINITIALIZED: // Default to "trap" behavior |
463 | 0 | Break(buf.buffer); |
464 | 0 | return; |
465 | 0 | } |
466 | 0 | } |
467 | | |
468 | | static void |
469 | | Abort(const char* aMsg) |
470 | 0 | { |
471 | 0 | mozalloc_abort(aMsg); |
472 | 0 | } |
473 | | |
474 | | static void |
475 | | RealBreak() |
476 | 0 | { |
477 | | #if defined(_WIN32) |
478 | | ::DebugBreak(); |
479 | | #elif defined(XP_MACOSX) |
480 | | raise(SIGTRAP); |
481 | | #elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__)) |
482 | | asm("int $3"); |
483 | | #elif defined(__arm__) |
484 | | asm( |
485 | | #ifdef __ARM_ARCH_4T__ |
486 | | /* ARMv4T doesn't support the BKPT instruction, so if the compiler target |
487 | | * is ARMv4T, we want to ensure the assembler will understand that ARMv5T |
488 | | * instruction, while keeping the resulting object tagged as ARMv4T. |
489 | | */ |
490 | | ".arch armv5t\n" |
491 | | ".object_arch armv4t\n" |
492 | | #endif |
493 | | "BKPT #0"); |
494 | | #elif defined(__aarch64__) |
495 | | asm("brk #0"); |
496 | | #elif defined(SOLARIS) |
497 | | #if defined(__i386__) || defined(__i386) || defined(__x86_64__) |
498 | | asm("int $3"); |
499 | | #else |
500 | | raise(SIGTRAP); |
501 | | #endif |
502 | | #else |
503 | | #warning do not know how to break on this platform |
504 | | #endif |
505 | | } |
506 | | |
507 | | // Abort() calls this function, don't call it! |
508 | | static void |
509 | | Break(const char* aMsg) |
510 | 0 | { |
511 | | #if defined(_WIN32) |
512 | | static int ignoreDebugger; |
513 | | if (!ignoreDebugger) { |
514 | | const char* shouldIgnoreDebugger = getenv("XPCOM_DEBUG_DLG"); |
515 | | ignoreDebugger = |
516 | | 1 + (shouldIgnoreDebugger && !strcmp(shouldIgnoreDebugger, "1")); |
517 | | } |
518 | | if ((ignoreDebugger == 2) || !::IsDebuggerPresent()) { |
519 | | DWORD code = IDRETRY; |
520 | | |
521 | | /* Create the debug dialog out of process to avoid the crashes caused by |
522 | | * Windows events leaking into our event loop from an in process dialog. |
523 | | * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg). |
524 | | * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792 |
525 | | */ |
526 | | PROCESS_INFORMATION pi; |
527 | | STARTUPINFOW si; |
528 | | wchar_t executable[MAX_PATH]; |
529 | | wchar_t* pName; |
530 | | |
531 | | memset(&pi, 0, sizeof(pi)); |
532 | | |
533 | | memset(&si, 0, sizeof(si)); |
534 | | si.cb = sizeof(si); |
535 | | si.wShowWindow = SW_SHOW; |
536 | | |
537 | | // 2nd arg of CreateProcess is in/out |
538 | | wchar_t* msgCopy = (wchar_t*)_alloca((strlen(aMsg) + 1) * sizeof(wchar_t)); |
539 | | wcscpy(msgCopy, NS_ConvertUTF8toUTF16(aMsg).get()); |
540 | | |
541 | | if (GetModuleFileNameW(GetModuleHandleW(L"xpcom.dll"), executable, MAX_PATH) && |
542 | | (pName = wcsrchr(executable, '\\')) != nullptr && |
543 | | wcscpy(pName + 1, L"windbgdlg.exe") && |
544 | | CreateProcessW(executable, msgCopy, nullptr, nullptr, |
545 | | false, DETACHED_PROCESS | NORMAL_PRIORITY_CLASS, |
546 | | nullptr, nullptr, &si, &pi)) { |
547 | | WaitForSingleObject(pi.hProcess, INFINITE); |
548 | | GetExitCodeProcess(pi.hProcess, &code); |
549 | | CloseHandle(pi.hProcess); |
550 | | CloseHandle(pi.hThread); |
551 | | } |
552 | | |
553 | | switch (code) { |
554 | | case IDABORT: |
555 | | //This should exit us |
556 | | raise(SIGABRT); |
557 | | //If we are ignored exit this way.. |
558 | | _exit(3); |
559 | | |
560 | | case IDIGNORE: |
561 | | return; |
562 | | } |
563 | | } |
564 | | |
565 | | RealBreak(); |
566 | | #elif defined(XP_MACOSX) |
567 | | /* Note that we put this Mac OS X test above the GNUC/x86 test because the |
568 | | * GNUC/x86 test is also true on Intel Mac OS X and we want the PPC/x86 |
569 | | * impls to be the same. |
570 | | */ |
571 | | RealBreak(); |
572 | | #elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__)) |
573 | | RealBreak(); |
574 | | #elif defined(__arm__) || defined(__aarch64__) |
575 | | RealBreak(); |
576 | | #elif defined(SOLARIS) |
577 | | RealBreak(); |
578 | | #else |
579 | | #warning do not know how to break on this platform |
580 | | #endif |
581 | | } |
582 | | |
583 | | nsresult |
584 | | nsDebugImpl::Create(nsISupports* aOuter, const nsIID& aIID, void** aInstancePtr) |
585 | 1 | { |
586 | 1 | static const nsDebugImpl* sImpl; |
587 | 1 | |
588 | 1 | if (NS_WARN_IF(aOuter)) { |
589 | 0 | return NS_ERROR_NO_AGGREGATION; |
590 | 0 | } |
591 | 1 | |
592 | 1 | if (!sImpl) { |
593 | 1 | sImpl = new nsDebugImpl(); |
594 | 1 | } |
595 | 1 | |
596 | 1 | return const_cast<nsDebugImpl*>(sImpl)->QueryInterface(aIID, aInstancePtr); |
597 | 1 | } |
598 | | |
599 | | //////////////////////////////////////////////////////////////////////////////// |
600 | | |
601 | | nsresult |
602 | | NS_ErrorAccordingToNSPR() |
603 | | { |
604 | | PRErrorCode err = PR_GetError(); |
605 | | switch (err) { |
606 | | case PR_OUT_OF_MEMORY_ERROR: return NS_ERROR_OUT_OF_MEMORY; |
607 | | case PR_WOULD_BLOCK_ERROR: return NS_BASE_STREAM_WOULD_BLOCK; |
608 | | case PR_FILE_NOT_FOUND_ERROR: return NS_ERROR_FILE_NOT_FOUND; |
609 | | case PR_READ_ONLY_FILESYSTEM_ERROR: return NS_ERROR_FILE_READ_ONLY; |
610 | | case PR_NOT_DIRECTORY_ERROR: return NS_ERROR_FILE_NOT_DIRECTORY; |
611 | | case PR_IS_DIRECTORY_ERROR: return NS_ERROR_FILE_IS_DIRECTORY; |
612 | | case PR_LOOP_ERROR: return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK; |
613 | | case PR_FILE_EXISTS_ERROR: return NS_ERROR_FILE_ALREADY_EXISTS; |
614 | | case PR_FILE_IS_LOCKED_ERROR: return NS_ERROR_FILE_IS_LOCKED; |
615 | | case PR_FILE_TOO_BIG_ERROR: return NS_ERROR_FILE_TOO_BIG; |
616 | | case PR_NO_DEVICE_SPACE_ERROR: return NS_ERROR_FILE_NO_DEVICE_SPACE; |
617 | | case PR_NAME_TOO_LONG_ERROR: return NS_ERROR_FILE_NAME_TOO_LONG; |
618 | | case PR_DIRECTORY_NOT_EMPTY_ERROR: return NS_ERROR_FILE_DIR_NOT_EMPTY; |
619 | | case PR_NO_ACCESS_RIGHTS_ERROR: return NS_ERROR_FILE_ACCESS_DENIED; |
620 | | default: return NS_ERROR_FAILURE; |
621 | | } |
622 | | } |
623 | | |
624 | | void |
625 | | NS_ABORT_OOM(size_t aSize) |
626 | 0 | { |
627 | 0 | CrashReporter::AnnotateOOMAllocationSize(aSize); |
628 | 0 | MOZ_CRASH("OOM"); |
629 | 0 | } |