tools/jprof/bfd.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 // vim:ts=8:sw=2:et:
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "leaky.h"
     8 #ifdef USE_BFD
     9 #include <stdio.h>
    10 #include <string.h>
    11 #include <fcntl.h>
    12 #include <unistd.h>
    13 #include <libgen.h>
    14 #include <bfd.h>
    15 #include <cxxabi.h>
    17 static bfd *try_debug_file(const char *filename, unsigned long crc32)
    18 {
    19   int fd = open(filename, O_RDONLY);
    20   if (fd < 0)
    21     return nullptr;
    23   unsigned char buf[4*1024];
    24   unsigned long crc = 0;
    26   while (1) {
    27     ssize_t count = read(fd, buf, sizeof(buf));
    28     if (count <= 0)
    29       break;
    31     crc = bfd_calc_gnu_debuglink_crc32(crc, buf, count);
    32   }
    34   close(fd);
    36   if (crc != crc32)
    37     return nullptr;
    39   bfd *object = bfd_openr(filename, nullptr);
    40   if (!bfd_check_format(object, bfd_object)) {
    41     bfd_close(object);
    42     return nullptr;
    43   }
    45   return object;
    46 }
    48 static bfd *find_debug_file(bfd *lib, const char *aFileName)
    49 {
    50   // check for a separate debug file with symbols
    51   asection *sect = bfd_get_section_by_name(lib, ".gnu_debuglink");
    53   if (!sect)
    54     return nullptr;
    56   bfd_size_type debuglinkSize = bfd_section_size (objfile->obfd, sect);
    58   char *debuglink = new char[debuglinkSize];
    59   bfd_get_section_contents(lib, sect, debuglink, 0, debuglinkSize);
    61   // crc checksum is aligned to 4 bytes, and after the NUL.
    62   int crc_offset = (int(strlen(debuglink)) & ~3) + 4;
    63   unsigned long crc32 = bfd_get_32(lib, debuglink + crc_offset);
    65   // directory component
    66   char *dirbuf = strdup(aFileName);
    67   const char *dir = dirname(dirbuf);
    69   static const char debug_subdir[] = ".debug";
    70   // This is gdb's default global debugging info directory, but gdb can
    71   // be instructed to use a different directory.
    72   static const char global_debug_dir[] = "/usr/lib/debug";
    74   char *filename =
    75     new char[strlen(global_debug_dir) + strlen(dir) + crc_offset + 3];
    77   // /path/debuglink
    78   sprintf(filename, "%s/%s", dir, debuglink);
    79   bfd *debugFile = try_debug_file(filename, crc32);
    80   if (!debugFile) {
    82     // /path/.debug/debuglink
    83     sprintf(filename, "%s/%s/%s", dir, debug_subdir, debuglink);
    84     debugFile = try_debug_file(filename, crc32);
    85     if (!debugFile) {
    87       // /usr/lib/debug/path/debuglink
    88       sprintf(filename, "%s/%s/%s", global_debug_dir, dir, debuglink);
    89       debugFile = try_debug_file(filename, crc32);
    90     }
    91   }
    93   delete[] filename;
    94   free(dirbuf);
    95   delete[] debuglink;
    97   return debugFile;
    98 }
   101 // Use an indirect array to avoid copying tons of objects
   102 Symbol ** leaky::ExtendSymbols(int num)
   103 {
   104   long n = numExternalSymbols + num;
   106   externalSymbols = (Symbol**)
   107                     realloc(externalSymbols,
   108                             (size_t) (sizeof(externalSymbols[0]) * n));
   109   Symbol *new_array = new Symbol[n];
   110   for (int i = 0; i < num; i++) {
   111     externalSymbols[i + numExternalSymbols] = &new_array[i];
   112   }
   113   lastSymbol = externalSymbols + n;
   114   Symbol **sp = externalSymbols + numExternalSymbols;
   115   numExternalSymbols = n;
   116   return sp;
   117 }
   119 #define NEXT_SYMBOL do { sp++; \
   120                          if (sp >= lastSymbol) { \
   121                            sp = ExtendSymbols(16384); \
   122                          } \
   123                        } while (0)
   125 void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
   126 {
   127   int initialSymbols = usefulSymbols;
   128   if (nullptr == externalSymbols) {
   129     externalSymbols = (Symbol**) calloc(sizeof(Symbol*),10000);
   130     Symbol *new_array = new Symbol[10000];
   131     for (int i = 0; i < 10000; i++) {
   132       externalSymbols[i] = &new_array[i];
   133     }
   134     numExternalSymbols = 10000;
   135   }
   136   Symbol** sp = externalSymbols + usefulSymbols;
   137   lastSymbol = externalSymbols + numExternalSymbols;
   139   // Create a dummy symbol for the library so, if it doesn't have any
   140   // symbols, we show it by library.
   141   (*sp)->Init(aFileName, aBaseAddress);
   142   NEXT_SYMBOL;
   144   bfd_boolean kDynamic = (bfd_boolean) false;
   146   static int firstTime = 1;
   147   if (firstTime) {
   148     firstTime = 0;
   149     bfd_init ();
   150   }
   152   bfd* lib = bfd_openr(aFileName, nullptr);
   153   if (nullptr == lib) {
   154     return;
   155   }
   156   if (!bfd_check_format(lib, bfd_object)) {
   157     bfd_close(lib);
   158     return;
   159   }
   161   bfd *symbolFile = find_debug_file(lib, aFileName);
   163   // read mini symbols
   164   PTR minisyms;
   165   unsigned int size;
   166   long symcount = 0;
   168   if (symbolFile) {
   169     symcount = bfd_read_minisymbols(symbolFile, kDynamic, &minisyms, &size);
   170     if (symcount == 0) {
   171       bfd_close(symbolFile);
   172     } else {
   173       bfd_close(lib);
   174     }
   175   }
   176   if (symcount == 0) {
   177     symcount = bfd_read_minisymbols(lib, kDynamic, &minisyms, &size);
   178     if (symcount == 0) {
   179       // symtab is empty; try dynamic symbols
   180       kDynamic = (bfd_boolean) true;
   181       symcount = bfd_read_minisymbols(lib, kDynamic, &minisyms, &size);
   182     }
   183     symbolFile = lib;
   184   }
   186   asymbol* store;
   187   store = bfd_make_empty_symbol(symbolFile);
   189   // Scan symbols
   190   size_t demangle_buffer_size = 128;
   191   char *demangle_buffer = (char*) malloc(demangle_buffer_size);
   192   bfd_byte* from = (bfd_byte *) minisyms;
   193   bfd_byte* fromend = from + symcount * size;
   194   for (; from < fromend; from += size) {
   195     asymbol *sym;
   196     sym = bfd_minisymbol_to_symbol(symbolFile, kDynamic, (const PTR) from, store);
   198     symbol_info syminfo;
   199     bfd_get_symbol_info (symbolFile, sym, &syminfo);
   201 //    if ((syminfo.type == 'T') || (syminfo.type == 't')) {
   202       const char* nm = bfd_asymbol_name(sym);
   203       if (nm && nm[0]) {
   204         char* dnm = nullptr;
   205         if (strncmp("__thunk", nm, 7)) {
   206           dnm =
   207             abi::__cxa_demangle(nm, demangle_buffer, &demangle_buffer_size, 0);
   208           if (dnm) {
   209             demangle_buffer = dnm;
   210           }
   211         }
   212         (*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress);
   213         NEXT_SYMBOL;
   214       }
   215 //    }
   216   }
   218   free(demangle_buffer);
   219   demangle_buffer = nullptr;
   221   bfd_close(symbolFile);
   223   int interesting = sp - externalSymbols;
   224   if (!quiet) {
   225     printf("%s provided %d symbols\n", aFileName,
   226            interesting - initialSymbols);
   227   }
   228   usefulSymbols = interesting;
   229 }
   231 #endif /* USE_BFD */

mercurial