summaryrefslogtreecommitdiffstats
path: root/contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc')
-rw-r--r--contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc97
1 files changed, 66 insertions, 31 deletions
diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index fc8a7d9..7028da6 100644
--- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -26,7 +26,9 @@
#include "sanitizer_symbolizer_libbacktrace.h"
#include "sanitizer_symbolizer_mac.h"
+#include <dlfcn.h> // for dlsym()
#include <errno.h>
+#include <stdint.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -61,6 +63,44 @@ const char *DemangleCXXABI(const char *name) {
return name;
}
+// As of now, there are no headers for the Swift runtime. Once they are
+// present, we will weakly link since we do not require Swift runtime to be
+// linked.
+typedef char *(*swift_demangle_ft)(const char *mangledName,
+ size_t mangledNameLength, char *outputBuffer,
+ size_t *outputBufferSize, uint32_t flags);
+static swift_demangle_ft swift_demangle_f;
+
+// This must not happen lazily at symbolication time, because dlsym uses
+// malloc and thread-local storage, which is not a good thing to do during
+// symbolication.
+static void InitializeSwiftDemangler() {
+ swift_demangle_f = (swift_demangle_ft)dlsym(RTLD_DEFAULT, "swift_demangle");
+}
+
+// Attempts to demangle a Swift name. The demangler will return nullptr if a
+// non-Swift name is passed in.
+const char *DemangleSwift(const char *name) {
+ if (!name) return nullptr;
+
+ // Check if we are dealing with a Swift mangled name first.
+ if (name[0] != '_' || name[1] != 'T') {
+ return nullptr;
+ }
+
+ if (swift_demangle_f)
+ return swift_demangle_f(name, internal_strlen(name), 0, 0, 0);
+
+ return nullptr;
+}
+
+const char *DemangleSwiftAndCXX(const char *name) {
+ if (!name) return nullptr;
+ if (const char *swift_demangled_name = DemangleSwift(name))
+ return swift_demangled_name;
+ return DemangleCXXABI(name);
+}
+
bool SymbolizerProcess::StartSymbolizerSubprocess() {
if (!FileExists(path_)) {
if (!reported_invalid_path_) {
@@ -74,6 +114,13 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
if (use_forkpty_) {
#if SANITIZER_MAC
fd_t fd = kInvalidFd;
+
+ // forkpty redirects stdout and stderr into a single stream, so we would
+ // receive error messages as standard replies. To avoid that, let's dup
+ // stderr and restore it in the child.
+ int saved_stderr = dup(STDERR_FILENO);
+ CHECK_GE(saved_stderr, 0);
+
// Use forkpty to disable buffering in the new terminal.
pid = internal_forkpty(&fd);
if (pid == -1) {
@@ -83,6 +130,11 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
return false;
} else if (pid == 0) {
// Child subprocess.
+
+ // Restore stderr.
+ CHECK_GE(dup2(saved_stderr, STDERR_FILENO), 0);
+ close(saved_stderr);
+
const char *argv[kArgVMax];
GetArgV(path_, argv);
execv(path_, const_cast<char **>(&argv[0]));
@@ -92,6 +144,8 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
// Continue execution in parent process.
input_fd_ = output_fd_ = fd;
+ close(saved_stderr);
+
// Disable echo in the new terminal, disable CR.
struct termios termflags;
tcgetattr(fd, &termflags);
@@ -137,47 +191,23 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
CHECK(infd);
CHECK(outfd);
- // Real fork() may call user callbacks registered with pthread_atfork().
- pid = internal_fork();
- if (pid == -1) {
- // Fork() failed.
+ const char *argv[kArgVMax];
+ GetArgV(path_, argv);
+ pid = StartSubprocess(path_, argv, /* stdin */ outfd[0],
+ /* stdout */ infd[1]);
+ if (pid < 0) {
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) {
+ if (!IsProcessRunning(pid)) {
// Either waitpid failed, or child has already exited.
Report("WARNING: external symbolizer didn't start up correctly!\n");
return false;
@@ -374,7 +404,7 @@ class InternalSymbolizer : public SymbolizerTool {
#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
const char *Symbolizer::PlatformDemangle(const char *name) {
- return DemangleCXXABI(name);
+ return DemangleSwiftAndCXX(name);
}
void Symbolizer::PlatformPrepareForSandboxing() {}
@@ -461,6 +491,11 @@ Symbolizer *Symbolizer::PlatformInit() {
return new(symbolizer_allocator_) Symbolizer(list);
}
+void Symbolizer::LateInitialize() {
+ Symbolizer::GetOrInit();
+ InitializeSwiftDemangler();
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
OpenPOWER on IntegriCloud