OLD | NEW |
---|---|
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "base/basictypes.h" | 24 #include "base/basictypes.h" |
25 #include "base/memory/scoped_ptr.h" | 25 #include "base/memory/scoped_ptr.h" |
26 #include "util/misc/initialization_state_dcheck.h" | 26 #include "util/misc/initialization_state_dcheck.h" |
27 #include "util/misc/uuid.h" | 27 #include "util/misc/uuid.h" |
28 #include "util/stdlib/pointer_container.h" | 28 #include "util/stdlib/pointer_container.h" |
29 #include "util/mac/process_types.h" | 29 #include "util/mac/process_types.h" |
30 | 30 |
31 namespace crashpad { | 31 namespace crashpad { |
32 | 32 |
33 class MachOImageSegmentReader; | 33 class MachOImageSegmentReader; |
34 class MachOImageSymbolTableReader; | |
34 class ProcessReader; | 35 class ProcessReader; |
35 | 36 |
36 //! \brief A reader for Mach-O images mapped into another process. | 37 //! \brief A reader for Mach-O images mapped into another process. |
37 //! | 38 //! |
38 //! This class is capable of reading both 32-bit (`mach_header`/`MH_MAGIC`) and | 39 //! This class is capable of reading both 32-bit (`mach_header`/`MH_MAGIC`) and |
39 //! 64-bit (`mach_header_64`/`MH_MAGIC_64`) images based on the bitness of the | 40 //! 64-bit (`mach_header_64`/`MH_MAGIC_64`) images based on the bitness of the |
40 //! remote process. | 41 //! remote process. |
41 class MachOImageReader { | 42 class MachOImageReader { |
42 public: | 43 public: |
43 MachOImageReader(); | 44 MachOImageReader(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 const process_types::section* GetSectionByName( | 156 const process_types::section* GetSectionByName( |
156 const std::string& segment_name, | 157 const std::string& segment_name, |
157 const std::string& section_name, | 158 const std::string& section_name, |
158 mach_vm_address_t* address) const; | 159 mach_vm_address_t* address) const; |
159 | 160 |
160 //! \brief Obtain section information by section index. | 161 //! \brief Obtain section information by section index. |
161 //! | 162 //! |
162 //! \param[in] index The index of the section to return, in the order that it | 163 //! \param[in] index The index of the section to return, in the order that it |
163 //! appears in the segment load commands. This is a 1-based index, | 164 //! appears in the segment load commands. This is a 1-based index, |
164 //! matching the section number values used for `nlist::n_sect`. | 165 //! matching the section number values used for `nlist::n_sect`. |
166 //! \param[out] containing_segment The segment that contains the section. | |
167 //! This parameter can be `NULL`. | |
Robert Sesek
2014/09/05 19:04:16
Ownership/lifetime?
| |
165 //! \param[out] address The actual address that the section was loaded at in | 168 //! \param[out] address The actual address that the section was loaded at in |
166 //! memory, taking any “slide” into account if the section did not load at | 169 //! memory, taking any “slide” into account if the section did not load at |
167 //! its preferred address as stored in the Mach-O image file. This | 170 //! its preferred address as stored in the Mach-O image file. This |
168 //! parameter can be `NULL`. | 171 //! parameter can be `NULL`. |
169 //! | 172 //! |
170 //! \return A pointer to the section information. If \a index is out of range, | 173 //! \return A pointer to the section information. If \a index is out of range, |
171 //! logs a warning and returns `NULL`. | 174 //! logs a warning and returns `NULL`. |
172 //! | 175 //! |
173 //! No parameter is provided for the section’s size, because it can be | 176 //! No parameter is provided for the section’s size, because it can be |
174 //! obtained from the returned process_types::section::size field. | 177 //! obtained from the returned process_types::section::size field. |
175 //! | 178 //! |
176 //! \note The process_types::section::addr field gives the section’s preferred | 179 //! \note The process_types::section::addr field gives the section’s preferred |
177 //! load address as stored in the Mach-O image file, and is not adjusted | 180 //! load address as stored in the Mach-O image file, and is not adjusted |
178 //! for any “slide” that may have occurred when the image was loaded. Use | 181 //! for any “slide” that may have occurred when the image was loaded. Use |
179 //! \a address to obtain the section’s actual load address. | 182 //! \a address to obtain the section’s actual load address. |
180 //! \note Unlike MachOImageSegmentReader::GetSectionAtIndex(), this method | 183 //! \note Unlike MachOImageSegmentReader::GetSectionAtIndex(), this method |
181 //! accepts out-of-range values for \a index, and returns `NULL` instead | 184 //! accepts out-of-range values for \a index, and returns `NULL` instead |
182 //! of aborting execution upon encountering an out-of-range value. This is | 185 //! of aborting execution upon encountering an out-of-range value. This is |
183 //! because a Mach-O image file’s symbol table refers to this per-module | 186 //! because a Mach-O image file’s symbol table refers to this per-module |
184 //! section index, and an out-of-range index in that case should be | 187 //! section index, and an out-of-range index in that case should be |
185 //! treated as a data error (where the data is beyond this code’s control) | 188 //! treated as a data error (where the data is beyond this code’s control) |
186 //! and handled non-fatally by reporting the error to the caller. | 189 //! and handled non-fatally by reporting the error to the caller. |
187 const process_types::section* GetSectionAtIndex( | 190 const process_types::section* GetSectionAtIndex( |
188 size_t index, | 191 size_t index, |
192 const MachOImageSegmentReader** containing_segment, | |
189 mach_vm_address_t* address) const; | 193 mach_vm_address_t* address) const; |
190 | 194 |
195 //! \brief Looks up a symbol in the image’s symbol table. | |
196 //! | |
197 //! This method is capable of locating external defined symbols: those without | |
198 //! `N_STAB` (debugging) or `N_PEXT` (private external) set, and with `N_EXT` | |
199 //! (external) set. Only `N_ABS` (absolute) and `N_SECT` (defined in section) | |
200 //! symbols are supported. `N_UNDF` (undefined) and `N_INDR` (indirect) | |
201 //! symbols cannot be located through this mechanism, nor can `N_PEXT` | |
Robert Sesek
2014/09/05 19:04:16
This sounds contradictory to what you wrote on lin
| |
202 //! (private external) symbols. | |
203 //! | |
204 //! \param[in] name The name of the symbol to look up, “mangled” or | |
205 //! “decorated” appropriately. For example, use `"_main"` to look up the | |
206 //! symbol for the C `main()` function, and use `"__Z4Funcv"` to look up | |
207 //! the symbol for the C++ `Func()` function. Contrary to `dlsym()`, the | |
208 //! leading underscore must not be stripped when using this interface. | |
209 //! \param[out] value If the lookup was successful, this will be set to the | |
210 //! value of the symbol, adjusted for any “slide” as needed. The value can | |
211 //! be used as an address in the remote process’ address space where the | |
212 //! pointee of the symbol exists in memory. | |
213 //! | |
214 //! \return `true` if the symbol lookup was successful and the symbol was | |
215 //! found. `false` otherwise, including error conditions (for which a | |
216 //! warning message will be logged), modules without symbol tables, and | |
217 //! symbol names not found in the symbol table. | |
218 //! | |
219 //! \note Symbol values returned via this interface are adjusted for “slide” | |
220 //! as appropriate, in contrast to the underlying implementation, | |
221 //! MachOImageSymbolTableReader::LookUpExternalDefinedSymbol(). | |
222 //! | |
223 //! \warning Symbols that are resolved by running symbol resolvers | |
224 //! (`.symbol_resolver`) are not properly handled by this interface. The | |
225 //! address of the symbol resolver is returned because that’s what shows | |
226 //! up in the symbol table, rather than the effective address of the | |
227 //! resolved symbol as used by dyld after running the resolver. The only | |
228 //! way to detect this situation would be to read the `LC_DYLD_INFO` or | |
229 //! `LC_DYLD_INFO_ONLY` load command if present and looking for the | |
230 //! `EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER` flag, but that would just be | |
231 //! able to detect symbols with a resolver, it would not be able to | |
232 //! resolve them from out-of-process, so it’s not currently done. | |
233 bool LookUpExternalDefinedSymbol(const std::string& name, | |
234 mach_vm_address_t* value) const; | |
235 | |
191 //! \brief Returns a Mach-O dylib image’s current version. | 236 //! \brief Returns a Mach-O dylib image’s current version. |
192 //! | 237 //! |
193 //! This information comes from the `dylib_current_version` field of a dylib’s | 238 //! This information comes from the `dylib_current_version` field of a dylib’s |
194 //! `LC_ID_DYLIB` load command. For dylibs without this load command, `0` will | 239 //! `LC_ID_DYLIB` load command. For dylibs without this load command, `0` will |
195 //! be returned. | 240 //! be returned. |
196 //! | 241 //! |
197 //! This method may only be called on Mach-O images for which FileType() | 242 //! This method may only be called on Mach-O images for which FileType() |
198 //! returns `MH_DYLIB`. | 243 //! returns `MH_DYLIB`. |
199 uint32_t DylibVersion() const; | 244 uint32_t DylibVersion() const; |
200 | 245 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 const std::string& load_command_info); | 293 const std::string& load_command_info); |
249 bool ReadDylinkerCommand(mach_vm_address_t load_command_address, | 294 bool ReadDylinkerCommand(mach_vm_address_t load_command_address, |
250 const std::string& load_command_info); | 295 const std::string& load_command_info); |
251 bool ReadUUIDCommand(mach_vm_address_t load_command_address, | 296 bool ReadUUIDCommand(mach_vm_address_t load_command_address, |
252 const std::string& load_command_info); | 297 const std::string& load_command_info); |
253 bool ReadSourceVersionCommand(mach_vm_address_t load_command_address, | 298 bool ReadSourceVersionCommand(mach_vm_address_t load_command_address, |
254 const std::string& load_command_info); | 299 const std::string& load_command_info); |
255 bool ReadUnexpectedCommand(mach_vm_address_t load_command_address, | 300 bool ReadUnexpectedCommand(mach_vm_address_t load_command_address, |
256 const std::string& load_command_info); | 301 const std::string& load_command_info); |
257 | 302 |
303 // Performs deferred initialization of the symbol table. Because a module’s | |
304 // symbol table is often not needed, this is not handled in Initialize(), but | |
305 // is done lazily, on-demand as needed. | |
306 // | |
307 // symbol_table_initialized_ will be transitioned to the appropriate state. If | |
308 // initialization completes successfully, this will be the valid state. | |
309 // Otherwise, it will be left in the invalid state and a warning message will | |
310 // be logged. | |
311 // | |
312 // Note that if the object contains no symbol table, symbol_table_initialized_ | |
313 // will be set to the valid state, but symbol_table_ will be NULL. | |
314 void InitializeSymbolTable() const; | |
315 | |
258 PointerVector<MachOImageSegmentReader> segments_; | 316 PointerVector<MachOImageSegmentReader> segments_; |
259 std::map<std::string, size_t> segment_map_; | 317 std::map<std::string, size_t> segment_map_; |
260 std::string module_info_; | 318 std::string module_info_; |
261 std::string dylinker_name_; | 319 std::string dylinker_name_; |
262 crashpad::UUID uuid_; | 320 crashpad::UUID uuid_; |
263 mach_vm_address_t address_; | 321 mach_vm_address_t address_; |
264 mach_vm_size_t size_; | 322 mach_vm_size_t size_; |
265 mach_vm_size_t slide_; | 323 mach_vm_size_t slide_; |
266 uint64_t source_version_; | 324 uint64_t source_version_; |
267 scoped_ptr<process_types::symtab_command> symtab_command_; | 325 scoped_ptr<process_types::symtab_command> symtab_command_; |
268 scoped_ptr<process_types::dysymtab_command> dysymtab_command_; | 326 scoped_ptr<process_types::dysymtab_command> dysymtab_command_; |
327 | |
328 // symbol_table_ (and symbol_table_initialized_) are mutable in order to | |
329 // maintain LookUpExternalDefinedSymbol() as a const interface while allowing | |
330 // lazy initialization via InitializeSymbolTable(). This is logical | |
331 // const-ness, not physical const-ness. | |
332 mutable scoped_ptr<MachOImageSymbolTableReader> symbol_table_; | |
333 | |
269 scoped_ptr<process_types::dylib_command> id_dylib_command_; | 334 scoped_ptr<process_types::dylib_command> id_dylib_command_; |
270 ProcessReader* process_reader_; // weak | 335 ProcessReader* process_reader_; // weak |
271 uint32_t file_type_; | 336 uint32_t file_type_; |
272 InitializationStateDcheck initialized_; | 337 InitializationStateDcheck initialized_; |
273 | 338 |
339 // symbol_table_initialized_ protects symbol_table_: symbol_table_ can only | |
Robert Sesek
2014/09/05 19:04:16
Why are there members between the state and the ta
Mark Mentovai
2014/09/05 20:22:31
rsesek wrote:
| |
340 // be used when symbol_table_initialized_ is valid, although | |
341 // symbol_table_initialized_ being valid doesn’t imply that symbol_table_ is | |
342 // set. symbol_table_initialized_ will be valid without symbol_table_ being | |
343 // set in modules that have no symbol table. | |
344 mutable InitializationState symbol_table_initialized_; | |
345 | |
274 DISALLOW_COPY_AND_ASSIGN(MachOImageReader); | 346 DISALLOW_COPY_AND_ASSIGN(MachOImageReader); |
275 }; | 347 }; |
276 | 348 |
277 } // namespace crashpad | 349 } // namespace crashpad |
278 | 350 |
279 #endif // CRASHPAD_UTIL_MAC_MACH_O_IMAGE_READER_H_ | 351 #endif // CRASHPAD_UTIL_MAC_MACH_O_IMAGE_READER_H_ |
OLD | NEW |