[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