Merge changes I376d7695,Ied443375,I614d25e7

* changes:
  Use shared globals to init __progname + environ
  Move the abort message to libc_shared_globals
  Expose libc_shared_globals to libc.so with symbol
diff --git a/libc/Android.bp b/libc/Android.bp
index b7965c8..bc4dd9e 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -691,120 +691,32 @@
 
     arch: {
         arm: {
-            cflags: ["-DNO___MEMCPY_CHK"],
+            cflags: [
+                "-DNO___MEMCPY_CHK",
+                "-DRENAME___STRCAT_CHK",
+                "-DRENAME___STRCPY_CHK",
+            ],
             srcs: [
                 "arch-arm/generic/bionic/__memcpy_chk.S",
+
+                "arch-arm/cortex-a15/bionic/__strcat_chk.S",
+                "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
+
+                "arch-arm/cortex-a7/bionic/__strcat_chk.S",
+                "arch-arm/cortex-a7/bionic/__strcpy_chk.S",
+
+                "arch-arm/cortex-a9/bionic/__strcat_chk.S",
+                "arch-arm/cortex-a9/bionic/__strcpy_chk.S",
+
+                "arch-arm/krait/bionic/__strcat_chk.S",
+                "arch-arm/krait/bionic/__strcpy_chk.S",
+
+                "arch-arm/cortex-a53/bionic/__strcat_chk.S",
+                "arch-arm/cortex-a53/bionic/__strcpy_chk.S",
+
+                "arch-arm/denver/bionic/__strcat_chk.S",
+                "arch-arm/denver/bionic/__strcpy_chk.S",
             ],
-            neon: {
-                cflags: [
-                    "-DNO___STRCAT_CHK",
-                    "-DNO___STRCPY_CHK",
-                ],
-                srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a7: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a7/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a9: {
-                srcs: [
-                    "arch-arm/cortex-a9/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a9/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            krait: {
-                srcs: [
-                    "arch-arm/krait/bionic/__strcat_chk.S",
-                    "arch-arm/krait/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a53: {
-                srcs: [
-                    "arch-arm/cortex-a53/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a53/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a55: {
-                srcs: [
-                    "arch-arm/denver/bionic/__strcat_chk.S",
-                    "arch-arm/denver/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a73: {
-                srcs: [
-                    "arch-arm/denver/bionic/__strcat_chk.S",
-                    "arch-arm/denver/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a75: {
-                srcs: [
-                    "arch-arm/denver/bionic/__strcat_chk.S",
-                    "arch-arm/denver/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            cortex_a76: {
-                srcs: [
-                    "arch-arm/denver/bionic/__strcat_chk.S",
-                    "arch-arm/denver/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            denver: {
-                srcs: [
-                    "arch-arm/denver/bionic/__strcat_chk.S",
-                    "arch-arm/denver/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
-            kryo: {
-                srcs: [
-                    "arch-arm/krait/bionic/__strcat_chk.S",
-                    "arch-arm/krait/bionic/__strcpy_chk.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/__strcat_chk.S",
-                    "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
-                ],
-            },
         },
         arm64: {
             cflags: ["-DNO___MEMCPY_CHK"],
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
index ca29715..69e405f 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_a15)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -200,4 +200,4 @@
     .cfi_adjust_cfa_offset 8
     .cfi_rel_offset r4, 0
     .cfi_rel_offset r5, 4
-END(__strcat_chk)
+END(__strcat_chk_a15)
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
index 2679c02..ddde30e 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
 
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_a15)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -162,4 +162,4 @@
 
 #include "memcpy_base.S"
 
-END(__strcpy_chk)
+END(__strcpy_chk_a15)
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
index ca29715..72be243 100644
--- a/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_a53)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -200,4 +200,4 @@
     .cfi_adjust_cfa_offset 8
     .cfi_rel_offset r4, 0
     .cfi_rel_offset r5, 4
-END(__strcat_chk)
+END(__strcat_chk_a53)
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
index 2679c02..4922884 100644
--- a/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
 
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_a53)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -162,4 +162,4 @@
 
 #include "memcpy_base.S"
 
-END(__strcpy_chk)
+END(__strcpy_chk_a53)
diff --git a/libc/arch-arm/cortex-a7/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a7/bionic/__strcat_chk.S
index ca29715..36bda6b 100644
--- a/libc/arch-arm/cortex-a7/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a7/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_a7)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -200,4 +200,4 @@
     .cfi_adjust_cfa_offset 8
     .cfi_rel_offset r4, 0
     .cfi_rel_offset r5, 4
-END(__strcat_chk)
+END(__strcat_chk_a7)
diff --git a/libc/arch-arm/cortex-a7/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a7/bionic/__strcpy_chk.S
index 2679c02..edbabc7 100644
--- a/libc/arch-arm/cortex-a7/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a7/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
 
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_a7)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -162,4 +162,4 @@
 
 #include "memcpy_base.S"
 
-END(__strcpy_chk)
+END(__strcpy_chk_a7)
diff --git a/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
index 776c782..d20283e 100644
--- a/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
@@ -33,10 +33,14 @@
     .thumb
     .thumb_func
 
+    // To avoid warning about deprecated instructions, add an explicit
+    // arch. The code generated is exactly the same.
+    .arch armv7-a
+
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_a9)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -191,8 +195,8 @@
     pop     {r4, r5}
 
     // Fall through into the memcpy_base function.
-END(__strcat_chk)
+END(__strcat_chk_a9)
 
-#define MEMCPY_BASE         __strcat_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+#define MEMCPY_BASE         __strcat_chk_a9_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_a9_memcpy_base_aligned
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
index 1d5e70b..1f0a774 100644
--- a/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
@@ -33,9 +33,13 @@
     .thumb
     .thumb_func
 
+    // To avoid warning about deprecated instructions, add an explicit
+    // arch. The code generated is exactly the same.
+    .arch armv7-a
+
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_a9)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -159,8 +163,8 @@
     bhi     __strcpy_chk_fail
 
     // Fall through into the memcpy_base function.
-END(__strcpy_chk)
+END(__strcpy_chk_a9)
 
-#define MEMCPY_BASE         __strcpy_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#define MEMCPY_BASE         __strcpy_chk_a9_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_a9_memcpy_base_aligned
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/denver/bionic/__strcat_chk.S b/libc/arch-arm/denver/bionic/__strcat_chk.S
index d4f651c..1899908 100644
--- a/libc/arch-arm/denver/bionic/__strcat_chk.S
+++ b/libc/arch-arm/denver/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_denver)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -190,9 +190,9 @@
     mov     r2, r4
     add     r0, r0, r3
     pop     {r4, r5}
-END(__strcat_chk)
+END(__strcat_chk_denver)
 
-#define MEMCPY_BASE         __strcat_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+#define MEMCPY_BASE         __strcat_chk_denver_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_denver_memcpy_base_aligned
 
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/denver/bionic/__strcpy_chk.S b/libc/arch-arm/denver/bionic/__strcpy_chk.S
index 9295a00..9910c76 100644
--- a/libc/arch-arm/denver/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/denver/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
 
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_denver)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_def_cfa_offset 8
@@ -161,8 +161,8 @@
     bhi     __strcpy_chk_fail
 
     // Fall through into the memcpy_base function.
-END(__strcpy_chk)
+END(__strcpy_chk_denver)
 
-#define MEMCPY_BASE         __strcpy_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#define MEMCPY_BASE         __strcpy_chk_denver_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_denver_memcpy_base_aligned
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/dynamic_function_dispatch.cpp b/libc/arch-arm/dynamic_function_dispatch.cpp
index 17f0087..90eff56 100644
--- a/libc/arch-arm/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm/dynamic_function_dispatch.cpp
@@ -220,6 +220,26 @@
     }
 }
 
