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 |