diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp')
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp index f26efe5c50b5..29cbf62acd5c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp @@ -20,6 +20,7 @@ #include <dlfcn.h> #include <errno.h> +#include <mach/mach.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> @@ -50,18 +51,65 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) { return true; } +#define K_ATOS_ENV_VAR "__check_mach_ports_lookup" + +// This cannot live in `AtosSymbolizerProcess` because instances of that object +// are allocated by the internal allocator which under ASan is poisoned with +// kAsanInternalHeapMagic. +static char kAtosMachPortEnvEntry[] = K_ATOS_ENV_VAR "=000000000000000"; + class AtosSymbolizerProcess : public SymbolizerProcess { public: - explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid) + explicit AtosSymbolizerProcess(const char *path) : SymbolizerProcess(path, /*use_posix_spawn*/ 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); + pid_str_[0] = '\0'; + } + + void LateInitialize() { + if (SANITIZER_IOSSIM) { + // `putenv()` may call malloc/realloc so it is only safe to do this + // during LateInitialize() or later (i.e. we can't do this in the + // constructor). We also can't do this in `StartSymbolizerSubprocess()` + // because in TSan we switch allocators when we're symbolizing. + // We use `putenv()` rather than `setenv()` so that we can later directly + // write into the storage without LibC getting involved to change what the + // variable is set to + int result = putenv(kAtosMachPortEnvEntry); + CHECK_EQ(result, 0); + } } private: bool StartSymbolizerSubprocess() override { // Configure sandbox before starting atos process. + + // 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", internal_getpid()); + + if (SANITIZER_IOSSIM) { + // `atos` in the simulator is restricted in its ability to retrieve the + // task port for the target process (us) so we need to do extra work + // to pass our task port to it. + mach_port_t ports[]{mach_task_self()}; + kern_return_t ret = + mach_ports_register(mach_task_self(), ports, /*count=*/1); + CHECK_EQ(ret, KERN_SUCCESS); + + // Set environment variable that signals to `atos` that it should look + // for our task port. We can't call `setenv()` here because it might call + // malloc/realloc. To avoid that we instead update the + // `mach_port_env_var_entry_` variable with our current PID. + uptr count = internal_snprintf(kAtosMachPortEnvEntry, + sizeof(kAtosMachPortEnvEntry), + K_ATOS_ENV_VAR "=%s", pid_str_); + CHECK_GE(count, sizeof(K_ATOS_ENV_VAR) + internal_strlen(pid_str_)); + // Document our assumption but without calling `getenv()` in normal + // builds. + DCHECK(getenv(K_ATOS_ENV_VAR)); + DCHECK_EQ(internal_strcmp(getenv(K_ATOS_ENV_VAR), pid_str_), 0); + } + return SymbolizerProcess::StartSymbolizerSubprocess(); } @@ -75,7 +123,7 @@ class AtosSymbolizerProcess : public SymbolizerProcess { argv[i++] = path_to_binary; argv[i++] = "-p"; argv[i++] = &pid_str_[0]; - if (GetMacosVersion() == MACOS_VERSION_MAVERICKS) { + if (GetMacosAlignedVersion() == MacosVersion(10, 9)) { // 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. @@ -85,8 +133,14 @@ class AtosSymbolizerProcess : public SymbolizerProcess { } char pid_str_[16]; + // Space for `\0` in `K_ATOS_ENV_VAR` is reused for `=`. + static_assert(sizeof(kAtosMachPortEnvEntry) == + (sizeof(K_ATOS_ENV_VAR) + sizeof(pid_str_)), + "sizes should match"); }; +#undef K_ATOS_ENV_VAR + static bool ParseCommandOutput(const char *str, uptr addr, char **out_name, char **out_module, char **out_file, uptr *line, uptr *start_address) { @@ -138,7 +192,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name, } AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator) - : process_(new(*allocator) AtosSymbolizerProcess(path, getpid())) {} + : process_(new (*allocator) AtosSymbolizerProcess(path)) {} bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { if (!process_) return false; @@ -188,6 +242,8 @@ bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { return true; } +void AtosSymbolizer::LateInitialize() { process_->LateInitialize(); } + } // namespace __sanitizer #endif // SANITIZER_MAC |