sanitizer_symbolizer_posix_libcdep.cc 26 KB

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