Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is shared between AddressSanitizer and ThreadSanitizer
     11 // run-time libraries.
     12 // POSIX-specific implementation of symbolizer parts.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "sanitizer_platform.h"
     16 #if SANITIZER_POSIX
     17 #include "sanitizer_allocator_internal.h"
     18 #include "sanitizer_common.h"
     19 #include "sanitizer_flags.h"
     20 #include "sanitizer_internal_defs.h"
     21 #include "sanitizer_linux.h"
     22 #include "sanitizer_placement_new.h"
     23 #include "sanitizer_procmaps.h"
     24 #include "sanitizer_symbolizer.h"
     25 #include "sanitizer_symbolizer_libbacktrace.h"
     26 
     27 #include <errno.h>
     28 #include <stdlib.h>
     29 #include <sys/wait.h>
     30 #include <unistd.h>
     31 
     32 // C++ demangling function, as required by Itanium C++ ABI. This is weak,
     33 // because we do not require a C++ ABI library to be linked to a program
     34 // using sanitizers; if it's not present, we'll just use the mangled name.
     35 namespace __cxxabiv1 {
     36   extern "C" SANITIZER_WEAK_ATTRIBUTE
     37   char *__cxa_demangle(const char *mangled, char *buffer,
     38                                   size_t *length, int *status);
     39 }
     40 
     41 namespace __sanitizer {
     42 
     43 // Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
     44 static const char *DemangleCXXABI(const char *name) {
     45   // FIXME: __cxa_demangle aggressively insists on allocating memory.
     46   // There's not much we can do about that, short of providing our
     47   // own demangler (libc++abi's implementation could be adapted so that
     48   // it does not allocate). For now, we just call it anyway, and we leak
     49   // the returned value.
     50   if (__cxxabiv1::__cxa_demangle)
     51     if (const char *demangled_name =
     52           __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
     53       return demangled_name;
     54 
     55   return name;
     56 }
     57 
     58 // Extracts the prefix of "str" that consists of any characters not
     59 // present in "delims" string, and copies this prefix to "result", allocating
     60 // space for it.
     61 // Returns a pointer to "str" after skipping extracted prefix and first
     62 // delimiter char.
     63 static const char *ExtractToken(const char *str, const char *delims,
     64                                 char **result) {
     65   uptr prefix_len = internal_strcspn(str, delims);
     66   *result = (char*)InternalAlloc(prefix_len + 1);
     67   internal_memcpy(*result, str, prefix_len);
     68   (*result)[prefix_len] = '\0';
     69   const char *prefix_end = str + prefix_len;
     70   if (*prefix_end != '\0') prefix_end++;
     71   return prefix_end;
     72 }
     73 
     74 // Same as ExtractToken, but converts extracted token to integer.
     75 static const char *ExtractInt(const char *str, const char *delims,
     76                               int *result) {
     77   char *buff;
     78   const char *ret = ExtractToken(str, delims, &buff);
     79   if (buff != 0) {
     80     *result = (int)internal_atoll(buff);
     81   }
     82   InternalFree(buff);
     83   return ret;
     84 }
     85 
     86 static const char *ExtractUptr(const char *str, const char *delims,
     87                                uptr *result) {
     88   char *buff;
     89   const char *ret = ExtractToken(str, delims, &buff);
     90   if (buff != 0) {
     91     *result = (uptr)internal_atoll(buff);
     92   }
     93   InternalFree(buff);
     94   return ret;
     95 }
     96 
     97 class ExternalSymbolizerInterface {
     98  public:
     99   // Can't declare pure virtual functions in sanitizer runtimes:
    100   // __cxa_pure_virtual might be unavailable.
    101   virtual char *SendCommand(bool is_data, const char *module_name,
    102                             uptr module_offset) {
    103     UNIMPLEMENTED();
    104   }
    105 };
    106 
    107 // SymbolizerProcess encapsulates communication between the tool and
    108 // external symbolizer program, running in a different subprocess.
    109 // SymbolizerProcess may not be used from two threads simultaneously.
    110 class SymbolizerProcess : public ExternalSymbolizerInterface {
    111  public:
    112   explicit SymbolizerProcess(const char *path)
    113       : path_(path),
    114         input_fd_(kInvalidFd),
    115         output_fd_(kInvalidFd),
    116         times_restarted_(0),
    117         failed_to_start_(false),
    118         reported_invalid_path_(false) {
    119     CHECK(path_);
    120     CHECK_NE(path_[0], '\0');
    121   }
    122 
    123   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
    124     for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
    125       // Start or restart symbolizer if we failed to send command to it.
    126       if (char *res = SendCommandImpl(is_data, module_name, module_offset))
    127         return res;
    128       Restart();
    129     }
    130     if (!failed_to_start_) {
    131       Report("WARNING: Failed to use and restart external symbolizer!\n");
    132       failed_to_start_ = true;
    133     }
    134     return 0;
    135   }
    136 
    137  private:
    138   bool Restart() {
    139     if (input_fd_ != kInvalidFd)
    140       internal_close(input_fd_);
    141     if (output_fd_ != kInvalidFd)
    142       internal_close(output_fd_);
    143     return StartSymbolizerSubprocess();
    144   }
    145 
    146   char *SendCommandImpl(bool is_data, const char *module_name,
    147                         uptr module_offset) {
    148     if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
    149       return 0;
    150     CHECK(module_name);
    151     if (!RenderInputCommand(buffer_, kBufferSize, is_data, module_name,
    152                             module_offset))
    153       return 0;
    154     if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
    155       return 0;
    156     if (!readFromSymbolizer(buffer_, kBufferSize))
    157       return 0;
    158     return buffer_;
    159   }
    160 
    161   bool readFromSymbolizer(char *buffer, uptr max_length) {
    162     if (max_length == 0)
    163       return true;
    164     uptr read_len = 0;
    165     while (true) {
    166       uptr just_read = internal_read(input_fd_, buffer + read_len,
    167                                      max_length - read_len - 1);
    168       // We can't read 0 bytes, as we don't expect external symbolizer to close
    169       // its stdout.
    170       if (just_read == 0 || just_read == (uptr)-1) {
    171         Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
    172         return false;
    173       }
    174       read_len += just_read;
    175       if (ReachedEndOfOutput(buffer, read_len))
    176         break;
    177     }
    178     buffer[read_len] = '\0';
    179     return true;
    180   }
    181 
    182   bool writeToSymbolizer(const char *buffer, uptr length) {
    183     if (length == 0)
    184       return true;
    185     uptr write_len = internal_write(output_fd_, buffer, length);
    186     if (write_len == 0 || write_len == (uptr)-1) {
    187       Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
    188       return false;
    189     }
    190     return true;
    191   }
    192 
    193   bool StartSymbolizerSubprocess() {
    194     if (!FileExists(path_)) {
    195       if (!reported_invalid_path_) {
    196         Report("WARNING: invalid path to external symbolizer!\n");
    197         reported_invalid_path_ = true;
    198       }
    199       return false;
    200     }
    201 
    202     int *infd = NULL;
    203     int *outfd = NULL;
    204     // The client program may close its stdin and/or stdout and/or stderr
    205     // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
    206     // In this case the communication between the forked processes may be
    207     // broken if either the parent or the child tries to close or duplicate
    208     // these descriptors. The loop below produces two pairs of file
    209     // descriptors, each greater than 2 (stderr).
    210     int sock_pair[5][2];
    211     for (int i = 0; i < 5; i++) {
    212       if (pipe(sock_pair[i]) == -1) {
    213         for (int j = 0; j < i; j++) {
    214           internal_close(sock_pair[j][0]);
    215           internal_close(sock_pair[j][1]);
    216         }
    217         Report("WARNING: Can't create a socket pair to start "
    218                "external symbolizer (errno: %d)\n", errno);
    219         return false;
    220       } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
    221         if (infd == NULL) {
    222           infd = sock_pair[i];
    223         } else {
    224           outfd = sock_pair[i];
    225           for (int j = 0; j < i; j++) {
    226             if (sock_pair[j] == infd) continue;
    227             internal_close(sock_pair[j][0]);
    228             internal_close(sock_pair[j][1]);
    229           }
    230           break;
    231         }
    232       }
    233     }
    234     CHECK(infd);
    235     CHECK(outfd);
    236 
    237     // Real fork() may call user callbacks registered with pthread_atfork().
    238     int pid = internal_fork();
    239     if (pid == -1) {
    240       // Fork() failed.
    241       internal_close(infd[0]);
    242       internal_close(infd[1]);
    243       internal_close(outfd[0]);
    244       internal_close(outfd[1]);
    245       Report("WARNING: failed to fork external symbolizer "
    246              " (errno: %d)\n", errno);
    247       return false;
    248     } else if (pid == 0) {
    249       // Child subprocess.
    250       internal_close(STDOUT_FILENO);
    251       internal_close(STDIN_FILENO);
    252       internal_dup2(outfd[0], STDIN_FILENO);
    253       internal_dup2(infd[1], STDOUT_FILENO);
    254       internal_close(outfd[0]);
    255       internal_close(outfd[1]);
    256       internal_close(infd[0]);
    257       internal_close(infd[1]);
    258       for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
    259         internal_close(fd);
    260       ExecuteWithDefaultArgs(path_);
    261       internal__exit(1);
    262     }
    263 
    264     // Continue execution in parent process.
    265     internal_close(outfd[0]);
    266     internal_close(infd[1]);
    267     input_fd_ = infd[0];
    268     output_fd_ = outfd[1];
    269 
    270     // Check that symbolizer subprocess started successfully.
    271     int pid_status;
    272     SleepForMillis(kSymbolizerStartupTimeMillis);
    273     int exited_pid = waitpid(pid, &pid_status, WNOHANG);
    274     if (exited_pid != 0) {
    275       // Either waitpid failed, or child has already exited.
    276       Report("WARNING: external symbolizer didn't start up correctly!\n");
    277       return false;
    278     }
    279 
    280     return true;
    281   }
    282 
    283   virtual bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
    284                                   const char *module_name,
    285                                   uptr module_offset) const {
    286     UNIMPLEMENTED();
    287   }
    288 
    289   virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
    290     UNIMPLEMENTED();
    291   }
    292 
    293   virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
    294     UNIMPLEMENTED();
    295   }
    296 
    297   const char *path_;
    298   int input_fd_;
    299   int output_fd_;
    300 
    301   static const uptr kBufferSize = 16 * 1024;
    302   char buffer_[kBufferSize];
    303 
    304   static const uptr kMaxTimesRestarted = 5;
    305   static const int kSymbolizerStartupTimeMillis = 10;
    306   uptr times_restarted_;
    307   bool failed_to_start_;
    308   bool reported_invalid_path_;
    309 };
    310 
    311 // For now we assume the following protocol:
    312 // For each request of the form
    313 //   <module_name> <module_offset>
    314 // passed to STDIN, external symbolizer prints to STDOUT response:
    315 //   <function_name>
    316 //   <file_name>:<line_number>:<column_number>
    317 //   <function_name>
    318 //   <file_name>:<line_number>:<column_number>
    319 //   ...
    320 //   <empty line>
    321 class LLVMSymbolizerProcess : public SymbolizerProcess {
    322  public:
    323   explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
    324 
    325  private:
    326   bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
    327                           const char *module_name, uptr module_offset) const {
    328     internal_snprintf(buffer, max_length, "%s\"%s\" 0x%zx\n",
    329                       is_data ? "DATA " : "", module_name, module_offset);
    330     return true;
    331   }
    332 
    333   bool ReachedEndOfOutput(const char *buffer, uptr length) const {
    334     // Empty line marks the end of llvm-symbolizer output.
    335     return length >= 2 && buffer[length - 1] == '\n' &&
    336            buffer[length - 2] == '\n';
    337   }
    338 
    339   void ExecuteWithDefaultArgs(const char *path_to_binary) const {
    340 #if defined(__x86_64__)
    341     const char* const kSymbolizerArch = "--default-arch=x86_64";
    342 #elif defined(__i386__)
    343     const char* const kSymbolizerArch = "--default-arch=i386";
    344 #elif defined(__powerpc64__)
    345     const char* const kSymbolizerArch = "--default-arch=powerpc64";
    346 #else
    347     const char* const kSymbolizerArch = "--default-arch=unknown";
    348 #endif
    349     execl(path_to_binary, path_to_binary, kSymbolizerArch, (char *)0);
    350   }
    351 };
    352 
    353 class Addr2LineProcess : public SymbolizerProcess {
    354  public:
    355   Addr2LineProcess(const char *path, const char *module_name)
    356       : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {}
    357 
    358   const char *module_name() const { return module_name_; }
    359 
    360  private:
    361   bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
    362                           const char *module_name, uptr module_offset) const {
    363     if (is_data)
    364       return false;
    365     CHECK_EQ(0, internal_strcmp(module_name, module_name_));
    366     internal_snprintf(buffer, max_length, "0x%zx\n", module_offset);
    367     return true;
    368   }
    369 
    370   bool ReachedEndOfOutput(const char *buffer, uptr length) const {
    371     // Output should consist of two lines.
    372     int num_lines = 0;
    373     for (uptr i = 0; i < length; ++i) {
    374       if (buffer[i] == '\n')
    375         num_lines++;
    376       if (num_lines >= 2)
    377         return true;
    378     }
    379     return false;
    380   }
    381 
    382   void ExecuteWithDefaultArgs(const char *path_to_binary) const {
    383     execl(path_to_binary, path_to_binary, "-Cfe", module_name_, (char *)0);
    384   }
    385 
    386   const char *module_name_;  // Owned, leaked.
    387 };
    388 
    389 class Addr2LinePool : public ExternalSymbolizerInterface {
    390  public:
    391   explicit Addr2LinePool(const char *addr2line_path,
    392                          LowLevelAllocator *allocator)
    393       : addr2line_path_(addr2line_path), allocator_(allocator),
    394         addr2line_pool_(16) {}
    395 
    396   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
    397     if (is_data)
    398       return 0;
    399     Addr2LineProcess *addr2line = 0;
    400     for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
    401       if (0 ==
    402           internal_strcmp(module_name, addr2line_pool_[i]->module_name())) {
    403         addr2line = addr2line_pool_[i];
    404         break;
    405       }
    406     }
    407     if (!addr2line) {
    408       addr2line =
    409           new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
    410       addr2line_pool_.push_back(addr2line);
    411     }
    412     return addr2line->SendCommand(is_data, module_name, module_offset);
    413   }
    414 
    415  private:
    416   const char *addr2line_path_;
    417   LowLevelAllocator *allocator_;
    418   InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
    419 };
    420 
    421 #if SANITIZER_SUPPORTS_WEAK_HOOKS
    422 extern "C" {
    423 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    424 bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
    425                                 char *Buffer, int MaxLength);
    426 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    427 bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
    428                                 char *Buffer, int MaxLength);
    429 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    430 void __sanitizer_symbolize_flush();
    431 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    432 int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
    433                                    int MaxLength);
    434 }  // extern "C"
    435 
    436 class InternalSymbolizer {
    437  public:
    438   typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
    439 
    440   static InternalSymbolizer *get(LowLevelAllocator *alloc) {
    441     if (__sanitizer_symbolize_code != 0 &&
    442         __sanitizer_symbolize_data != 0) {
    443       return new(*alloc) InternalSymbolizer();
    444     }
    445     return 0;
    446   }
    447 
    448   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
    449     SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
    450                                                 : __sanitizer_symbolize_code;
    451     if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
    452       return buffer_;
    453     return 0;
    454   }
    455 
    456   void Flush() {
    457     if (__sanitizer_symbolize_flush)
    458       __sanitizer_symbolize_flush();
    459   }
    460 
    461   const char *Demangle(const char *name) {
    462     if (__sanitizer_symbolize_demangle) {
    463       for (uptr res_length = 1024;
    464            res_length <= InternalSizeClassMap::kMaxSize;) {
    465         char *res_buff = static_cast<char*>(InternalAlloc(res_length));
    466         uptr req_length =
    467             __sanitizer_symbolize_demangle(name, res_buff, res_length);
    468         if (req_length > res_length) {
    469           res_length = req_length + 1;
    470           InternalFree(res_buff);
    471           continue;
    472         }
    473         return res_buff;
    474       }
    475     }
    476     return name;
    477   }
    478 
    479  private:
    480   InternalSymbolizer() { }
    481 
    482   static const int kBufferSize = 16 * 1024;
    483   static const int kMaxDemangledNameSize = 1024;
    484   char buffer_[kBufferSize];
    485 };
    486 #else  // SANITIZER_SUPPORTS_WEAK_HOOKS
    487 
    488 class InternalSymbolizer {
    489  public:
    490   static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
    491   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
    492     return 0;
    493   }
    494   void Flush() { }
    495   const char *Demangle(const char *name) { return name; }
    496 };
    497 
    498 #endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
    499 
    500 class POSIXSymbolizer : public Symbolizer {
    501  public:
    502   POSIXSymbolizer(ExternalSymbolizerInterface *external_symbolizer,
    503                   InternalSymbolizer *internal_symbolizer,
    504                   LibbacktraceSymbolizer *libbacktrace_symbolizer)
    505       : Symbolizer(),
    506         external_symbolizer_(external_symbolizer),
    507         internal_symbolizer_(internal_symbolizer),
    508         libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
    509 
    510   uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) {
    511     BlockingMutexLock l(&mu_);
    512     if (max_frames == 0)
    513       return 0;
    514     const char *module_name;
    515     uptr module_offset;
    516     if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
    517       return 0;
    518     // First, try to use libbacktrace symbolizer (if it's available).
    519     if (libbacktrace_symbolizer_ != 0) {
    520       mu_.CheckLocked();
    521       uptr res = libbacktrace_symbolizer_->SymbolizeCode(
    522           addr, frames, max_frames, module_name, module_offset);
    523       if (res > 0)
    524         return res;
    525     }
    526     const char *str = SendCommand(false, module_name, module_offset);
    527     if (str == 0) {
    528       // Symbolizer was not initialized or failed. Fill only data
    529       // about module name and offset.
    530       AddressInfo *info = &frames[0];
    531       info->Clear();
    532       info->FillAddressAndModuleInfo(addr, module_name, module_offset);
    533       return 1;
    534     }
    535     uptr frame_id = 0;
    536     for (frame_id = 0; frame_id < max_frames; frame_id++) {
    537       AddressInfo *info = &frames[frame_id];
    538       char *function_name = 0;
    539       str = ExtractToken(str, "\n", &function_name);
    540       CHECK(function_name);
    541       if (function_name[0] == '\0') {
    542         // There are no more frames.
    543         break;
    544       }
    545       info->Clear();
    546       info->FillAddressAndModuleInfo(addr, module_name, module_offset);
    547       info->function = function_name;
    548       // Parse <file>:<line>:<column> buffer.
    549       char *file_line_info = 0;
    550       str = ExtractToken(str, "\n", &file_line_info);
    551       CHECK(file_line_info);
    552       const char *line_info = ExtractToken(file_line_info, ":", &info->file);
    553       line_info = ExtractInt(line_info, ":", &info->line);
    554       line_info = ExtractInt(line_info, "", &info->column);
    555       InternalFree(file_line_info);
    556 
    557       // Functions and filenames can be "??", in which case we write 0
    558       // to address info to mark that names are unknown.
    559       if (0 == internal_strcmp(info->function, "??")) {
    560         InternalFree(info->function);
    561         info->function = 0;
    562       }
    563       if (0 == internal_strcmp(info->file, "??")) {
    564         InternalFree(info->file);
    565         info->file = 0;
    566       }
    567     }
    568     if (frame_id == 0) {
    569       // Make sure we return at least one frame.
    570       AddressInfo *info = &frames[0];
    571       info->Clear();
    572       info->FillAddressAndModuleInfo(addr, module_name, module_offset);
    573       frame_id = 1;
    574     }
    575     return frame_id;
    576   }
    577 
    578   bool SymbolizeData(uptr addr, DataInfo *info) {
    579     BlockingMutexLock l(&mu_);
    580     LoadedModule *module = FindModuleForAddress(addr);
    581     if (module == 0)
    582       return false;
    583     const char *module_name = module->full_name();
    584     uptr module_offset = addr - module->base_address();
    585     internal_memset(info, 0, sizeof(*info));
    586     info->address = addr;
    587     info->module = internal_strdup(module_name);
    588     info->module_offset = module_offset;
    589     // First, try to use libbacktrace symbolizer (if it's available).
    590     if (libbacktrace_symbolizer_ != 0) {
    591       mu_.CheckLocked();
    592       if (libbacktrace_symbolizer_->SymbolizeData(info))
    593         return true;
    594     }
    595     const char *str = SendCommand(true, module_name, module_offset);
    596     if (str == 0)
    597       return true;
    598     str = ExtractToken(str, "\n", &info->name);
    599     str = ExtractUptr(str, " ", &info->start);
    600     str = ExtractUptr(str, "\n", &info->size);
    601     info->start += module->base_address();
    602     return true;
    603   }
    604 
    605   bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
    606                                    uptr *module_address) {
    607     BlockingMutexLock l(&mu_);
    608     return FindModuleNameAndOffsetForAddress(pc, module_name, module_address);
    609   }
    610 
    611   bool CanReturnFileLineInfo() {
    612     return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
    613            libbacktrace_symbolizer_ != 0;
    614   }
    615 
    616   void Flush() {
    617     BlockingMutexLock l(&mu_);
    618     if (internal_symbolizer_ != 0) {
    619       SymbolizerScope sym_scope(this);
    620       internal_symbolizer_->Flush();
    621     }
    622   }
    623 
    624   const char *Demangle(const char *name) {
    625     BlockingMutexLock l(&mu_);
    626     // Run hooks even if we don't use internal symbolizer, as cxxabi
    627     // demangle may call system functions.
    628     SymbolizerScope sym_scope(this);
    629     // Try to use libbacktrace demangler (if available).
    630     if (libbacktrace_symbolizer_ != 0) {
    631       if (const char *demangled = libbacktrace_symbolizer_->Demangle(name))
    632         return demangled;
    633     }
    634     if (internal_symbolizer_ != 0)
    635       return internal_symbolizer_->Demangle(name);
    636     return DemangleCXXABI(name);
    637   }
    638 
    639   void PrepareForSandboxing() {
    640 #if SANITIZER_LINUX && !SANITIZER_ANDROID
    641     BlockingMutexLock l(&mu_);
    642     // Cache /proc/self/exe on Linux.
    643     CacheBinaryName();
    644 #endif
    645   }
    646 
    647  private:
    648   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
    649     mu_.CheckLocked();
    650     // First, try to use internal symbolizer.
    651     if (internal_symbolizer_) {
    652       SymbolizerScope sym_scope(this);
    653       return internal_symbolizer_->SendCommand(is_data, module_name,
    654                                                module_offset);
    655     }
    656     // Otherwise, fall back to external symbolizer.
    657     if (external_symbolizer_) {
    658       SymbolizerScope sym_scope(this);
    659       return external_symbolizer_->SendCommand(is_data, module_name,
    660                                                module_offset);
    661     }
    662     return 0;
    663   }
    664 
    665   LoadedModule *FindModuleForAddress(uptr address) {
    666     mu_.CheckLocked();
    667     bool modules_were_reloaded = false;
    668     if (modules_ == 0 || !modules_fresh_) {
    669       modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate(
    670           kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
    671       CHECK(modules_);
    672       n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
    673                                     /* filter */ 0);
    674       CHECK_GT(n_modules_, 0);
    675       CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
    676       modules_fresh_ = true;
    677       modules_were_reloaded = true;
    678     }
    679     for (uptr i = 0; i < n_modules_; i++) {
    680       if (modules_[i].containsAddress(address)) {
    681         return &modules_[i];
    682       }
    683     }
    684     // Reload the modules and look up again, if we haven't tried it yet.
    685     if (!modules_were_reloaded) {
    686       // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
    687       // It's too aggressive to reload the list of modules each time we fail
    688       // to find a module for a given address.
    689       modules_fresh_ = false;
    690       return FindModuleForAddress(address);
    691     }
    692     return 0;
    693   }
    694 
    695   bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
    696                                          uptr *module_offset) {
    697     mu_.CheckLocked();
    698     LoadedModule *module = FindModuleForAddress(address);
    699     if (module == 0)
    700       return false;
    701     *module_name = module->full_name();
    702     *module_offset = address - module->base_address();
    703     return true;
    704   }
    705 
    706   // 16K loaded modules should be enough for everyone.
    707   static const uptr kMaxNumberOfModuleContexts = 1 << 14;
    708   LoadedModule *modules_;  // Array of module descriptions is leaked.
    709   uptr n_modules_;
    710   // If stale, need to reload the modules before looking up addresses.
    711   bool modules_fresh_;
    712   BlockingMutex mu_;
    713 
    714   ExternalSymbolizerInterface *external_symbolizer_;  // Leaked.
    715   InternalSymbolizer *const internal_symbolizer_;     // Leaked.
    716   LibbacktraceSymbolizer *libbacktrace_symbolizer_;   // Leaked.
    717 };
    718 
    719 Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) {
    720   if (!common_flags()->symbolize) {
    721     return new(symbolizer_allocator_) POSIXSymbolizer(0, 0, 0);
    722   }
    723   InternalSymbolizer* internal_symbolizer =
    724       InternalSymbolizer::get(&symbolizer_allocator_);
    725   ExternalSymbolizerInterface *external_symbolizer = 0;
    726   LibbacktraceSymbolizer *libbacktrace_symbolizer = 0;
    727 
    728   if (!internal_symbolizer) {
    729     libbacktrace_symbolizer =
    730         LibbacktraceSymbolizer::get(&symbolizer_allocator_);
    731     if (!libbacktrace_symbolizer) {
    732       if (path_to_external && path_to_external[0] == '\0') {
    733         // External symbolizer is explicitly disabled. Do nothing.
    734       } else {
    735         // Find path to llvm-symbolizer if it's not provided.
    736         if (!path_to_external)
    737           path_to_external = FindPathToBinary("llvm-symbolizer");
    738         if (path_to_external) {
    739           external_symbolizer = new(symbolizer_allocator_)
    740               LLVMSymbolizerProcess(path_to_external);
    741         } else if (common_flags()->allow_addr2line) {
    742           // If llvm-symbolizer is not found, try to use addr2line.
    743           if (const char *addr2line_path = FindPathToBinary("addr2line")) {
    744             external_symbolizer = new(symbolizer_allocator_)
    745                 Addr2LinePool(addr2line_path, &symbolizer_allocator_);
    746           }
    747         }
    748       }
    749     }
    750   }
    751 
    752   return new(symbolizer_allocator_) POSIXSymbolizer(
    753       external_symbolizer, internal_symbolizer, libbacktrace_symbolizer);
    754 }
    755 
    756 }  // namespace __sanitizer
    757 
    758 #endif  // SANITIZER_POSIX
    759