text: // Copyright 2014 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/mac/thread_snapshot_mac.h"
  
  #include "base/check_op.h"
  #include "snapshot/mac/cpu_context_mac.h"
  #include "snapshot/mac/process_reader_mac.h"
  
  namespace crashpad {
  namespace internal {
  
  ThreadSnapshotMac::ThreadSnapshotMac()
      : ThreadSnapshot(),
        context_union_(),
        context_(),
        stack_(),
        thread_id_(0),
        thread_specific_data_address_(0),
        thread_(MACH_PORT_NULL),
        suspend_count_(0),
        priority_(0),
        initialized_() {
  }
  
  ThreadSnapshotMac::~ThreadSnapshotMac() {
  }
  
  bool ThreadSnapshotMac::Initialize(
      ProcessReaderMac* process_reader,
      const ProcessReaderMac::Thread& process_reader_thread) {
    INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
  
    thread_ = process_reader_thread.port;
    thread_id_ = process_reader_thread.id;
    suspend_count_ = process_reader_thread.suspend_count;
    priority_ = process_reader_thread.priority;
    thread_specific_data_address_ =
        process_reader_thread.thread_specific_data_address;
  
    stack_.Initialize(process_reader->Memory(),
                      process_reader_thread.stack_region_address,
                      process_reader_thread.stack_region_size);
  
  #if defined(ARCH_CPU_X86_FAMILY)
    if (process_reader->Is64Bit()) {
      context_.architecture = kCPUArchitectureX86_64;
      context_.x86_64 = &context_union_.x86_64;
      InitializeCPUContextX86_64(context_.x86_64,
                                 THREAD_STATE_NONE,
                                 nullptr,
                                 0,
                                 &process_reader_thread.thread_context.t64,
                                 &process_reader_thread.float_context.f64,
                                 &process_reader_thread.debug_context.d64);
    } else {
      context_.architecture = kCPUArchitectureX86;
      context_.x86 = &context_union_.x86;
      InitializeCPUContextX86(context_.x86,
                              THREAD_STATE_NONE,
                              nullptr,
                              0,
                              &process_reader_thread.thread_context.t32,
                              &process_reader_thread.float_context.f32,
                              &process_reader_thread.debug_context.d32);
    }
  #elif defined(ARCH_CPU_ARM64)
    context_.architecture = kCPUArchitectureARM64;
    context_.arm64 = &context_union_.arm64;
    InitializeCPUContextARM64(context_.arm64,
                              THREAD_STATE_NONE,
                              nullptr,
                              0,
                              &process_reader_thread.thread_context,
                              &process_reader_thread.float_context,
                              &process_reader_thread.debug_context);
  #else
  #error Port to your CPU architecture
  #endif
  
    INITIALIZATION_STATE_SET_VALID(initialized_);
    return true;
  }
  
  const CPUContext* ThreadSnapshotMac::Context() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return &context_;
  }
  
  const MemorySnapshot* ThreadSnapshotMac::Stack() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return &stack_;
  }
  
  uint64_t ThreadSnapshotMac::ThreadID() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return thread_id_;
  }
  
  int ThreadSnapshotMac::SuspendCount() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return suspend_count_;
  }
  
  int ThreadSnapshotMac::Priority() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return priority_;
  }
  
  uint64_t ThreadSnapshotMac::ThreadSpecificDataAddress() const {
    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
    return thread_specific_data_address_;
  }
  
  std::vector<const MemorySnapshot*> ThreadSnapshotMac::ExtraMemory() const {
    return std::vector<const MemorySnapshot*>();
  }
  
  }  // namespace internal
  }  // namespace crashpad
  