diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2014-11-05 22:44:36 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-11-05 22:44:36 +0000 |
commit | 2eb3d6daf27d0698811912bf62cc113cbebca8e0 (patch) | |
tree | 87896d94c29ba4d174bfa7f907c355bb7bc06584 /lib/sanitizer_common/sanitizer_stacktrace_printer.cc | |
parent | 822401938dff8288be4582b1c5c962e009479d43 (diff) | |
download | compiler-rt-2eb3d6daf27d0698811912bf62cc113cbebca8e0.tar.gz |
[Sanitizer] Introduce generic stack frame rendering machinery
Summary:
This commit introduces function __sanitizer::RenderFrame()
that allows to render the contents of AddressInfo (essentially, symbolized stack frame)
using the custom format string. This function can be used to
implement stack frame formatting for both ThreadSanitizer and
generic StackTrace::Print(), used in another places. This paves the
way towards allowing user to control the format of stack frames,
obtaining them in any format he desires, and/or enforcing the consistent
output from all sanitizers.
Test Plan: compiler-rt test suite
Reviewers: kcc
Reviewed By: kcc
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D6140
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@221409 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_stacktrace_printer.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_stacktrace_printer.cc | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_stacktrace_printer.cc b/lib/sanitizer_common/sanitizer_stacktrace_printer.cc new file mode 100644 index 000000000..7b37dbcf3 --- /dev/null +++ b/lib/sanitizer_common/sanitizer_stacktrace_printer.cc @@ -0,0 +1,132 @@ +//===-- sanitizer_common.cc -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is shared between sanitizers' run-time libraries. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_stacktrace_printer.h" + +namespace __sanitizer { + +static const char *StripFunctionName(const char *function, const char *prefix) { + if (function == 0) return 0; + if (prefix == 0) return function; + uptr prefix_len = internal_strlen(prefix); + if (0 == internal_strncmp(function, prefix, prefix_len)) + return function + prefix_len; + return function; +} + +static const char kDefaultFormat[] = " #%n %p %F %L"; + +void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, + const AddressInfo &info, const char *strip_path_prefix, + const char *strip_func_prefix) { + if (0 == internal_strcmp(format, "DEFAULT")) + format = kDefaultFormat; + for (const char *p = format; *p != '\0'; p++) { + if (*p != '%') { + buffer->append("%c", *p); + continue; + } + p++; + switch (*p) { + case '%': + buffer->append("%%"); + break; + // Frame number and all fields of AddressInfo structure. + case 'n': + buffer->append("%zu", frame_no); + break; + case 'p': + buffer->append("0x%zx", info.address); + break; + case 'm': + buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix)); + break; + case 'o': + buffer->append("0x%zx", info.module_offset); + break; + case 'f': + buffer->append("%s", StripFunctionName(info.function, strip_func_prefix)); + break; + case 'q': + buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown + ? info.function_offset + : 0x0); + break; + case 's': + buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix)); + break; + case 'l': + buffer->append("%d", info.line); + break; + case 'c': + buffer->append("%d", info.column); + break; + // Smarter special cases. + case 'F': + // Function name and offset, if file is unknown. + if (info.function) { + buffer->append("in %s", + StripFunctionName(info.function, strip_func_prefix)); + if (!info.file && info.function_offset != AddressInfo::kUnknown) + buffer->append("+0x%zx", info.function_offset); + } + break; + case 'S': + // File/line information. + RenderSourceLocation(buffer, info.file, info.line, info.column, + strip_path_prefix); + break; + case 'L': + // Source location, or module location. + if (info.file) { + RenderSourceLocation(buffer, info.file, info.line, info.column, + strip_path_prefix); + } else if (info.module) { + RenderModuleLocation(buffer, info.module, info.module_offset, + strip_path_prefix); + } else { + buffer->append("(<unknown module>)"); + } + break; + case 'M': + // Module basename and offset, or PC. + if (info.module) + buffer->append("(%s+%p)", StripModuleName(info.module), + (void *)info.module_offset); + else + buffer->append("(%p)", (void *)info.address); + break; + default: + Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", + *p, *p); + Die(); + } + } +} + +void RenderSourceLocation(InternalScopedString *buffer, const char *file, + int line, int column, const char *strip_path_prefix) { + buffer->append("%s", StripPathPrefix(file, strip_path_prefix)); + if (line > 0) { + buffer->append(":%d", line); + if (column > 0) + buffer->append(":%d", column); + } +} + +void RenderModuleLocation(InternalScopedString *buffer, const char *module, + uptr offset, const char *strip_path_prefix) { + buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix), + offset); +} + +} // namespace __sanitizer |