/* 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/. */
/* * This custom library loading code is only meant to be called * during initialization. As a result, it takes no special * precautions to be threadsafe. Any of the library loading functions * like mozload should not be available to other code.
*/
#ifndef RELEASE_OR_BETA /* Official builds have the debuggable flag set to false, which disables * the backtrace dumper from bionic. However, as it is useful for native * crashes happening before the crash reporter is registered, re-enable * it on non release builds (i.e. nightly and aurora). * Using a constructor so that it is re-enabled as soon as libmozglue.so * is loaded.
*/
__attribute__((constructor)) void make_dumpable() { prctl(PR_SET_DUMPABLE, 1); } #endif
typedefint mozglueresult;
using LoadGeckoLibsResult =
mozilla::Result<mozilla::Ok, mozilla::BootstrapError>;
Dl_info info = {}; if ((sigact.sa_flags & SA_SIGINFO) &&
__wrap_dladdr(reinterpret_cast<void*>(sigact.sa_sigaction), &info) &&
info.dli_fname && strstr(info.dli_fname, "libxul.so")) { return; // Existing signal handler is in libxul (i.e. we have crash // reporter).
}
staticvoid EnsureBaseProfilerInitialized() { // There is no single entry-point into C++ code on Android. // Instead, GeckoThread and GeckoLibLoader call various functions to load // libraries one-by-one. // We want to capture all that library loading in the profiler, so we need to // kick off the base profiler at the beginning of whichever function is called // first. // We currently assume that all these functions are called on the same thread. staticbool sInitialized = false; if (sInitialized) { return;
}
// The stack depth we observe here will be determined by the stack of // whichever caller enters this code first. In practice this means that we may // miss some root-most frames, which hopefully shouldn't ruin profiling. int stackBase = 5;
mozilla::baseprofiler::profiler_init(&stackBase);
sInitialized = true;
}
static mozglueresult loadSQLiteLibs() { if (sqlite_handle) return SUCCESS;
#ifdef MOZ_FOLD_LIBS if (loadNSSLibs() != SUCCESS) return FAILURE; #else
sqlite_handle = dlopenLibrary("libmozsqlite3.so"); if (!sqlite_handle) {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libmozsqlite3!"); return FAILURE;
} #endif
if (!nss_handle) {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnss3!"); return FAILURE;
}
#ifndef MOZ_FOLD_LIBS if (!nspr_handle) {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnspr4!"); return FAILURE;
}
if (!plc_handle) {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libplc4!"); return FAILURE;
} #endif
staticvoid FreeArgv(char** argv, int argc) { for (int ix = 0; ix < argc; ix++) { // String was allocated with strndup, so need to use free to deallocate.
free(argv[ix]);
} delete[] (argv);
}
int argc = 0; char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
if (!jfds) { if (gBootstrap == nullptr) {
FreeArgv(argv, argc); return;
}
#ifdef MOZ_LINKER
ElfLoader::Singleton.ExpectShutdown(false); #endif
gBootstrap->XRE_SetGeckoThreadEnv(jenv); if (!argv) {
__android_log_print(ANDROID_LOG_FATAL, "mozglue", "Failed to get arguments for %s",
xpcshell ? "XRE_XPCShellMain" : "XRE_main"); return;
} if (xpcshell) {
MOZ_ASSERT(outFilePath); constchar* outFilePathRaw =
jenv->GetStringUTFChars(outFilePath, nullptr);
FILE* outFile = outFilePathRaw ? fopen(outFilePathRaw, "w") : nullptr; if (outFile) {
XREShellData shellData; // We redirect both stdout and stderr to the same file, to conform with // what runxpcshell.py does on Desktop.
shellData.outFile = outFile;
shellData.errFile = outFile; int result =
gBootstrap->XRE_XPCShellMain(argc, argv, nullptr, &shellData);
fclose(shellData.outFile); if (result) {
__android_log_print(ANDROID_LOG_INFO, "mozglue", "XRE_XPCShellMain returned %d", result);
}
} else {
__android_log_print(ANDROID_LOG_FATAL, "mozglue", "XRE_XPCShellMain cannot open %s", outFilePathRaw);
} if (outFilePathRaw) {
jenv->ReleaseStringUTFChars(outFilePath, outFilePathRaw);
}
} else {
BootstrapConfig config;
config.appData = &sAppData;
config.appDataPath = nullptr;
int result = gBootstrap->XRE_main(argc, argv, config); if (result) {
__android_log_print(ANDROID_LOG_INFO, "mozglue", "XRE_main returned %d",
result);
}
} #ifdef MOZ_LINKER
ElfLoader::Singleton.ExpectShutdown(true); #endif
} else { if (argc < 2) {
FreeArgv(argv, argc); return;
}
SetGeckoProcessType(argv[--argc]);
SetGeckoChildID(argv[--argc]); #ifdefined(MOZ_MEMORY) // XRE_IsContentProcess is not accessible here
jemalloc_reset_small_alloc_randomization( /* aRandomizeSmall */ GetGeckoProcessType() !=
GeckoProcessType_Content); #endif
// Does current process name end with ':media'? staticbool IsMediaProcess() {
pid_t pid = getpid(); char str[256];
SprintfLiteral(str, "/proc/%d/cmdline", pid);
FILE* f = fopen(str, "r"); if (f) {
fgets(str, sizeof(str), f);
fclose(f); const size_t strLen = strlen(str); constchar suffix[] = ":media"; const size_t suffixLen = sizeof(suffix) - 1; if (strLen >= suffixLen &&
!strncmp(str + strLen - suffixLen, suffix, suffixLen)) { returntrue;
}
} returnfalse;
}
#ifndef SYS_rt_tgsigqueueinfo # define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo #endif /* Copy of http://androidxref.com/7.1.1_r6/xref/bionic/linker/debugger.cpp#262, * with debuggerd related code stripped. * * Copyright (C) 2008 The Android Open Source Project * 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. * * 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.
*/ staticvoid CatchFatalSignals(int num, siginfo_t* info, void* context) { // It's possible somebody cleared the SA_SIGINFO flag, which would mean // our "info" arg holds an undefined value. struct sigaction action = {}; if ((sigaction(num, nullptr, &action) < 0) ||
!(action.sa_flags & SA_SIGINFO)) {
info = nullptr;
}
// We need to return from the signal handler so that debuggerd can dump the // thread that crashed, but returning here does not guarantee that the signal // will be thrown again, even for SIGSEGV and friends, since the signal could // have been sent manually. Resend the signal with rt_tgsigqueueinfo(2) to // preserve the SA_SIGINFO contents.
signal(num, SIG_DFL);
struct siginfo si; if (!info) {
memset(&si, 0, sizeof(si));
si.si_code = SI_USER;
si.si_pid = getpid();
si.si_uid = getuid();
info = &si;
} elseif (info->si_code >= 0 || info->si_code == SI_TKILL) { // rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels // that contain commit 66dd34a (3.9+). The manpage claims to only allow // negative si_code values that are not SI_TKILL, but 66dd34a changed the // check to allow all si_code values in calls coming from inside the house.
}
int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), num, info); if (rc != 0) {
__android_log_print(ANDROID_LOG_FATAL, "mozglue", "failed to resend signal during crash: %s",
strerror(errno));
_exit(0);
}
}
extern"C" APKOPEN_EXPORT void MOZ_JNICALL
Java_org_mozilla_gecko_mozglue_GeckoLoader_suppressCrashDialog(JNIEnv* jenv,
jclass jc) {
MOZ_RELEASE_ASSERT(IsMediaProcess(), "Suppress crash dialog only for media process"); // Restoring to SIG_DFL will crash on x86/Android M devices (see bug 1374556) // so copy Android code // (http://androidxref.com/7.1.1_r6/xref/bionic/linker/debugger.cpp#302). See // comments above CatchFatalSignals() for copyright notice. struct sigaction action;
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_sigaction = &CatchFatalSignals;
action.sa_flags = SA_RESTART | SA_SIGINFO;
// Use the alternate signal stack if available so we can catch stack // overflows.
action.sa_flags |= SA_ONSTACK;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.2Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.