1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_copier.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/bits.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker namespace base {
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker StackCopier::~StackCopier() = default;
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker // static
RewritePointerIfInOriginalStack(const uint8_t * original_stack_bottom,const uintptr_t * original_stack_top,const uint8_t * stack_copy_bottom,uintptr_t pointer)15*6777b538SAndroid Build Coastguard Worker uintptr_t StackCopier::RewritePointerIfInOriginalStack(
16*6777b538SAndroid Build Coastguard Worker const uint8_t* original_stack_bottom,
17*6777b538SAndroid Build Coastguard Worker const uintptr_t* original_stack_top,
18*6777b538SAndroid Build Coastguard Worker const uint8_t* stack_copy_bottom,
19*6777b538SAndroid Build Coastguard Worker uintptr_t pointer) {
20*6777b538SAndroid Build Coastguard Worker auto original_stack_bottom_uint =
21*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(original_stack_bottom);
22*6777b538SAndroid Build Coastguard Worker auto original_stack_top_uint =
23*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(original_stack_top);
24*6777b538SAndroid Build Coastguard Worker auto stack_copy_bottom_uint = reinterpret_cast<uintptr_t>(stack_copy_bottom);
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker if (pointer < original_stack_bottom_uint ||
27*6777b538SAndroid Build Coastguard Worker pointer >= original_stack_top_uint)
28*6777b538SAndroid Build Coastguard Worker return pointer;
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker return stack_copy_bottom_uint + (pointer - original_stack_bottom_uint);
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker // static
34*6777b538SAndroid Build Coastguard Worker NO_SANITIZE("address")
CopyStackContentsAndRewritePointers(const uint8_t * original_stack_bottom,const uintptr_t * original_stack_top,size_t platform_stack_alignment,uintptr_t * stack_buffer_bottom)35*6777b538SAndroid Build Coastguard Worker const uint8_t* StackCopier::CopyStackContentsAndRewritePointers(
36*6777b538SAndroid Build Coastguard Worker const uint8_t* original_stack_bottom,
37*6777b538SAndroid Build Coastguard Worker const uintptr_t* original_stack_top,
38*6777b538SAndroid Build Coastguard Worker size_t platform_stack_alignment,
39*6777b538SAndroid Build Coastguard Worker uintptr_t* stack_buffer_bottom) {
40*6777b538SAndroid Build Coastguard Worker const uint8_t* byte_src = original_stack_bottom;
41*6777b538SAndroid Build Coastguard Worker // The first address in the stack with pointer alignment. Pointer-aligned
42*6777b538SAndroid Build Coastguard Worker // values from this point to the end of the stack are possibly rewritten using
43*6777b538SAndroid Build Coastguard Worker // RewritePointerIfInOriginalStack(). Bytes before this cannot be a pointer
44*6777b538SAndroid Build Coastguard Worker // because they occupy less space than a pointer would.
45*6777b538SAndroid Build Coastguard Worker const uint8_t* first_aligned_address =
46*6777b538SAndroid Build Coastguard Worker bits::AlignUp(byte_src, sizeof(uintptr_t));
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker // The stack copy bottom, which is offset from |stack_buffer_bottom| by the
49*6777b538SAndroid Build Coastguard Worker // same alignment as in the original stack. This guarantees identical
50*6777b538SAndroid Build Coastguard Worker // alignment between values in the original stack and the copy. This uses the
51*6777b538SAndroid Build Coastguard Worker // platform stack alignment rather than pointer alignment so that the stack
52*6777b538SAndroid Build Coastguard Worker // copy is aligned to platform expectations.
53*6777b538SAndroid Build Coastguard Worker uint8_t* stack_copy_bottom =
54*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(stack_buffer_bottom) +
55*6777b538SAndroid Build Coastguard Worker (byte_src - bits::AlignDown(byte_src, platform_stack_alignment));
56*6777b538SAndroid Build Coastguard Worker uint8_t* byte_dst = stack_copy_bottom;
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker // Copy bytes verbatim up to the first aligned address.
59*6777b538SAndroid Build Coastguard Worker for (; byte_src < first_aligned_address; ++byte_src, ++byte_dst)
60*6777b538SAndroid Build Coastguard Worker *byte_dst = *byte_src;
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker // Copy the remaining stack by pointer-sized values, rewriting anything that
63*6777b538SAndroid Build Coastguard Worker // looks like a pointer into the stack.
64*6777b538SAndroid Build Coastguard Worker const uintptr_t* src = reinterpret_cast<const uintptr_t*>(byte_src);
65*6777b538SAndroid Build Coastguard Worker uintptr_t* dst = reinterpret_cast<uintptr_t*>(byte_dst);
66*6777b538SAndroid Build Coastguard Worker for (; src < original_stack_top; ++src, ++dst) {
67*6777b538SAndroid Build Coastguard Worker *dst = RewritePointerIfInOriginalStack(
68*6777b538SAndroid Build Coastguard Worker original_stack_bottom, original_stack_top, stack_copy_bottom, *src);
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker return stack_copy_bottom;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker } // namespace base
75