gcc/libsanitizer/sanitizer_common/sanitizer_allocator_combined.h
Jakub Jelinek 5d3805fca3 ubsan.c (ubsan_expand_null_ifn): Use _v1 suffixed type mismatch builtins...
* ubsan.c (ubsan_expand_null_ifn): Use _v1 suffixed type mismatch
	builtins, store max (log2 (align), 0) into uchar field instead of
	align into uptr field.
	(ubsan_expand_objsize_ifn): Use _v1 suffixed type mismatch builtins,
	store uchar 0 field instead of uptr 0 field.
	(instrument_nonnull_return): Use _v1 suffixed nonnull return builtin,
	instead of passing one address of struct with 2 locations pass
	two addresses of structs with 1 location each.
	* sanitizer.def (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH,
	BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT,
	BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN,
	BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT): Removed.
	(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1,
	BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT,
	BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1,
	BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT): New builtins.

	* c-c++-common/ubsan/float-cast-overflow-1.c: Drop value keyword
	from expected output regexps.
	* c-c++-common/ubsan/float-cast-overflow-2.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-3.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-4.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-5.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-6.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-8.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-9.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-10.c: Likewise.
	* g++.dg/ubsan/float-cast-overflow-bf.C: Likewise.
	* gcc.dg/ubsan/float-cast-overflow-bf.c: Likewise.
	* g++.dg/asan/default-options-1.C (__asan_default_options): Add
	used attribute.
	* g++.dg/asan/asan_test.C: Run with ASAN_OPTIONS=handle_segv=2
	in the environment.

	* All source files: Merge from upstream 315899.
        * asan/Makefile.am (nodist_saninclude_HEADERS): Add
	include/sanitizer/tsan_interface.h.
        * asan/libtool-version: Bump the libasan SONAME.
	* lsan/Makefile.am (sanitizer_lsan_files): Add lsan_common_mac.cc.
	(lsan_files): Add lsan_linux.cc, lsan_mac.cc and lsan_malloc_mac.cc.
        * sanitizer_common/Makefile.am (sanitizer_common_files): Add
	sancov_flags.cc, sanitizer_allocator_checks.cc,
	sanitizer_coverage_libcdep_new.cc, sanitizer_errno.cc,
	sanitizer_file.cc, sanitizer_mac_libcdep.cc and
	sanitizer_stoptheworld_mac.cc.  Remove sanitizer_coverage_libcdep.cc
	and sanitizer_coverage_mapping_libcdep.cc.
        * tsan/Makefile.am (tsan_files): Add tsan_external.cc.
	* ubsan/Makefile.am (DEFS): Add -DUBSAN_CAN_USE_CXXABI=1.
	(ubsan_files): Add ubsan_init_standalone.cc and
	ubsan_signals_standalone.cc.
	* ubsan/libtool-version: Bump the libubsan SONAME.
        * asan/Makefile.in: Regenerate.
        * lsan/Makefile.in: Regenerate.
        * sanitizer_common/Makefile.in: Regenerate.
        * tsan/Makefile.in: Regenerate.
	* ubsan/Makefile.in: Regenerate.

From-SVN: r253887
2017-10-19 13:23:59 +02:00

191 lines
5.8 KiB
C++