+typedef char* __strcpy_chk_func(char* dst, const char* src, size_t dst_len);
+DEFINE_IFUNC(__strcpy_chk) {
+    switch(get_cpu_variant()) {
+        case kCortexA7:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a7);
+        case kCortexA9:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a9);
+        case kKrait:
+        case kKryo:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_krait);
+        case kCortexA53:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a53);
+        case kCortexA55:
+        case kDenver:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_denver);
+        default:
+            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a15);
+    }
+}
+
 typedef char* stpcpy_func(char* __dst, const char* __src);
 DEFINE_IFUNC(stpcpy) {
     switch(get_cpu_variant()) {
@@ -240,6 +260,26 @@
     }
 }
 
+typedef char* __strcat_chk_func(char* dst, const char* src, size_t dst_buf_size);
+DEFINE_IFUNC(__strcat_chk) {
+    switch(get_cpu_variant()) {
+        case kCortexA7:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a7);
+        case kCortexA9:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a9);
+        case kKrait:
+        case kKryo:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_krait);
+        case kCortexA53:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a53);
+        case kCortexA55:
+        case kDenver:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_denver);
+        default:
+            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a15);
+    }
+}
+
 typedef int strcmp_func(const char* __lhs, const char* __rhs);
 DEFINE_IFUNC(strcmp) {
     switch(get_cpu_variant()) {
diff --git a/libc/arch-arm/krait/bionic/__strcat_chk.S b/libc/arch-arm/krait/bionic/__strcat_chk.S
index 32fa82d..9d4bffb 100644
--- a/libc/arch-arm/krait/bionic/__strcat_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
 // Get the length of src string, then get the source of the dst string.
 // Check that the two lengths together don't exceed the threshold, then
 // do a memcpy of the data.
-ENTRY(__strcat_chk)
+ENTRY(__strcat_chk_krait)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_adjust_cfa_offset 8
@@ -200,4 +200,4 @@
     .cfi_adjust_cfa_offset 8
     .cfi_rel_offset r4, 0
     .cfi_rel_offset r5, 4
-END(__strcat_chk)
+END(__strcat_chk_krait)
diff --git a/libc/arch-arm/krait/bionic/__strcpy_chk.S b/libc/arch-arm/krait/bionic/__strcpy_chk.S
index ca4cf7f..969e112 100644
--- a/libc/arch-arm/krait/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
 
 // Get the length of the source string first, then do a memcpy of the data
 // instead of a strcpy.
-ENTRY(__strcpy_chk)
+ENTRY(__strcpy_chk_krait)
     pld     [r0, #0]
     push    {r0, lr}
     .cfi_adjust_cfa_offset 8
@@ -162,4 +162,4 @@
 
 #include "memcpy_base.S"
 
-END(__strcpy_chk)
+END(__strcpy_chk_krait)
diff --git a/libc/arch-arm/static_function_dispatch.S b/libc/arch-arm/static_function_dispatch.S
index f3dd741..a8235c2 100644
--- a/libc/arch-arm/static_function_dispatch.S
+++ b/libc/arch-arm/static_function_dispatch.S
@@ -38,7 +38,9 @@
 FUNCTION_DELEGATE(memset, memset_generic)
 FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
 FUNCTION_DELEGATE(strcpy, strcpy_generic)
+FUNCTION_DELEGATE(__strcpy_chk, __strcpy_chk_generic)
 FUNCTION_DELEGATE(stpcpy, stpcpy_generic)
 FUNCTION_DELEGATE(strcat, strcat_generic)
+FUNCTION_DELEGATE(__strcat_chk, __strcat_chk_generic)
 FUNCTION_DELEGATE(strcmp, strcmp_generic)
 FUNCTION_DELEGATE(strlen, strlen_generic)
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 4b94573..20e265e 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -454,9 +454,14 @@
   return write(fd, buf, count);
 }
 
-#if !defined(NO___STRCAT_CHK)
+#if defined(RENAME___STRCAT_CHK)
+#define __STRCAT_CHK __strcat_chk_generic
+#else
+#define __STRCAT_CHK __strcat_chk
+#endif // RENAME___STRCAT_CHK
+
 // Runtime implementation of __builtin____strcat_chk (used directly by compiler, not in headers).
-extern "C" char* __strcat_chk(char* dst, const char* src, size_t dst_buf_size) {
+extern "C" char* __STRCAT_CHK(char* dst, const char* src, size_t dst_buf_size) {
   char* save = dst;
   size_t dst_len = __strlen_chk(dst, dst_buf_size);
 
@@ -472,17 +477,20 @@
 
   return save;
 }
-#endif // NO___STRCAT_CHK
 
-#if !defined(NO___STRCPY_CHK)
+#if defined(RENAME___STRCPY_CHK)
+#define __STRCPY_CHK __strcpy_chk_generic
+#else
+#define __STRCPY_CHK __strcpy_chk
+#endif // RENAME___STRCPY_CHK
+
 // Runtime implementation of __builtin____strcpy_chk (used directly by compiler, not in headers).
-extern "C" char* __strcpy_chk(char* dst, const char* src, size_t dst_len) {
+extern "C" char* __STRCPY_CHK(char* dst, const char* src, size_t dst_len) {
   // TODO: optimize so we don't scan src twice.
   size_t src_len = strlen(src) + 1;
   __check_buffer_access("strcpy", "write into", src_len, dst_len);
   return strcpy(dst, src);
 }
-#endif // NO___STRCPY_CHK
 
 #if !defined(NO___MEMCPY_CHK)
 // Runtime implementation of __memcpy_chk (used directly by compiler, not in headers).
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 7993681..b437f06 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -354,7 +354,9 @@
   std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
   async_safe_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
   if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
-    PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
+    if (!is_first_stage_init()) {
+      PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
+    }
     return false;
   }
 
@@ -993,8 +995,10 @@
   if (realpath_fd(fd, realpath)) {
     *realpath += separator;
   } else {
-    PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
-          normalized_path.c_str());
+    if (!is_first_stage_init()) {
+      PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+            normalized_path.c_str());
+    }
     *realpath = normalized_path;
   }
 
@@ -1024,7 +1028,10 @@
     if (fd != -1) {
       *file_offset = 0;
       if (!realpath_fd(fd, realpath)) {
-        PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", path);
+        if (!is_first_stage_init()) {
+          PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+                path);
+        }
         *realpath = path;
       }
     }
