Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 #ifndef CRASHPAD_UTIL_MAC_PROCESS_READER_H_ | |
| 16 #define CRASHPAD_UTIL_MAC_PROCESS_READER_H_ | |
| 17 | |
| 18 #include <mach/mach.h> | |
| 19 #include <sys/sysctl.h> | |
| 20 #include <sys/time.h> | |
| 21 #include <sys/types.h> | |
| 22 #include <time.h> | |
| 23 | |
| 24 #include <string> | |
| 25 #include <vector> | |
| 26 | |
| 27 #include "base/basictypes.h" | |
| 28 #include "base/memory/scoped_ptr.h" | |
| 29 #include "build/build_config.h" | |
| 30 #include "util/mach/task_memory.h" | |
| 31 #include "util/misc/initialization_state_dcheck.h" | |
| 32 | |
| 33 namespace crashpad { | |
| 34 | |
| 35 //! \brief Contains information about a thread that belongs to a task (process). | |
| 36 struct ProcessReaderThread { | |
| 37 #if defined(ARCH_CPU_X86_FAMILY) | |
| 38 union ThreadContext { | |
| 39 x86_thread_state64_t t64; | |
| 40 x86_thread_state32_t t32; | |
| 41 }; | |
| 42 union FloatContext { | |
| 43 x86_float_state64_t f64; | |
| 44 x86_float_state32_t f32; | |
| 45 }; | |
| 46 union DebugContext { | |
| 47 x86_debug_state64_t d64; | |
| 48 x86_debug_state32_t d32; | |
| 49 }; | |
| 50 #endif | |
| 51 | |
| 52 ProcessReaderThread(); | |
| 53 ~ProcessReaderThread() {} | |
| 54 | |
| 55 ThreadContext thread_context; | |
| 56 FloatContext float_context; | |
| 57 DebugContext debug_context; | |
| 58 uint64_t id; | |
| 59 mach_vm_address_t stack_region_address; | |
| 60 mach_vm_size_t stack_region_size; | |
| 61 mach_vm_address_t thread_specific_data_address; | |
| 62 mach_port_t port; | |
| 63 int suspend_count; | |
| 64 int priority; | |
| 65 }; | |
| 66 | |
| 67 //! \brief Contains information about a module loaded into a process. | |
| 68 struct ProcessReaderModule { | |
| 69 ProcessReaderModule(); | |
| 70 ~ProcessReaderModule(); | |
| 71 | |
| 72 std::string name; | |
| 73 mach_vm_address_t address; | |
| 74 time_t timestamp; | |
| 75 }; | |
| 76 | |
| 77 //! \brief Accesses information about another process, identified by a Mach | |
| 78 //! task. | |
| 79 class ProcessReader { | |
| 80 public: | |
| 81 ProcessReader(); | |
| 82 ~ProcessReader(); | |
| 83 | |
| 84 //! \brief Initializes this object. This method must be called before any | |
| 85 //! other. | |
| 86 //! | |
| 87 //! \param[in] task A send right to the target task’s task port. This object | |
| 88 //! does not take ownership of the send right. | |
| 89 //! | |
| 90 //! \return `true` on success, indicating that this object will respond | |
| 91 //! validly to further method calls. `false` on failure. On failure, no | |
| 92 //! further method calls should be made. | |
| 93 bool Initialize(mach_port_t task); | |
| 94 | |
| 95 //! \return `true` if the target task is a 64-bit process. | |
| 96 bool Is64Bit() const { return is_64_bit_; } | |
| 97 | |
| 98 //! \return The target task’s process ID. | |
| 99 pid_t ProcessID() const { return kern_proc_info_.kp_proc.p_pid; } | |
| 100 | |
| 101 //! \return The target task’s parent process ID. | |
| 102 pid_t ParentProcessID() const { return kern_proc_info_.kp_eproc.e_ppid; } | |
| 103 | |
| 104 //! \param[out] start_time The time that the process started. | |
| 105 void StartTime(timeval* start_time) const; | |
| 106 | |
| 107 //! \param[out] user_time The amount of time the process has executed code in | |
| 108 //! user mode. | |
| 109 //! \param[out] system_time The amount of time the process has executed code | |
| 110 //! in system mode. | |
| 111 //! | |
| 112 //! \return `true` on success, `false` on failure, with a warning logged. On | |
| 113 //! failure, \a user_time and \a system_time will be set to represent no | |
| 114 //! time spent executing code in user or system mode. | |
| 115 bool CPUTimes(timeval* user_time, timeval* system_time) const; | |
| 116 | |
| 117 //! \return Accesses the memory of the target task. | |
| 118 TaskMemory* Memory() { return task_memory_.get(); } | |
| 119 | |
| 120 //! \return The threads that are in the task (process). | |
| 121 const std::vector<ProcessReaderThread>& Threads(); | |
| 122 | |
| 123 //! \return The modules loaded in the process. | |
| 124 const std::vector<ProcessReaderModule>& Modules(); | |
| 125 | |
| 126 private: | |
| 127 //! Performs lazy initialization of the \a threads_ vector on behalf of | |
| 128 //! Threads(). | |
| 129 void InitializeThreads(); | |
| 130 | |
| 131 //! Performs lazy initialization of the \a modules_ vector on behalf of | |
| 132 //! Modules(). | |
| 133 void InitializeModules(); | |
| 134 | |
| 135 //! \brief Calculates the base address and size of the region used as a | |
| 136 //! thread’s stack. | |
| 137 //! | |
| 138 //! The region returned by this method may be formed by merging multiple | |
| 139 //! adjacent regions in a process’ memory map if appropriate. The base address | |
| 140 //! of the returned region may be lower than the \a stack_pointer passed in | |
| 141 //! when the ABI mandates a red zone below the stack pointer. | |
| 142 //! | |
| 143 //! \param[in] stack_pointer The stack pointer, referring to the top (lowest | |
| 144 //! address) of a thread’s stack. | |
| 145 //! \param[out] stack_region_size The size of the memory region used as the | |
| 146 //! thread’s stack. | |
| 147 //! | |
| 148 //! \return The base address (lowest address) of the memory region used as the | |
| 149 //! thread’s stack. | |
| 150 mach_vm_address_t CalculateStackRegion(mach_vm_address_t stack_pointer, | |
| 151 mach_vm_size_t* stack_region_size); | |
| 152 | |
| 153 //! \brief Adjusts the region for the red zone, if the ABI requires one. | |
| 154 //! | |
| 155 //! This method performs red zone calculation for CalculateStackRegion(). Its | |
| 156 //! parameters are local variables used within that method, and may be | |
| 157 //! modified as needed. | |
| 158 //! | |
| 159 //! Where a red zone is required, the region of memory captured for a thread’s | |
| 160 //! stack will be extended to include the red zone below the stack pointer, | |
| 161 //! provided that such memory is mapped, readable, and has the correct user | |
| 162 //! tag value. If these conditions cannot be met fully, as much of the red | |
| 163 //! zone will be captured as is possible while meeting these conditions. | |
| 164 //! | |
| 165 //! \param[inout] start_address The base address of the region to begin | |
| 166 //! capturing stack memory from. On entry, \a start_address is the stack | |
| 167 //! pointer. On return, \a start_address may be decreased to encompass a | |
| 168 //! red zone. | |
| 169 //! \param[inout] region_base The base address of the region that contains | |
| 170 //! stack memory. This is distinct from \a start_address in that \a | |
| 171 //! region_base will be page-aligned. On entry, \a region_base is the | |
| 172 //! base address of a region that contains \a start_address. On return, | |
| 173 //! if \a start_address is decremented and is outside of the region | |
| 174 //! originally described by \a region_base, \a region_base will also be | |
| 175 //! decremented appropriately. | |
| 176 //! \param[inout] region_side The size of the region that contains stack | |
|
Robert Sesek
2014/08/25 21:31:42
sp: region_size
| |
| 177 //! memory. This region begins at \a region_base. On return, if \a | |
| 178 //! region_base is decremented, \a region_size will be incremented | |
| 179 //! appropriately. | |
| 180 //! \param[in] user_tag The Mach VM system’s user tag for the region described | |
| 181 //! by the initial values of \a region_base and \a region_size. The red | |
| 182 //! zone will only be allowed to extend out of the region described by | |
| 183 //! these initial values if the user tag is appropriate for stack memory | |
| 184 //! and the expanded region has the same user tag value. | |
| 185 void LocateRedZone(mach_vm_address_t* start_address, | |
| 186 mach_vm_address_t* region_base, | |
| 187 mach_vm_address_t* region_size, | |
| 188 unsigned int user_tag); | |
| 189 | |
| 190 kinfo_proc kern_proc_info_; | |
| 191 std::vector<ProcessReaderThread> threads_; // owns send rights | |
| 192 std::vector<ProcessReaderModule> modules_; | |
| 193 scoped_ptr<TaskMemory> task_memory_; | |
| 194 mach_port_t task_; // weak | |
| 195 InitializationStateDcheck initialized_; | |
| 196 | |
| 197 // This shadows a bit in kern_proc_info_, but it’s accessed so frequently that | |
| 198 // it’s given a first-class field to save a few bit operations on each access. | |
| 199 bool is_64_bit_; | |
| 200 | |
| 201 bool initialized_threads_; | |
| 202 bool initialized_modules_; | |
| 203 | |
| 204 DISALLOW_COPY_AND_ASSIGN(ProcessReader); | |
| 205 }; | |
| 206 | |
| 207 } // namespace crashpad | |
| 208 | |
| 209 #endif // CRASHPAD_UTIL_MAC_PROCESS_READER_H_ | |
| OLD | NEW |