1ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===//
2ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//
3ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//                     The LLVM Compiler Infrastructure
4ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//
5ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// This file is distributed under the University of Illinois Open Source
6ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// License. See LICENSE.TXT for details.
7ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//
8ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===----------------------------------------------------------------------===//
9ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//
10ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// run-time libraries.
12ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// POSIX-specific implementation of symbolizer parts.
13ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===----------------------------------------------------------------------===//
14ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
15ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_platform.h"
16ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#if SANITIZER_POSIX
177847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_allocator_internal.h"
18ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_common.h"
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h"
20ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_internal_defs.h"
217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_linux.h"
227847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_placement_new.h"
237847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_procmaps.h"
247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_internal.h"
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_symbolizer_libbacktrace.h"
267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_mac.h"
27ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
28ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include <unistd.h>
29ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
307847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// C++ demangling function, as required by Itanium C++ ABI. This is weak,
317847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// because we do not require a C++ ABI library to be linked to a program
327847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// using sanitizers; if it's not present, we'll just use the mangled name.
337847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovnamespace __cxxabiv1 {
347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  extern "C" SANITIZER_WEAK_ATTRIBUTE
357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  char *__cxa_demangle(const char *mangled, char *buffer,
367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov                                  size_t *length, int *status);
377847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
387847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
39ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonovnamespace __sanitizer {
40ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
417847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *DemangleCXXABI(const char *name) {
437847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  // FIXME: __cxa_demangle aggressively insists on allocating memory.
447847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  // There's not much we can do about that, short of providing our
457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  // own demangler (libc++abi's implementation could be adapted so that
467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  // it does not allocate). For now, we just call it anyway, and we leak
477847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  // the returned value.
487847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  if (__cxxabiv1::__cxa_demangle)
497847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    if (const char *demangled_name =
507847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov          __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
517847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      return demangled_name;
527847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
537847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  return name;
547847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
557847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Parses one or more two-line strings in the following format:
5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   <function_name>
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   <file_name>:<line_number>[:<column_number>]
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// them use the same output format.
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool top_frame = true;
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizedStack *last = res;
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  while (true) {
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    char *function_name = 0;
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    str = ExtractToken(str, "\n", &function_name);
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(function_name);
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (function_name[0] == '\0') {
6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // There are no more frames.
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      break;
7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    SymbolizedStack *cur;
7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (top_frame) {
7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      cur = res;
7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      top_frame = false;
7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    } else {
7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      cur = SymbolizedStack::New(res->info.address);
787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      cur->info.FillModuleInfo(res->info.module, res->info.module_offset);
7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      last->next = cur;
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      last = cur;
8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AddressInfo *info = &cur->info;
8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    info->function = function_name;
8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Parse <file>:<line>:<column> buffer.
8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    char *file_line_info = 0;
8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    str = ExtractToken(str, "\n", &file_line_info);
8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(file_line_info);
8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    const char *line_info = ExtractToken(file_line_info, ":", &info->file);
9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    line_info = ExtractInt(line_info, ":", &info->line);
9186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    line_info = ExtractInt(line_info, "", &info->column);
9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    InternalFree(file_line_info);
9386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Functions and filenames can be "??", in which case we write 0
9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // to address info to mark that names are unknown.
9686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (0 == internal_strcmp(info->function, "??")) {
9786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      InternalFree(info->function);
9886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      info->function = 0;
9986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
10086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (0 == internal_strcmp(info->file, "??")) {
10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      InternalFree(info->file);
10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      info->file = 0;
10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
1067847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Parses a two-line string in the following format:
10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   <symbol_name>
10986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   <start_address> <size>
11086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Used by LLVMSymbolizer and InternalSymbolizer.
11186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  str = ExtractToken(str, "\n", &info->name);
11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  str = ExtractUptr(str, " ", &info->start);
11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  str = ExtractUptr(str, "\n", &info->size);
11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// For now we assume the following protocol:
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// For each request of the form
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <module_name> <module_offset>
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// passed to STDIN, external symbolizer prints to STDOUT response:
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <function_name>
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <file_name>:<line_number>:<column_number>
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <function_name>
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <file_name>:<line_number>:<column_number>
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   ...
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//   <empty line>
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesclass LLVMSymbolizerProcess : public SymbolizerProcess {
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines public:
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines private:
132909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // Empty line marks the end of llvm-symbolizer output.
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return length >= 2 && buffer[length - 1] == '\n' &&
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines           buffer[length - 2] == '\n';
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
138909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__)
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    const char* const kSymbolizerArch = "--default-arch=x86_64";
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif defined(__i386__)
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    const char* const kSymbolizerArch = "--default-arch=i386";
1436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__)
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    const char* const kSymbolizerArch = "--default-arch=powerpc64";
1456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)
1466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    const char* const kSymbolizerArch = "--default-arch=powerpc64le";
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    const char* const kSymbolizerArch = "--default-arch=unknown";
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
1506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
1516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    const char *const inline_flag = common_flags()->symbolize_inline_frames
1526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                                        ? "--inlining=true"
1536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                                        : "--inlining=false";
1546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    execl(path_to_binary, path_to_binary, inline_flag, kSymbolizerArch,
1556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines          (char *)0);
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass LLVMSymbolizer : public SymbolizerTool {
1607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar public:
1617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
1627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
1637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
1657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,
1667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                                      stack->info.module_offset)) {
1677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      ParseSymbolizePCOutput(buf, stack);
1687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      return true;
1697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    }
1707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return false;
1717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
1727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizeData(uptr addr, DataInfo *info) override {
1747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (const char *buf =
1757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar            SendCommand(/*is_data*/ true, info->module, info->module_offset)) {
1767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      ParseSymbolizeDataOutput(buf, info);
1777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      info->start += (addr - info->module_offset);  // Add the base address.
1787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      return true;
1797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    }
1807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return false;
1817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
1827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar private:
1847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *SendCommand(bool is_data, const char *module_name,
1857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                          uptr module_offset) {
1867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    CHECK(module_name);
1877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
1887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                      is_data ? "DATA " : "", module_name, module_offset);
1897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return symbolizer_process_->SendCommand(buffer_);
1907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
1917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  LLVMSymbolizerProcess *symbolizer_process_;
1937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static const uptr kBufferSize = 16 * 1024;
1947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  char buffer_[kBufferSize];
1957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar};
1967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesclass Addr2LineProcess : public SymbolizerProcess {
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines public:
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  Addr2LineProcess(const char *path, const char *module_name)
2002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {}
2012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const char *module_name() const { return module_name_; }
2032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines private:
205909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
2062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // Output should consist of two lines.
2072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    int num_lines = 0;
2082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    for (uptr i = 0; i < length; ++i) {
2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if (buffer[i] == '\n')
2102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        num_lines++;
2112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if (num_lines >= 2)
2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        return true;
2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return false;
2152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
2162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
217909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    execl(path_to_binary, path_to_binary, "-Cfe", module_name_, (char *)0);
2192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
2202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const char *module_name_;  // Owned, leaked.
2222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
2232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass Addr2LinePool : public SymbolizerTool {
2252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines public:
2262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  explicit Addr2LinePool(const char *addr2line_path,
2272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         LowLevelAllocator *allocator)
2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      : addr2line_path_(addr2line_path), allocator_(allocator),
2292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        addr2line_pool_(16) {}
2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
2327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (const char *buf =
2337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar            SendCommand(stack->info.module, stack->info.module_offset)) {
2347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      ParseSymbolizePCOutput(buf, stack);
2357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      return true;
2367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    }
2377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return false;
2387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
2397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
2407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizeData(uptr addr, DataInfo *info) override {
2417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return false;
2427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
2437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
2447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar private:
2457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *SendCommand(const char *module_name, uptr module_offset) {
2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Addr2LineProcess *addr2line = 0;
2472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      if (0 ==
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          internal_strcmp(module_name, addr2line_pool_[i]->module_name())) {
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        addr2line = addr2line_pool_[i];
2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        break;
2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      }
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (!addr2line) {
2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      addr2line =
2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      addr2line_pool_.push_back(addr2line);
2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
2597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
2607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    char buffer_[kBufferSize];
2617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
2627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return addr2line->SendCommand(buffer_);
2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  static const uptr kBufferSize = 32;
2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const char *addr2line_path_;
2672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  LowLevelAllocator *allocator_;
2682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
2697847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov};
2707847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
2717847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#if SANITIZER_SUPPORTS_WEAK_HOOKS
2727847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovextern "C" {
2737847d77b246635211c3bf465421d49d7af5226c1Alexey SamsonovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
2747847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovbool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
2757847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov                                char *Buffer, int MaxLength);
2767847d77b246635211c3bf465421d49d7af5226c1Alexey SamsonovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
2777847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovbool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
2787847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov                                char *Buffer, int MaxLength);
2797847d77b246635211c3bf465421d49d7af5226c1Alexey SamsonovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
2807847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovvoid __sanitizer_symbolize_flush();
2817847d77b246635211c3bf465421d49d7af5226c1Alexey SamsonovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
2827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovint __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
2837847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov                                   int MaxLength);
2847847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}  // extern "C"
2857847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
2867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass InternalSymbolizer : public SymbolizerTool {
2877847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov public:
288c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne  static InternalSymbolizer *get(LowLevelAllocator *alloc) {
2897847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    if (__sanitizer_symbolize_code != 0 &&
2907847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        __sanitizer_symbolize_data != 0) {
291c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne      return new(*alloc) InternalSymbolizer();
2927847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    }
2937847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    return 0;
2947847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
2957847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
2967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
2977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    bool result = __sanitizer_symbolize_code(
2987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar        stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
2997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (result) ParseSymbolizePCOutput(buffer_, stack);
3007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return result;
3017c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
3027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
3037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  bool SymbolizeData(uptr addr, DataInfo *info) override {
3047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
3057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                                             buffer_, kBufferSize);
3067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (result) {
3077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      ParseSymbolizeDataOutput(buffer_, info);
3087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      info->start += (addr - info->module_offset);  // Add the base address.
3097c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    }
3107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return result;
3117847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
3127847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  void Flush() override {
3147847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    if (__sanitizer_symbolize_flush)
3157847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      __sanitizer_symbolize_flush();
3167847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
3177847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *Demangle(const char *name) override {
3197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    if (__sanitizer_symbolize_demangle) {
3207847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      for (uptr res_length = 1024;
3217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov           res_length <= InternalSizeClassMap::kMaxSize;) {
3227847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        char *res_buff = static_cast<char*>(InternalAlloc(res_length));
3237847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        uptr req_length =
3247847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov            __sanitizer_symbolize_demangle(name, res_buff, res_length);
3257847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        if (req_length > res_length) {
3267847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov          res_length = req_length + 1;
3277847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov          InternalFree(res_buff);
3287847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov          continue;
3297847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        }
3307847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        return res_buff;
3317847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      }
3327847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    }
3337847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    return name;
3347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
3357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov private:
3377847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  InternalSymbolizer() { }
3387847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3397847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  static const int kBufferSize = 16 * 1024;
3407847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  static const int kMaxDemangledNameSize = 1024;
3417847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  char buffer_[kBufferSize];
3427847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov};
3437847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#else  // SANITIZER_SUPPORTS_WEAK_HOOKS
3447847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarclass InternalSymbolizer : public SymbolizerTool {
3467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov public:
347c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne  static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
3487847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov};
3497847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3507847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
3517847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
352909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarconst char *Symbolizer::PlatformDemangle(const char *name) {
353909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  return DemangleCXXABI(name);
354909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
3557847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
356909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarvoid Symbolizer::PlatformPrepareForSandboxing() {
3577847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#if SANITIZER_LINUX && !SANITIZER_ANDROID
358909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // Cache /proc/self/exe on Linux.
359909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  CacheBinaryName();
3607847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#endif
361909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
3627847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
3637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
3647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *path = common_flags()->external_symbolizer_path;
3657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  const char *binary_name = path ? StripModuleName(path) : "";
3667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (path && path[0] == '\0') {
3677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "External symbolizer is explicitly disabled.\n");
3687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return nullptr;
3697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  } else if (!internal_strcmp(binary_name, "llvm-symbolizer")) {
3707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
3717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return new(*allocator) LLVMSymbolizer(path, allocator);
3727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  } else if (!internal_strcmp(binary_name, "atos")) {
3737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if SANITIZER_MAC
3747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using atos at user-specified path: %s\n", path);
3757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return new(*allocator) AtosSymbolizer(path, allocator);
3767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else  // SANITIZER_MAC
3777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    Report("ERROR: Using `atos` is only supported on Darwin.\n");
3787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    Die();
3797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif  // SANITIZER_MAC
3807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  } else if (!internal_strcmp(binary_name, "addr2line")) {
3817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using addr2line at user-specified path: %s\n", path);
3827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return new(*allocator) Addr2LinePool(path, allocator);
3837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  } else if (path) {
3847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    Report("ERROR: External symbolizer path is set to '%s' which isn't "
3857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar           "a known symbolizer. Please set the path to the llvm-symbolizer "
3867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar           "binary or other known tool.\n", path);
3877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    Die();
3887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
3897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
3907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // Otherwise symbolizer program is unknown, let's search $PATH
3917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  CHECK(path == nullptr);
3927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
3937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
3947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return new(*allocator) LLVMSymbolizer(found_path, allocator);
3957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
3967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if SANITIZER_MAC
3977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (const char *found_path = FindPathToBinary("atos")) {
3987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using atos found at: %s\n", found_path);
3997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return new(*allocator) AtosSymbolizer(found_path, allocator);
4007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
4017c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif  // SANITIZER_MAC
4027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (common_flags()->allow_addr2line) {
4037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (const char *found_path = FindPathToBinary("addr2line")) {
4047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      VReport(2, "Using addr2line found at: %s\n", found_path);
4057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      return new(*allocator) Addr2LinePool(found_path, allocator);
4067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    }
4077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
4087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  return nullptr;
4097c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
4107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
4117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
4127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar                                  LowLevelAllocator *allocator) {
4132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!common_flags()->symbolize) {
4147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Symbolizer is disabled.\n");
4157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return;
4162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
4177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
4187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using internal symbolizer.\n");
4197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    list->push_back(tool);
4207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return;
4217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
4227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (SymbolizerTool *tool = LibbacktraceSymbolizer::get(allocator)) {
4237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "Using libbacktrace symbolizer.\n");
4247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    list->push_back(tool);
4257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return;
426e059bd35a33040c9ecbd291a190449f7a0a6f17fAlexey Samsonov  }
427c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne
4287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) {
4297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    list->push_back(tool);
4307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  } else {
4317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    VReport(2, "No internal or external symbolizer found.\n");
4327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  }
4337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
4347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if SANITIZER_MAC
4357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  VReport(2, "Using dladdr symbolizer.\n");
4367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  list->push_back(new(*allocator) DlAddrSymbolizer());
4377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif  // SANITIZER_MAC
4387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
4397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
4407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga NainarSymbolizer *Symbolizer::PlatformInit() {
4417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  IntrusiveList<SymbolizerTool> list;
4427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  list.clear();
4437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ChooseSymbolizerTools(&list, &symbolizer_allocator_);
444909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  return new(symbolizer_allocator_) Symbolizer(list);
4457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
446ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
447ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov}  // namespace __sanitizer
448ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov
449ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#endif  // SANITIZER_POSIX
450