Chromium Code Reviews| 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 |