<div dir="ltr">r<span style="color:rgb(0,0,0)">244645</span></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 11, 2015 at 10:13 AM, Hans Wennborg <span dir="ltr"><<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think this broke the build on Mac. From<br>
<a href="http://build.chromium.org/p/chromium.fyi/builders/ClangToTMac/builds/2626/steps/gclient%20runhooks/logs/stdio" rel="noreferrer" target="_blank">http://build.chromium.org/p/chromium.fyi/builders/ClangToTMac/builds/2626/steps/gclient%20runhooks/logs/stdio</a>:<br>
<br>
FAILED: /usr/bin/c++   -DHAVE_RPC_XDR_H=0 -DHAVE_TIRPC_RPC_XDR_H=0<br>
-DSANITIZER_NEEDS_SEGV=1 -Wall -std=c++11 -O3 -DNDEBUG -arch x86_64<br>
-arch i386 -isysroot<br>
/Applications/Xcode6.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk<br>
    -Wall -std=c++11 -mmacosx-version-min=10.9 -stdlib=libc++<br>
-isysroot /Applications/Xcode6.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk<br>
-fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer<br>
-funwind-tables -fno-stack-protector -fvisibility=hidden<br>
-fno-function-sections -fno-lto -O3 -gline-tables-only -Wno-gnu<br>
-Wno-variadic-macros -Wno-c99-extensions -Wno-non-virtual-dtor<br>
-fno-rtti -Wframe-larger-than=570 -Wglobal-constructors -MMD -MT<br>
lib/sanitizer_common/CMakeFiles/RTSanitizerCommon.osx.dir/sanitizer_symbolizer_posix_libcdep.cc.o<br>
-MF lib/sanitizer_common/CMakeFiles/RTSanitizerCommon.osx.dir/sanitizer_symbolizer_posix_libcdep.cc.o.d<br>
-o lib/sanitizer_common/CMakeFiles/RTSanitizerCommon.osx.dir/sanitizer_symbolizer_posix_libcdep.cc.o<br>
-c /b/build/slave/ClangToTMac/build/src/third_party/llvm/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc<br>
/b/build/slave/ClangToTMac/build/src/third_party/llvm/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc:116:11:<br>
error: use of undeclared identifier 'internal_close'; did you mean<br>
'internal_atoll'?<br>
          internal_close(sock_pair[j][0]);<br>
          ^~~~~~~~~~~~~~<br>
          internal_atoll<br>
