#include <linux/fs.h>
#include <cutils/fs.h>
#include <unistd.h>
+#ifdef HAVE_ANDROID_OS
+#include <sys/prctl.h>
+#endif
#include "Dalvik.h"
#include "test/Test.h"
dvmFprintf(stderr, " -Xzygote\n");
dvmFprintf(stderr, " -Xdexopt:{none,verified,all,full}\n");
dvmFprintf(stderr, " -Xnoquithandler\n");
- dvmFprintf(stderr,
- " -Xjnigreflimit:N (must be multiple of 100, >= 200)\n");
dvmFprintf(stderr, " -Xjniopts:{warnonly,forcecopy}\n");
dvmFprintf(stderr, " -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
dvmFprintf(stderr, " -Xstacktracefile:<filename>\n");
"[,hexopvalue[-endvalue]]*\n");
dvmFprintf(stderr, " -Xincludeselectedmethod\n");
dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n");
+ dvmFprintf(stderr, " -Xjitcodecachesize:decimalvalueofkbytes\n");
dvmFprintf(stderr, " -Xjitblocking\n");
dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* "
"(eg Ljava/lang/String\\;replace)\n");
dvmFprintf(stderr, "Invalid -XX:HeapMaxFree option '%s'\n", argv[i]);
return -1;
}
+ } else if (strcmp(argv[i], "-XX:LowMemoryMode") == 0) {
+ gDvm.lowMemoryMode = true;
} else if (strncmp(argv[i], "-XX:HeapTargetUtilization=", 26) == 0) {
const char* start = argv[i] + 26;
const char* end = start;
return -1;
}
} else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
- int lim = atoi(argv[i] + 15);
- if (lim < 200 || (lim % 100) != 0) {
- dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
- argv[i]+15);
- return -1;
- }
- gDvm.jniGrefLimit = lim;
+ // Ignored for backwards compatibility.
} else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
gDvm.jniTrace = strdup(argv[i] + 11);
} else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
gDvmJit.blockingMode = true;
} else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
gDvmJit.threshold = atoi(argv[i] + 15);
+ } else if (strncmp(argv[i], "-Xjitcodecachesize:", 19) == 0) {
+ gDvmJit.codeCacheSize = atoi(argv[i] + 19) * 1024;
+ if (gDvmJit.codeCacheSize == 0) {
+ gDvm.executionMode = kExecutionModeInterpFast;
+ }
} else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
gDvmJit.includeSelectedOp = true;
} else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
gDvm.heapStartingSize = 2 * 1024 * 1024; // Spec says 16MB; too big for us.
gDvm.heapMaximumSize = 16 * 1024 * 1024; // Spec says 75% physical mem
gDvm.heapGrowthLimit = 0; // 0 means no growth limit
+ gDvm.lowMemoryMode = false;
gDvm.stackSize = kDefaultStackSize;
gDvm.mainThreadStackSize = kDefaultStackSize;
// When the heap is less than the maximum or growth limited size,
gDvmJit.includeSelectedOffset = false;
gDvmJit.methodTable = NULL;
gDvmJit.classTable = NULL;
+ gDvmJit.codeCacheSize = DEFAULT_CODE_CACHE_SIZE;
gDvm.constInit = false;
gDvm.commonInit = false;
#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
sigaddset(&mask, SIGUSR2); // used to investigate JIT internals
#endif
- //sigaddset(&mask, SIGPIPE);
+ sigaddset(&mask, SIGPIPE);
cc = sigprocmask(SIG_BLOCK, &mask, NULL);
assert(cc == 0);
// First set up JniConstants, which is used by libcore.
JniConstants::init(pEnv);
+ // Set up our single JNI method.
+ // TODO: factor this out if we add more.
+ jclass c = pEnv->FindClass("java/lang/Class");
+ if (c == NULL) {
+ dvmAbort();
+ }
+ JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass);
+ const JNINativeMethod Java_java_lang_Class[] = {
+ { "getDex", "()Lcom/android/dex/Dex;", (void*) Java_java_lang_Class_getDex },
+ };
+ if (pEnv->RegisterNatives(c, Java_java_lang_Class, 1) != JNI_OK) {
+ dvmAbort();
+ }
+
// Most JNI libraries can just use System.loadLibrary, but you can't
// if you're the library that implements System.loadLibrary!
loadJniLibrary("javacore");
return true;
}
+/*
+ * Copied and modified slightly from system/core/toolbox/mount.c
+ */
+static std::string getMountsDevDir(const char *arg)
+{
+ char mount_dev[256];
+ char mount_dir[256];
+ int match;
+
+ FILE *fp = fopen("/proc/self/mounts", "r");
+ if (fp == NULL) {
+ ALOGE("Could not open /proc/self/mounts: %s", strerror(errno));
+ return "";
+ }
+
+ while ((match = fscanf(fp, "%255s %255s %*s %*s %*d %*d\n", mount_dev, mount_dir)) != EOF) {
+ mount_dev[255] = 0;
+ mount_dir[255] = 0;
+ if (match == 2 && (strcmp(arg, mount_dir) == 0)) {
+ fclose(fp);
+ return mount_dev;
+ }
+ }
+
+ fclose(fp);
+ return "";
+}
/*
* Do zygote-mode-only initialization.
const char* target_base = getenv("EMULATED_STORAGE_TARGET");
if (target_base != NULL) {
if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
- "uid=0,gid=1028,mode=0050") == -1) {
+ "uid=0,gid=1028,mode=0751") == -1) {
SLOGE("Failed to mount tmpfs to %s: %s", target_base, strerror(errno));
return -1;
}
}
+ // Mark /system as NOSUID | NODEV
+ const char* android_root = getenv("ANDROID_ROOT");
+
+ if (android_root == NULL) {
+ SLOGE("environment variable ANDROID_ROOT does not exist?!?!");
+ return -1;
+ }
+
+ std::string mountDev(getMountsDevDir(android_root));
+ if (mountDev.empty()) {
+ SLOGE("Unable to find mount point for %s", android_root);
+ return -1;
+ }
+
+ if (mount(mountDev.c_str(), android_root, "none",
+ MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_RDONLY | MS_BIND, NULL) == -1) {
+ SLOGE("Remount of %s failed: %s", android_root, strerror(errno));
+ return -1;
+ }
+
+#ifdef HAVE_ANDROID_OS
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+ // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
+ // EINVAL. Don't die on such kernels.
+ if (errno != EINVAL) {
+ SLOGE("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
+ return -1;
+ }
+ }
+#endif
+
return true;
}
*/
dvmPrintNativeBackTrace();
- /*
- * If we call abort(), all threads in the process receives a SIBABRT.
- * debuggerd dumps the stack trace of the main thread, whether or not
- * that was the thread that failed.
- *
- * By stuffing a value into a bogus address, we cause a segmentation
- * fault in the current thread, and get a useful log from debuggerd.
- * We can also trivially tell the difference between a VM crash and
- * a deliberate abort by looking at the fault address.
- */
- *((char*)0xdeadd00d) = result;
abort();
/* notreached */