tools/profiler/shared-libraries-linux.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "shared-libraries.h"
     7 #define PATH_MAX_TOSTRING(x) #x
     8 #define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
     9 #include <stdlib.h>
    10 #include <stdio.h>
    11 #include <string.h>
    12 #include <limits.h>
    13 #include <unistd.h>
    14 #include <fstream>
    15 #include "platform.h"
    16 #include "shared-libraries.h"
    18 #if !defined(MOZ_WIDGET_GONK)
    19 // TODO fix me with proper include
    20 #include "nsDebug.h"
    21 #ifdef ANDROID
    22 #include "ElfLoader.h" // dl_phdr_info
    23 #else
    24 #include <link.h> // dl_phdr_info
    25 #endif
    26 #include <features.h>
    27 #include <dlfcn.h>
    28 #include <sys/types.h>
    30 #ifdef ANDROID
    31 extern "C" __attribute__((weak))
    32 int dl_iterate_phdr(
    33           int (*callback) (struct dl_phdr_info *info,
    34                            size_t size, void *data),
    35           void *data);
    36 #endif
    38 int dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data)
    39 {
    40   SharedLibraryInfo& info = *reinterpret_cast<SharedLibraryInfo*>(data);
    42   if (dl_info->dlpi_phnum <= 0)
    43     return 0;
    45   unsigned long libStart = -1;
    46   unsigned long libEnd = 0;
    48   for (size_t i = 0; i < dl_info->dlpi_phnum; i++) {
    49     if (dl_info->dlpi_phdr[i].p_type != PT_LOAD) {
    50       continue;
    51     }
    52     unsigned long start = dl_info->dlpi_addr + dl_info->dlpi_phdr[i].p_vaddr;
    53     unsigned long end = start + dl_info->dlpi_phdr[i].p_memsz;
    54     if (start < libStart)
    55       libStart = start;
    56     if (end > libEnd)
    57       libEnd = end;
    58   }
    59   SharedLibrary shlib(libStart, libEnd, 0, "", dl_info->dlpi_name);
    60   info.AddSharedLibrary(shlib);
    62   return 0;
    63 }
    64 #endif
    66 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
    67 {
    68   SharedLibraryInfo info;
    70 #if !defined(MOZ_WIDGET_GONK)
    71   dl_iterate_phdr(dl_iterate_callback, &info);
    72 #ifndef ANDROID
    73   return info;
    74 #endif
    75 #endif
    77   pid_t pid = getpid();
    78   char path[PATH_MAX];
    79   snprintf(path, PATH_MAX, "/proc/%d/maps", pid);
    80   std::ifstream maps(path);
    81   std::string line;
    82   int count = 0;
    83   while (std::getline(maps, line)) {
    84     int ret;
    85     //XXX: needs input sanitizing
    86     unsigned long start;
    87     unsigned long end;
    88     char perm[6] = "";
    89     unsigned long offset;
    90     char name[PATH_MAX] = "";
    91     ret = sscanf(line.c_str(),
    92                  "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
    93                  &start, &end, perm, &offset, name);
    94     if (!strchr(perm, 'x')) {
    95       // Ignore non executable entries
    96       continue;
    97     }
    98     if (ret != 5 && ret != 4) {
    99       LOG("Get maps line failed");
   100       continue;
   101     }
   102 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
   103     // Use proc/pid/maps to get the dalvik-jit section since it has
   104     // no associated phdrs
   105     if (strcmp(name, "/dev/ashmem/dalvik-jit-code-cache") != 0)
   106       continue;
   107 #else
   108     if (strcmp(perm, "r-xp") != 0) {
   109       // Ignore entries that are writable and/or shared.
   110       // At least one graphics driver uses short-lived "rwxs" mappings
   111       // (see bug 926734 comment 5), so just checking for 'x' isn't enough.
   112       continue;
   113     }
   114 #endif
   115     SharedLibrary shlib(start, end, offset, "", name);
   116     info.AddSharedLibrary(shlib);
   117     if (count > 10000) {
   118       LOG("Get maps failed");
   119       break;
   120     }
   121     count++;
   122   }
   123   return info;
   124 }

mercurial