123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- //===-- common.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
- //
- //===----------------------------------------------------------------------===//
- #include "gwp_asan/common.h"
- #include "gwp_asan/stack_trace_compressor.h"
- #include <assert.h>
- using AllocationMetadata = gwp_asan::AllocationMetadata;
- using Error = gwp_asan::Error;
- namespace gwp_asan {
- const char *ErrorToString(const Error &E) {
- switch (E) {
- case Error::UNKNOWN:
- return "Unknown";
- case Error::USE_AFTER_FREE:
- return "Use After Free";
- case Error::DOUBLE_FREE:
- return "Double Free";
- case Error::INVALID_FREE:
- return "Invalid (Wild) Free";
- case Error::BUFFER_OVERFLOW:
- return "Buffer Overflow";
- case Error::BUFFER_UNDERFLOW:
- return "Buffer Underflow";
- }
- __builtin_trap();
- }
- constexpr size_t AllocationMetadata::kStackFrameStorageBytes;
- constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;
- void AllocationMetadata::RecordAllocation(uintptr_t AllocAddr,
- size_t AllocSize) {
- Addr = AllocAddr;
- RequestedSize = AllocSize;
- IsDeallocated = false;
- AllocationTrace.ThreadID = getThreadID();
- DeallocationTrace.TraceSize = 0;
- DeallocationTrace.ThreadID = kInvalidThreadID;
- }
- void AllocationMetadata::RecordDeallocation() {
- IsDeallocated = true;
- DeallocationTrace.ThreadID = getThreadID();
- }
- void AllocationMetadata::CallSiteInfo::RecordBacktrace(
- options::Backtrace_t Backtrace) {
- TraceSize = 0;
- if (!Backtrace)
- return;
- uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
- size_t BacktraceLength =
- Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
- // Backtrace() returns the number of available frames, which may be greater
- // than the number of frames in the buffer. In this case, we need to only pack
- // the number of frames that are in the buffer.
- if (BacktraceLength > kMaxTraceLengthToCollect)
- BacktraceLength = kMaxTraceLengthToCollect;
- TraceSize =
- compression::pack(UncompressedBuffer, BacktraceLength, CompressedTrace,
- AllocationMetadata::kStackFrameStorageBytes);
- }
- size_t AllocatorState::maximumAllocationSize() const { return PageSize; }
- uintptr_t AllocatorState::slotToAddr(size_t N) const {
- return GuardedPagePool + (PageSize * (1 + N)) + (maximumAllocationSize() * N);
- }
- bool AllocatorState::isGuardPage(uintptr_t Ptr) const {
- assert(pointerIsMine(reinterpret_cast<void *>(Ptr)));
- size_t PageOffsetFromPoolStart = (Ptr - GuardedPagePool) / PageSize;
- size_t PagesPerSlot = maximumAllocationSize() / PageSize;
- return (PageOffsetFromPoolStart % (PagesPerSlot + 1)) == 0;
- }
- static size_t addrToSlot(const AllocatorState *State, uintptr_t Ptr) {
- size_t ByteOffsetFromPoolStart = Ptr - State->GuardedPagePool;
- return ByteOffsetFromPoolStart /
- (State->maximumAllocationSize() + State->PageSize);
- }
- size_t AllocatorState::getNearestSlot(uintptr_t Ptr) const {
- if (Ptr <= GuardedPagePool + PageSize)
- return 0;
- if (Ptr > GuardedPagePoolEnd - PageSize)
- return MaxSimultaneousAllocations - 1;
- if (!isGuardPage(Ptr))
- return addrToSlot(this, Ptr);
- if (Ptr % PageSize <= PageSize / 2)
- return addrToSlot(this, Ptr - PageSize); // Round down.
- return addrToSlot(this, Ptr + PageSize); // Round up.
- }
- } // namespace gwp_asan
|