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/linker/linker.cpp b/linker/linker.cpp
index 277b823..b605ed9 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -289,7 +289,7 @@
 }
 
 soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
-                     struct stat* file_stat, off64_t file_offset,
+                     const struct stat* file_stat, off64_t file_offset,
                      uint32_t rtld_flags) {
   if (strlen(name) >= PATH_MAX) {
     async_safe_fatal("library name \"%s\" too long", name);
@@ -1011,6 +1011,28 @@
   return true;
 }
 
+static int open_library_at_path(ZipArchiveCache* zip_archive_cache,
+                                const char* path, off64_t* file_offset,
+                                std::string* realpath) {
+  int fd = -1;
+  if (strstr(path, kZipFileSeparator) != nullptr) {
+    fd = open_library_in_zipfile(zip_archive_cache, path, file_offset, realpath);
+  }
+
+  if (fd == -1) {
+    fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
+    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);
+        *realpath = path;
+      }
+    }
+  }
+
+  return fd;
+}
+
 static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
                                  const char* name, off64_t* file_offset,
                                  const std::vector<std::string>& paths,
@@ -1021,22 +1043,7 @@
       continue;
     }
 
-    int fd = -1;
-    if (strstr(buf, kZipFileSeparator) != nullptr) {
-      fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset, realpath);
-    }
-
-    if (fd == -1) {
-      fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
-      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.", buf);
-          *realpath = buf;
-        }
-      }
-    }
-
+    int fd = open_library_at_path(zip_archive_cache, buf, file_offset, realpath);
     if (fd != -1) {
       return fd;
     }
@@ -1098,6 +1105,11 @@
   return fd;
 }
 
+int open_executable(const char* path, off64_t* file_offset, std::string* realpath) {
+  ZipArchiveCache zip_archive_cache;
+  return open_library_at_path(&zip_archive_cache, path, file_offset, realpath);
+}
+
 const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
 #if !defined(__LP64__)
   // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029