/* * Copyright 2007 The Android Open Source Project * * Initialize the intercepts. */ #include "Common.h" #define __USE_GNU /* need RTLD_NEXT */ #include <dlfcn.h> #include <stdlib.h> #include <pthread.h> #include <string.h> #include <errno.h> #include <assert.h> #include <sys/stat.h> #include <sys/types.h> /* * Global state. */ struct WrapSimGlobals gWrapSim; pthread_once_t gWrapSimInitialized = PTHREAD_ONCE_INIT; /* * Initialize our global state. */ static void initGlobals(void) { memset(&gWrapSim, 0xdd, sizeof(gWrapSim)); gWrapSim.logFd = -1; gWrapSim.keyMap = NULL; /* * Find the original version of functions we override. */ _ws_access = dlsym(RTLD_NEXT, "access"); _ws_open = dlsym(RTLD_NEXT, "open"); _ws_open64 = dlsym(RTLD_NEXT, "open64"); _ws_close = dlsym(RTLD_NEXT, "close"); _ws_read = dlsym(RTLD_NEXT, "read"); _ws_readv = dlsym(RTLD_NEXT, "readv"); _ws_write = dlsym(RTLD_NEXT, "write"); _ws_writev = dlsym(RTLD_NEXT, "writev"); _ws_mmap = dlsym(RTLD_NEXT, "mmap"); _ws_mmap64 = dlsym(RTLD_NEXT, "mmap64"); _ws_ioctl = dlsym(RTLD_NEXT, "ioctl"); _ws_chdir = dlsym(RTLD_NEXT, "chdir"); _ws_chmod = dlsym(RTLD_NEXT, "chmod"); _ws_chown = dlsym(RTLD_NEXT, "chown"); _ws_creat = dlsym(RTLD_NEXT, "creat"); _ws_execve = dlsym(RTLD_NEXT, "execve"); _ws_getcwd = dlsym(RTLD_NEXT, "getcwd"); _ws_lchown = dlsym(RTLD_NEXT, "lchown"); _ws_link = dlsym(RTLD_NEXT, "link"); _ws_lstat = dlsym(RTLD_NEXT, "lstat"); _ws_lstat64 = dlsym(RTLD_NEXT, "lstat64"); _ws___lxstat = dlsym(RTLD_NEXT, "__lxstat"); _ws___lxstat64 = dlsym(RTLD_NEXT, "__lxstat64"); _ws_mkdir = dlsym(RTLD_NEXT, "mkdir"); _ws_readlink = dlsym(RTLD_NEXT, "readlink"); _ws_rename = dlsym(RTLD_NEXT, "rename"); _ws_rmdir = dlsym(RTLD_NEXT, "rmdir"); _ws_stat = dlsym(RTLD_NEXT, "stat"); _ws_stat64 = dlsym(RTLD_NEXT, "stat64"); _ws___xstat = dlsym(RTLD_NEXT, "__xstat"); _ws___xstat64 = dlsym(RTLD_NEXT, "__xstat64"); _ws_statfs = dlsym(RTLD_NEXT, "statfs"); _ws_statfs64 = dlsym(RTLD_NEXT, "statfs64"); _ws_symlink = dlsym(RTLD_NEXT, "symlink"); _ws_unlink = dlsym(RTLD_NEXT, "unlink"); _ws_utime = dlsym(RTLD_NEXT, "utime"); _ws_utimes = dlsym(RTLD_NEXT, "utimes"); _ws_execl = dlsym(RTLD_NEXT, "execl"); _ws_execle = dlsym(RTLD_NEXT, "execle"); _ws_execlp = dlsym(RTLD_NEXT, "execlp"); _ws_execv = dlsym(RTLD_NEXT, "execv"); _ws_execvp = dlsym(RTLD_NEXT, "execvp"); _ws_fopen = dlsym(RTLD_NEXT, "fopen"); _ws_fopen64 = dlsym(RTLD_NEXT, "fopen64"); _ws_freopen = dlsym(RTLD_NEXT, "freopen"); _ws_ftw = dlsym(RTLD_NEXT, "ftw"); _ws_opendir = dlsym(RTLD_NEXT, "opendir"); _ws_dlopen = dlsym(RTLD_NEXT, "dlopen"); _ws_setpriority = dlsym(RTLD_NEXT, "setpriority"); //_ws_pipe = dlsym(RTLD_NEXT, "pipe"); const char* logFileName = getenv("WRAPSIM_LOG"); if (logFileName != NULL ){ gWrapSim.logFd = _ws_open(logFileName, O_WRONLY|O_APPEND|O_CREAT, 0664); } /* log messages now work; say hello */ wsLog("--- initializing sim wrapper ---\n"); gWrapSim.simulatorFd = -1; pthread_mutex_init(&gWrapSim.startLock, NULL); pthread_cond_init(&gWrapSim.startCond, NULL); gWrapSim.startReady = 0; pthread_mutex_init(&gWrapSim.fakeFdLock, NULL); gWrapSim.fakeFdMap = wsAllocBitVector(kMaxFakeFdCount, 0); memset(gWrapSim.fakeFdList, 0, sizeof(gWrapSim.fakeFdList)); gWrapSim.numDisplays = 0; gWrapSim.keyInputDevice = NULL; /* * Get target for remapped "/system" and "/data". * * The ANDROID_PRODUCT_OUT env var *must* be set for rewriting to work. */ const char* outEnv = getenv("ANDROID_PRODUCT_OUT"); if (outEnv == NULL) { gWrapSim.remapBaseDir = NULL; wsLog("--- $ANDROID_PRODUCT_OUT not set, " "filename remapping disabled\n"); } else { /* grab string and append '/' -- note this never gets freed */ gWrapSim.remapBaseDirLen = strlen(outEnv); gWrapSim.remapBaseDir = strdup(outEnv); wsLog("--- name remap to %s\n", gWrapSim.remapBaseDir); } gWrapSim.initialized = 1; } /* * Creates a directory, or prints a log message if it fails. */ static int createTargetDirectory(const char *path, mode_t mode) { int ret; ret = mkdir(path, mode); if (ret == 0 || errno == EEXIST) { return 0; } wsLog("--- could not create target directory %s: %s\n", path, strerror(errno)); return ret; } /* * Any setup that would normally be done by init(8). * Note that since the syscall redirects have been installed * at this point, we are effectively operating within the * simulation context. */ static void initGeneral(void) { wsLog("--- preparing system\n"); /* Try to make sure that certain directories exist. * If we fail to create them, the errors will show up in the log, * but we keep going. */ createTargetDirectory("/data", 0777); createTargetDirectory("/data/dalvik-cache", 0777); } /* * Initialize all necessary state, and indicate that we're ready to go. */ static void initOnce(void) { initGlobals(); initGeneral(); } /* * Shared object initializer. glibc guarantees that this function is * called before dlopen() returns. It may be called multiple times. */ __attribute__((constructor)) static void initialize(void) { pthread_once(&gWrapSimInitialized, initOnce); }