diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp index 7ef499ce07b1..8fd682f943fe 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp @@ -21,6 +21,10 @@ #include "sanitizer_file.h" # include "sanitizer_interface_internal.h" +#if SANITIZER_LINUX +#include "sanitizer_posix.h" +#endif + namespace __sanitizer { void CatastrophicErrorWrite(const char *buffer, uptr length) { @@ -206,11 +210,35 @@ char *FindPathToBinary(const char *name) { return internal_strdup(name); } + uptr name_len = internal_strlen(name); + InternalMmapVector buffer(kMaxPathLength); + +#if SANITIZER_LINUX + // If we cannot find the requested binary in PATH, we should try to locate + // it next to the binary, in case it is shipped with the build itself + // (e.g. llvm-symbolizer shipped with sanitizer build to symbolize on client. + if (internal_readlink("/proc/self/exe", buffer.data(), kMaxPathLength) >= 0) { + uptr buf_len = internal_strlen(buffer.data()); + + /* Avoid using dirname() here */ + while (buf_len > 0) { + if (buffer[buf_len - 1] == '/') + break; + buf_len--; + } + + if (buf_len && buf_len + name_len + 1 <= kMaxPathLength) { + internal_memcpy(&buffer[buf_len], name, name_len); + buffer[buf_len + name_len] = '\0'; + if (FileExists(buffer.data())) + return internal_strdup(buffer.data()); + } + } +#endif + const char *path = GetEnv("PATH"); if (!path) return nullptr; - uptr name_len = internal_strlen(name); - InternalMmapVector buffer(kMaxPathLength); const char *beg = path; while (true) { const char *end = internal_strchrnul(beg, kPathSeparator);