brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 790a331 Raw
113 lines · cpp
1//===-- common.cpp ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "gwp_asan/common.h"10#include "gwp_asan/stack_trace_compressor.h"11 12#include <assert.h>13 14using AllocationMetadata = gwp_asan::AllocationMetadata;15using Error = gwp_asan::Error;16 17namespace gwp_asan {18 19const char *ErrorToString(const Error &E) {20  switch (E) {21  case Error::UNKNOWN:22    return "Unknown";23  case Error::USE_AFTER_FREE:24    return "Use After Free";25  case Error::DOUBLE_FREE:26    return "Double Free";27  case Error::INVALID_FREE:28    return "Invalid (Wild) Free";29  case Error::BUFFER_OVERFLOW:30    return "Buffer Overflow";31  case Error::BUFFER_UNDERFLOW:32    return "Buffer Underflow";33  }34  __builtin_trap();35}36 37constexpr size_t AllocationMetadata::kStackFrameStorageBytes;38constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;39 40void AllocationMetadata::RecordAllocation(uintptr_t AllocAddr,41                                          size_t AllocSize) {42  Addr = AllocAddr;43  RequestedSize = AllocSize;44  IsDeallocated = false;45 46  AllocationTrace.ThreadID = getThreadID();47  DeallocationTrace.TraceSize = 0;48  DeallocationTrace.ThreadID = kInvalidThreadID;49}50 51void AllocationMetadata::RecordDeallocation() {52  IsDeallocated = true;53  DeallocationTrace.ThreadID = getThreadID();54}55 56void AllocationMetadata::CallSiteInfo::RecordBacktrace(57    options::Backtrace_t Backtrace) {58  TraceSize = 0;59  if (!Backtrace)60    return;61 62  uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];63  size_t BacktraceLength =64      Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);65  // Backtrace() returns the number of available frames, which may be greater66  // than the number of frames in the buffer. In this case, we need to only pack67  // the number of frames that are in the buffer.68  if (BacktraceLength > kMaxTraceLengthToCollect)69    BacktraceLength = kMaxTraceLengthToCollect;70  TraceSize =71      compression::pack(UncompressedBuffer, BacktraceLength, CompressedTrace,72                        AllocationMetadata::kStackFrameStorageBytes);73}74 75size_t AllocatorState::maximumAllocationSize() const { return PageSize; }76 77uintptr_t AllocatorState::slotToAddr(size_t N) const {78  return GuardedPagePool + (PageSize * (1 + N)) + (maximumAllocationSize() * N);79}80 81bool AllocatorState::isGuardPage(uintptr_t Ptr) const {82  assert(pointerIsMine(reinterpret_cast<void *>(Ptr)));83  size_t PageOffsetFromPoolStart = (Ptr - GuardedPagePool) / PageSize;84  size_t PagesPerSlot = maximumAllocationSize() / PageSize;85  return (PageOffsetFromPoolStart % (PagesPerSlot + 1)) == 0;86}87 88static size_t addrToSlot(const AllocatorState *State, uintptr_t Ptr) {89  size_t ByteOffsetFromPoolStart = Ptr - State->GuardedPagePool;90  return ByteOffsetFromPoolStart /91         (State->maximumAllocationSize() + State->PageSize);92}93 94size_t AllocatorState::getNearestSlot(uintptr_t Ptr) const {95  if (Ptr <= GuardedPagePool + PageSize)96    return 0;97  if (Ptr > GuardedPagePoolEnd - PageSize)98    return MaxSimultaneousAllocations - 1;99 100  if (!isGuardPage(Ptr))101    return addrToSlot(this, Ptr);102 103  if (Ptr % PageSize <= PageSize / 2)104    return addrToSlot(this, Ptr - PageSize); // Round down.105  return addrToSlot(this, Ptr + PageSize);   // Round up.106}107 108uintptr_t AllocatorState::internallyDetectedErrorFaultAddress() const {109  return GuardedPagePoolEnd - 0x10;110}111 112} // namespace gwp_asan113