[go: nahoru, domu]

blob: 7d04c614697f367ba2ed92366c63b0e2ea487909 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2019 The Chromium Authors
Mike Wittman30bff492019-08-29 21:49:332// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/profiler/stack_copier.h"
6
Lei Zhang3901b61b2020-06-30 20:03:097#include "base/bits.h"
Mike Wittman30bff492019-08-29 21:49:338#include "base/compiler_specific.h"
9
10namespace base {
11
12StackCopier::~StackCopier() = default;
13
14// static
15uintptr_t StackCopier::RewritePointerIfInOriginalStack(
16 const uint8_t* original_stack_bottom,
17 const uintptr_t* original_stack_top,
18 const uint8_t* stack_copy_bottom,
19 uintptr_t pointer) {
20 auto original_stack_bottom_uint =
21 reinterpret_cast<uintptr_t>(original_stack_bottom);
22 auto original_stack_top_uint =
23 reinterpret_cast<uintptr_t>(original_stack_top);
24 auto stack_copy_bottom_uint = reinterpret_cast<uintptr_t>(stack_copy_bottom);
25
26 if (pointer < original_stack_bottom_uint ||
27 pointer >= original_stack_top_uint)
28 return pointer;
29
30 return stack_copy_bottom_uint + (pointer - original_stack_bottom_uint);
31}
32
33// static
34NO_SANITIZE("address")
35const uint8_t* StackCopier::CopyStackContentsAndRewritePointers(
36 const uint8_t* original_stack_bottom,
37 const uintptr_t* original_stack_top,
Peter Kastingef48a6f2022-06-16 19:25:3938 size_t platform_stack_alignment,
Mike Wittman30bff492019-08-29 21:49:3339 uintptr_t* stack_buffer_bottom) {
40 const uint8_t* byte_src = original_stack_bottom;
41 // The first address in the stack with pointer alignment. Pointer-aligned
42 // values from this point to the end of the stack are possibly rewritten using
43 // RewritePointerIfInOriginalStack(). Bytes before this cannot be a pointer
44 // because they occupy less space than a pointer would.
Mike Wittman668debf82020-07-28 03:10:3045 const uint8_t* first_aligned_address =
Benoit Lize7b302c42021-02-04 11:20:3846 bits::AlignUp(byte_src, sizeof(uintptr_t));
Mike Wittman30bff492019-08-29 21:49:3347
48 // The stack copy bottom, which is offset from |stack_buffer_bottom| by the
49 // same alignment as in the original stack. This guarantees identical
50 // alignment between values in the original stack and the copy. This uses the
51 // platform stack alignment rather than pointer alignment so that the stack
52 // copy is aligned to platform expectations.
53 uint8_t* stack_copy_bottom =
54 reinterpret_cast<uint8_t*>(stack_buffer_bottom) +
Mike Wittman668debf82020-07-28 03:10:3055 (byte_src - bits::AlignDown(byte_src, platform_stack_alignment));
Mike Wittman30bff492019-08-29 21:49:3356 uint8_t* byte_dst = stack_copy_bottom;
57
58 // Copy bytes verbatim up to the first aligned address.
59 for (; byte_src < first_aligned_address; ++byte_src, ++byte_dst)
60 *byte_dst = *byte_src;
61
62 // Copy the remaining stack by pointer-sized values, rewriting anything that
63 // looks like a pointer into the stack.
64 const uintptr_t* src = reinterpret_cast<const uintptr_t*>(byte_src);
65 uintptr_t* dst = reinterpret_cast<uintptr_t*>(byte_dst);
66 for (; src < original_stack_top; ++src, ++dst) {
67 *dst = RewritePointerIfInOriginalStack(
68 original_stack_bottom, original_stack_top, stack_copy_bottom, *src);
69 }
70
71 return stack_copy_bottom;
72}
73
74} // namespace base