Bug 687147 - Ensure Instruction and Data cache coherency after extracting libraries. r=mwu
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 23 Sep 2011 14:31:11 +0200
changeset 77416 e299d7fed89dd5fe24a234c226b4f3353a4eb338
parent 77415 c0b96cb41fc1f4a808afbe5278320f18429e0f7a
child 77417 b412c07605722b8a55d5849d4cd61404cfd2b857
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersmwu
bugs687147
milestone9.0a1
Bug 687147 - Ensure Instruction and Data cache coherency after extracting libraries. r=mwu
other-licenses/android/APKOpen.cpp
other-licenses/android/linker.c
--- a/other-licenses/android/APKOpen.cpp
+++ b/other-licenses/android/APKOpen.cpp
@@ -510,16 +510,21 @@ static void * mozload(const char * path,
       close(fd);
       return NULL;
     }
 
     offset = 0;
 
     if (cache_fd < 0) {
       extractLib(entry, data, buf);
+#ifdef ANDROID_ARM_LINKER
+      /* We just extracted data that is going to be executed in the future.
+       * We thus need to ensure Instruction and Data cache coherency. */
+      cacheflush((unsigned) buf, (unsigned) buf + entry->uncompressed_size, 0);
+#endif
       if (!skipLibCache)
         addLibCacheFd(path, fd, lib_size, buf);
     }
 
     // preload libxul, to avoid slowly demand-paging it
     if (!strcmp(path, "libxul.so"))
       madvise(buf, entry->uncompressed_size, MADV_WILLNEED);
     data = buf;
--- a/other-licenses/android/linker.c
+++ b/other-licenses/android/linker.c
@@ -1411,16 +1411,18 @@ static int reloc_library(soinfo *si, Elf
     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;
+    unsigned lowest_text_rel = 0xffffffff;
+
     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)
             continue;
 
         if (si->base + phdr->p_vaddr + phdr->p_filesz > ro_region_end)
@@ -1531,16 +1533,18 @@ static int reloc_library(soinfo *si, Elf
                      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;
         }
+        if ((reloc < ro_region_end) && (reloc < lowest_text_rel))
+            lowest_text_rel = reloc & ~PAGE_MASK;
 
 /* 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);
@@ -1637,18 +1641,25 @@ 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++;
     }
-    if (copy_page)
+    if (copy_page) {
         munmap(copy_page, PAGE_SIZE);
+#if defined(ANDROID_ARM_LINKER)
+        /* If we have a copy_page, it means we applied text relocations,
+         * which, in turn, means we need to maintain Instruction and Data
+         * caches coherent */
+        cacheflush(lowest_text_rel, (unsigned) ro_region_end, 0);
+#endif
+    }
     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;
@@ -1797,17 +1808,17 @@ static void call_constructors(soinfo *si
 
     if (si->init_func) {
         TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid,
               (unsigned)si->init_func, si->name);
         si->init_func();
         TRACE("[ %5d Done calling init_func for '%s' ]\n", pid, si->name);
     }
 
-    if (si->init_array && strncmp(si->name, "libmozalloc.so", 14)) {
+    if (si->init_array) {
         TRACE("[ %5d Calling init_array @ 0x%08x [%d] for '%s' ]\n", pid,
               (unsigned)si->init_array, si->init_array_count, si->name);
         call_array(si->init_array, si->init_array_count, 0);
         TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name);
     }
 }