// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/profiler/thread_delegate_posix.h" #include #include #include #include "base/memory/ptr_util.h" #include "base/process/process_handle.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/types/optional.h" #if !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) #include "base/profiler/stack_base_address_posix.h" #endif namespace base { // static std::unique_ptr ThreadDelegatePosix::Create( SamplingProfilerThreadToken thread_token) { absl::optional base_address; #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) base_address = thread_token.stack_base_address; #else base_address = GetThreadStackBaseAddress(thread_token.id, thread_token.pthread_id); #endif if (!base_address) return nullptr; return base::WrapUnique( new ThreadDelegatePosix(thread_token.id, *base_address)); } ThreadDelegatePosix::~ThreadDelegatePosix() = default; PlatformThreadId ThreadDelegatePosix::GetThreadId() const { return thread_id_; } uintptr_t ThreadDelegatePosix::GetStackBaseAddress() const { return thread_stack_base_address_; } std::vector ThreadDelegatePosix::GetRegistersToRewrite( RegisterContext* thread_context) { #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS) return { reinterpret_cast(&thread_context->arm_r0), reinterpret_cast(&thread_context->arm_r1), reinterpret_cast(&thread_context->arm_r2), reinterpret_cast(&thread_context->arm_r3), reinterpret_cast(&thread_context->arm_r4), reinterpret_cast(&thread_context->arm_r5), reinterpret_cast(&thread_context->arm_r6), reinterpret_cast(&thread_context->arm_r7), reinterpret_cast(&thread_context->arm_r8), reinterpret_cast(&thread_context->arm_r9), reinterpret_cast(&thread_context->arm_r10), reinterpret_cast(&thread_context->arm_fp), reinterpret_cast(&thread_context->arm_ip), reinterpret_cast(&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. }; #elif defined(ARCH_CPU_ARM_FAMILY) && \ defined(ARCH_CPU_64_BITS) // #if defined(ARCH_CPU_ARM_FAMILY) && // defined(ARCH_CPU_32_BITS) std::vector registers; registers.reserve(12); // Return the set of callee-save registers per the ARM 64-bit Procedure Call // Standard section 5.1.1, plus the stack pointer. registers.push_back(reinterpret_cast(&thread_context->sp)); for (size_t i = 19; i <= 29; ++i) registers.push_back(reinterpret_cast(&thread_context->regs[i])); return registers; #elif defined(ARCH_CPU_X86_FAMILY) && defined(ARCH_CPU_32_BITS) return { // Return the set of callee-save registers per the i386 System V ABI // section 2.2.3, plus the stack pointer. reinterpret_cast(&thread_context->gregs[REG_EBX]), reinterpret_cast(&thread_context->gregs[REG_EBP]), reinterpret_cast(&thread_context->gregs[REG_ESI]), reinterpret_cast(&thread_context->gregs[REG_EDI]), reinterpret_cast(&thread_context->gregs[REG_ESP]), }; #elif defined(ARCH_CPU_X86_FAMILY) && defined(ARCH_CPU_64_BITS) return { // Return the set of callee-save registers per the x86-64 System V ABI // section 3.2.1, plus the stack pointer. reinterpret_cast(&thread_context->gregs[REG_RBP]), reinterpret_cast(&thread_context->gregs[REG_RBX]), reinterpret_cast(&thread_context->gregs[REG_R12]), reinterpret_cast(&thread_context->gregs[REG_R13]), reinterpret_cast(&thread_context->gregs[REG_R14]), reinterpret_cast(&thread_context->gregs[REG_R15]), reinterpret_cast(&thread_context->gregs[REG_RSP]), }; #else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS) // Unimplemented for other architectures. return {}; #endif } ThreadDelegatePosix::ThreadDelegatePosix(PlatformThreadId id, uintptr_t base_address) : thread_id_(id), thread_stack_base_address_(base_address) {} } // namespace base