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