Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "mozilla/mozalloc_abort.h"
9 :
10 : #ifdef ANDROID
11 : # include <android/log.h>
12 : #endif
13 : #ifdef MOZ_WIDGET_ANDROID
14 : # include "APKOpen.h"
15 : # include "dlfcn.h"
16 : #endif
17 : #include <stdio.h>
18 :
19 : #include "mozilla/Assertions.h"
20 :
21 : void
22 0 : mozalloc_abort(const char* const msg)
23 : {
24 : #ifndef ANDROID
25 0 : fputs(msg, stderr);
26 0 : fputs("\n", stderr);
27 : #else
28 : __android_log_print(ANDROID_LOG_ERROR, "Gecko", "mozalloc_abort: %s", msg);
29 : #endif
30 : #ifdef MOZ_WIDGET_ANDROID
31 : abortThroughJava(msg);
32 : #endif
33 0 : MOZ_CRASH();
34 : }
35 :
36 : #ifdef MOZ_WIDGET_ANDROID
37 : template <size_t N>
38 : void fillAbortMessage(char (&msg)[N], uintptr_t retAddress) {
39 : /*
40 : * On Android, we often don't have reliable backtrace when crashing inside
41 : * abort(). Therefore, we try to find out who is calling abort() and add
42 : * that to the message.
43 : */
44 : Dl_info info = {};
45 : dladdr(reinterpret_cast<void*>(retAddress), &info);
46 :
47 : const char* const module = info.dli_fname ? info.dli_fname : "";
48 : const char* const base_module = strrchr(module, '/');
49 : const void* const module_offset =
50 : reinterpret_cast<void*>(retAddress - uintptr_t(info.dli_fbase));
51 : const char* const sym = info.dli_sname ? info.dli_sname : "";
52 :
53 : snprintf(msg, sizeof(msg), "abort() called from %s:%p (%s)",
54 : base_module ? base_module + 1 : module, module_offset, sym);
55 : }
56 : #endif
57 :
58 : #if defined(XP_UNIX) && !defined(MOZ_ASAN)
59 : // Define abort() here, so that it is used instead of the system abort(). This
60 : // lets us control the behavior when aborting, in order to get better results
61 : // on *NIX platforms. See mozalloc_abort for details.
62 : //
63 : // For AddressSanitizer, we must not redefine system abort because the ASan
64 : // option "abort_on_error=1" calls abort() and therefore causes the following
65 : // call chain with our redefined abort:
66 : //
67 : // ASan -> abort() -> moz_abort() -> MOZ_CRASH() -> Segmentation fault
68 : //
69 : // That segmentation fault will be interpreted as another bug by ASan and as a
70 : // result, ASan will just exit(1) instead of aborting.
71 0 : extern "C" void abort(void)
72 : {
73 : #ifdef MOZ_WIDGET_ANDROID
74 : char msg[64] = {};
75 : fillAbortMessage(msg, uintptr_t(__builtin_return_address(0)));
76 : #else
77 0 : const char* const msg = "Redirecting call to abort() to mozalloc_abort\n";
78 : #endif
79 :
80 0 : mozalloc_abort(msg);
81 :
82 : // We won't reach here because mozalloc_abort() is MOZ_NORETURN. But that
83 : // annotation isn't used on ARM (see mozalloc_abort.h for why) so we add a
84 : // redundant MOZ_CRASH() here to avoid a "'noreturn' function does return"
85 : // warning.
86 : MOZ_CRASH();
87 : }
88 : #endif
89 :
|