The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2007 The Android Open Source Project |
| 3 | * |
| 4 | * Initialize the intercepts. |
| 5 | */ |
| 6 | #include "Common.h" |
| 7 | |
| 8 | #define __USE_GNU /* need RTLD_NEXT */ |
| 9 | #include <dlfcn.h> |
| 10 | |
| 11 | #include <stdlib.h> |
| 12 | #include <pthread.h> |
| 13 | #include <string.h> |
| 14 | #include <errno.h> |
| 15 | #include <assert.h> |
| 16 | #include <sys/stat.h> |
| 17 | #include <sys/types.h> |
| 18 | |
| 19 | |
| 20 | /* |
| 21 | * Global state. |
| 22 | */ |
| 23 | struct WrapSimGlobals gWrapSim; |
| 24 | pthread_once_t gWrapSimInitialized = PTHREAD_ONCE_INIT; |
| 25 | |
| 26 | /* |
| 27 | * Initialize our global state. |
| 28 | */ |
| 29 | static void initGlobals(void) |
| 30 | { |
| 31 | memset(&gWrapSim, 0xdd, sizeof(gWrapSim)); |
| 32 | gWrapSim.logFd = -1; |
| 33 | gWrapSim.keyMap = NULL; |
| 34 | |
| 35 | /* |
| 36 | * Find the original version of functions we override. |
| 37 | */ |
| 38 | _ws_access = dlsym(RTLD_NEXT, "access"); |
| 39 | _ws_open = dlsym(RTLD_NEXT, "open"); |
| 40 | _ws_open64 = dlsym(RTLD_NEXT, "open64"); |
| 41 | |
| 42 | _ws_close = dlsym(RTLD_NEXT, "close"); |
Marco Nelissen | 542e4f1 | 2009-07-08 12:49:42 -0700 | [diff] [blame] | 43 | _ws_dup = dlsym(RTLD_NEXT, "dup"); |
The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 44 | _ws_read = dlsym(RTLD_NEXT, "read"); |
| 45 | _ws_readv = dlsym(RTLD_NEXT, "readv"); |
| 46 | _ws_write = dlsym(RTLD_NEXT, "write"); |
| 47 | _ws_writev = dlsym(RTLD_NEXT, "writev"); |
| 48 | _ws_mmap = dlsym(RTLD_NEXT, "mmap"); |
| 49 | _ws_mmap64 = dlsym(RTLD_NEXT, "mmap64"); |
| 50 | _ws_ioctl = dlsym(RTLD_NEXT, "ioctl"); |
| 51 | |
| 52 | _ws_chdir = dlsym(RTLD_NEXT, "chdir"); |
| 53 | _ws_chmod = dlsym(RTLD_NEXT, "chmod"); |
| 54 | _ws_chown = dlsym(RTLD_NEXT, "chown"); |
| 55 | _ws_creat = dlsym(RTLD_NEXT, "creat"); |
| 56 | _ws_execve = dlsym(RTLD_NEXT, "execve"); |
| 57 | _ws_getcwd = dlsym(RTLD_NEXT, "getcwd"); |
| 58 | _ws_lchown = dlsym(RTLD_NEXT, "lchown"); |
| 59 | _ws_link = dlsym(RTLD_NEXT, "link"); |
| 60 | _ws_lstat = dlsym(RTLD_NEXT, "lstat"); |
| 61 | _ws_lstat64 = dlsym(RTLD_NEXT, "lstat64"); |
| 62 | _ws___lxstat = dlsym(RTLD_NEXT, "__lxstat"); |
| 63 | _ws___lxstat64 = dlsym(RTLD_NEXT, "__lxstat64"); |
| 64 | _ws_mkdir = dlsym(RTLD_NEXT, "mkdir"); |
| 65 | _ws_readlink = dlsym(RTLD_NEXT, "readlink"); |
| 66 | _ws_rename = dlsym(RTLD_NEXT, "rename"); |
| 67 | _ws_rmdir = dlsym(RTLD_NEXT, "rmdir"); |
| 68 | _ws_stat = dlsym(RTLD_NEXT, "stat"); |
| 69 | _ws_stat64 = dlsym(RTLD_NEXT, "stat64"); |
| 70 | _ws___xstat = dlsym(RTLD_NEXT, "__xstat"); |
| 71 | _ws___xstat64 = dlsym(RTLD_NEXT, "__xstat64"); |
| 72 | _ws_statfs = dlsym(RTLD_NEXT, "statfs"); |
| 73 | _ws_statfs64 = dlsym(RTLD_NEXT, "statfs64"); |
| 74 | _ws_symlink = dlsym(RTLD_NEXT, "symlink"); |
| 75 | _ws_unlink = dlsym(RTLD_NEXT, "unlink"); |
| 76 | _ws_utime = dlsym(RTLD_NEXT, "utime"); |
| 77 | _ws_utimes = dlsym(RTLD_NEXT, "utimes"); |
| 78 | |
| 79 | _ws_execl = dlsym(RTLD_NEXT, "execl"); |
| 80 | _ws_execle = dlsym(RTLD_NEXT, "execle"); |
| 81 | _ws_execlp = dlsym(RTLD_NEXT, "execlp"); |
| 82 | _ws_execv = dlsym(RTLD_NEXT, "execv"); |
| 83 | _ws_execvp = dlsym(RTLD_NEXT, "execvp"); |
| 84 | _ws_fopen = dlsym(RTLD_NEXT, "fopen"); |
| 85 | _ws_fopen64 = dlsym(RTLD_NEXT, "fopen64"); |
| 86 | _ws_freopen = dlsym(RTLD_NEXT, "freopen"); |
| 87 | _ws_ftw = dlsym(RTLD_NEXT, "ftw"); |
| 88 | _ws_opendir = dlsym(RTLD_NEXT, "opendir"); |
| 89 | _ws_dlopen = dlsym(RTLD_NEXT, "dlopen"); |
| 90 | |
| 91 | _ws_setpriority = dlsym(RTLD_NEXT, "setpriority"); |
| 92 | //_ws_pipe = dlsym(RTLD_NEXT, "pipe"); |
| 93 | |
| 94 | const char* logFileName = getenv("WRAPSIM_LOG"); |
| 95 | if (logFileName != NULL ){ |
| 96 | gWrapSim.logFd = _ws_open(logFileName, O_WRONLY|O_APPEND|O_CREAT, 0664); |
| 97 | } |
| 98 | |
| 99 | /* log messages now work; say hello */ |
| 100 | wsLog("--- initializing sim wrapper ---\n"); |
| 101 | |
| 102 | gWrapSim.simulatorFd = -1; |
| 103 | |
| 104 | pthread_mutex_init(&gWrapSim.startLock, NULL); |
| 105 | pthread_cond_init(&gWrapSim.startCond, NULL); |
| 106 | gWrapSim.startReady = 0; |
| 107 | |
| 108 | pthread_mutex_init(&gWrapSim.fakeFdLock, NULL); |
| 109 | gWrapSim.fakeFdMap = wsAllocBitVector(kMaxFakeFdCount, 0); |
| 110 | memset(gWrapSim.fakeFdList, 0, sizeof(gWrapSim.fakeFdList)); |
| 111 | |
Marco Nelissen | 542e4f1 | 2009-07-08 12:49:42 -0700 | [diff] [blame] | 112 | pthread_mutex_init(&gWrapSim.atomicLock, NULL); |
| 113 | |
The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 114 | gWrapSim.numDisplays = 0; |
| 115 | |
| 116 | gWrapSim.keyInputDevice = NULL; |
| 117 | |
| 118 | /* |
| 119 | * Get target for remapped "/system" and "/data". |
| 120 | * |
| 121 | * The ANDROID_PRODUCT_OUT env var *must* be set for rewriting to work. |
| 122 | */ |
| 123 | const char* outEnv = getenv("ANDROID_PRODUCT_OUT"); |
| 124 | if (outEnv == NULL) { |
| 125 | gWrapSim.remapBaseDir = NULL; |
| 126 | wsLog("--- $ANDROID_PRODUCT_OUT not set, " |
| 127 | "filename remapping disabled\n"); |
| 128 | } else { |
| 129 | /* grab string and append '/' -- note this never gets freed */ |
| 130 | gWrapSim.remapBaseDirLen = strlen(outEnv); |
| 131 | gWrapSim.remapBaseDir = strdup(outEnv); |
| 132 | wsLog("--- name remap to %s\n", gWrapSim.remapBaseDir); |
| 133 | } |
| 134 | |
| 135 | gWrapSim.initialized = 1; |
| 136 | } |
| 137 | |
| 138 | /* |
| 139 | * Creates a directory, or prints a log message if it fails. |
| 140 | */ |
| 141 | static int createTargetDirectory(const char *path, mode_t mode) |
| 142 | { |
| 143 | int ret; |
| 144 | |
| 145 | ret = mkdir(path, mode); |
| 146 | if (ret == 0 || errno == EEXIST) { |
| 147 | return 0; |
| 148 | } |
| 149 | wsLog("--- could not create target directory %s: %s\n", |
| 150 | path, strerror(errno)); |
| 151 | return ret; |
| 152 | } |
| 153 | |
| 154 | /* |
| 155 | * Any setup that would normally be done by init(8). |
| 156 | * Note that since the syscall redirects have been installed |
| 157 | * at this point, we are effectively operating within the |
| 158 | * simulation context. |
| 159 | */ |
| 160 | static void initGeneral(void) |
| 161 | { |
| 162 | wsLog("--- preparing system\n"); |
| 163 | |
| 164 | /* Try to make sure that certain directories exist. |
| 165 | * If we fail to create them, the errors will show up in the log, |
| 166 | * but we keep going. |
| 167 | */ |
| 168 | createTargetDirectory("/data", 0777); |
| 169 | createTargetDirectory("/data/dalvik-cache", 0777); |
| 170 | } |
| 171 | |
| 172 | /* |
| 173 | * Initialize all necessary state, and indicate that we're ready to go. |
| 174 | */ |
| 175 | static void initOnce(void) |
| 176 | { |
| 177 | initGlobals(); |
| 178 | initGeneral(); |
| 179 | } |
| 180 | |
| 181 | /* |
| 182 | * Shared object initializer. glibc guarantees that this function is |
| 183 | * called before dlopen() returns. It may be called multiple times. |
| 184 | */ |
| 185 | __attribute__((constructor)) |
| 186 | static void initialize(void) |
| 187 | { |
| 188 | pthread_once(&gWrapSimInitialized, initOnce); |
| 189 | } |
| 190 | |
| 191 | |