Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/gwp_asan/common.cpp
35236 views
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "gwp_asan/common.h"
10
#include "gwp_asan/stack_trace_compressor.h"
11
12
#include <assert.h>
13
14
using AllocationMetadata = gwp_asan::AllocationMetadata;
15
using Error = gwp_asan::Error;
16
17
namespace gwp_asan {
18
19
const 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
37
constexpr size_t AllocationMetadata::kStackFrameStorageBytes;
38
constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;
39
40
void 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
51
void AllocationMetadata::RecordDeallocation() {
52
IsDeallocated = true;
53
DeallocationTrace.ThreadID = getThreadID();
54
}
55
56
void 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 greater
66
// than the number of frames in the buffer. In this case, we need to only pack
67
// 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
75
size_t AllocatorState::maximumAllocationSize() const { return PageSize; }
76
77
uintptr_t AllocatorState::slotToAddr(size_t N) const {
78
return GuardedPagePool + (PageSize * (1 + N)) + (maximumAllocationSize() * N);
79
}
80
81
bool 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
88
static 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
94
size_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
108
uintptr_t AllocatorState::internallyDetectedErrorFaultAddress() const {
109
return GuardedPagePoolEnd - 0x10;
110
}
111
112
} // namespace gwp_asan
113
114