[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