forked from OSchip/llvm-project
[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:
parent
585e65d330
commit
98504959a6
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]]
|
||||
}
|
Loading…
Reference in New Issue