summaryrefslogtreecommitdiffstats
path: root/chromium/base/profiler/stack_sampler_impl.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/base/profiler/stack_sampler_impl.cc
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/base/profiler/stack_sampler_impl.cc')
-rw-r--r--chromium/base/profiler/stack_sampler_impl.cc160
1 files changed, 97 insertions, 63 deletions
diff --git a/chromium/base/profiler/stack_sampler_impl.cc b/chromium/base/profiler/stack_sampler_impl.cc
index 0b808fba179..2c70cc85522 100644
--- a/chromium/base/profiler/stack_sampler_impl.cc
+++ b/chromium/base/profiler/stack_sampler_impl.cc
@@ -20,59 +20,6 @@
namespace base {
-namespace {
-
-// If the value at |pointer| points to the original stack, rewrite it to point
-// to the corresponding location in the copied stack. NO HEAP ALLOCATIONS.
-// static
-uintptr_t RewritePointerIfInOriginalStack(
- const uintptr_t* original_stack_bottom,
- const uintptr_t* original_stack_top,
- const uintptr_t* stack_copy_bottom,
- uintptr_t pointer) {
- auto original_stack_bottom_uint =
- reinterpret_cast<uintptr_t>(original_stack_bottom);
- auto original_stack_top_uint =
- reinterpret_cast<uintptr_t>(original_stack_top);
- auto stack_copy_bottom_uint = reinterpret_cast<uintptr_t>(stack_copy_bottom);
-
- if (pointer < original_stack_bottom_uint ||
- pointer >= original_stack_top_uint)
- return pointer;
-
- return stack_copy_bottom_uint + (pointer - original_stack_bottom_uint);
-}
-
-// Copies the stack to a buffer while rewriting possible pointers to locations
-// within the stack to point to the corresponding locations in the copy. This is
-// necessary to handle stack frames with dynamic stack allocation, where a
-// pointer to the beginning of the dynamic allocation area is stored on the
-// stack and/or in a non-volatile register.
-//
-// Eager rewriting of anything that looks like a pointer to the stack, as done
-// in this function, does not adversely affect the stack unwinding. The only
-// other values on the stack the unwinding depends on are return addresses,
-// which should not point within the stack memory. The rewriting is guaranteed
-// to catch all pointers because the stacks are guaranteed by the ABI to be
-// sizeof(uintptr_t*) aligned.
-//
-// NO HEAP ALLOCATIONS.
-//
-// static
-NO_SANITIZE("address")
-void CopyStackContentsAndRewritePointers(const uintptr_t* original_stack_bottom,
- const uintptr_t* original_stack_top,
- uintptr_t* stack_copy_bottom) {
- const uintptr_t* src = original_stack_bottom;
- uintptr_t* dst = stack_copy_bottom;
- for (; src < original_stack_top; ++src, ++dst) {
- *dst = RewritePointerIfInOriginalStack(
- original_stack_bottom, original_stack_top, stack_copy_bottom, *src);
- }
-}
-
-} // namespace
-
StackSamplerImpl::StackSamplerImpl(
std::unique_ptr<ThreadDelegate> thread_delegate,
std::unique_ptr<Unwinder> native_unwinder,
@@ -85,8 +32,8 @@ StackSamplerImpl::StackSamplerImpl(
StackSamplerImpl::~StackSamplerImpl() = default;
-void StackSamplerImpl::AddAuxUnwinder(Unwinder* unwinder) {
- aux_unwinder_ = unwinder;
+void StackSamplerImpl::AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder) {
+ aux_unwinder_ = std::move(unwinder);
aux_unwinder_->AddNonNativeModules(module_cache_);
}
@@ -106,7 +53,7 @@ void StackSamplerImpl::RecordStackFrames(StackBuffer* stack_buffer,
profile_builder->OnSampleCompleted(
WalkStack(module_cache_, &thread_context, stack_top,
- native_unwinder_.get(), aux_unwinder_));
+ native_unwinder_.get(), aux_unwinder_.get()));
}
// static
@@ -130,6 +77,7 @@ bool StackSamplerImpl::CopyStack(StackBuffer* stack_buffer,
RegisterContext* thread_context) {
const uintptr_t top = thread_delegate_->GetStackBaseAddress();
uintptr_t bottom = 0;
+ const uint8_t* stack_copy_bottom = nullptr;
{
// Allocation of the ScopedSuspendThread object itself is OK since it
// necessarily occurs before the thread is suspended by the object.
@@ -156,19 +104,18 @@ bool StackSamplerImpl::CopyStack(StackBuffer* stack_buffer,
profile_builder->RecordMetadata();
- CopyStackContentsAndRewritePointers(reinterpret_cast<uintptr_t*>(bottom),
- reinterpret_cast<uintptr_t*>(top),
- stack_buffer->buffer());
+ stack_copy_bottom = CopyStackContentsAndRewritePointers(
+ reinterpret_cast<uint8_t*>(bottom), reinterpret_cast<uintptr_t*>(top),
+ stack_buffer->buffer());
}
- *stack_top =
- reinterpret_cast<uintptr_t>(stack_buffer->buffer()) + (top - bottom);
+ *stack_top = reinterpret_cast<uintptr_t>(stack_copy_bottom) + (top - bottom);
for (uintptr_t* reg :
thread_delegate_->GetRegistersToRewrite(thread_context)) {
- *reg = RewritePointerIfInOriginalStack(reinterpret_cast<uintptr_t*>(bottom),
+ *reg = RewritePointerIfInOriginalStack(reinterpret_cast<uint8_t*>(bottom),
reinterpret_cast<uintptr_t*>(top),
- stack_buffer->buffer(), *reg);
+ stack_copy_bottom, *reg);
}
return true;
@@ -218,4 +165,91 @@ std::vector<Frame> StackSamplerImpl::WalkStack(ModuleCache* module_cache,
return stack;
}
+// If the value at |pointer| points to the original stack, rewrite it to point
+// to the corresponding location in the copied stack. NO HEAP ALLOCATIONS.
+// static
+uintptr_t RewritePointerIfInOriginalStack(const uint8_t* original_stack_bottom,
+ const uintptr_t* original_stack_top,
+ const uint8_t* stack_copy_bottom,
+ uintptr_t pointer) {
+ auto original_stack_bottom_uint =
+ reinterpret_cast<uintptr_t>(original_stack_bottom);
+ auto original_stack_top_uint =
+ reinterpret_cast<uintptr_t>(original_stack_top);
+ auto stack_copy_bottom_uint = reinterpret_cast<uintptr_t>(stack_copy_bottom);
+
+ if (pointer < original_stack_bottom_uint ||
+ pointer >= original_stack_top_uint)
+ return pointer;
+
+ return stack_copy_bottom_uint + (pointer - original_stack_bottom_uint);
+}
+
+// Copies the stack to a buffer while rewriting possible pointers to locations
+// within the stack to point to the corresponding locations in the copy. This is
+// necessary to handle stack frames with dynamic stack allocation, where a
+// pointer to the beginning of the dynamic allocation area is stored on the
+// stack and/or in a non-volatile register.
+//
+// Eager rewriting of anything that looks like a pointer to the stack, as done
+// in this function, does not adversely affect the stack unwinding. The only
+// other values on the stack the unwinding depends on are return addresses,
+// which should not point within the stack memory. The rewriting is guaranteed
+// to catch all pointers because the stacks are guaranteed by the ABI to be
+// sizeof(uintptr_t*) aligned.
+//
+// |original_stack_bottom| and |original_stack_top| are different pointer types
+// due on their differing guaranteed alignments -- the bottom may only be 1-byte
+// aligned while the top is aligned to double the pointer width.
+//
+// Returns a pointer to the bottom address in the copied stack. This value
+// matches the alignment of |original_stack_bottom| to ensure that the stack
+// contents have the same alignment as in the original stack. As a result the
+// value will be different than |stack_buffer_bottom| if |original_stack_bottom|
+// is not aligned to double the pointer width.
+//
+// NO HEAP ALLOCATIONS.
+//
+// static
+NO_SANITIZE("address")
+const uint8_t* CopyStackContentsAndRewritePointers(
+ const uint8_t* original_stack_bottom,
+ const uintptr_t* original_stack_top,
+ uintptr_t* stack_buffer_bottom) {
+ const uint8_t* byte_src = original_stack_bottom;
+ // The first address in the stack with pointer alignment. Pointer-aligned
+ // values from this point to the end of the stack are possibly rewritten using
+ // RewritePointerIfInOriginalStack(). Bytes before this cannot be a pointer
+ // because they occupy less space than a pointer would.
+ const uint8_t* first_aligned_address = reinterpret_cast<uint8_t*>(
+ (reinterpret_cast<uintptr_t>(byte_src) + sizeof(uintptr_t) - 1) &
+ ~(sizeof(uintptr_t) - 1));
+
+ // The stack copy bottom, which is offset from |stack_buffer_bottom| by the
+ // same alignment as in the original stack. This guarantees identical
+ // alignment between values in the original stack and the copy. This uses the
+ // platform stack alignment rather than pointer alignment so that the stack
+ // copy is aligned to platform expectations.
+ uint8_t* stack_copy_bottom =
+ reinterpret_cast<uint8_t*>(stack_buffer_bottom) +
+ (reinterpret_cast<uintptr_t>(byte_src) &
+ (StackSampler::StackBuffer::kPlatformStackAlignment - 1));
+ uint8_t* byte_dst = stack_copy_bottom;
+
+ // Copy bytes verbatim up to the first aligned address.
+ for (; byte_src < first_aligned_address; ++byte_src, ++byte_dst)
+ *byte_dst = *byte_src;
+
+ // Copy the remaining stack by pointer-sized values, rewriting anything that
+ // looks like a pointer into the stack.
+ const uintptr_t* src = reinterpret_cast<const uintptr_t*>(byte_src);
+ uintptr_t* dst = reinterpret_cast<uintptr_t*>(byte_dst);
+ for (; src < original_stack_top; ++src, ++dst) {
+ *dst = RewritePointerIfInOriginalStack(
+ original_stack_bottom, original_stack_top, stack_copy_bottom, *src);
+ }
+
+ return stack_copy_bottom;
+}
+
} // namespace base