//===-- sanitizer_allocator_combined.h --------------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Part of the Sanitizer Allocator.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_ALLOCATOR_H
#error This file must be included inside sanitizer_allocator.h
#endif
// This class implements a complete memory allocator by using two
// internal allocators:
// PrimaryAllocator is efficient, but may not allocate some sizes (alignments).
// When allocating 2^x bytes it should return 2^x aligned chunk.
// PrimaryAllocator is used via a local AllocatorCache.
// SecondaryAllocator can allocate anything, but is not efficient.
template <class PrimaryAllocator, class AllocatorCache,
class SecondaryAllocator> // NOLINT
class CombinedAllocator {
public:
typedef typename SecondaryAllocator::FailureHandler FailureHandler;
void InitLinkerInitialized(s32 release_to_os_interval_ms) {
primary_.Init(release_to_os_interval_ms);
secondary_.InitLinkerInitialized();
stats_.InitLinkerInitialized();
}
void Init(s32 release_to_os_interval_ms) {
primary_.Init(release_to_os_interval_ms);
secondary_.Init();
stats_.Init();
}
void *Allocate(AllocatorCache *cache, uptr size, uptr alignment) {
// Returning 0 on malloc(0) may break a lot of code.
if (size == 0)
size = 1;
if (size + alignment < size)
return FailureHandler::OnBadRequest();
uptr original_size = size;
// If alignment requirements are to be fulfilled by the frontend allocator
// rather than by the primary or secondary, passing an alignment lower than
// or equal to 8 will prevent any further rounding up, as well as the later
// alignment check.
if (alignment > 8)
size = RoundUpTo(size, alignment);
// The primary allocator should return a 2^x aligned allocation when
// requested 2^x bytes, hence using the rounded up 'size' when being
// serviced by the primary (this is no longer true when the primary is
// using a non-fixed base address). The secondary takes care of the
// alignment without such requirement, and allocating 'size' would use
// extraneous memory, so we employ 'original_size'.
void *res;
if (primary_.CanAllocate(size, alignment))
res = cache->Allocate(&primary_, primary_.ClassID(size));
else
res = secondary_.Allocate(&stats_, original_size, alignment);
if (!res)
return FailureHandler::OnOOM();
if (alignment > 8)
CHECK_EQ(reinterpret_cast<uptr>(res) & (alignment - 1), 0);
return res;
}
s32 ReleaseToOSIntervalMs() const {
return primary_.ReleaseToOSIntervalMs();
}
void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
primary_.SetReleaseToOSIntervalMs(release_to_os_interval_ms);
}
void Deallocate(AllocatorCache *cache, void *p) {
if (!p) return;
if (primary_.PointerIsMine(p))
cache->Deallocate(&primary_, primary_.GetSizeClass(p), p);
else
secondary_.Deallocate(&stats_, p);
}
void *Reallocate(AllocatorCache *cache, void *p, uptr new_size,
uptr alignment) {
if (!p)
return Allocate(cache, new_size, alignment);
if (!new_size) {
Deallocate(cache, p);
return nullptr;
}
CHECK(PointerIsMine(p));
uptr old_size = GetActuallyAllocatedSize(p);
uptr memcpy_size = Min(new_size, old_size);
void *new_p = Allocate(cache, new_size, alignment);
if (new_p)
internal_memcpy(new_p, p, memcpy_size);
Deallocate(cache, p);
return new_p;
}
bool PointerIsMine(void *p) {
if (primary_.PointerIsMine(p))
return true;
return secondary_.PointerIsMine(p);
}
bool FromPrimary(void *p) {
return primary_.PointerIsMine(p);
}
void *GetMetaData(const void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetMetaData(p);
return secondary_.GetMetaData(p);
}
void *GetBlockBegin(const void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetBlockBegin(p);
return secondary_.GetBlockBegin(p);
}
// This function does the same as GetBlockBegin, but is much faster.
// Must be called with the allocator locked.
void *GetBlockBeginFastLocked(void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetBlockBegin(p);
return secondary_.GetBlockBeginFastLocked(p);
}
uptr GetActuallyAllocatedSize(void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetActuallyAllocatedSize(p);
return secondary_.GetActuallyAllocatedSize(p);
}
uptr TotalMemoryUsed() {
return primary_.TotalMemoryUsed() + secondary_.TotalMemoryUsed();
}
void TestOnlyUnmap() { primary_.TestOnlyUnmap(); }
void InitCache(AllocatorCache *cache) {
cache->Init(&stats_);
}
void DestroyCache(AllocatorCache *cache) {
cache->Destroy(&primary_, &stats_);
}
void SwallowCache(AllocatorCache *cache) {
cache->Drain(&primary_);
}
void GetStats(AllocatorStatCounters s) const {
stats_.Get(s);
}
void PrintStats() {
primary_.PrintStats();
secondary_.PrintStats();
}
// ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
// introspection API.
void ForceLock() {
primary_.ForceLock();
secondary_.ForceLock();
}
void ForceUnlock() {
secondary_.ForceUnlock();
primary_.ForceUnlock();
}
// Iterate over all existing chunks.
// The allocator must be locked when calling this function.
void ForEachChunk(ForEachChunkCallback callback, void *arg) {
primary_.ForEachChunk(callback, arg);
secondary_.ForEachChunk(callback, arg);
}
private:
PrimaryAllocator primary_;
SecondaryAllocator secondary_;
AllocatorGlobalStats stats_;
};