Bug 1414506 - Move dl_phdr_info filling and callback invocation to a separate class. r=froydnj
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 23 Jan 2018 15:50:38 +0900
changeset 400878 ce1f9ca065cf854404d1182d311b4156fd7b08b7
parent 400877 534f60b7cb2b41b9bc7024b34332521160054c9f
child 400879 3b862e2b9e0b6caee20037f3f7bb33c88468876a
push id33320
push userdluca@mozilla.com
push dateFri, 26 Jan 2018 01:54:08 +0000
treeherdermozilla-central@723b25eb3dd8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1414506
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1414506 - Move dl_phdr_info filling and callback invocation to a separate class. r=froydnj We're going to introduce two code paths that need to fill dl_phdr_info from different iterators, so first move the code to a separate class, that both code paths will be able to call.
mozglue/linker/ElfLoader.cpp
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -100,32 +100,46 @@ int
   if (!handle) {
     return dladdr(addr, info);
   }
   info->dli_fname = handle->GetPath();
   info->dli_fbase = handle->GetBase();
   return 1;
 }
 
-int
-__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
+class DlIteratePhdrHelper
 {
-  if (!ElfLoader::Singleton.dbg)
-    return -1;
+public:
+  DlIteratePhdrHelper()
+  {
+    int pipefd[2];
+    valid_pipe = (pipe(pipefd) == 0);
+    read_fd.reset(pipefd[0]);
+    write_fd.reset(pipefd[1]);
+  }
+
+  int fill_and_call(dl_phdr_cb callback, const void* l_addr,
+                    const char* l_name, void* data);
 
-  int pipefd[2];
-  bool valid_pipe = (pipe(pipefd) == 0);
-  AutoCloseFD read_fd(pipefd[0]);
-  AutoCloseFD write_fd(pipefd[1]);
+private:
+  bool valid_pipe;
+  AutoCloseFD read_fd;
+  AutoCloseFD write_fd;
+};
 
-  for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin();
-       it < ElfLoader::Singleton.dbg.end(); ++it) {
+// This function is called for each shared library iterated over by
+// dl_iterate_phdr, and is used to fill a dl_phdr_info which is then
+// sent through to the dl_iterate_phdr callback.
+int
+DlIteratePhdrHelper::fill_and_call(dl_phdr_cb callback, const void* l_addr,
+                                   const char* l_name, void *data)
+{
     dl_phdr_info info;
-    info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
-    info.dlpi_name = it->l_name;
+    info.dlpi_addr = reinterpret_cast<Elf::Addr>(l_addr);
+    info.dlpi_name = l_name;
     info.dlpi_phdr = nullptr;
     info.dlpi_phnum = 0;
 
     // Assuming l_addr points to Elf headers (in most cases, this is true),
     // get the Phdr location from there.
     // Unfortunately, when l_addr doesn't point to Elf headers, it may point
     // to unmapped memory, or worse, unreadable memory. The only way to detect
     // the latter without causing a SIGSEGV is to use the pointer in a system
@@ -142,17 +156,17 @@ int
     // start over with a new pipe.
     int can_read = true;
     if (valid_pipe) {
       int ret;
       char raw_ehdr[sizeof(Elf::Ehdr)];
       static_assert(sizeof(raw_ehdr) < PIPE_BUF, "PIPE_BUF is too small");
       do {
         // writes are atomic when smaller than PIPE_BUF, per POSIX.1-2008.
-        ret = write(write_fd, it->l_addr, sizeof(raw_ehdr));
+        ret = write(write_fd, l_addr, sizeof(raw_ehdr));
       } while (ret == -1 && errno == EINTR);
       if (ret != sizeof(raw_ehdr)) {
         if (ret == -1 && errno == EFAULT) {
           can_read = false;
         } else {
           valid_pipe = false;
         }
       } else {
@@ -167,25 +181,38 @@ int
                  (ret == -1 && errno == EINTR));
         if (nbytes != sizeof(raw_ehdr)) {
           valid_pipe = false;
         }
       }
     }
 
     if (valid_pipe && can_read) {
-      const Elf::Ehdr *ehdr = Elf::Ehdr::validate(it->l_addr);
+      const Elf::Ehdr *ehdr = Elf::Ehdr::validate(l_addr);
       if (ehdr) {
         info.dlpi_phdr = reinterpret_cast<const Elf::Phdr *>(
                          reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff);
         info.dlpi_phnum = ehdr->e_phnum;
       }
     }
 
-    int ret = callback(&info, sizeof(dl_phdr_info), data);
+    return callback(&info, sizeof(dl_phdr_info), data);
+}
+
+int
+__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
+{
+  if (!ElfLoader::Singleton.dbg)
+    return -1;
+
+  DlIteratePhdrHelper helper;
+
+  for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin();
+       it < ElfLoader::Singleton.dbg.end(); ++it) {
+    int ret = helper.fill_and_call(callback, it->l_addr, it->l_name, data);
     if (ret)
       return ret;
   }
   return 0;
 }
 
 #ifdef __ARM_EABI__
 const void *