[compiler-rt] 9ba623c - [asan] Add %d variable to external_symbolizer_path option, so that user can specify paths relative to the location of the binary.
Amy Huang via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 4 15:45:21 PST 2021
Author: Amy Huang
Date: 2021-02-04T15:43:02-08:00
New Revision: 9ba623c655e9696fa36496fa5962a2da0a9f37ab
URL: https://github.com/llvm/llvm-project/commit/9ba623c655e9696fa36496fa5962a2da0a9f37ab
DIFF: https://github.com/llvm/llvm-project/commit/9ba623c655e9696fa36496fa5962a2da0a9f37ab.diff
LOG: [asan] Add %d variable to external_symbolizer_path option, so that user can specify paths relative to the location of the binary.
We want way to set a path to llvm-symbolizer that isn't relative
to the current working directory; this change adds a variable that
expands to the path relative to the current binary.
This approach came from comments in https://reviews.llvm.org/D93070
Differential Revision: https://reviews.llvm.org/D94563
Added:
compiler-rt/test/sanitizer_common/TestCases/external_symbolizer_path.cpp
Modified:
compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp
compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
index 87efda5bd372..10b5c82f180b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
@@ -274,6 +274,14 @@ uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) {
return name_len;
}
+uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) {
+ ReadBinaryNameCached(buf, buf_len);
+ const char *exec_name_pos = StripModuleName(buf);
+ uptr name_len = exec_name_pos - buf;
+ buf[name_len] = '\0';
+ return name_len;
+}
+
#if !SANITIZER_GO
void PrintCmdline() {
char **argv = GetArgv();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index a6532eee164d..2fecc3b4bf7c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -248,6 +248,7 @@ const char *StripModuleName(const char *module);
// OS
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
+uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len);
uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
const char *GetProcessName();
void UpdateProcessName();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp
index 21048be73041..d52e96a7c381 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp
@@ -35,6 +35,7 @@ void CommonFlags::CopyFrom(const CommonFlags &other) {
// Copy the string from "s" to "out", making the following substitutions:
// %b = binary basename
// %p = pid
+// %d = binary directory
void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
char *out_end = out + out_size;
while (*s && out < out_end - 1) {
@@ -64,6 +65,12 @@ void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
s += 2; // skip "%p"
break;
}
+ case 'd': {
+ uptr len = ReadBinaryDir(out, out_end - out);
+ out += len;
+ s += 2; // skip "%d"
+ break;
+ }
default:
*out++ = *s++;
break;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
index 4dd5cc3ad7cb..76e1f2eeb929 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
@@ -400,6 +400,13 @@ const char *Symbolizer::PlatformDemangle(const char *name) {
static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
const char *path = common_flags()->external_symbolizer_path;
+
+ if (path && internal_strchr(path, '%')) {
+ char *new_path = (char *)InternalAlloc(kMaxPathLength);
+ SubstituteForFlagValue(path, new_path, kMaxPathLength);
+ path = new_path;
+ }
+
const char *binary_name = path ? StripModuleName(path) : "";
if (path && path[0] == '\0') {
VReport(2, "External symbolizer is explicitly disabled.\n");
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
index 7db7d3b0eb9d..dc611a01a500 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
@@ -288,8 +288,15 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
return;
}
- // Add llvm-symbolizer in case the binary has dwarf.
+ // Add llvm-symbolizer.
const char *user_path = common_flags()->external_symbolizer_path;
+
+ if (user_path && internal_strchr(user_path, '%')) {
+ char *new_path = (char *)InternalAlloc(kMaxPathLength);
+ SubstituteForFlagValue(user_path, new_path, kMaxPathLength);
+ user_path = new_path;
+ }
+
const char *path =
user_path ? user_path : FindPathToBinary("llvm-symbolizer.exe");
if (path) {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index 63c90785f270..1b591f1bdcbb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -1049,10 +1049,23 @@ const char *SignalContext::Describe() const {
}
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
- // FIXME: Actually implement this function.
- CHECK_GT(buf_len, 0);
- buf[0] = 0;
- return 0;
+ if (buf_len == 0)
+ return 0;
+
+ // Get the UTF-16 path and convert to UTF-8.
+ wchar_t binname_utf16[kMaxPathLength];
+ int binname_utf16_len =
+ GetModuleFileNameW(NULL, binname_utf16, ARRAY_SIZE(binname_utf16));
+ if (binname_utf16_len == 0) {
+ buf[0] = '\0';
+ return 0;
+ }
+ int binary_name_len = ::WideCharToMultiByte(
+ CP_UTF8, 0, binname_utf16, binname_utf16_len, buf, buf_len, NULL, NULL);
+ if ((unsigned)binary_name_len == buf_len)
+ --binary_name_len;
+ buf[binary_name_len] = '\0';
+ return binary_name_len;
}
uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
index 4d9f2c1c831b..fcf8b14aeba5 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
@@ -461,12 +461,9 @@ TEST(SanitizerCommon, ReservedAddressRangeUnmap) {
EXPECT_DEATH(address_range.Unmap(base_addr + (PageSize * 2), PageSize), ".*");
}
-// Windows has no working ReadBinaryName.
-#if !SANITIZER_WINDOWS
TEST(SanitizerCommon, ReadBinaryNameCached) {
char buf[256];
EXPECT_NE((uptr)0, ReadBinaryNameCached(buf, sizeof(buf)));
}
-#endif
} // namespace __sanitizer
diff --git a/compiler-rt/test/sanitizer_common/TestCases/external_symbolizer_path.cpp b/compiler-rt/test/sanitizer_common/TestCases/external_symbolizer_path.cpp
new file mode 100644
index 000000000000..d7e120713773
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/external_symbolizer_path.cpp
@@ -0,0 +1,30 @@
+// REQUIRES: shell
+// RUN: rm -rf %t.bin
+// RUN: mkdir %t.bin
+// RUN: cp $(which llvm-symbolizer) %t.bin
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: %clangxx -O0 %s -o %t && cd %t.dir
+// RUN: %env_tool_opts=external_symbolizer_path=%d/external_symbolizer_path.cpp.tmp.bin/llvm-symbolizer \
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=FOUND
+// RUN: rm -rf %t.bin/llvm-symbolizer
+// RUN: cd ..
+// RUN: %clangxx -O0 %s -o %t && cd %t.dir
+// RUN: %env_tool_opts=external_symbolizer_path=%d/external_symbolizer_path.cpp.tmp.bin/llvm-symbolizer \
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=NOT-FOUND
+
+#include <sanitizer/common_interface_defs.h>
+#include <stdio.h>
+
+static void Symbolize() {
+ char buffer[100];
+ __sanitizer_symbolize_pc(__builtin_return_address(0), "%p %F %L", buffer,
+ sizeof(buffer));
+ printf("%s\n", buffer);
+}
+
+int main() {
+ // FOUND: {{0x.* in main}}
+ // NOT-FOUND: WARNING: invalid path to external symbolizer!
+ Symbolize();
+}
More information about the llvm-commits
mailing list