llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp
Teresa Johnson 3d4bba302d [MemProf] Memory profiling runtime support
See RFC for background:
http://lists.llvm.org/pipermail/llvm-dev/2020-June/142744.html

Follow on companion to the clang/llvm instrumentation support in D85948
and committed earlier.

This patch adds the compiler-rt runtime support for the memory
profiling.

Note that much of this support was cloned from asan (and then greatly
simplified and renamed). For example the interactions with the
sanitizer_common allocators, error handling, interception, etc.

The bulk of the memory profiling specific code can be found in the
MemInfoBlock, MemInfoBlockCache, and related classes defined and used
in memprof_allocator.cpp.

For now, the memory profile is dumped to text (stderr by default, but
honors the sanitizer_common log_path flag). It is dumped in either a
default verbose format, or an optional terse format.

This patch also adds a set of tests for the core functionality.

Differential Revision: https://reviews.llvm.org/D87120
2020-10-16 09:47:02 -07:00

146 lines
4.9 KiB
C++

//===-- sanitizer_allocator_report.cpp --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc.
///
//===----------------------------------------------------------------------===//
#include "sanitizer_allocator.h"
#include "sanitizer_allocator_report.h"
#include "sanitizer_common.h"
#include "sanitizer_report_decorator.h"
namespace __sanitizer {
class ScopedAllocatorErrorReport {
public:
ScopedAllocatorErrorReport(const char *error_summary_,
const StackTrace *stack_)
: error_summary(error_summary_),
stack(stack_) {
Printf("%s", d.Error());
}
~ScopedAllocatorErrorReport() {
Printf("%s", d.Default());
stack->Print();
PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(error_summary, stack);
}
private:
ScopedErrorReportLock lock;
const char *error_summary;
const StackTrace* const stack;
const SanitizerCommonDecorator d;
};
void NORETURN ReportCallocOverflow(uptr count, uptr size,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("calloc-overflow", stack);
Report("ERROR: %s: calloc parameters overflow: count * size (%zd * %zd) "
"cannot be represented in type size_t\n", SanitizerToolName, count,
size);
}
Die();
}
void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("reallocarray-overflow", stack);
Report(
"ERROR: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
"cannot be represented in type size_t\n",
SanitizerToolName, count, size);
}
Die();
}
void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("pvalloc-overflow", stack);
Report("ERROR: %s: pvalloc parameters overflow: size 0x%zx rounded up to "
"system page size 0x%zx cannot be represented in type size_t\n",
SanitizerToolName, size, GetPageSizeCached());
}
Die();
}
void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("invalid-allocation-alignment", stack);
Report("ERROR: %s: invalid allocation alignment: %zd, alignment must be a "
"power of two\n", SanitizerToolName, alignment);
}
Die();
}
void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("invalid-aligned-alloc-alignment", stack);
#if SANITIZER_POSIX
Report("ERROR: %s: invalid alignment requested in "
"aligned_alloc: %zd, alignment must be a power of two and the "
"requested size 0x%zx must be a multiple of alignment\n",
SanitizerToolName, alignment, size);
#else
Report("ERROR: %s: invalid alignment requested in aligned_alloc: %zd, "
"the requested size 0x%zx must be a multiple of alignment\n",
SanitizerToolName, alignment, size);
#endif
}
Die();
}
void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment",
stack);
Report(
"ERROR: %s: invalid alignment requested in "
"posix_memalign: %zd, alignment must be a power of two and a "
"multiple of sizeof(void*) == %zd\n",
SanitizerToolName, alignment, sizeof(void *));
}
Die();
}
void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size,
const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("allocation-size-too-big", stack);
Report("ERROR: %s: requested allocation size 0x%zx exceeds maximum "
"supported size of 0x%zx\n", SanitizerToolName, user_size, max_size);
}
Die();
}
void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("out-of-memory", stack);
Report("ERROR: %s: allocator is out of memory trying to allocate 0x%zx "
"bytes\n", SanitizerToolName, requested_size);
}
Die();
}
void NORETURN ReportRssLimitExceeded(const StackTrace *stack) {
{
ScopedAllocatorErrorReport report("rss-limit-exceeded", stack);
Report("ERROR: %s: allocator exceeded the RSS limit\n", SanitizerToolName);
}
Die();
}
} // namespace __sanitizer