[compiler-rt] 9850495 - [dfsan] Add stack-trace printing functions to dfsan interface

George Balatsouras via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 14 14:09:13 PDT 2021


Author: George Balatsouras
Date: 2021-06-14T14:09:00-07:00
New Revision: 98504959a6f114866cbf523e44d2f45e755626d5

URL: https://github.com/llvm/llvm-project/commit/98504959a6f114866cbf523e44d2f45e755626d5
DIFF: https://github.com/llvm/llvm-project/commit/98504959a6f114866cbf523e44d2f45e755626d5.diff

LOG: [dfsan] Add stack-trace printing functions to dfsan interface

Reviewed By: stephan.yichao.zhao

Differential Revision: https://reviews.llvm.org/D104165

Added: 
    compiler-rt/test/dfsan/stack_trace.c

Modified: 
    compiler-rt/include/sanitizer/dfsan_interface.h
    compiler-rt/lib/dfsan/dfsan.cpp
    compiler-rt/lib/dfsan/done_abilist.txt

Removed: 
    


################################################################################
diff  --git a/compiler-rt/include/sanitizer/dfsan_interface.h b/compiler-rt/include/sanitizer/dfsan_interface.h
index 57bd37625419b..ea2283284e096 100644
--- a/compiler-rt/include/sanitizer/dfsan_interface.h
+++ b/compiler-rt/include/sanitizer/dfsan_interface.h
@@ -105,8 +105,8 @@ void dfsan_print_origin_trace(const void *addr, const char *description);
 ///   int len = dfsan_sprint_origin_trace(&var, nullptr, buf, sizeof(buf));
 ///
 ///   if (len < sizeof(buf)) {
-///     ProcessOriginTrace(tmpbuf);
-///   else {
+///     ProcessOriginTrace(buf);
+///   } else {
 ///     char *tmpbuf = new char[len + 1];
 ///     dfsan_sprint_origin_trace(&var, nullptr, tmpbuf, len + 1);
 ///     ProcessOriginTrace(tmpbuf);
@@ -125,6 +125,19 @@ void dfsan_print_origin_trace(const void *addr, const char *description);
 size_t dfsan_sprint_origin_trace(const void *addr, const char *description,
                                  char *out_buf, size_t out_buf_size);
 
+/// Prints the stack trace leading to this call to a pre-allocated output
+/// buffer.
+///
+/// For usage examples, see dfsan_sprint_origin_trace.
+///
+/// \param [out] out_buf The output buffer to write the results to.
+/// \param out_buf_size The size of \p out_buf.
+///
+/// \returns The number of symbols that should have been written to \p out_buf
+/// (not including trailing null byte '\0'). Thus, the string is truncated iff
+/// return value is not less than \p out_buf_size.
+size_t dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size);
+
 /// Retrieves the very first origin associated with the data at the given
 /// address.
 dfsan_origin dfsan_get_init_origin(const void *addr);

diff  --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index e31177c38f5e7..6e9ad107e2233 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -824,10 +824,6 @@ dfsan_get_init_origin(const void *addr) {
   return origin_id;
 }
 
-#define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
-  BufferedStackTrace stack;                 \
-  stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal);
-
 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
                                                  void *context,
                                                  bool request_fast,
@@ -841,10 +837,19 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
 }
 
 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_print_stack_trace() {
-  GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
+  GET_CALLER_PC_BP;
+  GET_STORE_STACK_TRACE_PC_BP(pc, bp);
   stack.Print();
 }
 
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE size_t
+dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size) {
+  CHECK(out_buf);
+  GET_CALLER_PC_BP;
+  GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+  return stack.PrintTo(out_buf, out_buf_size);
+}
+
 void Flags::SetDefaults() {
 #define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
 #include "dfsan_flags.inc"

diff  --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt
index 38aeb881495f7..ca26eab406b03 100644
--- a/compiler-rt/lib/dfsan/done_abilist.txt
+++ b/compiler-rt/lib/dfsan/done_abilist.txt
@@ -32,6 +32,8 @@ fun:dfsan_print_origin_trace=uninstrumented
 fun:dfsan_print_origin_trace=discard
 fun:dfsan_sprint_origin_trace=uninstrumented
 fun:dfsan_sprint_origin_trace=discard
+fun:dfsan_sprint_stack_trace=uninstrumented
+fun:dfsan_sprint_stack_trace=discard
 fun:dfsan_get_origin=uninstrumented
 fun:dfsan_get_origin=custom
 fun:dfsan_get_init_origin=uninstrumented

diff  --git a/compiler-rt/test/dfsan/stack_trace.c b/compiler-rt/test/dfsan/stack_trace.c
new file mode 100644
index 0000000000000..5cfab32d8bc80
--- /dev/null
+++ b/compiler-rt/test/dfsan/stack_trace.c
@@ -0,0 +1,66 @@
+// RUN: %clang_dfsan -gmlt %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+//
+// REQUIRES: x86_64-target-arch
+
+#include <assert.h>
+#include <sanitizer/dfsan_interface.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NOINLINE __attribute__((noinline))
+
+NOINLINE size_t bar(int depth, char *buf, size_t len) {
+  if (!depth) {
+    return dfsan_sprint_stack_trace(buf, len);
+  }
+
+  return bar(depth - 1, buf, len);
+}
+
+NOINLINE size_t baz(int depth, char *buf, size_t len) {
+  return bar(depth, buf, len);
+}
+
+int main(int argc, char *argv[]) {
+  char buf[3000];
+  size_t length = dfsan_sprint_stack_trace(buf, sizeof(buf));
+  assert(length < sizeof(buf));
+  printf("==OUTPUT==\n%s==EOS==\n", buf);
+
+  // CHECK: ==OUTPUT==
+  // CHECK: #0 {{.*}} in main [[FILEPATH:.*]]/stack_trace.c:[[# @LINE - 5 ]]
+  // CHECK: ==EOS==
+
+  length = baz(8, buf, sizeof(buf));
+  printf("==OUTPUT==\n%s==EOS==\n", buf);
+
+  // CHECK: ==OUTPUT==
+  // CHECK: #0 {{.*}} in dfs$bar [[FILEPATH]]/stack_trace.c:15
+  // CHECK-COUNT-8: #{{[1-9]+}} {{.*}} in dfs$bar [[FILEPATH]]/stack_trace.c:18
+  // CHECK: #9 {{.*}} in dfs$baz [[FILEPATH]]/stack_trace.c:22
+  // CHECK: #10 {{.*}} in main [[FILEPATH]]/stack_trace.c:[[# @LINE - 7 ]]
+  // CHECK: ==EOS==
+
+  char tinybuf[8];
+  size_t same_length = baz(8, tinybuf, sizeof(tinybuf));
+
+  printf("==TRUNCATED OUTPUT==\n%s==EOS==\n", tinybuf);
+  // CHECK: ==TRUNCATED OUTPUT==
+  // CHECK:     #0 ==EOS==
+
+  printf("Returned length: %zu\n", length);
+  printf("Actual length: %zu\n", strlen(buf));
+  printf("Returned length with truncation: %zu\n", same_length);
+
+  // CHECK: Returned length: [[#LEN:]]
+  // CHECK: Actual length: [[#LEN]]
+  // CHECK: Returned length with truncation: [[#LEN]]
+
+  buf[0] = '\0';
+  length = baz(8, buf, 0);
+  printf("Output=\"%s\"\n", buf);
+  printf("Returned length: %zu\n", length);
+  // CHECK: Output=""
+  // CHECK: Returned length: [[#LEN]]
+}


        


More information about the llvm-commits mailing list