ltrace: Fix incompatibilities with Android linker
authorMichał Bednarski <bednarski.michal2@gmail.com>
Sat, 14 May 2016 15:22:21 +0000 (17:22 +0200)
committerMichał Bednarski <bednarski.michal2@gmail.com>
Sat, 14 May 2016 15:22:21 +0000 (17:22 +0200)
- Find libraries in LD_LIBRARY_PATH if relative path is found in debug
  link_map
- Skip main executable
- Skip /system/bin/linker and [vdso]
- Only set proc->e_machine once, as it might be set wrongly if we later
  try to load library that we couldn't find

disabled-packages/ltrace/ltrace-elf.c.patch
disabled-packages/ltrace/sysdeps-linux-gnu-proc.c.patch [new file with mode: 0644]

index eaa1812..7e5f824 100644 (file)
@@ -1,6 +1,8 @@
---- ltrace-2def9f1217374cc8371105993003b2c663aefda7/ltrace-elf.c       2016-04-11 21:30:04.000000000 +0200
-+++ src/ltrace-elf.c   2016-05-07 21:23:17.999754862 +0200
-@@ -423,7 +423,9 @@
+diff --git a/ltrace-elf.c b/ltrace-elf.c
+index f439cb0..60f1941 100644
+--- a/ltrace-elf.c
++++ b/ltrace-elf.c
+@@ -423,7 +423,9 @@ ltelf_destroy(struct ltelf *lte)
        debug(DEBUG_FUNCTION, "close_elf()");
        elf_end(lte->elf);
        close(lte->fd);
  }
  
  static void
+@@ -1149,9 +1151,11 @@ read_module(struct library *lib, struct process *proc,
+        * determine whether ABI is supported.  This is to get
+        * reasonable error messages when trying to run 64-bit binary
+        * with 32-bit ltrace.  It is desirable to preserve this.  */
+-      proc->e_machine = lte.ehdr.e_machine;
+-      proc->e_class = lte.ehdr.e_ident[EI_CLASS];
+-      get_arch_dep(proc);
++      if (proc->e_machine == 0) {
++              proc->e_machine = lte.ehdr.e_machine;
++              proc->e_class = lte.ehdr.e_ident[EI_CLASS];
++              get_arch_dep(proc);
++      }
+       /* Find out the base address.  For PIE main binaries we look
+        * into auxv, otherwise we scan phdrs.  */
diff --git a/disabled-packages/ltrace/sysdeps-linux-gnu-proc.c.patch b/disabled-packages/ltrace/sysdeps-linux-gnu-proc.c.patch
new file mode 100644 (file)
index 0000000..af2d7c1
--- /dev/null
@@ -0,0 +1,59 @@
+diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c
+index 953fd86..bdb96cb 100644
+--- a/sysdeps/linux-gnu/proc.c
++++ b/sysdeps/linux-gnu/proc.c
+@@ -524,9 +524,53 @@ crawl_linkmap(struct process *proc, struct lt_r_debug_64 *dbg)
+                   || strcmp(lib_name, "linux-vdso.so.1") == 0
+                   || strcmp(lib_name, "linux-gate.so.1") == 0
+                   || strcmp(lib_name, "linux-vdso32.so.1") == 0
+-                  || strcmp(lib_name, "linux-vdso64.so.1") == 0)
++                  || strcmp(lib_name, "linux-vdso64.so.1") == 0
++                  || strcmp(lib_name, "[vdso]") == 0
++                  /* Android linker includes itself in list of libraries
++                   * on GNU linker it appears as empty string */
++                  || strcmp(lib_name, "/system/bin/linker") == 0
++                  || strcmp(lib_name, "/system/bin/linker64") == 0)
+                       continue;
++              /* On Android main executable is included in library list
++               * On GNU it appears as empty string */
++              if (rlm.l_prev == 0 && strstr(lib_name, ".so") == NULL) {
++                      continue;
++              }
++
++              /* Android < 6 provides just library name without full path,
++               * will find full path ourselves */
++              if (lib_name[0] != '/') {
++                      char local_path[1024];
++                      /* Include path from LD_LIBRARY_PATH */
++                      const char *path = getenv("LD_LIBRARY_PATH");
++                      if (path) {
++                              strlcpy(local_path, path, sizeof(local_path));
++                      } else {
++                              local_path[0] = '\0';
++                      }
++                      /* Include default path (hardcoded in /system/bin/linker) */
++                      strlcat(
++                                      local_path,
++                                      select_32_64(proc, ":/vendor/lib:/system/lib", ":/vendor/lib64:/system/lib64"),
++                                      sizeof(local_path)
++                      );
++
++                      char *local_path_ptr = local_path;
++                      const char *tested_path;
++                      char full_lib_name[BUFSIZ];
++                      while ((tested_path = strsep(&local_path_ptr, ":"))) {
++                              if (tested_path[0] == '\0') {
++                                      continue;
++                              }
++                              snprintf(full_lib_name, sizeof(full_lib_name), "%s/%s", tested_path, lib_name);
++                              if (access(full_lib_name, F_OK) == 0) {
++                                      strlcpy(lib_name, full_lib_name, sizeof(lib_name));
++                                      break;
++                              }
++                      }
++              }
++
+               /* Do we have that library already?  */
+               if (proc_each_library(proc, NULL, library_with_key_cb, &key))
+                       continue;