From fae18c2fc4923916cfbf2c552d6782b4b8d9f8a4 Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Thu, 22 Feb 2018 16:48:50 -0800 Subject: [PATCH] fuchsia: Add implementation of ThreadSnapshot This is mostly empty except for the ID, until I concoct a way to get the stack out of Fuchsia, and implement context capture. Bug: crashpad:196 Change-Id: I26d0622d44aefba88750f7ec6feb1a6e95467208 Reviewed-on: https://chromium-review.googlesource.com/932941 Reviewed-by: Mark Mentovai Commit-Queue: Scott Graham --- snapshot/BUILD.gn | 2 + snapshot/fuchsia/process_snapshot_fuchsia.cc | 13 +++ snapshot/fuchsia/process_snapshot_fuchsia.h | 5 + snapshot/fuchsia/thread_snapshot_fuchsia.cc | 96 ++++++++++++++++++++ snapshot/fuchsia/thread_snapshot_fuchsia.h | 81 +++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 snapshot/fuchsia/thread_snapshot_fuchsia.cc create mode 100644 snapshot/fuchsia/thread_snapshot_fuchsia.h diff --git a/snapshot/BUILD.gn b/snapshot/BUILD.gn index 84df23f1..5ccc735e 100644 --- a/snapshot/BUILD.gn +++ b/snapshot/BUILD.gn @@ -179,6 +179,8 @@ static_library("snapshot") { "fuchsia/process_reader_fuchsia.h", "fuchsia/process_snapshot_fuchsia.cc", "fuchsia/process_snapshot_fuchsia.h", + "fuchsia/thread_snapshot_fuchsia.cc", + "fuchsia/thread_snapshot_fuchsia.h", ] } diff --git a/snapshot/fuchsia/process_snapshot_fuchsia.cc b/snapshot/fuchsia/process_snapshot_fuchsia.cc index f3d22907..9d0897d8 100644 --- a/snapshot/fuchsia/process_snapshot_fuchsia.cc +++ b/snapshot/fuchsia/process_snapshot_fuchsia.cc @@ -29,6 +29,7 @@ bool ProcessSnapshotFuchsia::Initialize(zx_handle_t process) { return false; } + InitializeThreads(); InitializeModules(); INITIALIZATION_STATE_SET_VALID(initialized_); @@ -170,6 +171,18 @@ std::vector ProcessSnapshotFuchsia::ExtraMemory() const { return std::vector(); } +void ProcessSnapshotFuchsia::InitializeThreads() { + const std::vector& process_reader_threads = + process_reader_.Threads(); + for (const ProcessReaderFuchsia::Thread& process_reader_thread : + process_reader_threads) { + auto thread = std::make_unique(); + if (thread->Initialize(&process_reader_, process_reader_thread)) { + threads_.push_back(std::move(thread)); + } + } +} + void ProcessSnapshotFuchsia::InitializeModules() { for (const ProcessReaderFuchsia::Module& reader_module : process_reader_.Modules()) { diff --git a/snapshot/fuchsia/process_snapshot_fuchsia.h b/snapshot/fuchsia/process_snapshot_fuchsia.h index d94dec7b..eb077330 100644 --- a/snapshot/fuchsia/process_snapshot_fuchsia.h +++ b/snapshot/fuchsia/process_snapshot_fuchsia.h @@ -25,6 +25,7 @@ #include "snapshot/elf/elf_image_reader.h" #include "snapshot/elf/module_snapshot_elf.h" #include "snapshot/fuchsia/process_reader_fuchsia.h" +#include "snapshot/fuchsia/thread_snapshot_fuchsia.h" #include "snapshot/process_snapshot.h" #include "snapshot/unloaded_module_snapshot.h" #include "util/misc/initialization_state_dcheck.h" @@ -73,9 +74,13 @@ class ProcessSnapshotFuchsia : public ProcessSnapshot { std::vector ExtraMemory() const override; private: + // Initializes threads_ on behalf of Initialize(). + void InitializeThreads(); + // Initializes modules_ on behalf of Initialize(). void InitializeModules(); + std::vector> threads_; std::vector> modules_; ProcessReaderFuchsia process_reader_; std::map annotations_simple_map_; diff --git a/snapshot/fuchsia/thread_snapshot_fuchsia.cc b/snapshot/fuchsia/thread_snapshot_fuchsia.cc new file mode 100644 index 00000000..ce1aeb33 --- /dev/null +++ b/snapshot/fuchsia/thread_snapshot_fuchsia.cc @@ -0,0 +1,96 @@ +// Copyright 2018 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "snapshot/fuchsia/thread_snapshot_fuchsia.h" + +#include "base/logging.h" + +namespace crashpad { +namespace internal { + +ThreadSnapshotFuchsia::ThreadSnapshotFuchsia() + : ThreadSnapshot(), + context_arch_(), + context_(), + stack_(), + thread_id_(ZX_KOID_INVALID), + thread_specific_data_address_(0), + initialized_() {} + +ThreadSnapshotFuchsia::~ThreadSnapshotFuchsia() {} + +bool ThreadSnapshotFuchsia::Initialize( + ProcessReaderFuchsia* process_reader, + const ProcessReaderFuchsia::Thread& thread) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + +#if defined(ARCH_CPU_X86_64) + context_.architecture = kCPUArchitectureX86_64; + context_.x86_64 = &context_arch_; +// TODO(scottmg): Implement context capture for x64. +#elif defined(ARCH_CPU_ARM64) + context_.architecture = kCPUArchitectureARM64; + context_.arm64 = &context_arch_; +// TODO(scottmg): Implement context capture for arm64. +#else +#error Port. +#endif + + // TODO(scottmg): https://crashpad.chromium.org/bug/196. Initialize stack_ and + // TLS address here. API request for stack range filed upstream at ZX-1748. + + thread_id_ = thread.id; + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +const CPUContext* ThreadSnapshotFuchsia::Context() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &context_; +} + +const MemorySnapshot* ThreadSnapshotFuchsia::Stack() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &stack_; +} + +uint64_t ThreadSnapshotFuchsia::ThreadID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return thread_id_; +} + +int ThreadSnapshotFuchsia::SuspendCount() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + // There is not (currently) a suspend count for threads on Fuchsia. + return 0; +} + +int ThreadSnapshotFuchsia::Priority() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + // There is not (currently) thread priorities on Fuchsia. + return 0; +} + +uint64_t ThreadSnapshotFuchsia::ThreadSpecificDataAddress() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return thread_specific_data_address_; +} + +std::vector ThreadSnapshotFuchsia::ExtraMemory() const { + return std::vector(); +} + +} // namespace internal +} // namespace crashpad diff --git a/snapshot/fuchsia/thread_snapshot_fuchsia.h b/snapshot/fuchsia/thread_snapshot_fuchsia.h new file mode 100644 index 00000000..db975976 --- /dev/null +++ b/snapshot/fuchsia/thread_snapshot_fuchsia.h @@ -0,0 +1,81 @@ +// Copyright 2018 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_ +#define CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_ + +#include +#include + +#include "base/macros.h" +#include "build/build_config.h" +#include "snapshot/cpu_context.h" +#include "snapshot/fuchsia/process_reader_fuchsia.h" +#include "snapshot/memory_snapshot.h" +#include "snapshot/memory_snapshot_generic.h" +#include "snapshot/thread_snapshot.h" +#include "util/misc/initialization_state_dcheck.h" + +namespace crashpad { +namespace internal { + +//! \brief A ThreadSnapshot of a thread on a Fuchsia system. +class ThreadSnapshotFuchsia final : public ThreadSnapshot { + public: + ThreadSnapshotFuchsia(); + ~ThreadSnapshotFuchsia() override; + + //! \brief Initializes the object. + //! + //! \param[in] process_reader A ProcessReaderFuchsia for the process + //! containing the thread. + //! \param[in] thread The thread within the ProcessReaderFuchsia for + //! which the snapshot should be created. + //! + //! \return `true` if the snapshot could be created, `false` otherwise with + //! a message logged. + bool Initialize(ProcessReaderFuchsia* process_reader, + const ProcessReaderFuchsia::Thread& thread); + + // ThreadSnapshot: + + const CPUContext* Context() const override; + const MemorySnapshot* Stack() const override; + uint64_t ThreadID() const override; + int SuspendCount() const override; + int Priority() const override; + uint64_t ThreadSpecificDataAddress() const override; + std::vector ExtraMemory() const override; + + private: +#if defined(ARCH_CPU_X86_64) + CPUContextX86_64 context_arch_; +#elif defined(ARCH_CPU_ARM64) + CPUContextARM64 context_arch_; +#else +#error Port. +#endif + CPUContext context_; + MemorySnapshotGeneric stack_; + zx_koid_t thread_id_; + zx_vaddr_t thread_specific_data_address_; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(ThreadSnapshotFuchsia); +}; + +} // namespace internal +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_