From 279ca87e68d80e6f858483bacb10bd7249b389d0 Mon Sep 17 00:00:00 2001 From: Mark Mentovai Date: Fri, 17 Oct 2014 14:00:58 -0400 Subject: [PATCH] Add ProcessSnapshotMac. R=rsesek@chromium.org Review URL: https://codereview.chromium.org/650223007 --- snapshot/mac/process_snapshot_mac.cc | 161 +++++++++++++++++++++++++++ snapshot/mac/process_snapshot_mac.h | 107 ++++++++++++++++++ snapshot/snapshot.gyp | 2 + 3 files changed, 270 insertions(+) create mode 100644 snapshot/mac/process_snapshot_mac.cc create mode 100644 snapshot/mac/process_snapshot_mac.h diff --git a/snapshot/mac/process_snapshot_mac.cc b/snapshot/mac/process_snapshot_mac.cc new file mode 100644 index 00000000..c241c982 --- /dev/null +++ b/snapshot/mac/process_snapshot_mac.cc @@ -0,0 +1,161 @@ +// 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/process_snapshot_mac.h" + +namespace crashpad { + +ProcessSnapshotMac::ProcessSnapshotMac() + : ProcessSnapshot(), + system_(), + threads_(), + modules_(), + exception_(), + process_reader_(), + snapshot_time_(), + initialized_() { +} + +ProcessSnapshotMac::~ProcessSnapshotMac() { +} + +bool ProcessSnapshotMac::Initialize(task_t task) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + + if (gettimeofday(&snapshot_time_, nullptr) != 0) { + PLOG(ERROR) << "gettimeofday"; + return false; + } + + if (!process_reader_.Initialize(task)) { + return false; + } + + system_.Initialize(&process_reader_, &snapshot_time_); + + InitializeThreads(); + InitializeModules(); + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +bool ProcessSnapshotMac::InitializeException( + thread_t exception_thread, + exception_type_t exception, + const mach_exception_data_type_t* code, + mach_msg_type_number_t code_count, + thread_state_flavor_t flavor, + const natural_t* state, + mach_msg_type_number_t state_count) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + DCHECK(!exception_); + + exception_.reset(new internal::ExceptionSnapshotMac()); + if (!exception_->Initialize(&process_reader_, + exception_thread, + exception, + code, + code_count, + flavor, + state, + state_count)) { + exception_.reset(); + return false; + } + + return true; +} + +pid_t ProcessSnapshotMac::ProcessID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return process_reader_.ProcessID(); +} + +pid_t ProcessSnapshotMac::ParentProcessID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return process_reader_.ProcessID(); +} + +void ProcessSnapshotMac::SnapshotTime(timeval* snapshot_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + *snapshot_time = snapshot_time_; +} + +void ProcessSnapshotMac::ProcessStartTime(timeval* start_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + process_reader_.StartTime(start_time); +} + +void ProcessSnapshotMac::ProcessCPUTimes(timeval* user_time, + timeval* system_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + process_reader_.CPUTimes(user_time, system_time); +} + +const SystemSnapshot* ProcessSnapshotMac::System() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &system_; +} + +std::vector ProcessSnapshotMac::Threads() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + std::vector threads; + for (internal::ThreadSnapshotMac* thread : threads_) { + threads.push_back(thread); + } + return threads; +} + +std::vector ProcessSnapshotMac::Modules() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + std::vector modules; + for (internal::ModuleSnapshotMac* module : modules_) { + modules.push_back(module); + } + return modules; +} + +const ExceptionSnapshot* ProcessSnapshotMac::Exception() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return exception_.get(); +} + +void ProcessSnapshotMac::InitializeThreads() { + const std::vector& process_reader_threads = + process_reader_.Threads(); + for (const ProcessReader::Thread& process_reader_thread : + process_reader_threads) { + internal::ThreadSnapshotMac* thread = new internal::ThreadSnapshotMac(); + threads_.push_back(thread); + if (!thread->Initialize(&process_reader_, process_reader_thread)) { + threads_.pop_back(); + } + } +} + +void ProcessSnapshotMac::InitializeModules() { + const std::vector& process_reader_modules = + process_reader_.Modules(); + for (const ProcessReader::Module& process_reader_module : + process_reader_modules) { + internal::ModuleSnapshotMac* module = new internal::ModuleSnapshotMac(); + modules_.push_back(module); + if (!module->Initialize(&process_reader_, process_reader_module)) { + modules_.pop_back(); + } + } +} + +} // namespace crashpad diff --git a/snapshot/mac/process_snapshot_mac.h b/snapshot/mac/process_snapshot_mac.h new file mode 100644 index 00000000..2edf32ce --- /dev/null +++ b/snapshot/mac/process_snapshot_mac.h @@ -0,0 +1,107 @@ +// 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. + +#ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_SNAPSHOT_MAC_H_ +#define CRASHPAD_SNAPSHOT_MAC_PROCESS_SNAPSHOT_MAC_H_ + +#include +#include +#include + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "snapshot/exception_snapshot.h" +#include "snapshot/mac/exception_snapshot_mac.h" +#include "snapshot/mac/module_snapshot_mac.h" +#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/system_snapshot_mac.h" +#include "snapshot/mac/thread_snapshot_mac.h" +#include "snapshot/module_snapshot.h" +#include "snapshot/process_snapshot.h" +#include "snapshot/system_snapshot.h" +#include "snapshot/thread_snapshot.h" +#include "util/misc/initialization_state_dcheck.h" +#include "util/stdlib/pointer_container.h" + +namespace crashpad { + +//! \brief A ProcessSnapshot of a running (or crashed) process running on a Mac +//! OS X system. +class ProcessSnapshotMac final : public ProcessSnapshot { + public: + ProcessSnapshotMac(); + ~ProcessSnapshotMac(); + + //! \brief Initializes the object. + //! + //! \param[in] task The task to create a snapshot from. + //! + //! \return `true` if the snapshot could be created, `false` otherwise with + //! an appropriate message logged. + bool Initialize(task_t task); + + //! \brief Initializes the object’s exception. + //! + //! This populates the data to be returned by Exception(). The parameters may + //! be passed directly through from a Mach exception handler. + //! + //! This method must not be called until after a successful call to + //! Initialize(). + //! + //! \return `true` if the exception information could be initialized, `false` + //! otherwise with an appropriate message logged. When this method returns + //! `false`, the ProcessSnapshotMac object’s validity remains unchanged. + bool InitializeException(thread_t exception_thread, + exception_type_t exception, + const mach_exception_data_type_t* code, + mach_msg_type_number_t code_count, + thread_state_flavor_t flavor, + const natural_t* state, + mach_msg_type_number_t state_count); + + // ProcessSnapshot: + + pid_t ProcessID() const override; + pid_t ParentProcessID() const override; + void SnapshotTime(timeval* snapshot_time) const override; + void ProcessStartTime(timeval* start_time) const override; + void ProcessCPUTimes(timeval* user_time, timeval* system_time) const override; + const SystemSnapshot* System() const override; + std::vector Threads() const override; + std::vector Modules() const override; + const ExceptionSnapshot* Exception() const override; + + private: + // Initializes threads_ on behalf of Initialize(). + void InitializeThreads(); + + // Initializes modules_ on behalf of Initialize(). + void InitializeModules(); + + internal::SystemSnapshotMac system_; + PointerVector threads_; + PointerVector modules_; + scoped_ptr exception_; + ProcessReader process_reader_; + timeval snapshot_time_; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotMac); +}; + +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_MAC_PROCESS_SNAPSHOT_MAC_H_ diff --git a/snapshot/snapshot.gyp b/snapshot/snapshot.gyp index 1792f890..3b1a8d62 100644 --- a/snapshot/snapshot.gyp +++ b/snapshot/snapshot.gyp @@ -49,6 +49,8 @@ 'mac/module_snapshot_mac.h', 'mac/process_reader.cc', 'mac/process_reader.h', + 'mac/process_snapshot_mac.cc', + 'mac/process_snapshot_mac.h', 'mac/process_types.cc', 'mac/process_types.h', 'mac/process_types/all.proctype',