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