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

Reviewed By: stephan.yichao.zhao

Differential Revision: https://reviews.llvm.org/D104165
This commit is contained in:
George Balatsouras 2021-06-11 17:54:19 -07:00
parent 585e65d330
commit 98504959a6
4 changed files with 93 additions and 7 deletions

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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]]
}