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