@@ -1071,7 +1078,10 @@
       if (fd != -1) {
         *file_offset = 0;
         if (!realpath_fd(fd, realpath)) {
-          PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", name);
+          if (!is_first_stage_init()) {
+            PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+                  name);
+          }
           *realpath = name;
         }
       }
@@ -1354,8 +1364,12 @@
     }
 
     if (!realpath_fd(extinfo->library_fd, &realpath)) {
-      PRINT("warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
-            "Will use given name.", name);
+      if (!is_first_stage_init()) {
+        PRINT(
+            "warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
+            "Will use given name.",
+            name);
+      }
       realpath = name;
     }
 
@@ -1510,9 +1524,9 @@
 static void soinfo_unload(soinfo* si);
 
 static void shuffle(std::vector<LoadTask*>* v) {
-  if (is_init()) {
-    // arc4random* is not available in init because /dev/random hasn't yet been
-    // created.
+  if (is_first_stage_init()) {
+    // arc4random* is not available in first stage init because /dev/random
+    // hasn't yet been created.
     return;
   }
   for (size_t i = 0, size = v->size(); i < size; ++i) {
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 7edfd54..aa12b6e 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -194,11 +194,19 @@
 static ExecutableInfo get_executable_info(KernelArgumentBlock& args) {
   ExecutableInfo result = {};
 
-  if (is_init()) {
-    // /proc fs is not mounted when init starts. Therefore we can't use
-    // /proc/self/exe for init.
+  if (is_first_stage_init()) {
+    // /proc fs is not mounted when first stage init starts. Therefore we can't
+    // use /proc/self/exe for init.
     stat("/init", &result.file_stat);
-    result.path = "/init";
+
+    // /init may be a symlink, so try to read it as such.
+    char path[PATH_MAX];
+    ssize_t path_len = readlink("/init", path, sizeof(path));
+    if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+      result.path = "/init";
+    } else {
+      result.path = std::string(path, path_len);
+    }
   } else {
     // Stat "/proc/self/exe" instead of executable_path because
     // the executable could be unlinked by this point and it should
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 0123d3c..34ac606 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -547,9 +547,9 @@
   uint8_t* first = align_up(mmap_ptr, align);
   uint8_t* last = align_down(mmap_ptr + mmap_size, align) - size;
 
-  // arc4random* is not available in init because /dev/urandom hasn't yet been
+  // arc4random* is not available in first stage init because /dev/urandom hasn't yet been
   // created. Don't randomize then.
-  size_t n = is_init() ? 0 : arc4random_uniform((last - first) / PAGE_SIZE + 1);
+  size_t n = is_first_stage_init() ? 0 : arc4random_uniform((last - first) / PAGE_SIZE + 1);
   uint8_t* start = first + n * PAGE_SIZE;
   munmap(mmap_ptr, start - mmap_ptr);
   munmap(start + size, mmap_ptr + mmap_size - (start + size));
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 71e8a4d..93079ca 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -748,7 +748,7 @@
   // Make sure the handle is unique and does not collide
   // with special values which are RTLD_DEFAULT and RTLD_NEXT.
   do {
-    if (!is_init()) {
+    if (!is_first_stage_init()) {
       arc4random_buf(&handle_, sizeof(handle_));
     } else {
       // arc4random* is not available in init because /dev/urandom hasn't yet been
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index d08b161..e926671 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -247,7 +247,7 @@
   }
 }
 
-bool is_init() {
-  static bool ret = (getpid() == 1);
+bool is_first_stage_init() {
+  static bool ret = (getpid() == 1 && access("/proc/self/exe", F_OK) == -1);
   return ret;
 }
diff --git a/linker/linker_utils.h b/linker/linker_utils.h
index b15082d..34a597b 100644
--- a/linker/linker_utils.h
+++ b/linker/linker_utils.h
@@ -55,4 +55,4 @@
 off64_t page_start(off64_t offset);
 size_t page_offset(off64_t offset);
 bool safe_add(off64_t* out, off64_t a, size_t b);
-bool is_init();
+bool is_first_stage_init();