crashpad/snapshot/mac/process_reader_mac.h
Mark Mentovai 809939c9d1 mac: Crashpad for macOS on arm64, phase 1: build it
This gets all production code for Chrome building, excluding tests.
There aren’t any guarantees that anything works yet.

This is mostly a lot of CPU context shuffling.

In contrast to macOS on x86, there’s no need to support 32-bit arm on
macOS, because this new platform is 64-bit-only from its inception.

Bug: crashpad:345
Change-Id: I187239b6a969005a3458af7fe30c44147a57f95f
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2285961
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
2020-07-08 16:18:40 +00:00

257 lines
9.7 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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_READER_MAC_H_
#define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_
#include <mach/mach.h>
#include <stdint.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "build/build_config.h"
#include "util/misc/initialization_state_dcheck.h"
#include "util/posix/process_info.h"
#include "util/process/process_memory_mac.h"
namespace crashpad {
class MachOImageReader;
//! \brief Accesses information about another process, identified by a Mach
//! task.
class ProcessReaderMac {
public:
//! \brief Contains information about a thread that belongs to a task
//! (process).
struct Thread {
#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;
};
#elif defined(ARCH_CPU_ARM64)
using ThreadContext = arm_thread_state64_t;
using FloatContext = arm_neon_state64_t;
using DebugContext = arm_debug_state64_t;
#endif
Thread();
~Thread() {}
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;
thread_t port;
int suspend_count;
int priority;
};
//! \brief Contains information about a module loaded into a process.
struct Module {
Module();
~Module();
//! \brief The pathname used to load the module from disk.
std::string name;
//! \brief An image reader for the module.
//!
//! The lifetime of this MachOImageReader is scoped to the lifetime of the
//! ProcessReaderMac that created it.
//!
//! This field may be `nullptr` if a reader could not be created for the
//! module.
const MachOImageReader* reader;
//! \brief The modules timestamp.
//!
//! This field will be `0` if its value cannot be determined. It can only be
//! determined for images that are loaded by dyld, so it will be `0` for the
//! main executable and for dyld itself.
time_t timestamp;
};
ProcessReaderMac();
~ProcessReaderMac();
//! \brief Initializes this object. This method must be called before any
//! other.
//!
//! \param[in] task A send right to the target tasks 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(task_t task);
//! \return `true` if the target task is a 64-bit process.
bool Is64Bit() const { return is_64_bit_; }
//! \return The target tasks process ID.
pid_t ProcessID() const { return process_info_.ProcessID(); }
//! \return The target tasks parent process ID.
pid_t ParentProcessID() const { return process_info_.ParentProcessID(); }
//! \brief Determines the target process start time.
//!
//! \param[out] start_time The time that the process started.
void StartTime(timeval* start_time) const;
//! \brief Determines the target process execution time.
//!
//! \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.
const ProcessMemoryMac* Memory() const { return &process_memory_; }
//! \return The threads that are in the task (process). The first element (at
//! index `0`) corresponds to the main thread.
const std::vector<Thread>& Threads();
//! \return The modules loaded in the process. The first element (at index
//! `0`) corresponds to the main executable, and the final element
//! corresponds to the dynamic loader, dyld.
const std::vector<Module>& Modules();
//! \brief Determines the location of the `dyld_all_image_infos` structure in
//! the process address space.
//!
//! This function is an internal implementation detail of Modules(), and
//! should not normally be used directly. It is exposed solely for use by test
//! code.
//!
//! \param[out] all_image_info_size The size of the `dyld_all_image_infos`
//! structure. Optional, may be `nullptr` if not required.
//!
//! \return The address of the `dyld_all_image_infos` structure in the
//! process address space, with \a all_image_info_size set appropriately.
//! On failure, returns `0` with a message logged.
mach_vm_address_t DyldAllImageInfo(mach_vm_size_t* all_image_info_size);
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
//! threads 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 threads stack.
//! \param[out] stack_region_size The size of the memory region used as the
//! threads stack.
//!
//! \return The base address (lowest address) of the memory region used as the
//! threads 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 threads
//! 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[in,out] 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[in,out] 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[in,out] 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 systems 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);
ProcessInfo process_info_;
std::vector<Thread> threads_; // owns send rights
std::vector<Module> modules_;
std::vector<std::unique_ptr<MachOImageReader>> module_readers_;
ProcessMemoryMac process_memory_;
task_t task_; // weak
InitializationStateDcheck initialized_;
// This shadows a method of process_info_, but its accessed so frequently
// that its given a first-class field to save a call and a few bit operations
// on each access.
bool is_64_bit_;
bool initialized_threads_;
bool initialized_modules_;
DISALLOW_COPY_AND_ASSIGN(ProcessReaderMac);
};
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_