Path: blob/main/contrib/llvm-project/compiler-rt/lib/gwp_asan/common.cpp
35236 views
//===-- common.cpp ----------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "gwp_asan/common.h"9#include "gwp_asan/stack_trace_compressor.h"1011#include <assert.h>1213using AllocationMetadata = gwp_asan::AllocationMetadata;14using Error = gwp_asan::Error;1516namespace gwp_asan {1718const char *ErrorToString(const Error &E) {19switch (E) {20case Error::UNKNOWN:21return "Unknown";22case Error::USE_AFTER_FREE:23return "Use After Free";24case Error::DOUBLE_FREE:25return "Double Free";26case Error::INVALID_FREE:27return "Invalid (Wild) Free";28case Error::BUFFER_OVERFLOW:29return "Buffer Overflow";30case Error::BUFFER_UNDERFLOW:31return "Buffer Underflow";32}33__builtin_trap();34}3536constexpr size_t AllocationMetadata::kStackFrameStorageBytes;37constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;3839void AllocationMetadata::RecordAllocation(uintptr_t AllocAddr,40size_t AllocSize) {41Addr = AllocAddr;42RequestedSize = AllocSize;43IsDeallocated = false;4445AllocationTrace.ThreadID = getThreadID();46DeallocationTrace.TraceSize = 0;47DeallocationTrace.ThreadID = kInvalidThreadID;48}4950void AllocationMetadata::RecordDeallocation() {51IsDeallocated = true;52DeallocationTrace.ThreadID = getThreadID();53}5455void AllocationMetadata::CallSiteInfo::RecordBacktrace(56options::Backtrace_t Backtrace) {57TraceSize = 0;58if (!Backtrace)59return;6061uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];62size_t BacktraceLength =63Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);64// Backtrace() returns the number of available frames, which may be greater65// than the number of frames in the buffer. In this case, we need to only pack66// the number of frames that are in the buffer.67if (BacktraceLength > kMaxTraceLengthToCollect)68BacktraceLength = kMaxTraceLengthToCollect;69TraceSize =70compression::pack(UncompressedBuffer, BacktraceLength, CompressedTrace,71AllocationMetadata::kStackFrameStorageBytes);72}7374size_t AllocatorState::maximumAllocationSize() const { return PageSize; }7576uintptr_t AllocatorState::slotToAddr(size_t N) const {77return GuardedPagePool + (PageSize * (1 + N)) + (maximumAllocationSize() * N);78}7980bool AllocatorState::isGuardPage(uintptr_t Ptr) const {81assert(pointerIsMine(reinterpret_cast<void *>(Ptr)));82size_t PageOffsetFromPoolStart = (Ptr - GuardedPagePool) / PageSize;83size_t PagesPerSlot = maximumAllocationSize() / PageSize;84return (PageOffsetFromPoolStart % (PagesPerSlot + 1)) == 0;85}8687static size_t addrToSlot(const AllocatorState *State, uintptr_t Ptr) {88size_t ByteOffsetFromPoolStart = Ptr - State->GuardedPagePool;89return ByteOffsetFromPoolStart /90(State->maximumAllocationSize() + State->PageSize);91}9293size_t AllocatorState::getNearestSlot(uintptr_t Ptr) const {94if (Ptr <= GuardedPagePool + PageSize)95return 0;96if (Ptr > GuardedPagePoolEnd - PageSize)97return MaxSimultaneousAllocations - 1;9899if (!isGuardPage(Ptr))100return addrToSlot(this, Ptr);101102if (Ptr % PageSize <= PageSize / 2)103return addrToSlot(this, Ptr - PageSize); // Round down.104return addrToSlot(this, Ptr + PageSize); // Round up.105}106107uintptr_t AllocatorState::internallyDetectedErrorFaultAddress() const {108return GuardedPagePoolEnd - 0x10;109}110111} // namespace gwp_asan112113114