xref: /aosp_15_r20/external/cronet/base/allocator/partition_allocator/src/partition_alloc/stack/stack.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PARTITION_ALLOC_STACK_STACK_H_
6 #define PARTITION_ALLOC_STACK_STACK_H_
7 
8 #include <cstdint>
9 #include <functional>
10 #include <mutex>
11 #include <unordered_map>
12 #include <utility>
13 
14 #include "partition_alloc/internal_allocator.h"
15 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
16 #include "partition_alloc/partition_alloc_base/component_export.h"
17 #include "partition_alloc/partition_alloc_base/thread_annotations.h"
18 #include "partition_alloc/partition_alloc_base/threading/platform_thread.h"
19 #include "partition_alloc/partition_lock.h"
20 
21 namespace partition_alloc::internal {
22 
23 // Returns the current stack pointer.
24 // TODO(bikineev,1202644): Remove this once base/stack_util.h lands.
25 PA_NOINLINE PA_COMPONENT_EXPORT(PARTITION_ALLOC) uintptr_t* GetStackPointer();
26 // Returns the top of the stack using system API.
27 PA_COMPONENT_EXPORT(PARTITION_ALLOC) void* GetStackTop();
28 
29 // Interface for stack visitation.
30 class StackVisitor {
31  public:
32   virtual void VisitStack(uintptr_t* stack_ptr, uintptr_t* stack_top) = 0;
33 };
34 
35 // Abstraction over the stack. Supports handling of:
36 // - native stack;
37 // - SafeStack:
38 // https://releases.llvm.org/10.0.0/tools/clang/docs/SafeStack.html
PA_COMPONENT_EXPORT(PARTITION_ALLOC)39 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) Stack final {
40  public:
41   // Sets start of the stack.
42   explicit Stack(void* stack_top);
43 
44   // Word-aligned iteration of the stack. Flushes callee saved registers and
45   // passes the range of the stack on to |visitor|.
46   void IteratePointers(StackVisitor* visitor) const;
47 
48   // Returns the top of the stack.
49   void* stack_top() const { return stack_top_; }
50 
51  private:
52   void* stack_top_;
53 };
54 
55 // A class to keep stack top pointers through thread creation/destruction.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)56 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) StackTopRegistry {
57  public:
58   static StackTopRegistry& Get();
59   void NotifyThreadCreated(void* stack_top = GetStackPointer());
60   void NotifyThreadDestroyed();
61   void* GetCurrentThreadStackTop() const;
62 
63  private:
64   using StackTops =
65       std::unordered_map<base::PlatformThreadId,
66                          void*,
67                          std::hash<base::PlatformThreadId>,
68                          std::equal_to<>,
69                          internal::InternalAllocator<
70                              std::pair<const base::PlatformThreadId, void*>>>;
71 
72   friend class base::NoDestructor<StackTopRegistry>;
73 
74   StackTopRegistry();
75   ~StackTopRegistry();
76 
77   // TLS emulation of stack tops. Since this is guaranteed to go through
78   // non-quarantinable partition, using it from safepoints is safe.
79   mutable Lock lock_;
80   StackTops stack_tops_ PA_GUARDED_BY(lock_);
81 };
82 
83 }  // namespace partition_alloc::internal
84 
85 #endif  // PARTITION_ALLOC_STACK_STACK_H_
86