Allow invoking the linker on an executable.

The executable can be inside a zip file using the same syntax used for
shared objects: path.zip!/libentry.so.

The linker currently requires an absolute path. This restriction could be
loosened, but it didn't seem important? If it allowed non-absolute paths,
we'd need to decide how to handle:
 - foo/bar      (relative to CWD?)
 - foo          (search PATH / LD_LIBRARY_PATH, or also relative to CWD?)
 - foo.zip!/bar (normalize_path() requires an absolute path)

The linker adjusts the argc/argv passed to main() and to constructor
functions to hide the initial linker argument, but doesn't adjust the auxv
vector or files like /proc/self/{exe,cmdline,auxv,stat}. Those files will
report that the kernel loaded the linker as an executable.

I think the linker_logger.cpp change guarding against (g_argv == NULL)
isn't actually necessary, but it seemed like a good idea given that I'm
delaying initialization of g_argv until after C++ constructors have run.

Bug: http://b/112050209
Test: bionic unit tests
Change-Id: I846faf98b16fd34218946f6167e8b451897debe5
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 44fab01..cb98cae 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -79,21 +79,61 @@
   ASSERT_EQ(3370318, lib_global_protected_get_serial());
 }
 
-TEST(dl, exec_linker) {
 #if defined(__BIONIC__)
 #if defined(__LP64__)
   static constexpr const char* kPathToLinker = "/system/bin/linker64";
 #else
   static constexpr const char* kPathToLinker = "/system/bin/linker";
 #endif
+#endif
+
+TEST(dl, exec_linker) {
+#if defined(__BIONIC__)
+  std::string usage_prefix = std::string("Usage: ") + kPathToLinker;
   ExecTestHelper eth;
-  std::string expected_output = std::string("This is ") + kPathToLinker +
-                                ", the helper program for dynamic executables.\n";
-  eth.SetArgs( { kPathToLinker, nullptr });
+  eth.SetArgs({ kPathToLinker, nullptr });
+  eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
+  ASSERT_EQ(0u, eth.GetOutput().find(usage_prefix)) << "Test output:\n" << eth.GetOutput();
+#endif
+}
+
+TEST(dl, exec_linker_load_file) {
+#if defined(__BIONIC__)
+  std::string helper = GetTestlibRoot() +
+      "/exec_linker_helper/exec_linker_helper";
+  std::string expected_output =
+      "ctor: argc=1 argv[0]=" + helper + "\n" +
+      "main: argc=1 argv[0]=" + helper + "\n" +
+      "helper_func called\n";
+  ExecTestHelper eth;
+  eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr });
   eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str());
 #endif
 }
 
+TEST(dl, exec_linker_load_from_zip) {
+#if defined(__BIONIC__)
+  std::string helper = GetTestlibRoot() +
+      "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip!/libdir/exec_linker_helper";
+  std::string expected_output =
+      "ctor: argc=1 argv[0]=" + helper + "\n" +
+      "main: argc=1 argv[0]=" + helper + "\n" +
+      "helper_func called\n";
+  ExecTestHelper eth;
+  eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr });
+  eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str());
+#endif
+}
+
+TEST(dl, exec_linker_load_self) {
+#if defined(__BIONIC__)
+  std::string error_message = "error: linker cannot load itself\n";
+  ExecTestHelper eth;
+  eth.SetArgs({ kPathToLinker, kPathToLinker, nullptr });
+  eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str());
+#endif
+}
+
 TEST(dl, preinit_system_calls) {
 #if defined(__BIONIC__)
   std::string helper = GetTestlibRoot() +