Revert "Revert "Reenable support for non-PIE executables""

* Conditionally revert under TARGET_NEEDS_NON_PIE_SUPPORT flag

This reverts commit 76e289c026f11126fc88841b3019fd5bb419bb67.

[mikeioannina]: Fix 5.1 compatibility
6.0 compatibility fixes by Stefan Berger <s.berger81@gmail.com>

Change-Id: I438b1f9f3dff2503a2dd51acbf2351d57f9e0f0b
diff --git a/linker/linker.cpp b/linker/linker.cpp
index ae3dbef..a2442a0 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2827,10 +2827,10 @@
 
     const ElfW(Sym)* s = nullptr;
     soinfo* lsi = nullptr;
+    const version_info* vi = nullptr;
 
     if (sym != 0) {
       sym_name = get_string(symtab_[sym].st_name);
-      const version_info* vi = nullptr;
 
       if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
         return false;
@@ -3132,6 +3132,7 @@
         *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
         break;
       case R_ARM_COPY:
+#ifndef ENABLE_NON_PIE_SUPPORT
         /*
          * ET_EXEC is not supported so this should not happen.
          *
@@ -3143,6 +3144,50 @@
          */
         DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
         return false;
+#else
+        if ((flags_ & FLAG_EXE) == 0) {
+            /*
+             * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+             *
+             * Section 4.6.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", get_realpath());
+            return false;
+        }
+        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) {
+            const ElfW(Sym)* src = nullptr;
+
+            if (!soinfo_do_lookup(NULL, sym_name, vi, &lsi, global_group, local_group, &src)) {
+                DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", get_realpath());
+                return false;
+            }
+            if (lsi->has_DT_SYMBOLIC) {
+                DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+                       "library %s (built with -Bsymbolic?)", get_realpath(), lsi->soname_);
+                return false;
+            }
+            if (s->st_size < src->st_size) {
+                DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+                       get_realpath(), s->st_size, src->st_size);
+                return false;
+            }
+            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", get_realpath());
+            return false;
+        }
+        break;
+#endif
 #elif defined(__i386__)
       case R_386_32:
         count_relocation(kRelocRelative);
@@ -4354,11 +4399,13 @@
   }
   si->dynamic = nullptr;
 
+#ifndef ENABLE_NON_PIE_SUPPORT
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
   if (elf_hdr->e_type != ET_DYN) {
     __libc_fatal("\"%s\": error: only position independent executables (PIE) are supported.",
                  args.argv[0]);
   }
+#endif
 
   // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
   parse_LD_LIBRARY_PATH(ldpath_env);