1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
base / allocator / partition_allocator / src / partition_alloc / pointers / instance_tracer.h [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_POINTERS_INSTANCE_TRACER_H_
#define PARTITION_ALLOC_POINTERS_INSTANCE_TRACER_H_
#include <array>
#include <atomic>
#include <cstdint>
#include <utility>
#include <vector>
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h"
namespace base::internal {
#if !PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER)
// When the buildflag is disabled, use a minimal no-state implementation so
// sizeof(raw_ptr<T>) == sizeof(T*).
class InstanceTracer {
public:
constexpr uint64_t owner_id() const { return 0; }
constexpr static void Trace([[maybe_unused]] uint64_t owner_id,
[[maybe_unused]] uintptr_t address) {}
constexpr static void Untrace([[maybe_unused]] uint64_t owner_id) {}
};
#else
class PA_TRIVIAL_ABI InstanceTracer {
public:
constexpr InstanceTracer() : owner_id_(CreateOwnerId()) {}
// Copy constructing InstanceTracer should not inherit the owner ID; the new
// InstanceTracer needs a new ID to be separately tracked.
constexpr InstanceTracer(const InstanceTracer&) : InstanceTracer() {}
// Similarly, copy assigning an InstanceTracer should not take the owner ID
// from the right-hand side; it should preserve the owner ID.
constexpr InstanceTracer& operator=(const InstanceTracer&) { return *this; }
constexpr InstanceTracer(InstanceTracer&&) : InstanceTracer() {}
constexpr InstanceTracer& operator=(InstanceTracer&&) { return *this; }
constexpr uint64_t owner_id() const { return owner_id_; }
constexpr static void Trace(uint64_t owner_id,
bool may_dangle,
uintptr_t address) {
if (partition_alloc::internal::base::is_constant_evaluated() ||
owner_id == 0) {
return;
}
TraceImpl(owner_id, may_dangle, address);
}
constexpr static void Untrace(uint64_t owner_id) {
if (partition_alloc::internal::base::is_constant_evaluated() ||
owner_id == 0) {
return;
}
UntraceImpl(owner_id);
}
PA_COMPONENT_EXPORT(RAW_PTR)
static std::vector<std::array<const void*, 32>> GetStackTracesForDanglingRefs(
uintptr_t allocation);
PA_COMPONENT_EXPORT(RAW_PTR)
static std::vector<std::array<const void*, 32>>
GetStackTracesForAddressForTest(const void* address);
private:
PA_COMPONENT_EXPORT(RAW_PTR)
static void TraceImpl(uint64_t owner_id, bool may_dangle, uintptr_t address);
PA_COMPONENT_EXPORT(RAW_PTR) static void UntraceImpl(uint64_t owner_id);
constexpr uint64_t CreateOwnerId() {
if (partition_alloc::internal::base::is_constant_evaluated()) {
return 0;
}
return ++counter_;
}
PA_COMPONENT_EXPORT(RAW_PTR) static std::atomic<uint64_t> counter_;
// 0 is treated as 'ownerless'. It is used as a sentinel for constexpr
// raw_ptrs or other places where owner tracking doesn't make sense.
uint64_t owner_id_ = 0;
};
#endif
} // namespace base::internal
#endif // PARTITION_ALLOC_POINTERS_INSTANCE_TRACER_H_