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 #include "util/stdlib/pointer_container.h" | |
33 | |
34 namespace crashpad { | |
35 | |
36 class MachOImageReader; | |
37 | |
38 //! \brief Accesses information about another process, identified by a Mach | |
39 //! task. | |
40 class ProcessReader { | |
41 public: | |
42 //! \brief Contains information about a thread that belongs to a task | |
43 //! (process). | |
44 struct Thread { | |
45 #if defined(ARCH_CPU_X86_FAMILY) | |
46 union ThreadContext { | |
47 x86_thread_state64_t t64; | |
48 x86_thread_state32_t t32; | |
49 }; | |
50 union FloatContext { | |
51 x86_float_state64_t f64; | |
52 x86_float_state32_t f32; | |
53 }; | |
54 union DebugContext { | |
55 x86_debug_state64_t d64; | |
56 x86_debug_state32_t d32; | |
57 }; | |
58 #endif | |
59 | |
60 Thread(); | |
61 ~Thread() {} | |
62 | |
63 ThreadContext thread_context; | |
64 FloatContext float_context; | |
65 DebugContext debug_context; | |
66 uint64_t id; | |
67 mach_vm_address_t stack_region_address; | |
68 mach_vm_size_t stack_region_size; | |
69 mach_vm_address_t thread_specific_data_address; | |
70 thread_t port; | |
71 int suspend_count; | |
72 int priority; | |
73 }; | |
74 | |
75 //! \brief Contains information about a module loaded into a process. | |
76 struct Module { | |
77 Module(); | |
78 ~Module(); | |
79 | |
80 //! \brief The pathname used to load the module from disk. | |
81 std::string name; | |
82 | |
83 //! \brief An image reader for the module. | |
84 //! | |
85 //! The lifetime of this MachOImageReader is scoped to the lifetime of the | |
86 //! ProcessReader that created it. | |
87 const MachOImageReader* reader; | |
88 | |
89 //! \brief The module’s timestamp. | |
90 //! | |
91 //! This field will be `0` if its value cannot be determined. It can only be | |
92 //! determined for images that are loaded by dyld, so it will be `0` for the | |
93 //! main executable and for dyld itself. | |
94 time_t timestamp; | |
95 }; | |
96 | |
97 ProcessReader(); | |
98 ~ProcessReader(); | |
99 | |
100 //! \brief Initializes this object. This method must be called before any | |
101 //! other. | |
102 //! | |
103 //! \param[in] task A send right to the target task’s task port. This object | |
104 //! does not take ownership of the send right. | |
105 //! | |
106 //! \return `true` on success, indicating that this object will respond | |
107 //! validly to further method calls. `false` on failure. On failure, no | |
108 //! further method calls should be made. | |
109 bool Initialize(task_t task); | |
110 | |
111 //! \return `true` if the target task is a 64-bit process. | |
112 bool Is64Bit() const { return is_64_bit_; } | |
113 | |
114 //! \return The target task’s process ID. | |
115 pid_t ProcessID() const { return kern_proc_info_.kp_proc.p_pid; } | |
116 | |
117 //! \return The target task’s parent process ID. | |
118 pid_t ParentProcessID() const { return kern_proc_info_.kp_eproc.e_ppid; } | |
119 | |
120 //! \param[out] start_time The time that the process started. | |
121 void StartTime(timeval* start_time) const; | |
122 | |
123 //! \param[out] user_time The amount of time the process has executed code in | |
124 //! user mode. | |
125 //! \param[out] system_time The amount of time the process has executed code | |
126 //! in system mode. | |
127 //! | |
128 //! \return `true` on success, `false` on failure, with a warning logged. On | |
129 //! failure, \a user_time and \a system_time will be set to represent no | |
130 //! time spent executing code in user or system mode. | |
131 bool CPUTimes(timeval* user_time, timeval* system_time) const; | |
132 | |
133 //! \return Accesses the memory of the target task. | |
134 TaskMemory* Memory() { return task_memory_.get(); } | |
135 | |
136 //! \return The threads that are in the task (process). The first element (at | |
137 //! index `0`) corresponds to the main thread. | |
138 const std::vector<Thread>& Threads(); | |
139 | |
140 //! \return The modules loaded in the process. The first element (at index | |
141 //! `0`) corresponds to the main executable, and the final element | |
142 //! corresponds to the dynamic loader, dyld. | |
143 const std::vector<Module>& Modules(); | |
144 | |
145 private: | |
146 //! Performs lazy initialization of the \a threads_ vector on behalf of | |
147 //! Threads(). | |
148 void InitializeThreads(); | |
149 | |
150 //! Performs lazy initialization of the \a modules_ vector on behalf of | |
151 //! Modules(). | |
152 void InitializeModules(); | |
153 | |
154 //! \brief Calculates the base address and size of the region used as a | |
155 //! thread’s stack. | |
156 //! | |
157 //! The region returned by this method may be formed by merging multiple | |
158 //! adjacent regions in a process’ memory map if appropriate. The base address | |
159 //! of the returned region may be lower than the \a stack_pointer passed in | |
160 //! when the ABI mandates a red zone below the stack pointer. | |
161 //! | |
162 //! \param[in] stack_pointer The stack pointer, referring to the top (lowest | |
163 //! address) of a thread’s stack. | |
164 //! \param[out] stack_region_size The size of the memory region used as the | |
165 //! thread’s stack. | |
166 //! | |
167 //! \return The base address (lowest address) of the memory region used as the | |
168 //! thread’s stack. | |
169 mach_vm_address_t CalculateStackRegion(mach_vm_address_t stack_pointer, | |
170 mach_vm_size_t* stack_region_size); | |
171 | |
172 //! \brief Adjusts the region for the red zone, if the ABI requires one. | |
173 //! | |
174 //! This method performs red zone calculation for CalculateStackRegion(). Its | |
175 //! parameters are local variables used within that method, and may be | |
176 //! modified as needed. | |
177 //! | |
178 //! Where a red zone is required, the region of memory captured for a thread’s | |
179 //! stack will be extended to include the red zone below the stack pointer, | |
180 //! provided that such memory is mapped, readable, and has the correct user | |
181 //! tag value. If these conditions cannot be met fully, as much of the red | |
182 //! zone will be captured as is possible while meeting these conditions. | |
183 //! | |
184 //! \param[inout] start_address The base address of the region to begin | |
185 //! capturing stack memory from. On entry, \a start_address is the stack | |
186 //! pointer. On return, \a start_address may be decreased to encompass a | |
187 //! red zone. | |
188 //! \param[inout] region_base The base address of the region that contains | |
189 //! stack memory. This is distinct from \a start_address in that \a | |
190 //! region_base will be page-aligned. On entry, \a region_base is the | |
191 //! base address of a region that contains \a start_address. On return, | |
192 //! if \a start_address is decremented and is outside of the region | |
193 //! originally described by \a region_base, \a region_base will also be | |
194 //! decremented appropriately. | |
195 //! \param[inout] region_size The size of the region that contains stack | |
196 //! memory. This region begins at \a region_base. On return, if \a | |
197 //! region_base is decremented, \a region_size will be incremented | |
198 //! appropriately. | |
199 //! \param[in] user_tag The Mach VM system’s user tag for the region described | |
200 //! by the initial values of \a region_base and \a region_size. The red | |
201 //! zone will only be allowed to extend out of the region described by | |
202 //! these initial values if the user tag is appropriate for stack memory | |
203 //! and the expanded region has the same user tag value. | |
204 void LocateRedZone(mach_vm_address_t* start_address, | |
205 mach_vm_address_t* region_base, | |
206 mach_vm_address_t* region_size, | |
207 unsigned int user_tag); | |
208 | |
209 kinfo_proc kern_proc_info_; | |
210 std::vector<Thread> threads_; // owns send rights | |
211 std::vector<Module> modules_; | |
212 PointerVector<MachOImageReader> module_readers_; | |
213 scoped_ptr<TaskMemory> task_memory_; | |
214 task_t task_; // weak | |
215 InitializationStateDcheck initialized_; | |
216 | |
217 // This shadows a bit in kern_proc_info_, but it’s accessed so frequently that | |
218 // it’s given a first-class field to save a few bit operations on each access. | |
219 bool is_64_bit_; | |
220 | |
221 bool initialized_threads_; | |
222 bool initialized_modules_; | |
223 | |
224 DISALLOW_COPY_AND_ASSIGN(ProcessReader); | |
225 }; | |
226 | |
227 } // namespace crashpad | |
228 | |
229 #endif // CRASHPAD_UTIL_MAC_PROCESS_READER_H_ | |
OLD | NEW |