Commit a31d7d44 authored by Mike Wittman's avatar Mike Wittman Committed by Commit Bot

Implement ThreadDelegateAndroid and supply to StackCopierSignal

Implements the ThreadDelegate abstraction for Android, providing the
stack base address and registers that may require rewriting to update
them from pointing to the original stack to the copied stack.

Removes code from the TracingSamplerProfiler that was attempting
to use the StackSamplingProfiler with the built-in Android
StackSampler. This had no effect previously and crashes with the
current skeleton implementation. Tracing will be able to use the
built-in sampler when it's in a more mature state.

Bug: 988579
Change-Id: I4c44bbec33f2e1457c03de37d8c852a85eb9d65b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1764288Reviewed-by: default avatarCharlie Andrews <charliea@chromium.org>
Reviewed-by: default avatarssid <ssid@chromium.org>
Commit-Queue: Mike Wittman <wittman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#694911}
parent 2a13e691
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <windows.h> #include <windows.h>
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
#include <mach/machine/thread_status.h> #include <mach/machine/thread_status.h>
#elif defined(OS_ANDROID) && !defined(ARCH_CPU_64_BITS)
#include <sys/ucontext.h>
#endif #endif
namespace base { namespace base {
...@@ -83,6 +85,23 @@ inline uintptr_t& RegisterContextInstructionPointer( ...@@ -83,6 +85,23 @@ inline uintptr_t& RegisterContextInstructionPointer(
return AsUintPtr(&context->__rip); return AsUintPtr(&context->__rip);
} }
#elif defined(OS_ANDROID) && defined(ARCH_CPU_ARM_FAMILY) && \
defined(ARCH_CPU_32_BITS) // #if defined(OS_WIN)
using RegisterContext = mcontext_t;
inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
return AsUintPtr(&context->arm_sp);
}
inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
return AsUintPtr(&context->arm_fp);
}
inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
return AsUintPtr(&context->arm_ip);
}
#else // #if defined(OS_WIN) #else // #if defined(OS_WIN)
// Placeholders for other platforms. // Placeholders for other platforms.
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
namespace base { namespace base {
StackCopierSignal::StackCopierSignal() = default; StackCopierSignal::StackCopierSignal(
std::unique_ptr<ThreadDelegate> thread_delegate)
: thread_delegate_(std::move(thread_delegate)) {}
StackCopierSignal::~StackCopierSignal() = default; StackCopierSignal::~StackCopierSignal() = default;
......
...@@ -5,16 +5,20 @@ ...@@ -5,16 +5,20 @@
#ifndef BASE_PROFILER_STACK_COPIER_SIGNAL_H_ #ifndef BASE_PROFILER_STACK_COPIER_SIGNAL_H_
#define BASE_PROFILER_STACK_COPIER_SIGNAL_H_ #define BASE_PROFILER_STACK_COPIER_SIGNAL_H_
#include <memory>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/profiler/stack_copier.h" #include "base/profiler/stack_copier.h"
namespace base { namespace base {
class ThreadDelegate;
// Supports stack copying on platforms where a signal must be delivered to the // Supports stack copying on platforms where a signal must be delivered to the
// profiled thread and the stack is copied from the signal handler. // profiled thread and the stack is copied from the signal handler.
class BASE_EXPORT StackCopierSignal : public StackCopier { class BASE_EXPORT StackCopierSignal : public StackCopier {
public: public:
StackCopierSignal(); StackCopierSignal(std::unique_ptr<ThreadDelegate> thread_delegate);
~StackCopierSignal() override; ~StackCopierSignal() override;
// StackCopier: // StackCopier:
...@@ -22,6 +26,9 @@ class BASE_EXPORT StackCopierSignal : public StackCopier { ...@@ -22,6 +26,9 @@ class BASE_EXPORT StackCopierSignal : public StackCopier {
uintptr_t* stack_top, uintptr_t* stack_top,
ProfileBuilder* profile_builder, ProfileBuilder* profile_builder,
RegisterContext* thread_context) override; RegisterContext* thread_context) override;
private:
std::unique_ptr<ThreadDelegate> thread_delegate_;
}; };
} // namespace base } // namespace base
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/profiler/native_unwinder_android.h" #include "base/profiler/native_unwinder_android.h"
#include "base/profiler/stack_copier_signal.h" #include "base/profiler/stack_copier_signal.h"
#include "base/profiler/stack_sampler_impl.h" #include "base/profiler/stack_sampler_impl.h"
#include "base/profiler/thread_delegate_android.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
namespace base { namespace base {
...@@ -18,7 +19,8 @@ std::unique_ptr<StackSampler> StackSampler::Create( ...@@ -18,7 +19,8 @@ std::unique_ptr<StackSampler> StackSampler::Create(
ModuleCache* module_cache, ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
return std::make_unique<StackSamplerImpl>( return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSignal>(), std::make_unique<StackCopierSignal>(
std::make_unique<ThreadDelegateAndroid>(thread_id)),
std::make_unique<NativeUnwinderAndroid>(), module_cache, test_delegate); std::make_unique<NativeUnwinderAndroid>(), module_cache, test_delegate);
} }
......
...@@ -2,8 +2,12 @@ ...@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <pthread.h>
#include "base/profiler/thread_delegate_android.h" #include "base/profiler/thread_delegate_android.h"
#include "build/build_config.h"
// IMPORTANT NOTE: Some functions within this implementation are invoked while // IMPORTANT NOTE: Some functions within this implementation are invoked while
// the target thread is suspended so it must not do any allocation from the // the target thread is suspended so it must not do any allocation from the
// heap, including indirectly via use of DCHECK/CHECK or other logging // heap, including indirectly via use of DCHECK/CHECK or other logging
...@@ -13,15 +17,50 @@ ...@@ -13,15 +17,50 @@
namespace base { namespace base {
namespace {
uintptr_t GetThreadStackBaseAddress(PlatformThreadId thread_id) {
pthread_attr_t attr;
pthread_getattr_np(thread_id, &attr);
void* base_address;
size_t size;
pthread_attr_getstack(&attr, &base_address, &size);
return reinterpret_cast<uintptr_t>(base_address);
}
} // namespace
ThreadDelegateAndroid::ThreadDelegateAndroid(PlatformThreadId thread_id)
: thread_stack_base_address_(GetThreadStackBaseAddress(thread_id)) {}
uintptr_t ThreadDelegateAndroid::GetStackBaseAddress() const { uintptr_t ThreadDelegateAndroid::GetStackBaseAddress() const {
// It's okay for the stub to return zero here: GetStackBaseAddress() if return thread_stack_base_address_;
// ScopedSuspendThread fails, which it always will in the stub.
return 0;
} }
std::vector<uintptr_t*> ThreadDelegateAndroid::GetRegistersToRewrite( std::vector<uintptr_t*> ThreadDelegateAndroid::GetRegistersToRewrite(
RegisterContext* thread_context) { RegisterContext* thread_context) {
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
return {
reinterpret_cast<uintptr_t*>(&thread_context->arm_r0),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r1),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r2),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r3),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r4),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r5),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r6),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r7),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r8),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r9),
reinterpret_cast<uintptr_t*>(&thread_context->arm_r10),
reinterpret_cast<uintptr_t*>(&thread_context->arm_fp),
reinterpret_cast<uintptr_t*>(&thread_context->arm_ip),
reinterpret_cast<uintptr_t*>(&thread_context->arm_sp),
// arm_lr and arm_pc do not require rewriting because they contain
// addresses of executable code, not addresses in the stack.
};
#else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
return {}; return {};
#endif
} }
} // namespace base } // namespace base
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/profiler/thread_delegate.h" #include "base/profiler/thread_delegate.h"
#include "base/threading/platform_thread.h"
namespace base { namespace base {
...@@ -16,7 +17,7 @@ namespace base { ...@@ -16,7 +17,7 @@ namespace base {
// TODO(https://crbug.com/988579): Implement this class. // TODO(https://crbug.com/988579): Implement this class.
class BASE_EXPORT ThreadDelegateAndroid : public ThreadDelegate { class BASE_EXPORT ThreadDelegateAndroid : public ThreadDelegate {
public: public:
ThreadDelegateAndroid() = default; ThreadDelegateAndroid(PlatformThreadId thread_id);
ThreadDelegateAndroid(const ThreadDelegateAndroid&) = delete; ThreadDelegateAndroid(const ThreadDelegateAndroid&) = delete;
ThreadDelegateAndroid& operator=(const ThreadDelegateAndroid&) = delete; ThreadDelegateAndroid& operator=(const ThreadDelegateAndroid&) = delete;
...@@ -25,6 +26,9 @@ class BASE_EXPORT ThreadDelegateAndroid : public ThreadDelegate { ...@@ -25,6 +26,9 @@ class BASE_EXPORT ThreadDelegateAndroid : public ThreadDelegate {
uintptr_t GetStackBaseAddress() const override; uintptr_t GetStackBaseAddress() const override;
std::vector<uintptr_t*> GetRegistersToRewrite( std::vector<uintptr_t*> GetRegistersToRewrite(
RegisterContext* thread_context) override; RegisterContext* thread_context) override;
private:
const uintptr_t thread_stack_base_address_;
}; };
} // namespace base } // namespace base
......
...@@ -547,19 +547,19 @@ void TracingSamplerProfiler::StartTracing( ...@@ -547,19 +547,19 @@ void TracingSamplerProfiler::StartTracing(
sampled_thread_id_, std::move(trace_writer), should_enable_filtering); sampled_thread_id_, std::move(trace_writer), should_enable_filtering);
profile_builder_ = profile_builder.get(); profile_builder_ = profile_builder.get();
// Create and start the stack sampling profiler. // Create and start the stack sampling profiler.
#if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \ #if defined(OS_ANDROID)
defined(OFFICIAL_BUILD) #if BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
auto* module_cache = profile_builder->GetModuleCache(); auto* module_cache = profile_builder->GetModuleCache();
profiler_ = std::make_unique<base::StackSamplingProfiler>( profiler_ = std::make_unique<base::StackSamplingProfiler>(
sampled_thread_id_, params, std::move(profile_builder), sampled_thread_id_, params, std::move(profile_builder),
std::make_unique<StackSamplerAndroid>(sampled_thread_id_, module_cache)); std::make_unique<StackSamplerAndroid>(sampled_thread_id_, module_cache));
profiler_->Start();
#else #endif // BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
#else // defined(OS_ANDROID)
profiler_ = std::make_unique<base::StackSamplingProfiler>( profiler_ = std::make_unique<base::StackSamplingProfiler>(
sampled_thread_id_, params, std::move(profile_builder)); sampled_thread_id_, params, std::move(profile_builder));
#endif
profiler_->Start(); profiler_->Start();
#endif // defined(OS_ANDROID)
} }
void TracingSamplerProfiler::StopTracing() { void TracingSamplerProfiler::StopTracing() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment