author | Mark Finkle <mfinkle@mozilla.com> |
Fri, 29 Oct 2010 10:07:54 -0400 | |
changeset 56683 | 1cf4edfb9525b7df05b38e413edd77dd94695271 |
parent 56682 | 799a83ba5f8637d6bbf730ce89ab89fbf33c4477 |
child 56684 | 3b73e3b886531fae356cbbeebcf5d70023cff7f9 |
push id | 1 |
push user | root |
push date | Tue, 26 Apr 2011 22:38:44 +0000 |
treeherder | mozilla-beta@bfdb6e623a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | fennec-should-load-pages |
bugs | 608239 |
milestone | 2.0b8pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -64,20 +64,16 @@ #include "mozilla/Omnijar.h" #include <sys/stat.h> #ifdef XP_WIN #include "nsIWinTaskbar.h" #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" #endif -#ifdef ANDROID -#include "APKOpen.h" -#endif - using mozilla::MonitorAutoEnter; using mozilla::ipc::GeckoChildProcessHost; template<> struct RunnableMethodTraits<GeckoChildProcessHost> { static void RetainCallee(GeckoChildProcessHost* obj) { } static void ReleaseCallee(GeckoChildProcessHost* obj) { } @@ -387,30 +383,16 @@ GeckoChildProcessHost::PerformAsyncLaunc #endif FilePath exePath; GetPathToBinary(exePath); #ifdef ANDROID // The java wrapper unpacks this for us but can't make it executable chmod(exePath.value().c_str(), 0700); - int cacheCount = 0; - const struct lib_cache_info * cache = getLibraryCache(); - nsCString cacheStr; - while (cache && - cacheCount++ < MAX_LIB_CACHE_ENTRIES && - strlen(cache->name)) { - mFileMap.push_back(std::pair<int,int>(cache->fd, cache->fd)); - cacheStr.Append(cache->name); - cacheStr.AppendPrintf(":%d;", cache->fd); - cache++; - } - // fill the last arg with something if there's no cache - if (cacheStr.IsEmpty()) - cacheStr.AppendLiteral("-"); #endif // remap the IPC socket fd to a well-known int, as the OS does for // STDOUT_FILENO, for example int srcChannelFd, dstChannelFd; channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd); mFileMap.push_back(std::pair<int,int>(srcChannelFd, dstChannelFd)); @@ -464,20 +446,16 @@ GeckoChildProcessHost::PerformAsyncLaunc // can't pretend being the child that's forked off. std::string mach_connection_name = StringPrintf("org.mozilla.machname.%d", base::RandInt(0, std::numeric_limits<int>::max())); childArgv.push_back(mach_connection_name.c_str()); #endif childArgv.push_back(childProcessType); -#ifdef ANDROID - childArgv.push_back(cacheStr.get()); -#endif - base::LaunchApp(childArgv, mFileMap, #if defined(OS_LINUX) || defined(OS_MACOSX) newEnvVars, #endif false, &process, arch); #ifdef XP_MACOSX // Wait for the child process to send us its 'task_t' data.
--- a/ipc/glue/SharedMemoryBasic_android.cpp +++ b/ipc/glue/SharedMemoryBasic_android.cpp @@ -51,17 +51,25 @@ #include "base/process_util.h" #include "SharedMemoryBasic.h" // // Temporarily go directly to the kernel interface until we can // interact better with libcutils. // -#include <linux/ashmem.h> +#define ASHMEM_DEVICE "/dev/ashmem" +#define ASHMEM_NAME_LEN 256 +#define __ASHMEMIOC 0x77 +#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) +#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) +#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) +#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) +#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long) +#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6) namespace mozilla { namespace ipc { static void LogError(const char* what) { __android_log_print(ANDROID_LOG_ERROR, "Gecko", @@ -89,17 +97,17 @@ SharedMemoryBasic::~SharedMemoryBasic() } bool SharedMemoryBasic::Create(size_t aNbytes) { NS_ABORT_IF_FALSE(-1 == mShmFd, "Already Create()d"); // Carve a new instance off of /dev/ashmem - int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); + int shmfd = open(ASHMEM_DEVICE, O_RDWR, 0600); if (-1 == shmfd) { LogError("ShmemAndroid::Create():open"); return false; } if (ioctl(shmfd, ASHMEM_SET_SIZE, aNbytes)) { LogError("ShmemAndroid::Unmap():ioctl(SET_SIZE)"); close(shmfd);
--- a/other-licenses/android/APKOpen.cpp +++ b/other-licenses/android/APKOpen.cpp @@ -29,39 +29,29 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* - * 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. - */ - #include <jni.h> #include <android/log.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> -#include <sys/limits.h> #include <errno.h> #include <string.h> #include <stdio.h> -#include <stdlib.h> #include <fcntl.h> #include <endian.h> #include <unistd.h> #include <zlib.h> -#include <linux/ashmem.h> #include "dlfcn.h" #include "APKOpen.h" /* compression methods */ #define STORE 0 #define DEFLATE 8 #define LZMA 14 @@ -114,37 +104,17 @@ struct cdir_end { uint32_t cdir_size; uint32_t cdir_offset; uint16_t comment_size; char comment[0]; } __attribute__((__packed__)); static size_t zip_size; static int zip_fd; -static struct mapping_info * lib_mapping; - -NS_EXPORT const struct mapping_info * -getLibraryMapping() -{ - return lib_mapping; -} - -static int -createAshmem(size_t bytes) -{ - int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); - if (fd < 0) - return -1; - - if (!ioctl(fd, ASHMEM_SET_SIZE, bytes)) - return fd; - - close(fd); - return -1; -} +NS_EXPORT struct mapping_info * lib_mapping; static void * map_file (const char *file) { int fd = open(file, O_RDONLY); if (fd == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoMapFile", "map_file open %s", strerror(errno)); return NULL; } @@ -345,90 +315,16 @@ extractLib(const struct cdir_entry *entr ret = inflateEnd(&strm); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg); if (strm.total_out != letoh32(entry->uncompressed_size)) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size)); } -static int cache_count = 0; -static struct lib_cache_info *cache_mapping = NULL; - -NS_EXPORT const struct lib_cache_info * -getLibraryCache() -{ - return cache_mapping; -} - -static void -ensureLibCache() -{ - if (!cache_mapping) - cache_mapping = (struct lib_cache_info *)calloc(MAX_LIB_CACHE_ENTRIES, - sizeof(*cache_mapping)); -} - -static void -fillLibCache(const char *buf) -{ - ensureLibCache(); - - char * str = strdup(buf); - if (!str) - return; - - char * saveptr; - char * nextstr = str; - do { - struct lib_cache_info *info = &cache_mapping[cache_count]; - - char * name = strtok_r(nextstr, ":", &saveptr); - if (!name) - break; - nextstr = NULL; - - char * fd_str = strtok_r(NULL, ";", &saveptr); - if (!fd_str) - break; - - long int fd = strtol(fd_str, NULL, 10); - if (fd == LONG_MIN || fd == LONG_MAX) - break; - strncpy(info->name, name, MAX_LIB_CACHE_NAME_LEN - 1); - info->fd = fd; - } while (cache_count++ < MAX_LIB_CACHE_ENTRIES); - free(str); -} - -static int -lookupLibCacheFd(const char *libName) -{ - if (!cache_mapping) - return -1; - - int count = cache_count; - while (count--) { - struct lib_cache_info *info = &cache_mapping[count]; - if (!strcmp(libName, info->name)) - return info->fd; - } - return -1; -} - -static void -addLibCacheFd(const char *libName, int fd) -{ - ensureLibCache(); - - struct lib_cache_info *info = &cache_mapping[cache_count++]; - strncpy(info->name, libName, MAX_LIB_CACHE_NAME_LEN - 1); - info->fd = fd; -} - static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { #ifdef DEBUG struct timeval t0, t1; gettimeofday(&t0, 0); #endif @@ -437,17 +333,19 @@ static void * mozload(const char * path, void * data = ((void *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size); void * handle; if (extractLibs) { char fullpath[256]; snprintf(fullpath, 256, "/data/data/org.mozilla.fennec/%s", path + 4); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 1", fullpath); handle = __wrap_dlopen(fullpath, RTLD_LAZY); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 2", fullpath); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + @@ -455,58 +353,42 @@ static void * mozload(const char * path, #endif return handle; } size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size); int fd = zip_fd; void * buf = NULL; - uint32_t lib_size = letoh32(entry->uncompressed_size); if (letoh16(file->compression) == DEFLATE) { - int cache_fd = lookupLibCacheFd(path + 4); - fd = cache_fd; - if (fd < 0) - fd = createAshmem(lib_size); -#ifdef DEBUG - else - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path + 4); -#endif - if (fd < 0) { - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get an ashmem buffer"); - return NULL; - } - buf = mmap(NULL, lib_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); + fd = -1; + buf = mmap(NULL, letoh32(entry->uncompressed_size), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); - close(fd); return NULL; } offset = 0; - if (cache_fd < 0) { - extractLib(entry, data, buf); - addLibCacheFd(path + 4, fd); - } + extractLib(entry, data, buf); data = buf; } #ifdef DEBUG - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d and offset %d", path, letoh32(entry->uncompressed_size), offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, - lib_size, offset); + letoh32(entry->uncompressed_size), offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); if (buf) - munmap(buf, lib_size); + munmap(buf, letoh32(entry->uncompressed_size)); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; @@ -663,22 +545,18 @@ ChildProcessInit(int argc, char* argv[]) for (i = 0; i < (argc - 1); i++) { if (strcmp(argv[i], "-omnijar")) continue; i = i + 1; break; } - fillLibCache(argv[argc - 1]); loadLibs(argv[i]); - // don't pass the last arg - it's only recognized by the lib cache - argc--; - typedef GeckoProcessType (*XRE_StringToChildProcessType_t)(char*); typedef nsresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType); XRE_StringToChildProcessType_t fXRE_StringToChildProcessType = (XRE_StringToChildProcessType_t)__wrap_dlsym(xul_handle, "XRE_StringToChildProcessType"); XRE_InitChildProcess_t fXRE_InitChildProcess = (XRE_InitChildProcess_t)__wrap_dlsym(xul_handle, "XRE_InitChildProcess"); GeckoProcessType proctype = fXRE_StringToChildProcessType(argv[--argc]);
--- a/other-licenses/android/APKOpen.h +++ b/other-licenses/android/APKOpen.h @@ -40,21 +40,11 @@ struct mapping_info { char * name; char * file_id; uintptr_t base; size_t len; size_t offset; }; -const struct mapping_info * getLibraryMapping(); - -#define MAX_LIB_CACHE_ENTRIES 32 -#define MAX_LIB_CACHE_NAME_LEN 32 - -struct lib_cache_info { - char name[MAX_LIB_CACHE_NAME_LEN]; - int fd; -}; - -const struct lib_cache_info * getLibraryCache(); +extern struct mapping_info * lib_mapping; #endif /* APKOpen_h */
--- a/other-licenses/android/linker.c +++ b/other-licenses/android/linker.c @@ -925,29 +925,28 @@ load_segments(int fd, size_t offset, voi /* we want to map in the segment on a page boundary */ tmp = base + (phdr->p_vaddr & (~PAGE_MASK)); /* add the # of bytes we masked off above to the total length. */ len = phdr->p_filesz + (phdr->p_vaddr & PAGE_MASK); TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); - if (fd == -1 || PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE) { + if (fd == -1) { pbase = mmap(tmp, len, PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, + 0); if (pbase != MAP_FAILED) { memcpy(pbase, header + ((phdr->p_offset) & (~PAGE_MASK)), len); mprotect(pbase, len, PFLAGS_TO_PROT(phdr->p_flags)); - } else - DL_ERR("%s: Memcpy mapping of segment failed!", si->name); - } else { + } + } else pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr->p_flags), - MAP_SHARED | MAP_FIXED, fd, + MAP_PRIVATE | MAP_FIXED, fd, offset + ((phdr->p_offset) & (~PAGE_MASK))); - } if (pbase == MAP_FAILED) { DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); goto fail; } report_mapping(si->name, pbase, len, phdr->p_offset & (~PAGE_MASK)); @@ -1234,17 +1233,17 @@ load_mapped_library(const char * name, i si->dynamic = (unsigned *)-1; if (alloc_mem_region(si) < 0) goto fail; TRACE("[ %5d allocated memory for %s @ %p (0x%08x) ]\n", pid, name, (void *)si->base, (unsigned) ext_sz); /* Now actually load the library's segments into right places in memory */ - if (load_segments(fd, offset, mem, si) < 0) { + if (load_segments(offset ? fd : -1, offset, mem, si) < 0) { if (si->ba_index >= 0) { ba_free(&ba_nonprelink, si->ba_index); si->ba_index = -1; } goto fail; } /* this might not be right. Technically, we don't even need this info @@ -1390,38 +1389,16 @@ static int reloc_library(soinfo *si, Elf { Elf32_Sym *symtab = si->symtab; const char *strtab = si->strtab; Elf32_Sym *s; unsigned base; Elf32_Rel *start = rel; unsigned idx; - /* crappy hack to ensure we don't write into the read-only region */ - - /* crappy hack part 1: find the read only region */ - int cnt; - void * ro_region_end = si->base; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)si->base; - Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)si->base + ehdr->e_phoff); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { - if (phdr->p_type != PT_LOAD || - PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE || - phdr->p_vaddr != 0) - continue; - - ro_region_end = si->base + phdr->p_filesz; - break; - } - - void * remapped_page = NULL; - void * copy_page = mmap(NULL, PAGE_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - for (idx = 0; idx < count; ++idx) { unsigned type = ELF32_R_TYPE(rel->r_info); unsigned sym = ELF32_R_SYM(rel->r_info); unsigned reloc = (unsigned)(rel->r_offset + si->base); unsigned sym_addr = 0; char *sym_name = NULL; DEBUG("%5d Processing '%s' relocation at index %d\n", pid, @@ -1497,33 +1474,16 @@ static int reloc_library(soinfo *si, Elf #endif sym_addr = (unsigned)(s->st_value + base); } COUNT_RELOC(RELOC_SYMBOL); } else { s = NULL; } - /* crappy hack part 2: make this page writable */ - void * reloc_page = reloc & ~PAGE_MASK; - if (reloc < ro_region_end && reloc_page != remapped_page) { - if (remapped_page != NULL) - mprotect(remapped_page, PAGE_SIZE, PROT_READ | PROT_EXEC); - memcpy(copy_page, reloc_page, PAGE_SIZE); - munmap(reloc_page, PAGE_SIZE); - if (mmap(reloc_page, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, - -1, 0) == MAP_FAILED) - DL_ERR("failed to map page for %s at 0x%08x! errno=%d", - si->name, reloc_page, errno); - - memcpy(reloc_page, copy_page, PAGE_SIZE); - remapped_page = reloc_page; - } - /* TODO: This is ugly. Split up the relocations by arch into * different files. */ switch(type){ #if defined(ANDROID_ARM_LINKER) case R_ARM_JUMP_SLOT: COUNT_RELOC(RELOC_ABSOLUTE); MARK(rel->r_offset); @@ -1619,17 +1579,16 @@ static int reloc_library(soinfo *si, Elf default: DL_ERR("%5d unknown reloc type %d @ %p (%d)", pid, type, rel, (int) (rel - start)); return -1; } rel++; } - munmap(copy_page, PAGE_SIZE); return 0; } #if defined(ANDROID_SH_LINKER) static int reloc_library_a(soinfo *si, Elf32_Rela *rela, unsigned count) { Elf32_Sym *symtab = si->symtab; const char *strtab = si->strtab;
--- a/toolkit/xre/nsAndroidStartup.cpp +++ b/toolkit/xre/nsAndroidStartup.cpp @@ -70,17 +70,17 @@ struct AutoAttachJavaThread { PRBool attached; }; static void* GeckoStart(void *data) { #ifdef MOZ_CRASHREPORTER - const struct mapping_info *info = getLibraryMapping(); + struct mapping_info *info = lib_mapping; while (info->name) { CrashReporter::AddLibraryMapping(info->name, info->file_id, info->base, info->len, info->offset); info++; } #endif AutoAttachJavaThread attacher;