sanitizer_symbolizer_posix_libcdep.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. //===-- sanitizer_symbolizer_posix_libcdep.cpp ----------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is shared between AddressSanitizer and ThreadSanitizer
  10. // run-time libraries.
  11. // POSIX-specific implementation of symbolizer parts.
  12. //===----------------------------------------------------------------------===//
  13. #include "sanitizer_platform.h"
  14. #if SANITIZER_POSIX
  15. #include "sanitizer_allocator_internal.h"
  16. #include "sanitizer_common.h"
  17. #include "sanitizer_file.h"
  18. #include "sanitizer_flags.h"
  19. #include "sanitizer_internal_defs.h"
  20. #include "sanitizer_linux.h"
  21. #include "sanitizer_placement_new.h"
  22. #include "sanitizer_posix.h"
  23. #include "sanitizer_procmaps.h"
  24. #include "sanitizer_symbolizer_internal.h"
  25. #include "sanitizer_symbolizer_libbacktrace.h"
  26. #include "sanitizer_symbolizer_mac.h"
  27. #include <dlfcn.h> // for dlsym()
  28. #include <errno.h>
  29. #include <stdint.h>
  30. #include <stdlib.h>
  31. #include <sys/wait.h>
  32. #include <unistd.h>
  33. // C++ demangling function, as required by Itanium C++ ABI. This is weak,
  34. // because we do not require a C++ ABI library to be linked to a program
  35. // using sanitizers; if it's not present, we'll just use the mangled name.
  36. namespace __cxxabiv1 {
  37. extern "C" SANITIZER_WEAK_ATTRIBUTE
  38. char *__cxa_demangle(const char *mangled, char *buffer,
  39. size_t *length, int *status);
  40. }
  41. namespace __sanitizer {
  42. // Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
  43. const char *DemangleCXXABI(const char *name) {
  44. // FIXME: __cxa_demangle aggressively insists on allocating memory.
  45. // There's not much we can do about that, short of providing our
  46. // own demangler (libc++abi's implementation could be adapted so that
  47. // it does not allocate). For now, we just call it anyway, and we leak
  48. // the returned value.
  49. if (&__cxxabiv1::__cxa_demangle)
  50. if (const char *demangled_name =
  51. __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
  52. return demangled_name;
  53. return name;
  54. }
  55. // As of now, there are no headers for the Swift runtime. Once they are
  56. // present, we will weakly link since we do not require Swift runtime to be
  57. // linked.
  58. typedef char *(*swift_demangle_ft)(const char *mangledName,
  59. size_t mangledNameLength, char *outputBuffer,
  60. size_t *outputBufferSize, uint32_t flags);
  61. static swift_demangle_ft swift_demangle_f;
  62. // This must not happen lazily at symbolication time, because dlsym uses
  63. // malloc and thread-local storage, which is not a good thing to do during
  64. // symbolication.
  65. static void InitializeSwiftDemangler() {
  66. swift_demangle_f = (swift_demangle_ft)dlsym(RTLD_DEFAULT, "swift_demangle");
  67. }
  68. // Attempts to demangle a Swift name. The demangler will return nullptr if a
  69. // non-Swift name is passed in.
  70. const char *DemangleSwift(const char *name) {
  71. if (swift_demangle_f)
  72. return swift_demangle_f(name, internal_strlen(name), 0, 0, 0);
  73. return nullptr;
  74. }
  75. const char *DemangleSwiftAndCXX(const char *name) {
  76. if (!name) return nullptr;
  77. if (const char *swift_demangled_name = DemangleSwift(name))
  78. return swift_demangled_name;
  79. return DemangleCXXABI(name);
  80. }
  81. static bool CreateTwoHighNumberedPipes(int *infd_, int *outfd_) {
  82. int *infd = NULL;
  83. int *outfd = NULL;
  84. // The client program may close its stdin and/or stdout and/or stderr
  85. // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
  86. // In this case the communication between the forked processes may be
  87. // broken if either the parent or the child tries to close or duplicate
  88. // these descriptors. The loop below produces two pairs of file
  89. // descriptors, each greater than 2 (stderr).
  90. int sock_pair[5][2];
  91. for (int i = 0; i < 5; i++) {
  92. if (pipe(sock_pair[i]) == -1) {
  93. for (int j = 0; j < i; j++) {
  94. internal_close(sock_pair[j][0]);
  95. internal_close(sock_pair[j][1]);
  96. }
  97. return false;
  98. } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
  99. if (infd == NULL) {
  100. infd = sock_pair[i];
  101. } else {
  102. outfd = sock_pair[i];
  103. for (int j = 0; j < i; j++) {
  104. if (sock_pair[j] == infd) continue;
  105. internal_close(sock_pair[j][0]);
  106. internal_close(sock_pair[j][1]);
  107. }
  108. break;
  109. }
  110. }
  111. }
  112. CHECK(infd);
  113. CHECK(outfd);
  114. infd_[0] = infd[0];
  115. infd_[1] = infd[1];
  116. outfd_[0] = outfd[0];
  117. outfd_[1] = outfd[1];
  118. return true;
  119. }
  120. bool SymbolizerProcess::StartSymbolizerSubprocess() {
  121. if (!FileExists(path_)) {
  122. if (!reported_invalid_path_) {
  123. Report("WARNING: invalid path to external symbolizer!\n");
  124. reported_invalid_path_ = true;
  125. }
  126. return false;
  127. }
  128. const char *argv[kArgVMax];
  129. GetArgV(path_, argv);
  130. pid_t pid;
  131. // Report how symbolizer is being launched for debugging purposes.
  132. if (Verbosity() >= 3) {
  133. // Only use `Report` for first line so subsequent prints don't get prefixed
  134. // with current PID.
  135. Report("Launching Symbolizer process: ");
  136. for (unsigned index = 0; index < kArgVMax && argv[index]; ++index)
  137. Printf("%s ", argv[index]);
  138. Printf("\n");
  139. }
  140. if (use_posix_spawn_) {
  141. #if SANITIZER_APPLE
  142. fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
  143. if (fd == kInvalidFd) {
  144. Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
  145. errno);
  146. return false;
  147. }
  148. input_fd_ = fd;
  149. output_fd_ = fd;
  150. #else // SANITIZER_APPLE
  151. UNIMPLEMENTED();
  152. #endif // SANITIZER_APPLE
  153. } else {
  154. fd_t infd[2] = {}, outfd[2] = {};
  155. if (!CreateTwoHighNumberedPipes(infd, outfd)) {
  156. Report("WARNING: Can't create a socket pair to start "
  157. "external symbolizer (errno: %d)\n", errno);
  158. return false;
  159. }
  160. pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
  161. /* stdout */ infd[1]);
  162. if (pid < 0) {
  163. internal_close(infd[0]);
  164. internal_close(outfd[1]);
  165. return false;
  166. }
  167. input_fd_ = infd[0];
  168. output_fd_ = outfd[1];
  169. }
  170. CHECK_GT(pid, 0);
  171. // Check that symbolizer subprocess started successfully.
  172. SleepForMillis(kSymbolizerStartupTimeMillis);
  173. if (!IsProcessRunning(pid)) {
  174. // Either waitpid failed, or child has already exited.
  175. Report("WARNING: external symbolizer didn't start up correctly!\n");
  176. return false;
  177. }
  178. return true;
  179. }
  180. class Addr2LineProcess final : public SymbolizerProcess {
  181. public:
  182. Addr2LineProcess(const char *path, const char *module_name)
  183. : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {}
  184. const char *module_name() const { return module_name_; }
  185. private:
  186. void GetArgV(const char *path_to_binary,
  187. const char *(&argv)[kArgVMax]) const override {
  188. int i = 0;
  189. argv[i++] = path_to_binary;
  190. if (common_flags()->demangle)
  191. argv[i++] = "-C";
  192. if (common_flags()->symbolize_inline_frames)
  193. argv[i++] = "-i";
  194. argv[i++] = "-fe";
  195. argv[i++] = module_name_;
  196. argv[i++] = nullptr;
  197. CHECK_LE(i, kArgVMax);
  198. }
  199. bool ReachedEndOfOutput(const char *buffer, uptr length) const override;
  200. bool ReadFromSymbolizer() override {
  201. if (!SymbolizerProcess::ReadFromSymbolizer())
  202. return false;
  203. auto &buff = GetBuff();
  204. // We should cut out output_terminator_ at the end of given buffer,
  205. // appended by addr2line to mark the end of its meaningful output.
  206. // We cannot scan buffer from it's beginning, because it is legal for it
  207. // to start with output_terminator_ in case given offset is invalid. So,
  208. // scanning from second character.
  209. char *garbage = internal_strstr(buff.data() + 1, output_terminator_);
  210. // This should never be NULL since buffer must end up with
  211. // output_terminator_.
  212. CHECK(garbage);
  213. // Trim the buffer.
  214. uintptr_t new_size = garbage - buff.data();
  215. GetBuff().resize(new_size);
  216. GetBuff().push_back('\0');
  217. return true;
  218. }
  219. const char *module_name_; // Owned, leaked.
  220. static const char output_terminator_[];
  221. };
  222. const char Addr2LineProcess::output_terminator_[] = "??\n??:0\n";
  223. bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
  224. uptr length) const {
  225. const size_t kTerminatorLen = sizeof(output_terminator_) - 1;
  226. // Skip, if we read just kTerminatorLen bytes, because Addr2Line output
  227. // should consist at least of two pairs of lines:
  228. // 1. First one, corresponding to given offset to be symbolized
  229. // (may be equal to output_terminator_, if offset is not valid).
  230. // 2. Second one for output_terminator_, itself to mark the end of output.
  231. if (length <= kTerminatorLen) return false;
  232. // Addr2Line output should end up with output_terminator_.
  233. return !internal_memcmp(buffer + length - kTerminatorLen,
  234. output_terminator_, kTerminatorLen);
  235. }
  236. class Addr2LinePool final : public SymbolizerTool {
  237. public:
  238. explicit Addr2LinePool(const char *addr2line_path,
  239. LowLevelAllocator *allocator)
  240. : addr2line_path_(addr2line_path), allocator_(allocator) {
  241. addr2line_pool_.reserve(16);
  242. }
  243. bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
  244. if (const char *buf =
  245. SendCommand(stack->info.module, stack->info.module_offset)) {
  246. ParseSymbolizePCOutput(buf, stack);
  247. return true;
  248. }
  249. return false;
  250. }
  251. bool SymbolizeData(uptr addr, DataInfo *info) override {
  252. return false;
  253. }
  254. private:
  255. const char *SendCommand(const char *module_name, uptr module_offset) {
  256. Addr2LineProcess *addr2line = 0;
  257. for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
  258. if (0 ==
  259. internal_strcmp(module_name, addr2line_pool_[i]->module_name())) {
  260. addr2line = addr2line_pool_[i];
  261. break;
  262. }
  263. }
  264. if (!addr2line) {
  265. addr2line =
  266. new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
  267. addr2line_pool_.push_back(addr2line);
  268. }
  269. CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
  270. char buffer[kBufferSize];
  271. internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
  272. module_offset, dummy_address_);
  273. return addr2line->SendCommand(buffer);
  274. }
  275. static const uptr kBufferSize = 64;
  276. const char *addr2line_path_;
  277. LowLevelAllocator *allocator_;
  278. InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
  279. static const uptr dummy_address_ =
  280. FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
  281. };
  282. # if SANITIZER_SUPPORTS_WEAK_HOOKS
  283. extern "C" {
  284. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
  285. __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
  286. char *Buffer, int MaxLength);
  287. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
  288. __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
  289. char *Buffer, int MaxLength);
  290. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
  291. __sanitizer_symbolize_flush();
  292. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int
  293. __sanitizer_symbolize_demangle(const char *Name, char *Buffer, int MaxLength);
  294. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
  295. __sanitizer_symbolize_set_demangle(bool Demangle);
  296. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
  297. __sanitizer_symbolize_set_inline_frames(bool InlineFrames);
  298. } // extern "C"
  299. class InternalSymbolizer final : public SymbolizerTool {
  300. public:
  301. static InternalSymbolizer *get(LowLevelAllocator *alloc) {
  302. if (__sanitizer_symbolize_set_demangle)
  303. CHECK(__sanitizer_symbolize_set_demangle(common_flags()->demangle));
  304. if (__sanitizer_symbolize_set_inline_frames)
  305. CHECK(__sanitizer_symbolize_set_inline_frames(
  306. common_flags()->symbolize_inline_frames));
  307. if (__sanitizer_symbolize_code && __sanitizer_symbolize_data)
  308. return new (*alloc) InternalSymbolizer();
  309. return 0;
  310. }
  311. bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
  312. bool result = __sanitizer_symbolize_code(
  313. stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
  314. if (result)
  315. ParseSymbolizePCOutput(buffer_, stack);
  316. return result;
  317. }
  318. bool SymbolizeData(uptr addr, DataInfo *info) override {
  319. bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
  320. buffer_, kBufferSize);
  321. if (result) {
  322. ParseSymbolizeDataOutput(buffer_, info);
  323. info->start += (addr - info->module_offset); // Add the base address.
  324. }
  325. return result;
  326. }
  327. void Flush() override {
  328. if (__sanitizer_symbolize_flush)
  329. __sanitizer_symbolize_flush();
  330. }
  331. const char *Demangle(const char *name) override {
  332. if (__sanitizer_symbolize_demangle) {
  333. for (uptr res_length = 1024;
  334. res_length <= InternalSizeClassMap::kMaxSize;) {
  335. char *res_buff = static_cast<char *>(InternalAlloc(res_length));
  336. uptr req_length =
  337. __sanitizer_symbolize_demangle(name, res_buff, res_length);
  338. if (req_length > res_length) {
  339. res_length = req_length + 1;
  340. InternalFree(res_buff);
  341. continue;
  342. }
  343. return res_buff;
  344. }
  345. }
  346. return name;
  347. }
  348. private:
  349. InternalSymbolizer() {}
  350. static const int kBufferSize = 16 * 1024;
  351. char buffer_[kBufferSize];
  352. };
  353. # else // SANITIZER_SUPPORTS_WEAK_HOOKS
  354. class InternalSymbolizer final : public SymbolizerTool {
  355. public:
  356. static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
  357. };
  358. # endif // SANITIZER_SUPPORTS_WEAK_HOOKS
  359. const char *Symbolizer::PlatformDemangle(const char *name) {
  360. return DemangleSwiftAndCXX(name);
  361. }
  362. static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
  363. const char *path = common_flags()->external_symbolizer_path;
  364. if (path && internal_strchr(path, '%')) {
  365. char *new_path = (char *)InternalAlloc(kMaxPathLength);
  366. SubstituteForFlagValue(path, new_path, kMaxPathLength);
  367. path = new_path;
  368. }
  369. const char *binary_name = path ? StripModuleName(path) : "";
  370. static const char kLLVMSymbolizerPrefix[] = "llvm-symbolizer";
  371. if (path && path[0] == '\0') {
  372. VReport(2, "External symbolizer is explicitly disabled.\n");
  373. return nullptr;
  374. } else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix,
  375. internal_strlen(kLLVMSymbolizerPrefix))) {
  376. VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
  377. return new(*allocator) LLVMSymbolizer(path, allocator);
  378. } else if (!internal_strcmp(binary_name, "atos")) {
  379. #if SANITIZER_APPLE
  380. VReport(2, "Using atos at user-specified path: %s\n", path);
  381. return new(*allocator) AtosSymbolizer(path, allocator);
  382. #else // SANITIZER_APPLE
  383. Report("ERROR: Using `atos` is only supported on Darwin.\n");
  384. Die();
  385. #endif // SANITIZER_APPLE
  386. } else if (!internal_strcmp(binary_name, "addr2line")) {
  387. VReport(2, "Using addr2line at user-specified path: %s\n", path);
  388. return new(*allocator) Addr2LinePool(path, allocator);
  389. } else if (path) {
  390. Report("ERROR: External symbolizer path is set to '%s' which isn't "
  391. "a known symbolizer. Please set the path to the llvm-symbolizer "
  392. "binary or other known tool.\n", path);
  393. Die();
  394. }
  395. // Otherwise symbolizer program is unknown, let's search $PATH
  396. CHECK(path == nullptr);
  397. #if SANITIZER_APPLE
  398. if (const char *found_path = FindPathToBinary("atos")) {
  399. VReport(2, "Using atos found at: %s\n", found_path);
  400. return new(*allocator) AtosSymbolizer(found_path, allocator);
  401. }
  402. #endif // SANITIZER_APPLE
  403. if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
  404. VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
  405. return new(*allocator) LLVMSymbolizer(found_path, allocator);
  406. }
  407. if (common_flags()->allow_addr2line) {
  408. if (const char *found_path = FindPathToBinary("addr2line")) {
  409. VReport(2, "Using addr2line found at: %s\n", found_path);
  410. return new(*allocator) Addr2LinePool(found_path, allocator);
  411. }
  412. }
  413. return nullptr;
  414. }
  415. static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
  416. LowLevelAllocator *allocator) {
  417. if (!common_flags()->symbolize) {
  418. VReport(2, "Symbolizer is disabled.\n");
  419. return;
  420. }
  421. if (IsAllocatorOutOfMemory()) {
  422. VReport(2, "Cannot use internal symbolizer: out of memory\n");
  423. } else if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
  424. VReport(2, "Using internal symbolizer.\n");
  425. list->push_back(tool);
  426. return;
  427. }
  428. if (SymbolizerTool *tool = LibbacktraceSymbolizer::get(allocator)) {
  429. VReport(2, "Using libbacktrace symbolizer.\n");
  430. list->push_back(tool);
  431. return;
  432. }
  433. if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) {
  434. list->push_back(tool);
  435. }
  436. #if SANITIZER_APPLE
  437. VReport(2, "Using dladdr symbolizer.\n");
  438. list->push_back(new(*allocator) DlAddrSymbolizer());
  439. #endif // SANITIZER_APPLE
  440. }
  441. Symbolizer *Symbolizer::PlatformInit() {
  442. IntrusiveList<SymbolizerTool> list;
  443. list.clear();
  444. ChooseSymbolizerTools(&list, &symbolizer_allocator_);
  445. return new(symbolizer_allocator_) Symbolizer(list);
  446. }
  447. void Symbolizer::LateInitialize() {
  448. Symbolizer::GetOrInit();
  449. InitializeSwiftDemangler();
  450. }
  451. } // namespace __sanitizer
  452. #endif // SANITIZER_POSIX