DynamicLoaderMacOSXDYLD.h revision 24bc5d9bfad2a1c562c27e7cf37e1c56d85c45e7
1//===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef liblldb_DynamicLoaderMacOSXDYLD_h_ 11#define liblldb_DynamicLoaderMacOSXDYLD_h_ 12 13// C Includes 14// C++ Includes 15#include <map> 16#include <vector> 17#include <string> 18 19// Other libraries and framework includes 20#include "llvm/Support/MachO.h" 21 22#include "lldb/Target/DynamicLoader.h" 23#include "lldb/Host/FileSpec.h" 24#include "lldb/Core/UUID.h" 25#include "lldb/Host/Mutex.h" 26#include "lldb/Target/Process.h" 27 28class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader 29{ 30public: 31 //------------------------------------------------------------------ 32 // Static Functions 33 //------------------------------------------------------------------ 34 static void 35 Initialize(); 36 37 static void 38 Terminate(); 39 40 static const char * 41 GetPluginNameStatic(); 42 43 static const char * 44 GetPluginDescriptionStatic(); 45 46 static lldb_private::DynamicLoader * 47 CreateInstance (lldb_private::Process *process, bool force); 48 49 DynamicLoaderMacOSXDYLD (lldb_private::Process *process); 50 51 virtual 52 ~DynamicLoaderMacOSXDYLD (); 53 //------------------------------------------------------------------ 54 /// Called after attaching a process. 55 /// 56 /// Allow DynamicLoader plug-ins to execute some code after 57 /// attaching to a process. 58 //------------------------------------------------------------------ 59 virtual void 60 DidAttach (); 61 62 virtual void 63 DidLaunch (); 64 65 virtual lldb::ThreadPlanSP 66 GetStepThroughTrampolinePlan (lldb_private::Thread &thread, 67 bool stop_others); 68 69 virtual lldb_private::Error 70 CanLoadImage (); 71 72 //------------------------------------------------------------------ 73 // PluginInterface protocol 74 //------------------------------------------------------------------ 75 virtual const char * 76 GetPluginName(); 77 78 virtual const char * 79 GetShortPluginName(); 80 81 virtual uint32_t 82 GetPluginVersion(); 83 84protected: 85 void 86 PrivateInitialize (lldb_private::Process *process); 87 88 void 89 PrivateProcessStateChanged (lldb_private::Process *process, 90 lldb::StateType state); 91 bool 92 LocateDYLD (); 93 94 bool 95 DidSetNotificationBreakpoint () const; 96 97 void 98 Clear (bool clear_process); 99 100 void 101 PutToLog (lldb_private::Log *log) const; 102 103 bool 104 ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr); 105 106 uint32_t 107 UpdateAllImageInfos (); 108 109 static bool 110 NotifyBreakpointHit (void *baton, 111 lldb_private::StoppointCallbackContext *context, 112 lldb::user_id_t break_id, 113 lldb::user_id_t break_loc_id); 114 void 115 UpdateAllImageInfosHeaderAndLoadCommands (); 116 117 bool 118 UpdateCommPageLoadAddress (lldb_private::Module *module); 119 120 uint32_t 121 AddrByteSize() 122 { 123 switch (m_dyld.header.magic) 124 { 125 case llvm::MachO::HeaderMagic32: 126 case llvm::MachO::HeaderMagic32Swapped: 127 return 4; 128 129 case llvm::MachO::HeaderMagic64: 130 case llvm::MachO::HeaderMagic64Swapped: 131 return 8; 132 133 default: 134 break; 135 } 136 return 0; 137 } 138 139 static lldb::ByteOrder 140 GetByteOrderFromMagic (uint32_t magic) 141 { 142 switch (magic) 143 { 144 case llvm::MachO::HeaderMagic32: 145 case llvm::MachO::HeaderMagic64: 146 return lldb::endian::InlHostByteOrder(); 147 148 case llvm::MachO::HeaderMagic32Swapped: 149 case llvm::MachO::HeaderMagic64Swapped: 150 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig) 151 return lldb::eByteOrderLittle; 152 else 153 return lldb::eByteOrderBig; 154 155 default: 156 break; 157 } 158 return lldb::eByteOrderInvalid; 159 } 160 161 bool 162 ReadMachHeader (lldb::addr_t addr, 163 llvm::MachO::mach_header *header, 164 lldb_private::DataExtractor *load_command_data); 165 class Segment 166 { 167 public: 168 169 Segment() : 170 name(), 171 addr(LLDB_INVALID_ADDRESS), 172 size(0) 173 { 174 } 175 176 lldb_private::ConstString name; 177 lldb::addr_t addr; 178 lldb::addr_t size; 179 180 bool 181 operator==(const Segment& rhs) const 182 { 183 return name == rhs.name && addr == rhs.addr && size == rhs.size; 184 } 185 186 void 187 PutToLog (lldb_private::Log *log, 188 lldb::addr_t slide) const; 189 190 }; 191 192 struct DYLDImageInfo 193 { 194 lldb::addr_t address; // Address of mach header for this dylib 195 lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. 196 lldb::addr_t mod_date; // Modification date for this dylib 197 lldb_private::FileSpec file_spec; // Resolved path for this dylib 198 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros 199 llvm::MachO::mach_header header; // The mach header for this image 200 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) 201 202 DYLDImageInfo() : 203 address(LLDB_INVALID_ADDRESS), 204 slide(0), 205 mod_date(0), 206 file_spec(), 207 uuid(), 208 header(), 209 segments() 210 { 211 } 212 213 void 214 Clear(bool load_cmd_data_only) 215 { 216 if (!load_cmd_data_only) 217 { 218 address = LLDB_INVALID_ADDRESS; 219 slide = 0; 220 mod_date = 0; 221 file_spec.Clear(); 222 ::memset (&header, 0, sizeof(header)); 223 } 224 uuid.Clear(); 225 segments.clear(); 226 } 227 228 bool 229 operator == (const DYLDImageInfo& rhs) const 230 { 231 return address == rhs.address 232 && slide == rhs.slide 233 && mod_date == rhs.mod_date 234 && file_spec == rhs.file_spec 235 && uuid == rhs.uuid 236 && memcmp(&header, &rhs.header, sizeof(header)) == 0 237 && segments == rhs.segments; 238 } 239 240 bool 241 UUIDValid() const 242 { 243 return uuid.IsValid(); 244 } 245 246 uint32_t 247 GetAddressByteSize () 248 { 249 if (header.cputype) 250 { 251 if (header.cputype & llvm::MachO::CPUArchABI64) 252 return 8; 253 else 254 return 4; 255 } 256 return 0; 257 } 258 259 lldb::ByteOrder 260 GetByteOrder() 261 { 262 switch (header.magic) 263 { 264 case llvm::MachO::HeaderMagic32: // MH_MAGIC 265 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 266 return lldb::endian::InlHostByteOrder(); 267 268 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM 269 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 270 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) 271 return lldb::eByteOrderBig; 272 else 273 return lldb::eByteOrderLittle; 274 default: 275 assert (!"invalid header.magic value"); 276 break; 277 } 278 return lldb::endian::InlHostByteOrder(); 279 } 280 281 lldb_private::ArchSpec 282 GetArchitecture () const 283 { 284 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); 285 } 286 287 const Segment * 288 FindSegment (const lldb_private::ConstString &name) const; 289 290 void 291 PutToLog (lldb_private::Log *log) const; 292 293 typedef std::vector<DYLDImageInfo> collection; 294 typedef collection::iterator iterator; 295 typedef collection::const_iterator const_iterator; 296 }; 297 298 struct DYLDAllImageInfos 299 { 300 uint32_t version; 301 uint32_t dylib_info_count; // Version >= 1 302 lldb::addr_t dylib_info_addr; // Version >= 1 303 lldb::addr_t notification; // Version >= 1 304 bool processDetachedFromSharedRegion; // Version >= 1 305 bool libSystemInitialized; // Version >= 2 306 lldb::addr_t dyldImageLoadAddress; // Version >= 2 307 308 DYLDAllImageInfos() : 309 version (0), 310 dylib_info_count (0), 311 dylib_info_addr (LLDB_INVALID_ADDRESS), 312 notification (LLDB_INVALID_ADDRESS), 313 processDetachedFromSharedRegion (false), 314 libSystemInitialized (false), 315 dyldImageLoadAddress (LLDB_INVALID_ADDRESS) 316 { 317 } 318 319 void 320 Clear() 321 { 322 version = 0; 323 dylib_info_count = 0; 324 dylib_info_addr = LLDB_INVALID_ADDRESS; 325 notification = LLDB_INVALID_ADDRESS; 326 processDetachedFromSharedRegion = false; 327 libSystemInitialized = false; 328 dyldImageLoadAddress = LLDB_INVALID_ADDRESS; 329 } 330 331 bool 332 IsValid() const 333 { 334 return version >= 1 || version <= 6; 335 } 336 }; 337 338 void 339 RegisterNotificationCallbacks(); 340 341 void 342 UnregisterNotificationCallbacks(); 343 344 uint32_t 345 ParseLoadCommands (const lldb_private::DataExtractor& data, 346 DYLDImageInfo& dylib_info, 347 lldb_private::FileSpec *lc_id_dylinker); 348 349 bool 350 UpdateImageLoadAddress(lldb_private::Module *module, 351 DYLDImageInfo& info); 352 353 bool 354 UnloadImageLoadAddress (lldb_private::Module *module, 355 DYLDImageInfo& info); 356 357 lldb::ModuleSP 358 FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, 359 bool can_create, 360 bool *did_create_ptr); 361 362 DYLDImageInfo * 363 GetImageInfo (lldb_private::Module *module); 364 365 bool 366 NeedToLocateDYLD () const; 367 368 bool 369 SetNotificationBreakpoint (); 370 371 bool 372 ReadAllImageInfosStructure (); 373 374 DYLDImageInfo m_dyld; // Info about the current dyld being used 375 lldb::addr_t m_dyld_all_image_infos_addr; 376 DYLDAllImageInfos m_dyld_all_image_infos; 377 uint32_t m_dyld_all_image_infos_stop_id; 378 lldb::user_id_t m_break_id; 379 DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information 380 uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for 381 mutable lldb_private::Mutex m_mutex; 382 lldb_private::Process::Notifications m_notification_callbacks; 383 384private: 385 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD); 386}; 387 388#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 389