diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-07-31 15:50:41 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:35:23 +0000 |
commit | 7b2ffa587235a47d4094787d72f38102089f402a (patch) | |
tree | 30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/base/profiler/stack_sampler_impl.cc | |
parent | d94af01c90575348c4e81a418257f254b6f8d225 (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.cc | 160 |
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 |