<div class="HOEnZb"><div class="h5"><br>
On Tue, Aug 11, 2015 at 8:51 AM, Reid Kleckner via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Author: rnk<br>
> Date: Tue Aug 11 10:51:40 2015<br>
> New Revision: 244616<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=244616&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=244616&view=rev</a><br>
> Log:<br>
> [Windows] Use llvm-symbolizer before using dbghelp<br>
><br>
> Summary:<br>
> llvm-symbolizer understands both PDBs and DWARF, so it's a better bet if<br>
> it's available. It prints out the function parameter types and column<br>
> numbers, so I needed to churn the expected test output a bit.<br>
><br>
> This makes most of the llvm-symbolizer subprocessing code<br>
> target-independent. Pipes on all platforms use fd_t, and we can use the<br>
> portable ReadFromFile / WriteToFile wrappers in symbolizer_sanitizer.cc.<br>
> Only the pipe creation and process spawning is Windows-specific.<br>
><br>
> Please check that the libcdep layering is still correct. I don't know<br>
> how to reproduce the build configuration that relies on that.<br>
><br>
> Reviewers: samsonov<br>
><br>
> Subscribers: llvm-commits<br>
><br>
> Differential Revision: <a href="http://reviews.llvm.org/D11791" rel="noreferrer" target="_blank">http://reviews.llvm.org/D11791</a><br>
><br>
> Added:<br>
>     compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc<br>
> Removed:<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h<br>
> Modified:<br>
>     compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc<br>
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc<br>
>     compiler-rt/trunk/test/asan/CMakeLists.txt<br>
>     compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc<br>
>     compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Tue Aug 11 10:51:40 2015<br>
> @@ -49,7 +49,6 @@ set(SANITIZER_LIBCDEP_SOURCES<br>
>    sanitizer_stoptheworld_linux_libcdep.cc<br>
>    sanitizer_symbolizer_libcdep.cc<br>
>    sanitizer_symbolizer_posix_libcdep.cc<br>
> -  sanitizer_symbolizer_process_libcdep.cc<br>
>    sanitizer_unwind_linux_libcdep.cc)<br>
><br>
>  # Explicitly list all sanitizer_common headers. Not all of these are<br>
> @@ -103,7 +102,6 @@ set(SANITIZER_HEADERS<br>
>    sanitizer_symbolizer_internal.h<br>
>    sanitizer_symbolizer_libbacktrace.h<br>
>    sanitizer_symbolizer_mac.h<br>
> -  sanitizer_symbolizer_win.h<br>
>    sanitizer_syscall_generic.inc<br>
>    sanitizer_syscall_linux_x86_64.inc<br>
>    sanitizer_thread_registry.h)<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h Tue Aug 11 10:51:40 2015<br>
> @@ -74,21 +74,27 @@ class SymbolizerProcess {<br>
>    explicit SymbolizerProcess(const char *path, bool use_forkpty = false);<br>
>    const char *SendCommand(const char *command);<br>
><br>
> - private:<br>
> -  bool Restart();<br>
> -  const char *SendCommandImpl(const char *command);<br>
> -  bool ReadFromSymbolizer(char *buffer, uptr max_length);<br>
> -  bool WriteToSymbolizer(const char *buffer, uptr length);<br>
> -  bool StartSymbolizerSubprocess();<br>
> -<br>
> + protected:<br>
>    virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {<br>
>      UNIMPLEMENTED();<br>
>    }<br>
><br>
> -  virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {<br>
> +  /// The maximum number of arguments required to invoke a tool process.<br>
> +  enum { kArgVMax = 6 };<br>
> +<br>
> +  /// Fill in an argv array to invoke the child process.<br>
> +  virtual void GetArgV(const char *path_to_binary,<br>
> +                       const char *(&argv)[kArgVMax]) const {<br>
>      UNIMPLEMENTED();<br>
>    }<br>
><br>
> + private:<br>
> +  bool Restart();<br>
> +  const char *SendCommandImpl(const char *command);<br>
> +  bool ReadFromSymbolizer(char *buffer, uptr max_length);<br>
> +  bool WriteToSymbolizer(const char *buffer, uptr length);<br>
> +  bool StartSymbolizerSubprocess();<br>
> +<br>
>    const char *path_;<br>
>    fd_t input_fd_;<br>
>    fd_t output_fd_;<br>
> @@ -104,6 +110,41 @@ class SymbolizerProcess {<br>
>    bool use_forkpty_;<br>
>  };<br>
><br>
> +class LLVMSymbolizerProcess;<br>
> +<br>
> +// This tool invokes llvm-symbolizer in a subprocess. It should be as portable<br>
> +// as the llvm-symbolizer tool is.<br>
> +class LLVMSymbolizer : public SymbolizerTool {<br>
> + public:<br>
> +  explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator);<br>
> +<br>
> +  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;<br>
> +<br>
> +  bool SymbolizeData(uptr addr, DataInfo *info) override;<br>
> +<br>
> + private:<br>
> +  const char *SendCommand(bool is_data, const char *module_name,<br>
> +                          uptr module_offset);<br>
> +<br>
> +  LLVMSymbolizerProcess *symbolizer_process_;<br>
> +  static const uptr kBufferSize = 16 * 1024;<br>
> +  char buffer_[kBufferSize];<br>
> +};<br>
> +<br>
> +// Parses one or more two-line strings in the following format:<br>
> +//   <function_name><br>
> +//   <file_name>:<line_number>[:<column_number>]<br>
> +// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of<br>
> +// them use the same output format.  Returns true if any useful debug<br>
> +// information was found.<br>
> +void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);<br>
> +<br>
> +// Parses a two-line string in the following format:<br>
> +//   <symbol_name><br>
> +//   <start_address> <size><br>
> +// Used by LLVMSymbolizer and InternalSymbolizer.<br>
> +void ParseSymbolizeDataOutput(const char *str, DataInfo *info);<br>
> +<br>
>  }  // namespace __sanitizer<br>
><br>
>  #endif  // SANITIZER_SYMBOLIZER_INTERNAL_H<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc Tue Aug 11 10:51:40 2015<br>
> @@ -184,4 +184,245 @@ Symbolizer *Symbolizer::GetOrInit() {<br>
>    return symbolizer_;<br>
>  }<br>
><br>
> +// For now we assume the following protocol:<br>
> +// For each request of the form<br>
> +//   <module_name> <module_offset><br>
> +// passed to STDIN, external symbolizer prints to STDOUT response:<br>
> +//   <function_name><br>
> +//   <file_name>:<line_number>:<column_number><br>
> +//   <function_name><br>
> +//   <file_name>:<line_number>:<column_number><br>
> +//   ...<br>
> +//   <empty line><br>
> +class LLVMSymbolizerProcess : public SymbolizerProcess {<br>
> + public:<br>
> +  explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}<br>
> +<br>
> + private:<br>
> +  bool ReachedEndOfOutput(const char *buffer, uptr length) const override {<br>
> +    // Empty line marks the end of llvm-symbolizer output.<br>
> +    return length >= 2 && buffer[length - 1] == '\n' &&<br>
> +           buffer[length - 2] == '\n';<br>
> +  }<br>
> +<br>
> +  void GetArgV(const char *path_to_binary,<br>
> +               const char *(&argv)[kArgVMax]) const override {<br>
> +#if defined(__x86_64h__)<br>
> +    const char* const kSymbolizerArch = "--default-arch=x86_64h";<br>
> +#elif defined(__x86_64__)<br>
> +    const char* const kSymbolizerArch = "--default-arch=x86_64";<br>
> +#elif defined(__i386__)<br>
> +    const char* const kSymbolizerArch = "--default-arch=i386";<br>
> +#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__)<br>
> +    const char* const kSymbolizerArch = "--default-arch=powerpc64";<br>
> +#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)<br>
> +    const char* const kSymbolizerArch = "--default-arch=powerpc64le";<br>
> +#else<br>
> +    const char* const kSymbolizerArch = "--default-arch=unknown";<br>
> +#endif<br>
> +<br>
> +    const char *const inline_flag = common_flags()->symbolize_inline_frames<br>
> +                                        ? "--inlining=true"<br>
> +                                        : "--inlining=false";<br>
> +    int i = 0;<br>
> +    argv[i++] = path_to_binary;<br>
> +    argv[i++] = inline_flag;<br>
> +    argv[i++] = kSymbolizerArch;<br>
> +    argv[i++] = nullptr;<br>
> +  }<br>
> +};<br>
> +<br>
> +LLVMSymbolizer::LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)<br>
> +    : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}<br>
> +<br>
> +// Parse a <file>:<line>[:<column>] buffer. The file path may contain colons on<br>
> +// Windows, so extract tokens from the right hand side first. The column info is<br>
> +// also optional.<br>
> +static const char *ParseFileLineInfo(AddressInfo *info, const char *str) {<br>
> +  char *file_line_info = 0;<br>
> +  str = ExtractToken(str, "\n", &file_line_info);<br>
> +  CHECK(file_line_info);<br>
> +  // Parse the last :<int>, which must be there.<br>
> +  char *last_colon = internal_strrchr(file_line_info, ':');<br>
> +  CHECK(last_colon);<br>
> +  int line_or_column = internal_atoll(last_colon + 1);<br>
> +  // Truncate the string at the last colon and find the next-to-last colon.<br>
> +  *last_colon = '\0';<br>
> +  last_colon = internal_strrchr(file_line_info, ':');<br>
> +  if (last_colon && IsDigit(last_colon[1])) {<br>
> +    // If the second-to-last colon is followed by a digit, it must be the line<br>
> +    // number, and the previous parsed number was a column.<br>
> +    info->line = internal_atoll(last_colon + 1);<br>
> +    info->column = line_or_column;<br>
> +    *last_colon = '\0';<br>
> +  } else {<br>
> +    // Otherwise, we have line info but no column info.<br>
> +    info->line = line_or_column;<br>
> +    info->column = 0;<br>
> +  }<br>
> +  ExtractToken(file_line_info, "", &info->file);<br>
> +  InternalFree(file_line_info);<br>
> +  return str;<br>
> +}<br>
> +<br>
> +// Parses one or more two-line strings in the following format:<br>
> +//   <function_name><br>
> +//   <file_name>:<line_number>[:<column_number>]<br>
> +// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of<br>
> +// them use the same output format.<br>
> +void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {<br>
> +  bool top_frame = true;<br>
> +  SymbolizedStack *last = res;<br>
> +  while (true) {<br>
> +    char *function_name = 0;<br>
> +    str = ExtractToken(str, "\n", &function_name);<br>
> +    CHECK(function_name);<br>
> +    if (function_name[0] == '\0') {<br>
> +      // There are no more frames.<br>
> +      InternalFree(function_name);<br>
> +      break;<br>
> +    }<br>
> +    SymbolizedStack *cur;<br>
> +    if (top_frame) {<br>
> +      cur = res;<br>
> +      top_frame = false;<br>
> +    } else {<br>
> +      cur = SymbolizedStack::New(res->info.address);<br>
> +      cur->info.FillModuleInfo(res->info.module, res->info.module_offset);<br>
> +      last->next = cur;<br>
> +      last = cur;<br>
> +    }<br>
> +<br>
> +    AddressInfo *info = &cur->info;<br>
> +    info->function = function_name;<br>
> +    str = ParseFileLineInfo(info, str);<br>
> +<br>
> +    // Functions and filenames can be "??", in which case we write 0<br>
> +    // to address info to mark that names are unknown.<br>
> +    if (0 == internal_strcmp(info->function, "??")) {<br>
> +      InternalFree(info->function);<br>
> +      info->function = 0;<br>
> +    }<br>
> +    if (0 == internal_strcmp(info->file, "??")) {<br>
> +      InternalFree(info->file);<br>
> +      info->file = 0;<br>
> +    }<br>
> +  }<br>
> +}<br>
> +<br>
> +// Parses a two-line string in the following format:<br>
> +//   <symbol_name><br>
> +//   <start_address> <size><br>
> +// Used by LLVMSymbolizer and InternalSymbolizer.<br>
> +void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {<br>
> +  str = ExtractToken(str, "\n", &info->name);<br>
> +  str = ExtractUptr(str, " ", &info->start);<br>
> +  str = ExtractUptr(str, "\n", &info->size);<br>
> +}<br>
> +<br>
> +bool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {<br>
> +  if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,<br>
> +                                    stack->info.module_offset)) {<br>
> +    ParseSymbolizePCOutput(buf, stack);<br>
> +    return true;<br>
> +  }<br>
> +  return false;<br>
> +}<br>
> +<br>
> +bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {<br>
> +  if (const char *buf =<br>
> +          SendCommand(/*is_data*/ true, info->module, info->module_offset)) {<br>
> +    ParseSymbolizeDataOutput(buf, info);<br>
> +    info->start += (addr - info->module_offset); // Add the base address.<br>
> +    return true;<br>
> +  }<br>
> +  return false;<br>
> +}<br>
> +<br>
> +const char *LLVMSymbolizer::SendCommand(bool is_data, const char *module_name,<br>
> +                                        uptr module_offset) {<br>
> +  CHECK(module_name);<br>
> +  internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",<br>
> +                    is_data ? "DATA " : "", module_name, module_offset);<br>
> +  return symbolizer_process_->SendCommand(buffer_);<br>
> +}<br>
> +<br>
> +SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)<br>
> +    : path_(path),<br>
> +      input_fd_(kInvalidFd),<br>
> +      output_fd_(kInvalidFd),<br>
> +      times_restarted_(0),<br>
> +      failed_to_start_(false),<br>
> +      reported_invalid_path_(false),<br>
> +      use_forkpty_(use_forkpty) {<br>
> +  CHECK(path_);<br>
> +  CHECK_NE(path_[0], '\0');<br>
> +}<br>
> +<br>
> +const char *SymbolizerProcess::SendCommand(const char *command) {<br>
> +  for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {<br>
> +    // Start or restart symbolizer if we failed to send command to it.<br>
> +    if (const char *res = SendCommandImpl(command))<br>
> +      return res;<br>
> +    Restart();<br>
> +  }<br>
> +  if (!failed_to_start_) {<br>
> +    Report("WARNING: Failed to use and restart external symbolizer!\n");<br>
> +    failed_to_start_ = true;<br>
> +  }<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +const char *SymbolizerProcess::SendCommandImpl(const char *command) {<br>
> +  if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)<br>
> +      return 0;<br>
> +  if (!WriteToSymbolizer(command, internal_strlen(command)))<br>
> +      return 0;<br>
> +  if (!ReadFromSymbolizer(buffer_, kBufferSize))<br>
> +      return 0;<br>
> +  return buffer_;<br>
> +}<br>
> +<br>
> +bool SymbolizerProcess::Restart() {<br>
> +  if (input_fd_ != kInvalidFd)<br>
> +    CloseFile(input_fd_);<br>
> +  if (output_fd_ != kInvalidFd)<br>
> +    CloseFile(output_fd_);<br>
> +  return StartSymbolizerSubprocess();<br>
> +}<br>
> +<br>
> +bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {<br>
> +  if (max_length == 0)<br>
> +    return true;<br>
> +  uptr read_len = 0;<br>
> +  while (true) {<br>
> +    uptr just_read = 0;<br>
> +    bool success = ReadFromFile(input_fd_, buffer + read_len,<br>
> +                                max_length - read_len - 1, &just_read);<br>
> +    // We can't read 0 bytes, as we don't expect external symbolizer to close<br>
> +    // its stdout.<br>
> +    if (!success || just_read == 0) {<br>
> +      Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);<br>
> +      return false;<br>
> +    }<br>
> +    read_len += just_read;<br>
> +    if (ReachedEndOfOutput(buffer, read_len))<br>
> +      break;<br>
> +  }<br>
> +  buffer[read_len] = '\0';<br>
> +  return true;<br>
> +}<br>
> +<br>
> +bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {<br>
> +  if (length == 0)<br>
> +    return true;<br>
> +  uptr write_len = 0;<br>
> +  bool success = WriteToFile(output_fd_, buffer, length, &write_len);<br>
> +  if (!success || write_len != length) {<br>
> +    Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);<br>
> +    return false;<br>
> +  }<br>
> +  return true;<br>
> +}<br>
> +<br>
>  }  // namespace __sanitizer<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_mac.cc Tue Aug 11 10:51:40 2015<br>
> @@ -44,28 +44,33 @@ bool DlAddrSymbolizer::SymbolizeData(upt<br>
>  class AtosSymbolizerProcess : public SymbolizerProcess {<br>
>   public:<br>
>    explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)<br>
> -      : SymbolizerProcess(path, /*use_forkpty*/ true),<br>
> -        parent_pid_(parent_pid) {}<br>
> +      : SymbolizerProcess(path, /*use_forkpty*/ true) {<br>
> +    // Put the string command line argument in the object so that it outlives<br>
> +    // the call to GetArgV.<br>
> +    internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid_);<br>
> +  }<br>
><br>
>   private:<br>
>    bool ReachedEndOfOutput(const char *buffer, uptr length) const override {<br>
>      return (length >= 1 && buffer[length - 1] == '\n');<br>
>    }<br>
><br>
> -  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {<br>
> -    char pid_str[16];<br>
> -    internal_snprintf(pid_str, sizeof(pid_str), "%d", parent_pid_);<br>
> +  void GetArgV(const char *path_to_binary,<br>
> +               const char *(&argv)[kArgVMax]) const override {<br>
> +    int i = 0;<br>
> +    argv[i++] = path_to_binary;<br>
> +    argv[i++] = "-p";<br>
> +    argv[i++] = &pid_str_[0];<br>
>      if (GetMacosVersion() == MACOS_VERSION_MAVERICKS) {<br>
>        // On Mavericks atos prints a deprecation warning which we suppress by<br>
>        // passing -d. The warning isn't present on other OSX versions, even the<br>
>        // newer ones.<br>
> -      execl(path_to_binary, path_to_binary, "-p", pid_str, "-d", (char *)0);<br>
> -    } else {<br>
> -      execl(path_to_binary, path_to_binary, "-p", pid_str, (char *)0);<br>
> +      argv[i++] = "-d";<br>
>      }<br>
> +    argv[i++] = nullptr;<br>
>    }<br>
><br>
> -  pid_t parent_pid_;<br>
> +  char pid_str_[16];<br>
>  };<br>
><br>
>  static const char *kAtosErrorMessages[] = {<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Tue Aug 11 10:51:40 2015<br>
> @@ -25,8 +25,15 @@<br>
>  #include "sanitizer_symbolizer_libbacktrace.h"<br>
>  #include "sanitizer_symbolizer_mac.h"<br>
><br>
> +#include <errno.h><br>
> +#include <stdlib.h><br>
> +#include <sys/wait.h><br>
>  #include <unistd.h><br>
><br>
> +#if SANITIZER_MAC<br>
> +#include <util.h>  // for forkpty()<br>
> +#endif  // SANITIZER_MAC<br>
> +<br>
>  // C++ demangling function, as required by Itanium C++ ABI. This is weak,<br>
>  // because we do not require a C++ ABI library to be linked to a program<br>
>  // using sanitizers; if it's not present, we'll just use the mangled name.<br>
> @@ -53,149 +60,130 @@ const char *DemangleCXXABI(const char *n<br>
>    return name;<br>
>  }<br>
><br>
> -// Parses one or more two-line strings in the following format:<br>
> -//   <function_name><br>
> -//   <file_name>:<line_number>[:<column_number>]<br>
> -// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of<br>
> -// them use the same output format.<br>
> -static void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {<br>
> -  bool top_frame = true;<br>
> -  SymbolizedStack *last = res;<br>
> -  while (true) {<br>
> -    char *function_name = 0;<br>
> -    str = ExtractToken(str, "\n", &function_name);<br>
> -    CHECK(function_name);<br>
> -    if (function_name[0] == '\0') {<br>
> -      // There are no more frames.<br>
> -      InternalFree(function_name);<br>
> -      break;<br>
> -    }<br>
> -    SymbolizedStack *cur;<br>
> -    if (top_frame) {<br>
> -      cur = res;<br>
> -      top_frame = false;<br>
> -    } else {<br>
> -      cur = SymbolizedStack::New(res->info.address);<br>
> -      cur->info.FillModuleInfo(res->info.module, res->info.module_offset);<br>
> -      last->next = cur;<br>
> -      last = cur;<br>
> -    }<br>
> -<br>
> -    AddressInfo *info = &cur->info;<br>
> -    info->function = function_name;<br>
> -    // Parse <file>:<line>:<column> buffer.<br>
> -    char *file_line_info = 0;<br>
> -    str = ExtractToken(str, "\n", &file_line_info);<br>
> -    CHECK(file_line_info);<br>
> -    const char *line_info = ExtractToken(file_line_info, ":", &info->file);<br>
> -    line_info = ExtractInt(line_info, ":", &info->line);<br>
> -    line_info = ExtractInt(line_info, "", &info->column);<br>
> -    InternalFree(file_line_info);<br>
> -<br>
> -    // Functions and filenames can be "??", in which case we write 0<br>
> -    // to address info to mark that names are unknown.<br>
> -    if (0 == internal_strcmp(info->function, "??")) {<br>
> -      InternalFree(info->function);<br>
> -      info->function = 0;<br>
> -    }<br>
> -    if (0 == internal_strcmp(info->file, "??")) {<br>
> -      InternalFree(info->file);<br>
> -      info->file = 0;<br>
> -    }<br>
> -  }<br>
> -}<br>
> -<br>
> -// Parses a two-line string in the following format:<br>
> -//   <symbol_name><br>
> -//   <start_address> <size><br>
> -// Used by LLVMSymbolizer and InternalSymbolizer.<br>
> -static void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {<br>
> -  str = ExtractToken(str, "\n", &info->name);<br>
> -  str = ExtractUptr(str, " ", &info->start);<br>
> -  str = ExtractUptr(str, "\n", &info->size);<br>
> -}<br>
> -<br>
> -// For now we assume the following protocol:<br>
> -// For each request of the form<br>
> -//   <module_name> <module_offset><br>
> -// passed to STDIN, external symbolizer prints to STDOUT response:<br>
> -//   <function_name><br>
> -//   <file_name>:<line_number>:<column_number><br>
> -//   <function_name><br>
> -//   <file_name>:<line_number>:<column_number><br>
> -//   ...<br>
> -//   <empty line><br>
> -class LLVMSymbolizerProcess : public SymbolizerProcess {<br>
> - public:<br>
> -  explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}<br>
> -<br>
> - private:<br>
> -  bool ReachedEndOfOutput(const char *buffer, uptr length) const override {<br>
> -    // Empty line marks the end of llvm-symbolizer output.<br>
> -    return length >= 2 && buffer[length - 1] == '\n' &&<br>
> -           buffer[length - 2] == '\n';<br>
> -  }<br>
> -<br>
> -  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {<br>
> -#if defined(__x86_64h__)<br>
> -    const char* const kSymbolizerArch = "--default-arch=x86_64h";<br>
> -#elif defined(__x86_64__)<br>
> -    const char* const kSymbolizerArch = "--default-arch=x86_64";<br>
> -#elif defined(__i386__)<br>
> -    const char* const kSymbolizerArch = "--default-arch=i386";<br>
> -#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__)<br>
> -    const char* const kSymbolizerArch = "--default-arch=powerpc64";<br>
> -#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)<br>
> -    const char* const kSymbolizerArch = "--default-arch=powerpc64le";<br>
> -#else<br>
> -    const char* const kSymbolizerArch = "--default-arch=unknown";<br>
> -#endif<br>
> -<br>
> -    const char *const inline_flag = common_flags()->symbolize_inline_frames<br>
> -                                        ? "--inlining=true"<br>
> -                                        : "--inlining=false";<br>
> -    execl(path_to_binary, path_to_binary, inline_flag, kSymbolizerArch,<br>
> -          (char *)0);<br>
> -  }<br>
> -};<br>
> -<br>
> -class LLVMSymbolizer : public SymbolizerTool {<br>
> - public:<br>
> -  explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)<br>
> -      : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}<br>
> -<br>
> -  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {<br>
> -    if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,<br>
> -                                      stack->info.module_offset)) {<br>
> -      ParseSymbolizePCOutput(buf, stack);<br>
> -      return true;<br>
> +bool SymbolizerProcess::StartSymbolizerSubprocess() {<br>
> +  if (!FileExists(path_)) {<br>
> +    if (!reported_invalid_path_) {<br>
> +      Report("WARNING: invalid path to external symbolizer!\n");<br>
> +      reported_invalid_path_ = true;<br>
>      }<br>
>      return false;<br>
>    }<br>
><br>
> -  bool SymbolizeData(uptr addr, DataInfo *info) override {<br>
> -    if (const char *buf =<br>
> -            SendCommand(/*is_data*/ true, info->module, info->module_offset)) {<br>
> -      ParseSymbolizeDataOutput(buf, info);<br>
> -      info->start += (addr - info->module_offset);  // Add the base address.<br>
> -      return true;<br>
> -    }<br>
> +  int pid;<br>
> +  if (use_forkpty_) {<br>
> +#if SANITIZER_MAC<br>
> +    fd_t fd = kInvalidFd;<br>
> +    // Use forkpty to disable buffering in the new terminal.<br>
> +    pid = forkpty(&fd, 0, 0, 0);<br>
> +    if (pid == -1) {<br>
> +      // forkpty() failed.<br>
> +      Report("WARNING: failed to fork external symbolizer (errno: %d)\n",<br>
> +             errno);<br>
> +      return false;<br>
> +    } else if (pid == 0) {<br>
> +      // Child subprocess.<br>
> +      const char *argv[kArgVMax];<br>
> +      GetArgV(path_, argv);<br>
> +      execv(path_, const_cast<char **>(&argv[0]));<br>
> +      internal__exit(1);<br>
> +    }<br>
> +<br>
> +    // Continue execution in parent process.<br>
> +    input_fd_ = output_fd_ = fd;<br>
> +<br>
> +    // Disable echo in the new terminal, disable CR.<br>
> +    struct termios termflags;<br>
> +    tcgetattr(fd, &termflags);<br>
> +    termflags.c_oflag &= ~ONLCR;<br>
> +    termflags.c_lflag &= ~ECHO;<br>
> +    tcsetattr(fd, TCSANOW, &termflags);<br>
> +#else  // SANITIZER_MAC<br>
> +    UNIMPLEMENTED();<br>
> +#endif  // SANITIZER_MAC<br>
> +  } else {<br>
> +    int *infd = NULL;<br>
> +    int *outfd = NULL;<br>
> +    // The client program may close its stdin and/or stdout and/or stderr<br>
> +    // thus allowing socketpair to reuse file descriptors 0, 1 or 2.<br>
> +    // In this case the communication between the forked processes may be<br>
> +    // broken if either the parent or the child tries to close or duplicate<br>
> +    // these descriptors. The loop below produces two pairs of file<br>
> +    // descriptors, each greater than 2 (stderr).<br>
> +    int sock_pair[5][2];<br>
> +    for (int i = 0; i < 5; i++) {<br>
> +      if (pipe(sock_pair[i]) == -1) {<br>
> +        for (int j = 0; j < i; j++) {<br>
> +          internal_close(sock_pair[j][0]);<br>
> +          internal_close(sock_pair[j][1]);<br>
> +        }<br>
> +        Report("WARNING: Can't create a socket pair to start "<br>
> +               "external symbolizer (errno: %d)\n", errno);<br>
> +        return false;<br>
> +      } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {<br>
> +        if (infd == NULL) {<br>
> +          infd = sock_pair[i];<br>
> +        } else {<br>
> +          outfd = sock_pair[i];<br>
> +          for (int j = 0; j < i; j++) {<br>
> +            if (sock_pair[j] == infd) continue;<br>
> +            internal_close(sock_pair[j][0]);<br>
> +            internal_close(sock_pair[j][1]);<br>
> +          }<br>
> +          break;<br>
> +        }<br>
> +      }<br>
> +    }<br>
> +    CHECK(infd);<br>
> +    CHECK(outfd);<br>
> +<br>
> +    // Real fork() may call user callbacks registered with pthread_atfork().<br>
> +    pid = internal_fork();<br>
> +    if (pid == -1) {<br>
> +      // Fork() failed.<br>
> +      internal_close(infd[0]);<br>
> +      internal_close(infd[1]);<br>
> +      internal_close(outfd[0]);<br>
> +      internal_close(outfd[1]);<br>
> +      Report("WARNING: failed to fork external symbolizer "<br>
> +             " (errno: %d)\n", errno);<br>
> +      return false;<br>
> +    } else if (pid == 0) {<br>
> +      // Child subprocess.<br>
> +      internal_close(STDOUT_FILENO);<br>
> +      internal_close(STDIN_FILENO);<br>
> +      internal_dup2(outfd[0], STDIN_FILENO);<br>
> +      internal_dup2(infd[1], STDOUT_FILENO);<br>
> +      internal_close(outfd[0]);<br>
> +      internal_close(outfd[1]);<br>
> +      internal_close(infd[0]);<br>
> +      internal_close(infd[1]);<br>
> +      for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)<br>
> +        internal_close(fd);<br>
> +      const char *argv[kArgVMax];<br>
> +      GetArgV(path_, argv);<br>
> +      execv(path_, const_cast<char **>(&argv[0]));<br>
> +      internal__exit(1);<br>
> +    }<br>
> +<br>
> +    // Continue execution in parent process.<br>
> +    internal_close(outfd[0]);<br>
> +    internal_close(infd[1]);<br>
> +    input_fd_ = infd[0];<br>
> +    output_fd_ = outfd[1];<br>
> +  }<br>
> +<br>
> +  // Check that symbolizer subprocess started successfully.<br>
> +  int pid_status;<br>
> +  SleepForMillis(kSymbolizerStartupTimeMillis);<br>
> +  int exited_pid = waitpid(pid, &pid_status, WNOHANG);<br>
> +  if (exited_pid != 0) {<br>
> +    // Either waitpid failed, or child has already exited.<br>
> +    Report("WARNING: external symbolizer didn't start up correctly!\n");<br>
>      return false;<br>
>    }<br>
><br>
> - private:<br>
> -  const char *SendCommand(bool is_data, const char *module_name,<br>
> -                          uptr module_offset) {<br>
> -    CHECK(module_name);<br>
> -    internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",<br>
> -                      is_data ? "DATA " : "", module_name, module_offset);<br>
> -    return symbolizer_process_->SendCommand(buffer_);<br>
> -  }<br>
> -<br>
> -  LLVMSymbolizerProcess *symbolizer_process_;<br>
> -  static const uptr kBufferSize = 16 * 1024;<br>
> -  char buffer_[kBufferSize];<br>
> -};<br>
> +  return true;<br>
> +}<br>
><br>
>  class Addr2LineProcess : public SymbolizerProcess {<br>
>   public:<br>
> @@ -217,8 +205,13 @@ class Addr2LineProcess : public Symboliz<br>
>      return false;<br>
>    }<br>
><br>
> -  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {<br>
> -    execl(path_to_binary, path_to_binary, "-Cfe", module_name_, (char *)0);<br>
> +  void GetArgV(const char *path_to_binary,<br>
> +               const char *(&argv)[kArgVMax]) const override {<br>
> +    int i = 0;<br>
> +    argv[i++] = path_to_binary;<br>
> +    argv[i++] = "-Cfe";<br>
> +    argv[i++] = module_name_;<br>
> +    argv[i++] = nullptr;<br>
>    }<br>
><br>
>    const char *module_name_;  // Owned, leaked.<br>
><br>
> Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc?rev=244615&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc?rev=244615&view=auto</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc (removed)<br>
> @@ -1,231 +0,0 @@<br>
> -//===-- sanitizer_symbolizer_process_libcdep.cc ---------------------------===//<br>
> -//<br>
> -//                     The LLVM Compiler Infrastructure<br>
> -//<br>
> -// This file is distributed under the University of Illinois Open Source<br>
> -// License. See LICENSE.TXT for details.<br>
> -//<br>
> -//===----------------------------------------------------------------------===//<br>
> -//<br>
> -// Implementation of SymbolizerProcess used by external symbolizers.<br>
> -//<br>
> -//===----------------------------------------------------------------------===//<br>
> -<br>
> -#include "sanitizer_platform.h"<br>
> -#if SANITIZER_POSIX<br>
> -#include "sanitizer_posix.h"<br>
> -#include "sanitizer_symbolizer_internal.h"<br>
> -<br>
> -#include <errno.h><br>
> -#include <stdlib.h><br>
> -#include <sys/wait.h><br>
> -#include <unistd.h><br>
> -<br>
> -#if SANITIZER_MAC<br>
> -#include <util.h>  // for forkpty()<br>
> -#endif  // SANITIZER_MAC<br>
> -<br>
> -namespace __sanitizer {<br>
> -<br>
> -SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)<br>
> -    : path_(path),<br>
> -      input_fd_(kInvalidFd),<br>
> -      output_fd_(kInvalidFd),<br>
> -      times_restarted_(0),<br>
> -      failed_to_start_(false),<br>
> -      reported_invalid_path_(false),<br>
> -      use_forkpty_(use_forkpty) {<br>
> -  CHECK(path_);<br>
> -  CHECK_NE(path_[0], '\0');<br>
> -}<br>
> -<br>
> -const char *SymbolizerProcess::SendCommand(const char *command) {<br>
> -  for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {<br>
> -    // Start or restart symbolizer if we failed to send command to it.<br>
> -    if (const char *res = SendCommandImpl(command))<br>
> -      return res;<br>
> -    Restart();<br>
> -  }<br>
> -  if (!failed_to_start_) {<br>
> -    Report("WARNING: Failed to use and restart external symbolizer!\n");<br>
> -    failed_to_start_ = true;<br>
> -  }<br>
> -  return 0;<br>
> -}<br>
> -<br>
> -bool SymbolizerProcess::Restart() {<br>
> -  if (input_fd_ != kInvalidFd)<br>
> -    CloseFile(input_fd_);<br>
> -  if (output_fd_ != kInvalidFd)<br>
> -    CloseFile(output_fd_);<br>
> -  return StartSymbolizerSubprocess();<br>
> -}<br>
> -<br>
> -const char *SymbolizerProcess::SendCommandImpl(const char *command) {<br>
> -  if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)<br>
> -      return 0;<br>
> -  if (!WriteToSymbolizer(command, internal_strlen(command)))<br>
> -      return 0;<br>
> -  if (!ReadFromSymbolizer(buffer_, kBufferSize))<br>
> -      return 0;<br>
> -  return buffer_;<br>
> -}<br>
> -<br>
> -bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {<br>
> -  if (max_length == 0)<br>
> -    return true;<br>
> -  uptr read_len = 0;<br>
> -  while (true) {<br>
> -    uptr just_read = 0;<br>
> -    bool success = ReadFromFile(input_fd_, buffer + read_len,<br>
> -                                max_length - read_len - 1, &just_read);<br>
> -    // We can't read 0 bytes, as we don't expect external symbolizer to close<br>
> -    // its stdout.<br>
> -    if (!success || just_read == 0) {<br>
> -      Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);<br>
> -      return false;<br>
> -    }<br>
> -    read_len += just_read;<br>
> -    if (ReachedEndOfOutput(buffer, read_len))<br>
> -      break;<br>
> -  }<br>
> -  buffer[read_len] = '\0';<br>
> -  return true;<br>
> -}<br>
> -<br>
> -bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {<br>
> -  if (length == 0)<br>
> -    return true;<br>
> -  uptr write_len = 0;<br>
> -  bool success = WriteToFile(output_fd_, buffer, length, &write_len);<br>
> -  if (!success || write_len != length) {<br>
> -    Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);<br>
> -    return false;<br>
> -  }<br>
> -  return true;<br>
> -}<br>
> -<br>
> -bool SymbolizerProcess::StartSymbolizerSubprocess() {<br>
> -  if (!FileExists(path_)) {<br>
> -    if (!reported_invalid_path_) {<br>
> -      Report("WARNING: invalid path to external symbolizer!\n");<br>
> -      reported_invalid_path_ = true;<br>
> -    }<br>
> -    return false;<br>
> -  }<br>
> -<br>
> -  int pid;<br>
> -  if (use_forkpty_) {<br>
> -#if SANITIZER_MAC<br>
> -    fd_t fd = kInvalidFd;<br>
> -    // Use forkpty to disable buffering in the new terminal.<br>
> -    pid = forkpty(&fd, 0, 0, 0);<br>
> -    if (pid == -1) {<br>
> -      // forkpty() failed.<br>
> -      Report("WARNING: failed to fork external symbolizer (errno: %d)\n",<br>
> -             errno);<br>
> -      return false;<br>
> -    } else if (pid == 0) {<br>
> -      // Child subprocess.<br>
> -      ExecuteWithDefaultArgs(path_);<br>
> -      internal__exit(1);<br>
> -    }<br>
> -<br>
> -    // Continue execution in parent process.<br>
> -    input_fd_ = output_fd_ = fd;<br>
> -<br>
> -    // Disable echo in the new terminal, disable CR.<br>
> -    struct termios termflags;<br>
> -    tcgetattr(fd, &termflags);<br>
> -    termflags.c_oflag &= ~ONLCR;<br>
> -    termflags.c_lflag &= ~ECHO;<br>
> -    tcsetattr(fd, TCSANOW, &termflags);<br>
> -#else  // SANITIZER_MAC<br>
> -    UNIMPLEMENTED();<br>
> -#endif  // SANITIZER_MAC<br>
> -  } else {<br>
> -    int *infd = NULL;<br>
> -    int *outfd = NULL;<br>
> -    // The client program may close its stdin and/or stdout and/or stderr<br>
> -    // thus allowing socketpair to reuse file descriptors 0, 1 or 2.<br>
> -    // In this case the communication between the forked processes may be<br>
> -    // broken if either the parent or the child tries to close or duplicate<br>
> -    // these descriptors. The loop below produces two pairs of file<br>
> -    // descriptors, each greater than 2 (stderr).<br>
> -    int sock_pair[5][2];<br>
> -    for (int i = 0; i < 5; i++) {<br>
> -      if (pipe(sock_pair[i]) == -1) {<br>
> -        for (int j = 0; j < i; j++) {<br>
> -          internal_close(sock_pair[j][0]);<br>
> -          internal_close(sock_pair[j][1]);<br>
> -        }<br>
> -        Report("WARNING: Can't create a socket pair to start "<br>
> -               "external symbolizer (errno: %d)\n", errno);<br>
> -        return false;<br>
> -      } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {<br>
> -        if (infd == NULL) {<br>
> -          infd = sock_pair[i];<br>
> -        } else {<br>
> -          outfd = sock_pair[i];<br>
> -          for (int j = 0; j < i; j++) {<br>
> -            if (sock_pair[j] == infd) continue;<br>
> -            internal_close(sock_pair[j][0]);<br>
> -            internal_close(sock_pair[j][1]);<br>
> -          }<br>
> -          break;<br>
> -        }<br>
> -      }<br>
> -    }<br>
> -    CHECK(infd);<br>
> -    CHECK(outfd);<br>
> -<br>
> -    // Real fork() may call user callbacks registered with pthread_atfork().<br>
> -    pid = internal_fork();<br>
> -    if (pid == -1) {<br>
> -      // Fork() failed.<br>
> -      internal_close(infd[0]);<br>
> -      internal_close(infd[1]);<br>
> -      internal_close(outfd[0]);<br>
> -      internal_close(outfd[1]);<br>
> -      Report("WARNING: failed to fork external symbolizer "<br>
> -             " (errno: %d)\n", errno);<br>
> -      return false;<br>
> -    } else if (pid == 0) {<br>
> -      // Child subprocess.<br>
> -      internal_close(STDOUT_FILENO);<br>
> -      internal_close(STDIN_FILENO);<br>
> -      internal_dup2(outfd[0], STDIN_FILENO);<br>
> -      internal_dup2(infd[1], STDOUT_FILENO);<br>
> -      internal_close(outfd[0]);<br>
> -      internal_close(outfd[1]);<br>
> -      internal_close(infd[0]);<br>
> -      internal_close(infd[1]);<br>
> -      for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)<br>
> -        internal_close(fd);<br>
> -      ExecuteWithDefaultArgs(path_);<br>
> -      internal__exit(1);<br>
> -    }<br>
> -<br>
> -    // Continue execution in parent process.<br>
> -    internal_close(outfd[0]);<br>
> -    internal_close(infd[1]);<br>
> -    input_fd_ = infd[0];<br>
> -    output_fd_ = outfd[1];<br>
> -  }<br>
> -<br>
> -  // Check that symbolizer subprocess started successfully.<br>
> -  int pid_status;<br>
> -  SleepForMillis(kSymbolizerStartupTimeMillis);<br>
> -  int exited_pid = waitpid(pid, &pid_status, WNOHANG);<br>
> -  if (exited_pid != 0) {<br>
> -    // Either waitpid failed, or child has already exited.<br>
> -    Report("WARNING: external symbolizer didn't start up correctly!\n");<br>
> -    return false;<br>
> -  }<br>
> -<br>
> -  return true;<br>
> -}<br>
> -<br>
> -}  // namespace __sanitizer<br>
> -<br>
> -#endif  // SANITIZER_POSIX<br>
><br>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc Tue Aug 11 10:51:40 2015<br>
> @@ -18,13 +18,21 @@<br>
>  #include <dbghelp.h><br>
>  #pragma comment(lib, "dbghelp.lib")<br>
><br>
> -#include "sanitizer_symbolizer_win.h"<br>
>  #include "sanitizer_symbolizer_internal.h"<br>
><br>
>  namespace __sanitizer {<br>
><br>
>  namespace {<br>
><br>
> +class WinSymbolizerTool : public SymbolizerTool {<br>
> + public:<br>
> +  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;<br>
> +  bool SymbolizeData(uptr addr, DataInfo *info) override {<br>
> +    return false;<br>
> +  }<br>
> +  const char *Demangle(const char *name) override;<br>
> +};<br>
> +<br>
>  bool is_dbghelp_initialized = false;<br>
><br>
>  bool TrySymInitialize() {<br>
> @@ -115,7 +123,9 @@ bool WinSymbolizerTool::SymbolizePC(uptr<br>
>      frame->info.file = internal_strdup(line_info.FileName);<br>
>      frame->info.line = line_info.LineNumber;<br>
>    }<br>
> -  return true;<br>
> +  // Only consider this a successful symbolization attempt if we got file info.<br>
> +  // Otherwise, try llvm-symbolizer.<br>
> +  return got_fileline;<br>
>  }<br>
><br>
>  const char *WinSymbolizerTool::Demangle(const char *name) {<br>
> @@ -137,10 +147,128 @@ void Symbolizer::PlatformPrepareForSandb<br>
>    // Do nothing.<br>
>  }<br>
><br>
> +namespace {<br>
> +struct ScopedHandle {<br>
> +  ScopedHandle() : h_(nullptr) {}<br>
> +  explicit ScopedHandle(HANDLE h) : h_(h) {}<br>
> +  ~ScopedHandle() {<br>
> +    if (h_)<br>
> +      ::CloseHandle(h_);<br>
> +  }<br>
> +  HANDLE get() { return h_; }<br>
> +  HANDLE *receive() { return &h_; }<br>
> +  HANDLE release() {<br>
> +    HANDLE h = h_;<br>
> +    h_ = nullptr;<br>
> +    return h;<br>
> +  }<br>
> +  HANDLE h_;<br>
> +};<br>
> +} // namespace<br>
> +<br>
> +bool SymbolizerProcess::StartSymbolizerSubprocess() {<br>
> +  // Create inherited pipes for stdin and stdout.<br>
> +  ScopedHandle stdin_read, stdin_write;<br>
> +  ScopedHandle stdout_read, stdout_write;<br>
> +  SECURITY_ATTRIBUTES attrs;<br>
> +  attrs.nLength = sizeof(SECURITY_ATTRIBUTES);<br>
> +  attrs.bInheritHandle = TRUE;<br>
> +  attrs.lpSecurityDescriptor = nullptr;<br>
> +  if (!::CreatePipe(stdin_read.receive(), stdin_write.receive(), &attrs, 0) ||<br>
> +      !::CreatePipe(stdout_read.receive(), stdout_write.receive(), &attrs, 0))<br>
> +    return false;<br>
> +<br>
> +  // Don't inherit the writing end of stdin or the reading end of stdout.<br>
> +  if (!SetHandleInformation(stdin_write.get(), HANDLE_FLAG_INHERIT, 0) ||<br>
> +      !SetHandleInformation(stdout_read.get(), HANDLE_FLAG_INHERIT, 0))<br>
> +    return false;<br>
> +<br>
> +  // Compute the command line. Wrap double quotes around everything.<br>
> +  const char *argv[kArgVMax];<br>
> +  GetArgV(path_, argv);<br>
> +  InternalScopedString command_line(kMaxPathLength * 3);<br>
> +  for (int i = 0; argv[i]; i++) {<br>
> +    const char *arg = argv[i];<br>
> +    int arglen = internal_strlen(arg);<br>
> +    // Check that tool command lines are simple and that complete escaping is<br>
> +    // unnecessary.<br>
> +    CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");<br>
> +    CHECK(!internal_strstr(arg, "\\\\") &&<br>
> +          "double backslashes in args unsupported");<br>
> +    CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&<br>
> +          "args ending in backslash and empty args unsupported");<br>
> +    command_line.append("\"%s\" ", arg);<br>
> +  }<br>
> +  VReport(3, "Launching symbolizer command: %s\n", command_line.data());<br>
> +<br>
> +  // Launch llvm-symbolizer with stdin and stdout redirected.<br>
> +  STARTUPINFOA si;<br>
> +  memset(&si, 0, sizeof(si));<br>
> +  si.cb = sizeof(si);<br>
> +  si.dwFlags |= STARTF_USESTDHANDLES;<br>
> +  si.hStdInput = stdin_read.get();<br>
> +  si.hStdOutput = stdout_write.get();<br>
> +  PROCESS_INFORMATION pi;<br>
> +  memset(&pi, 0, sizeof(pi));<br>
> +  if (!CreateProcessA(path_,               // Executable<br>
> +                      command_line.data(), // Command line<br>
> +                      nullptr,             // Process handle not inheritable<br>
> +                      nullptr,             // Thread handle not inheritable<br>
> +                      TRUE,                // Set handle inheritance to TRUE<br>
> +                      0,                   // Creation flags<br>
> +                      nullptr,             // Use parent's environment block<br>
> +                      nullptr,             // Use parent's starting directory<br>
> +                      &si, &pi)) {<br>
> +    VReport(2, "WARNING: %s failed to create process for %s (error code: %d)\n",<br>
> +            SanitizerToolName, path_, GetLastError());<br>
> +    return false;<br>
> +  }<br>
> +<br>
> +  // Process creation succeeded, so transfer handle ownership into the fields.<br>
> +  input_fd_ = stdout_read.release();<br>
> +  output_fd_ = stdin_write.release();<br>
> +<br>
> +  // The llvm-symbolizer process is responsible for quitting itself when the<br>
> +  // stdin pipe is closed, so we don't need these handles. Close them to prevent<br>
> +  // leaks. If we ever want to try to kill the symbolizer process from the<br>
> +  // parent, we'll want to hang on to these handles.<br>
> +  CloseHandle(pi.hProcess);<br>
> +  CloseHandle(pi.hThread);<br>
> +  return true;<br>
> +}<br>
> +<br>
> +static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,<br>
> +                                  LowLevelAllocator *allocator) {<br>
> +  if (!common_flags()->symbolize) {<br>
> +    VReport(2, "Symbolizer is disabled.\n");<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  // Add llvm-symbolizer in case the binary has dwarf.<br>
> +  const char *user_path = common_flags()->external_symbolizer_path;<br>
> +  const char *path =<br>
> +      user_path ? user_path : FindPathToBinary("llvm-symbolizer.exe");<br>
> +  if (path) {<br>
> +    VReport(2, "Using llvm-symbolizer at %spath: %s\n",<br>
> +            user_path ? "user-specified " : "", path);<br>
> +    list->push_back(new(*allocator) LLVMSymbolizer(path, allocator));<br>
> +  } else {<br>
> +    if (user_path && user_path[0] == '\0') {<br>
> +      VReport(2, "External symbolizer is explicitly disabled.\n");<br>
> +    } else {<br>
> +      VReport(2, "External symbolizer is not present.\n");<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Add the dbghelp based symbolizer.<br>
> +  list->push_back(new(*allocator) WinSymbolizerTool());<br>
> +}<br>
> +<br>
>  Symbolizer *Symbolizer::PlatformInit() {<br>
>    IntrusiveList<SymbolizerTool> list;<br>
>    list.clear();<br>
> -  list.push_back(new(symbolizer_allocator_) WinSymbolizerTool());<br>
> +  ChooseSymbolizerTools(&list, &symbolizer_allocator_);<br>
> +<br>
>    return new(symbolizer_allocator_) Symbolizer(list);<br>
>  }<br>
><br>
><br>
> Removed: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h?rev=244615&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h?rev=244615&view=auto</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h (original)<br>
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h (removed)<br>
> @@ -1,31 +0,0 @@<br>
> -//===-- sanitizer_symbolizer_win.h ------------------------------*- C++ -*-===//<br>
> -//<br>
> -//                     The LLVM Compiler Infrastructure<br>
> -//<br>
> -// This file is distributed under the University of Illinois Open Source<br>
> -// License. See LICENSE.TXT for details.<br>
> -//<br>
> -//===----------------------------------------------------------------------===//<br>
> -//<br>
> -// Header file for the Windows symbolizer tool.<br>
> -//<br>
> -//===----------------------------------------------------------------------===//<br>
> -#ifndef SANITIZER_SYMBOLIZER_WIN_H<br>
> -#define SANITIZER_SYMBOLIZER_WIN_H<br>
> -<br>
> -#include "sanitizer_symbolizer_internal.h"<br>
> -<br>
> -namespace __sanitizer {<br>
> -<br>
> -class WinSymbolizerTool : public SymbolizerTool {<br>
> - public:<br>
> -  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;<br>
> -  bool SymbolizeData(uptr addr, DataInfo *info) override {<br>
> -    return false;<br>
> -  }<br>
> -  const char *Demangle(const char *name) override;<br>
> -};<br>
> -<br>
> -}  // namespace __sanitizer<br>
> -<br>
> -#endif  // SANITIZER_SYMBOLIZER_WIN_H<br>
><br>
> Modified: compiler-rt/trunk/test/asan/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/CMakeLists.txt?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/CMakeLists.txt?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/test/asan/CMakeLists.txt (original)<br>
> +++ compiler-rt/trunk/test/asan/CMakeLists.txt Tue Aug 11 10:51:40 2015<br>
> @@ -13,6 +13,17 @@ macro(get_bits_for_arch arch bits)<br>
>    endif()<br>
>  endmacro()<br>
><br>
> +set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})<br>
> +if(NOT COMPILER_RT_STANDALONE_BUILD)<br>
> +  list(APPEND ASAN_TEST_DEPS asan)<br>
> +  if(WIN32 AND COMPILER_RT_HAS_LLD_SOURCES)<br>
> +    list(APPEND ASAN_TEST_DEPS<br>
> +      lld<br>
> +    )<br>
> +  endif()<br>
> +endif()<br>
> +set(ASAN_DYNAMIC_TEST_DEPS ${ASAN_TEST_DEPS})<br>
> +<br>
>  foreach(arch ${ASAN_SUPPORTED_ARCH})<br>
>    if(ANDROID)<br>
>      set(ASAN_TEST_TARGET_ARCH ${arch}-android)<br>
> @@ -55,12 +66,6 @@ foreach(arch ${ASAN_SUPPORTED_ARCH})<br>
>    endif()<br>
>  endforeach()<br>
><br>
> -set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})<br>
> -if(NOT COMPILER_RT_STANDALONE_BUILD)<br>
> -  list(APPEND ASAN_TEST_DEPS asan)<br>
> -endif()<br>
> -set(ASAN_DYNAMIC_TEST_DEPS ${ASAN_TEST_DEPS})<br>
> -<br>
>  # Add unit tests.<br>
>  if(COMPILER_RT_INCLUDE_TESTS)<br>
>    set(ASAN_TEST_DYNAMIC False)<br>
><br>
> Added: compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc?rev=244616&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc?rev=244616&view=auto</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc (added)<br>
> +++ compiler-rt/trunk/test/asan/TestCases/Windows/fuse-lld.cc Tue Aug 11 10:51:40 2015<br>
> @@ -0,0 +1,23 @@<br>
> +// If we have LLD, see that things more or less work.<br>
> +//<br>
> +// REQUIRES: lld<br>
> +//<br>
> +// FIXME: Use -fuse-ld=lld after the old COFF linker is removed.<br>
> +// FIXME: Test will fail until we add flags for requesting dwarf or cv.<br>
> +// RUNX: %clangxx_asan -O2 %s -o %t.exe -fuse-ld=lld -Wl,-debug<br>
> +// RUN: %clangxx_asan -c -O2 %s -o %t.o -gdwarf<br>
> +// RUN: lld-link2 %t.o -out:%t.exe -debug -defaultlib:libcmt %asan_lib %asan_cxx_lib<br>
> +// RUN: not %run %t.exe 2>&1 | FileCheck %s<br>
> +<br>
> +#include <stdlib.h><br>
> +<br>
> +int main() {<br>
> +  char *x = (char*)malloc(10 * sizeof(char));<br>
> +  free(x);<br>
> +  return x[5];<br>
> +  // CHECK: heap-use-after-free<br>
> +  // CHECK: free<br>
> +  // CHECK: main{{.*}}fuse-lld.cc:[[@LINE-4]]:3<br>
> +  // CHECK: malloc<br>
> +  // CHECK: main{{.*}}fuse-lld.cc:[[@LINE-7]]:20<br>
> +}<br>
><br>
> Modified: compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc (original)<br>
> +++ compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc Tue Aug 11 10:51:40 2015<br>
> @@ -10,6 +10,6 @@ static void NullDeref(int *ptr) {<br>
>  }<br>
>  int main() {<br>
>    NullDeref((int*)0);<br>
> -  // CHECK: {{    #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]]<br>
> +  // CHECK: {{    #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]]:3<br>
>    // CHECK: AddressSanitizer can not provide additional info.<br>
>  }<br>
><br>
> Modified: compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc?rev=244616&r1=244615&r2=244616&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc?rev=244616&r1=244615&r2=244616&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc (original)<br>
> +++ compiler-rt/trunk/test/asan/TestCases/Windows/report_after_syminitialize.cc Tue Aug 11 10:51:40 2015<br>
> @@ -1,4 +1,5 @@<br>
> -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s<br>
> +// RUN: %clangxx_asan -O0 %s -o %t<br>
> +// RUN: env ASAN_OPTIONS=external_symbolizer_path=asdf not %run %t 2>&1 | FileCheck %s<br>
><br>
>  #include <windows.h><br>
>  #include <dbghelp.h><br>
> @@ -13,7 +14,8 @@ int main() {<br>
><br>
>    *(volatile int*)0 = 42;<br>
>    // CHECK: ERROR: AddressSanitizer: access-violation on unknown address<br>
> +  // CHECK-NEXT: {{WARNING: Failed to use and restart external symbolizer}}<br>
>    // CHECK-NEXT: {{WARNING: .*DbgHelp}}<br>
> -  // CHECK: {{#0 0x.* in main.*report_after_syminitialize.cc:}}[[@LINE-3]]<br>
> +  // CHECK: {{#0 0x.* in main.*report_after_syminitialize.cc:}}[[@LINE-4]]<br>
>    // CHECK: AddressSanitizer can not provide additional info.<br>
>  }<br>
</div></div></blockquote></div><br></div>