Revert "Remove text-relocation support for lp32"

This reverts commit cb00add1b382d1e3045876d7e1ccbee2fdce976b.

Bug: 20020312
Bug: 20013628
Change-Id: I8baa3d4b6c7fef50c9e2531257d5b96762099eb3
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 49c10a7..ebf125e 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2297,8 +2297,13 @@
         break;
 
       case DT_TEXTREL:
-        DL_ERR("text relocations (DT_TEXTREL) found in the ELF file \"%s\"", name);
+#if defined(__LP64__)
+        DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", name);
         return false;
+#else
+        has_text_relocations = true;
+        break;
+#endif
 
       case DT_SYMBOLIC:
         has_DT_SYMBOLIC = true;
@@ -2310,8 +2315,12 @@
 
       case DT_FLAGS:
         if (d->d_un.d_val & DF_TEXTREL) {
-          DL_ERR("text relocations (DF_TEXTREL) found in the ELF file \"%s\"", name);
+#if defined(__LP64__)
+          DL_ERR("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", name);
           return false;
+#else
+          has_text_relocations = true;
+#endif
         }
         if (d->d_un.d_val & DF_SYMBOLIC) {
           has_DT_SYMBOLIC = true;
@@ -2420,6 +2429,20 @@
     local_group_root_ = this;
   }
 
+#if !defined(__LP64__)
+  if (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.
+    DL_WARN("%s has text relocations. This is wasting memory and prevents "
+            "security hardening. Please fix.", name);
+    if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+      DL_ERR("can't unprotect loadable segments for \"%s\": %s",
+             name, strerror(errno));
+      return false;
+    }
+  }
+#endif
+
   if (android_relocs_ != nullptr) {
     // check signature
     if (android_relocs_size_ > 3 &&
@@ -2490,6 +2513,17 @@
 
   DEBUG("[ finished linking %s ]", name);
 
+#if !defined(__LP64__)
+  if (has_text_relocations) {
+    // All relocations are done, we can protect our segments back to read-only.
+    if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+      DL_ERR("can't protect segments for \"%s\": %s",
+             name, strerror(errno));
+      return false;
+    }
+  }
+#endif
+
   /* We can also turn on GNU RELRO protection */
   if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
     DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",