]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blobdiff - linker/linker.cpp
Merge "Reinstate the x86 dynamic linker warning for text relocations."
[android-sdk/platform-bionic.git] / linker / linker.cpp
index ca2601a4475ea5becdc14c8d67c21e2c55d1f714..45889485f982a895af9195b59181b9dd3b0d6609 100644 (file)
@@ -59,6 +59,7 @@
  *
  * open issues / todo:
  *
+ * - are we doing everything we should for ARM_COPY relocations?
  * - cleaner error reporting
  * - after linking, set as much stuff as possible to READONLY
  *   and NOEXEC
@@ -668,8 +669,7 @@ static int open_library(const char* name) {
     }
     // ...but nvidia binary blobs (at least) rely on this behavior, so fall through for now.
 #if defined(__LP64__)
-    // TODO: uncomment this after bug b/7465467 is fixed.
-    // return -1;
+    return -1;
 #endif
   }
 
@@ -827,7 +827,7 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
   }
 }
 
-soinfo* do_dlopen(const char* name, int flags, soinfo* caller, const android_dlextinfo* extinfo) {
+soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
   if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NOLOAD)) != 0) {
     DL_ERR("invalid flags to dlopen: %x", flags);
     return NULL;
@@ -840,9 +840,6 @@ soinfo* do_dlopen(const char* name, int flags, soinfo* caller, const android_dle
   soinfo* si = find_library(name, flags, extinfo);
   if (si != NULL) {
     si->CallConstructors();
-    if (caller != NULL) {
-      caller->add_child(si);
-    }
   }
   protect_data(PROT_READ);
   return si;
@@ -1040,17 +1037,52 @@ static int soinfo_relocate(soinfo* si, ElfW(Rela)* rela, unsigned count, soinfo*
         break;
 
     case R_AARCH64_COPY:
-        /*
-         * ET_EXEC is not supported so this should not happen.
-         *
-         * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-         *
-         * Section 4.7.1.10 "Dynamic relocations"
-         * R_AARCH64_COPY may only appear in executable objects where e_type is
-         * set to ET_EXEC.
-         */
-        DL_ERR("%s R_AARCH64_COPY relocations are not supported", si->name);
-        return -1;
+        if ((si->flags & FLAG_EXE) == 0) {
+            /*
+              * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+              *
+              * Section 4.7.1.10 "Dynamic relocations"
+              * R_AARCH64_COPY may only appear in executable objects where e_type is
+              * set to ET_EXEC.
+              *
+              * FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+              * We should explicitly disallow ET_DYN executables from having
+              * R_AARCH64_COPY relocations.
+              */
+            DL_ERR("%s R_AARCH64_COPY relocations only supported for ET_EXEC", si->name);
+            return -1;
+        }
+        count_relocation(kRelocCopy);
+        MARK(rela->r_offset);
+        TRACE_TYPE(RELO, "RELO COPY %16llx <- %lld @ %16llx %s\n",
+                   reloc,
+                   s->st_size,
+                   (sym_addr + rela->r_addend),
+                   sym_name);
+        if (reloc == (sym_addr + rela->r_addend)) {
+            ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+            if (src == NULL) {
+                DL_ERR("%s R_AARCH64_COPY relocation source cannot be resolved", si->name);
+                return -1;
+            }
+            if (lsi->has_DT_SYMBOLIC) {
+                DL_ERR("%s invalid R_AARCH64_COPY relocation against DT_SYMBOLIC shared "
+                       "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+                return -1;
+            }
+            if (s->st_size < src->st_size) {
+                DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%lld < %lld)",
+                       si->name, s->st_size, src->st_size);
+                return -1;
+            }
+            memcpy(reinterpret_cast<void*>(reloc),
+                   reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+        } else {
+            DL_ERR("%s R_AARCH64_COPY relocation target cannot be resolved", si->name);
+            return -1;
+        }
+        break;
     case R_AARCH64_TLS_TPREL64:
         TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
                    reloc, (sym_addr + rela->r_addend), rela->r_offset);
@@ -1228,17 +1260,48 @@ static int soinfo_relocate(soinfo* si, ElfW(Rel)* rel, unsigned count, soinfo* n
             *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
             break;
         case R_ARM_COPY:
-            /*
-             * ET_EXEC is not supported so this should not happen.
-             *
-             * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-             *
-             * Section 4.7.1.10 "Dynamic relocations"
-             * R_ARM_COPY may only appear in executable objects where e_type is
-             * set to ET_EXEC.
-             */
-            DL_ERR("%s R_ARM_COPY relocations are not supported", si->name);
-            return -1;
+            if ((si->flags & FLAG_EXE) == 0) {
+                /*
+                 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+                 *
+                 * Section 4.7.1.10 "Dynamic relocations"
+                 * R_ARM_COPY may only appear in executable objects where e_type is
+                 * set to ET_EXEC.
+                 *
+                 * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+                 * We should explicitly disallow ET_DYN executables from having
+                 * R_ARM_COPY relocations.
+                 */
+                DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
+                return -1;
+            }
+            count_relocation(kRelocCopy);
+            MARK(rel->r_offset);
+            TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name);
+            if (reloc == sym_addr) {
+                ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+                if (src == NULL) {
+                    DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", si->name);
+                    return -1;
+                }
+                if (lsi->has_DT_SYMBOLIC) {
+                    DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+                           "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+                    return -1;
+                }
+                if (s->st_size < src->st_size) {
+                    DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+                           si->name, s->st_size, src->st_size);
+                    return -1;
+                }
+                memcpy(reinterpret_cast<void*>(reloc),
+                       reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+            } else {
+                DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", si->name);
+                return -1;
+            }
+            break;
 #elif defined(__i386__)
         case R_386_JMP_SLOT:
             count_relocation(kRelocAbsolute);
@@ -1866,10 +1929,8 @@ static bool soinfo_link_image(soinfo* si, const android_dlextinfo* extinfo) {
     if (si->has_text_relocations) {
         // Make segments writable to allow text relocations to work properly. We will later call
         // phdr_table_protect_segments() after all of them are applied and all constructors are run.
-#if !defined(__i386__) // The platform itself has too many text relocations on x86.
         DL_WARN("%s has text relocations. This is wasting memory and prevents "
                 "security hardening. Please fix.", si->name);
-#endif
         if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
             DL_ERR("can't unprotect loadable segments for \"%s\": %s",
                    si->name, strerror(errno));
@@ -2108,11 +2169,13 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
     si->dynamic = NULL;
     si->ref_count = 1;
 
+#if defined(__LP64__)
     ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
     if (elf_hdr->e_type != ET_DYN) {
         __libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
         exit(EXIT_FAILURE);
     }
+#endif
 
     // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
     parse_LD_LIBRARY_PATH(ldpath_env);