Merge changes Ia0c0018c,I2f1fc8b4,Ibe964c3b,I791da8ac
am: 9da992c271

Change-Id: Iea6c640fc20f1586b5ebb1ad7a6308b5c70a992d
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 37a3189..dec575b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2931,8 +2931,11 @@
 }
 #else
 static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
+  // The i386 psABI specifies that R_386_GLOB_DAT doesn't have an addend. The ARM ELF ABI document
+  // (IHI0044F) specifies that R_ARM_GLOB_DAT has an addend, but Bionic isn't adding it.
   if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE ||
       ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE ||
+      ELFW(R_TYPE)(rel->r_info) == R_GENERIC_ABSOLUTE ||
       ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_DTPREL ||
       ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_TPREL) {
     return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
@@ -3056,6 +3059,7 @@
 
         switch (type) {
           case R_GENERIC_JUMP_SLOT:
+          case R_GENERIC_ABSOLUTE:
           case R_GENERIC_GLOB_DAT:
           case R_GENERIC_RELATIVE:
           case R_GENERIC_IRELATIVE:
@@ -3063,17 +3067,8 @@
           case R_GENERIC_TLS_DTPREL:
           case R_GENERIC_TLS_TPREL:
           case R_GENERIC_TLSDESC:
-#if defined(__aarch64__)
-          case R_AARCH64_ABS64:
-          case R_AARCH64_ABS32:
-          case R_AARCH64_ABS16:
-#elif defined(__x86_64__)
+#if defined(__x86_64__)
           case R_X86_64_32:
-          case R_X86_64_64:
-#elif defined(__arm__)
-          case R_ARM_ABS32:
-#elif defined(__i386__)
-          case R_386_32:
 #endif
             /*
              * The sym_addr was initialized to be zero above, or the relocation
@@ -3153,10 +3148,11 @@
 
         *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
         break;
+      case R_GENERIC_ABSOLUTE:
       case R_GENERIC_GLOB_DAT:
         count_relocation(kRelocAbsolute);
         MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n",
+        TRACE_TYPE(RELO, "RELO ABSOLUTE/GLOB_DAT %16p <- %16p %s\n",
                    reinterpret_cast<void*>(reloc),
                    reinterpret_cast<void*>(sym_addr + addend), sym_name);
         *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
@@ -3202,6 +3198,17 @@
           *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
         }
         break;
+      case R_GENERIC_COPY:
+        // Copy relocations allow read-only data or code in a non-PIE executable to access a
+        // variable from a DSO. The executable reserves extra space in its .bss section, and the
+        // linker copies the variable into the extra space. The executable then exports its copy
+        // to interpose the copy in the DSO.
+        //
+        // Bionic only supports PIE executables, so copy relocations aren't supported. The ARM and
+        // AArch64 ABI documents only allow them for ET_EXEC (non-PIE) objects. See IHI0056B and
+        // IHI0044F.
+        DL_ERR("%s COPY relocations are not supported", get_realpath());
+        return false;
       case R_GENERIC_TLS_TPREL:
         count_relocation(kRelocRelative);
         MARK(rel->r_offset);
@@ -3296,121 +3303,14 @@
         break;
 #endif  // defined(__aarch64__)
 
-#if defined(__aarch64__)
-      case R_AARCH64_ABS64:
-        count_relocation(kRelocAbsolute);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n",
-                   reloc, sym_addr + addend, sym_name);
-        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
-        break;
-      case R_AARCH64_ABS32:
-        count_relocation(kRelocAbsolute);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
-                   reloc, sym_addr + addend, sym_name);
-        {
-          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
-          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
-          if ((min_value <= (sym_addr + addend)) &&
-              ((sym_addr + addend) <= max_value)) {
-            *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
-          } else {
-            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
-                   sym_addr + addend, min_value, max_value);
-            return false;
-          }
-        }
-        break;
-      case R_AARCH64_ABS16:
-        count_relocation(kRelocAbsolute);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
-                   reloc, sym_addr + addend, sym_name);
-        {
-          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
-          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
-          if ((min_value <= (sym_addr + addend)) &&
-              ((sym_addr + addend) <= max_value)) {
-            *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
-          } else {
-            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
-                   sym_addr + addend, min_value, max_value);
-            return false;
-          }
-        }
-        break;
-      case R_AARCH64_PREL64:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n",
-                   reloc, sym_addr + addend, rel->r_offset, sym_name);
-        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
-        break;
-      case R_AARCH64_PREL32:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
-                   reloc, sym_addr + addend, rel->r_offset, sym_name);
-        {
-          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
-          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
-          if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
-              ((sym_addr + addend - rel->r_offset) <= max_value)) {
-            *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
-          } else {
-            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
-                   sym_addr + addend - rel->r_offset, min_value, max_value);
-            return false;
-          }
-        }
-        break;
-      case R_AARCH64_PREL16:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
-                   reloc, sym_addr + addend, rel->r_offset, sym_name);
-        {
-          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
-          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
-          if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
-              ((sym_addr + addend - rel->r_offset) <= max_value)) {
-            *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
-          } else {
-            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
-                   sym_addr + addend - rel->r_offset, min_value, max_value);
-            return false;
-          }
-        }
-        break;
-
-      case R_AARCH64_COPY:
-        /*
-         * ET_EXEC is not supported so this should not happen.
-         *
-         * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
-         *
-         * Section 4.6.11 "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", get_realpath());
-        return false;
-#elif defined(__x86_64__)
+#if defined(__x86_64__)
       case R_X86_64_32:
-        count_relocation(kRelocRelative);
+        count_relocation(kRelocAbsolute);
         MARK(rel->r_offset);
         TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
                    static_cast<size_t>(sym_addr), sym_name);
         *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend;
         break;
-      case R_X86_64_64:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
-                   static_cast<size_t>(sym_addr), sym_name);
-        *reinterpret_cast<Elf64_Addr*>(reloc) = sym_addr + addend;
-        break;
       case R_X86_64_PC32:
         count_relocation(kRelocRelative);
         MARK(rel->r_offset);
@@ -3419,39 +3319,7 @@
                    static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name);
         *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend - reloc;
         break;
-#elif defined(__arm__)
-      case R_ARM_ABS32:
-        count_relocation(kRelocAbsolute);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name);
-        *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
-        break;
-      case R_ARM_REL32:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s",
-                   reloc, sym_addr, rel->r_offset, sym_name);
-        *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.6.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", get_realpath());
-        return false;
 #elif defined(__i386__)
-      case R_386_32:
-        count_relocation(kRelocRelative);
-        MARK(rel->r_offset);
-        TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name);
-        *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
-        break;
       case R_386_PC32:
         count_relocation(kRelocRelative);
         MARK(rel->r_offset);
diff --git a/linker/linker_relocs.h b/linker/linker_relocs.h
index 1da5ebe..93d899e 100644
--- a/linker/linker_relocs.h
+++ b/linker/linker_relocs.h
@@ -35,9 +35,12 @@
 #if defined (__aarch64__)
 
 #define R_GENERIC_JUMP_SLOT     R_AARCH64_JUMP_SLOT
+// R_AARCH64_ABS64 is classified as a static relocation but it is common in DSOs.
+#define R_GENERIC_ABSOLUTE      R_AARCH64_ABS64
 #define R_GENERIC_GLOB_DAT      R_AARCH64_GLOB_DAT
 #define R_GENERIC_RELATIVE      R_AARCH64_RELATIVE
 #define R_GENERIC_IRELATIVE     R_AARCH64_IRELATIVE
+#define R_GENERIC_COPY          R_AARCH64_COPY
 #define R_GENERIC_TLS_DTPMOD    R_AARCH64_TLS_DTPMOD
 #define R_GENERIC_TLS_DTPREL    R_AARCH64_TLS_DTPREL
 #define R_GENERIC_TLS_TPREL     R_AARCH64_TLS_TPREL
@@ -46,9 +49,12 @@
 #elif defined (__arm__)
 
 #define R_GENERIC_JUMP_SLOT     R_ARM_JUMP_SLOT
+// R_ARM_ABS32 is classified as a static relocation but it is common in DSOs.
+#define R_GENERIC_ABSOLUTE      R_ARM_ABS32
 #define R_GENERIC_GLOB_DAT      R_ARM_GLOB_DAT
 #define R_GENERIC_RELATIVE      R_ARM_RELATIVE
 #define R_GENERIC_IRELATIVE     R_ARM_IRELATIVE
+#define R_GENERIC_COPY          R_ARM_COPY
 #define R_GENERIC_TLS_DTPMOD    R_ARM_TLS_DTPMOD32
 #define R_GENERIC_TLS_DTPREL    R_ARM_TLS_DTPOFF32
 #define R_GENERIC_TLS_TPREL     R_ARM_TLS_TPOFF32
@@ -57,9 +63,11 @@
 #elif defined (__i386__)
 
 #define R_GENERIC_JUMP_SLOT     R_386_JMP_SLOT
+#define R_GENERIC_ABSOLUTE      R_386_32
 #define R_GENERIC_GLOB_DAT      R_386_GLOB_DAT
 #define R_GENERIC_RELATIVE      R_386_RELATIVE
 #define R_GENERIC_IRELATIVE     R_386_IRELATIVE
+#define R_GENERIC_COPY          R_386_COPY
 #define R_GENERIC_TLS_DTPMOD    R_386_TLS_DTPMOD32
 #define R_GENERIC_TLS_DTPREL    R_386_TLS_DTPOFF32
 #define R_GENERIC_TLS_TPREL     R_386_TLS_TPOFF
@@ -68,9 +76,11 @@
 #elif defined (__x86_64__)
 
 #define R_GENERIC_JUMP_SLOT     R_X86_64_JUMP_SLOT
+#define R_GENERIC_ABSOLUTE      R_X86_64_64
 #define R_GENERIC_GLOB_DAT      R_X86_64_GLOB_DAT
 #define R_GENERIC_RELATIVE      R_X86_64_RELATIVE
 #define R_GENERIC_IRELATIVE     R_X86_64_IRELATIVE
+#define R_GENERIC_COPY          R_X86_64_COPY
 #define R_GENERIC_TLS_DTPMOD    R_X86_64_DTPMOD64
 #define R_GENERIC_TLS_DTPREL    R_X86_64_DTPOFF64
 #define R_GENERIC_TLS_TPREL     R_X86_64_TPOFF64