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_