summaryrefslogtreecommitdiff
path: root/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (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.cpp68
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