mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-21 15:11:37 +08:00
210 lines
7.8 KiB
C
210 lines
7.8 KiB
C
|
// 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_UTIL_MAC_PROCESS_READER_H_
|
|||
|
#define CRASHPAD_UTIL_MAC_PROCESS_READER_H_
|
|||
|
|
|||
|
#include <mach/mach.h>
|
|||
|
#include <sys/sysctl.h>
|
|||
|
#include <sys/time.h>
|
|||
|
#include <sys/types.h>
|
|||
|
#include <time.h>
|
|||
|
|
|||
|
#include <string>
|
|||
|
#include <vector>
|
|||
|
|
|||
|
#include "base/basictypes.h"
|
|||
|
#include "base/memory/scoped_ptr.h"
|
|||
|
#include "build/build_config.h"
|
|||
|
#include "util/mach/task_memory.h"
|
|||
|
#include "util/misc/initialization_state_dcheck.h"
|
|||
|
|
|||
|
namespace crashpad {
|
|||
|
|
|||
|
//! \brief Contains information about a thread that belongs to a task (process).
|
|||
|
struct ProcessReaderThread {
|
|||
|
#if defined(ARCH_CPU_X86_FAMILY)
|
|||
|
union ThreadContext {
|
|||
|
x86_thread_state64_t t64;
|
|||
|
x86_thread_state32_t t32;
|
|||
|
};
|
|||
|
union FloatContext {
|
|||
|
x86_float_state64_t f64;
|
|||
|
x86_float_state32_t f32;
|
|||
|
};
|
|||
|
union DebugContext {
|
|||
|
x86_debug_state64_t d64;
|
|||
|
x86_debug_state32_t d32;
|
|||
|
};
|
|||
|
#endif
|
|||
|
|
|||
|
ProcessReaderThread();
|
|||
|
~ProcessReaderThread() {}
|
|||
|
|
|||
|
ThreadContext thread_context;
|
|||
|
FloatContext float_context;
|
|||
|
DebugContext debug_context;
|
|||
|
uint64_t id;
|
|||
|
mach_vm_address_t stack_region_address;
|
|||
|
mach_vm_size_t stack_region_size;
|
|||
|
mach_vm_address_t thread_specific_data_address;
|
|||
|
mach_port_t port;
|
|||
|
int suspend_count;
|
|||
|
int priority;
|
|||
|
};
|
|||
|
|
|||
|
//! \brief Contains information about a module loaded into a process.
|
|||
|
struct ProcessReaderModule {
|
|||
|
ProcessReaderModule();
|
|||
|
~ProcessReaderModule();
|
|||
|
|
|||
|
std::string name;
|
|||
|
mach_vm_address_t address;
|
|||
|
time_t timestamp;
|
|||
|
};
|
|||
|
|
|||
|
//! \brief Accesses information about another process, identified by a Mach
|
|||
|
//! task.
|
|||
|
class ProcessReader {
|
|||
|
public:
|
|||
|
ProcessReader();
|
|||
|
~ProcessReader();
|
|||
|
|
|||
|
//! \brief Initializes this object. This method must be called before any
|
|||
|
//! other.
|
|||
|
//!
|
|||
|
//! \param[in] task A send right to the target task’s task port. This object
|
|||
|
//! does not take ownership of the send right.
|
|||
|
//!
|
|||
|
//! \return `true` on success, indicating that this object will respond
|
|||
|
//! validly to further method calls. `false` on failure. On failure, no
|
|||
|
//! further method calls should be made.
|
|||
|
bool Initialize(mach_port_t task);
|
|||
|
|
|||
|
//! \return `true` if the target task is a 64-bit process.
|
|||
|
bool Is64Bit() const { return is_64_bit_; }
|
|||
|
|
|||
|
//! \return The target task’s process ID.
|
|||
|
pid_t ProcessID() const { return kern_proc_info_.kp_proc.p_pid; }
|
|||
|
|
|||
|
//! \return The target task’s parent process ID.
|
|||
|
pid_t ParentProcessID() const { return kern_proc_info_.kp_eproc.e_ppid; }
|
|||
|
|
|||
|
//! \param[out] start_time The time that the process started.
|
|||
|
void StartTime(timeval* start_time) const;
|
|||
|
|
|||
|
//! \param[out] user_time The amount of time the process has executed code in
|
|||
|
//! user mode.
|
|||
|
//! \param[out] system_time The amount of time the process has executed code
|
|||
|
//! in system mode.
|
|||
|
//!
|
|||
|
//! \return `true` on success, `false` on failure, with a warning logged. On
|
|||
|
//! failure, \a user_time and \a system_time will be set to represent no
|
|||
|
//! time spent executing code in user or system mode.
|
|||
|
bool CPUTimes(timeval* user_time, timeval* system_time) const;
|
|||
|
|
|||
|
//! \return Accesses the memory of the target task.
|
|||
|
TaskMemory* Memory() { return task_memory_.get(); }
|
|||
|
|
|||
|
//! \return The threads that are in the task (process).
|
|||
|
const std::vector<ProcessReaderThread>& Threads();
|
|||
|
|
|||
|
//! \return The modules loaded in the process.
|
|||
|
const std::vector<ProcessReaderModule>& Modules();
|
|||
|
|
|||
|
private:
|
|||
|
//! Performs lazy initialization of the \a threads_ vector on behalf of
|
|||
|
//! Threads().
|
|||
|
void InitializeThreads();
|
|||
|
|
|||
|
//! Performs lazy initialization of the \a modules_ vector on behalf of
|
|||
|
//! Modules().
|
|||
|
void InitializeModules();
|
|||
|
|
|||
|
//! \brief Calculates the base address and size of the region used as a
|
|||
|
//! thread’s stack.
|
|||
|
//!
|
|||
|
//! The region returned by this method may be formed by merging multiple
|
|||
|
//! adjacent regions in a process’ memory map if appropriate. The base address
|
|||
|
//! of the returned region may be lower than the \a stack_pointer passed in
|
|||
|
//! when the ABI mandates a red zone below the stack pointer.
|
|||
|
//!
|
|||
|
//! \param[in] stack_pointer The stack pointer, referring to the top (lowest
|
|||
|
//! address) of a thread’s stack.
|
|||
|
//! \param[out] stack_region_size The size of the memory region used as the
|
|||
|
//! thread’s stack.
|
|||
|
//!
|
|||
|
//! \return The base address (lowest address) of the memory region used as the
|
|||
|
//! thread’s stack.
|
|||
|
mach_vm_address_t CalculateStackRegion(mach_vm_address_t stack_pointer,
|
|||
|
mach_vm_size_t* stack_region_size);
|
|||
|
|
|||
|
//! \brief Adjusts the region for the red zone, if the ABI requires one.
|
|||
|
//!
|
|||
|
//! This method performs red zone calculation for CalculateStackRegion(). Its
|
|||
|
//! parameters are local variables used within that method, and may be
|
|||
|
//! modified as needed.
|
|||
|
//!
|
|||
|
//! Where a red zone is required, the region of memory captured for a thread’s
|
|||
|
//! stack will be extended to include the red zone below the stack pointer,
|
|||
|
//! provided that such memory is mapped, readable, and has the correct user
|
|||
|
//! tag value. If these conditions cannot be met fully, as much of the red
|
|||
|
//! zone will be captured as is possible while meeting these conditions.
|
|||
|
//!
|
|||
|
//! \param[inout] start_address The base address of the region to begin
|
|||
|
//! capturing stack memory from. On entry, \a start_address is the stack
|
|||
|
//! pointer. On return, \a start_address may be decreased to encompass a
|
|||
|
//! red zone.
|
|||
|
//! \param[inout] region_base The base address of the region that contains
|
|||
|
//! stack memory. This is distinct from \a start_address in that \a
|
|||
|
//! region_base will be page-aligned. On entry, \a region_base is the
|
|||
|
//! base address of a region that contains \a start_address. On return,
|
|||
|
//! if \a start_address is decremented and is outside of the region
|
|||
|
//! originally described by \a region_base, \a region_base will also be
|
|||
|
//! decremented appropriately.
|
|||
|
//! \param[inout] region_size The size of the region that contains stack
|
|||
|
//! memory. This region begins at \a region_base. On return, if \a
|
|||
|
//! region_base is decremented, \a region_size will be incremented
|
|||
|
//! appropriately.
|
|||
|
//! \param[in] user_tag The Mach VM system’s user tag for the region described
|
|||
|
//! by the initial values of \a region_base and \a region_size. The red
|
|||
|
//! zone will only be allowed to extend out of the region described by
|
|||
|
//! these initial values if the user tag is appropriate for stack memory
|
|||
|
//! and the expanded region has the same user tag value.
|
|||
|
void LocateRedZone(mach_vm_address_t* start_address,
|
|||
|
mach_vm_address_t* region_base,
|
|||
|
mach_vm_address_t* region_size,
|
|||
|
unsigned int user_tag);
|
|||
|
|
|||
|
kinfo_proc kern_proc_info_;
|
|||
|
std::vector<ProcessReaderThread> threads_; // owns send rights
|
|||
|
std::vector<ProcessReaderModule> modules_;
|
|||
|
scoped_ptr<TaskMemory> task_memory_;
|
|||
|
mach_port_t task_; // weak
|
|||
|
InitializationStateDcheck initialized_;
|
|||
|
|
|||
|
// This shadows a bit in kern_proc_info_, but it’s accessed so frequently that
|
|||
|
// it’s given a first-class field to save a few bit operations on each access.
|
|||
|
bool is_64_bit_;
|
|||
|
|
|||
|
bool initialized_threads_;
|
|||
|
bool initialized_modules_;
|
|||
|
|
|||
|
DISALLOW_COPY_AND_ASSIGN(ProcessReader);
|
|||
|
};
|
|||
|
|
|||
|
} // namespace crashpad
|
|||
|
|
|||
|
#endif // CRASHPAD_UTIL_MAC_PROCESS_READER_H_
|