DynamicLoaderMacOSXDYLD.h revision 6e3dc10663891a232585968ddd3b19df563dbb96
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 vmaddr(LLDB_INVALID_ADDRESS), 172 vmsize(0), 173 fileoff(0), 174 filesize(0), 175 maxprot(0), 176 initprot(0), 177 nsects(0), 178 flags(0) 179 { 180 } 181 182 lldb_private::ConstString name; 183 lldb::addr_t vmaddr; 184 lldb::addr_t vmsize; 185 lldb::addr_t fileoff; 186 lldb::addr_t filesize; 187 uint32_t maxprot; 188 uint32_t initprot; 189 uint32_t nsects; 190 uint32_t flags; 191 192 bool 193 operator==(const Segment& rhs) const 194 { 195 return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; 196 } 197 198 void 199 PutToLog (lldb_private::Log *log, 200 lldb::addr_t slide) const; 201 202 }; 203 204 struct DYLDImageInfo 205 { 206 lldb::addr_t address; // Address of mach header for this dylib 207 lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. 208 lldb::addr_t mod_date; // Modification date for this dylib 209 lldb_private::FileSpec file_spec; // Resolved path for this dylib 210 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros 211 llvm::MachO::mach_header header; // The mach header for this image 212 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) 213 214 DYLDImageInfo() : 215 address(LLDB_INVALID_ADDRESS), 216 slide(0), 217 mod_date(0), 218 file_spec(), 219 uuid(), 220 header(), 221 segments() 222 { 223 } 224 225 void 226 Clear(bool load_cmd_data_only) 227 { 228 if (!load_cmd_data_only) 229 { 230 address = LLDB_INVALID_ADDRESS; 231 slide = 0; 232 mod_date = 0; 233 file_spec.Clear(); 234 ::memset (&header, 0, sizeof(header)); 235 } 236 uuid.Clear(); 237 segments.clear(); 238 } 239 240 bool 241 operator == (const DYLDImageInfo& rhs) const 242 { 243 return address == rhs.address 244 && slide == rhs.slide 245 && mod_date == rhs.mod_date 246 && file_spec == rhs.file_spec 247 && uuid == rhs.uuid 248 && memcmp(&header, &rhs.header, sizeof(header)) == 0 249 && segments == rhs.segments; 250 } 251 252 bool 253 UUIDValid() const 254 { 255 return uuid.IsValid(); 256 } 257 258 uint32_t 259 GetAddressByteSize () 260 { 261 if (header.cputype) 262 { 263 if (header.cputype & llvm::MachO::CPUArchABI64) 264 return 8; 265 else 266 return 4; 267 } 268 return 0; 269 } 270 271 lldb::ByteOrder 272 GetByteOrder() 273 { 274 switch (header.magic) 275 { 276 case llvm::MachO::HeaderMagic32: // MH_MAGIC 277 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 278 return lldb::endian::InlHostByteOrder(); 279 280 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM 281 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 282 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) 283 return lldb::eByteOrderBig; 284 else 285 return lldb::eByteOrderLittle; 286 default: 287 assert (!"invalid header.magic value"); 288 break; 289 } 290 return lldb::endian::InlHostByteOrder(); 291 } 292 293 lldb_private::ArchSpec 294 GetArchitecture () const 295 { 296 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); 297 } 298 299 const Segment * 300 FindSegment (const lldb_private::ConstString &name) const; 301 302 void 303 PutToLog (lldb_private::Log *log) const; 304 305 typedef std::vector<DYLDImageInfo> collection; 306 typedef collection::iterator iterator; 307 typedef collection::const_iterator const_iterator; 308 }; 309 310 struct DYLDAllImageInfos 311 { 312 uint32_t version; 313 uint32_t dylib_info_count; // Version >= 1 314 lldb::addr_t dylib_info_addr; // Version >= 1 315 lldb::addr_t notification; // Version >= 1 316 bool processDetachedFromSharedRegion; // Version >= 1 317 bool libSystemInitialized; // Version >= 2 318 lldb::addr_t dyldImageLoadAddress; // Version >= 2 319 320 DYLDAllImageInfos() : 321 version (0), 322 dylib_info_count (0), 323 dylib_info_addr (LLDB_INVALID_ADDRESS), 324 notification (LLDB_INVALID_ADDRESS), 325 processDetachedFromSharedRegion (false), 326 libSystemInitialized (false), 327 dyldImageLoadAddress (LLDB_INVALID_ADDRESS) 328 { 329 } 330 331 void 332 Clear() 333 { 334 version = 0; 335 dylib_info_count = 0; 336 dylib_info_addr = LLDB_INVALID_ADDRESS; 337 notification = LLDB_INVALID_ADDRESS; 338 processDetachedFromSharedRegion = false; 339 libSystemInitialized = false; 340 dyldImageLoadAddress = LLDB_INVALID_ADDRESS; 341 } 342 343 bool 344 IsValid() const 345 { 346 return version >= 1 || version <= 6; 347 } 348 }; 349 350 void 351 RegisterNotificationCallbacks(); 352 353 void 354 UnregisterNotificationCallbacks(); 355 356 uint32_t 357 ParseLoadCommands (const lldb_private::DataExtractor& data, 358 DYLDImageInfo& dylib_info, 359 lldb_private::FileSpec *lc_id_dylinker); 360 361 bool 362 UpdateImageLoadAddress(lldb_private::Module *module, 363 DYLDImageInfo& info); 364 365 bool 366 UnloadImageLoadAddress (lldb_private::Module *module, 367 DYLDImageInfo& info); 368 369 lldb::ModuleSP 370 FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, 371 bool can_create, 372 bool *did_create_ptr); 373 374 DYLDImageInfo * 375 GetImageInfo (lldb_private::Module *module); 376 377 bool 378 NeedToLocateDYLD () const; 379 380 bool 381 SetNotificationBreakpoint (); 382 383 bool 384 ReadAllImageInfosStructure (); 385 386 DYLDImageInfo m_dyld; // Info about the current dyld being used 387 lldb::addr_t m_dyld_all_image_infos_addr; 388 DYLDAllImageInfos m_dyld_all_image_infos; 389 uint32_t m_dyld_all_image_infos_stop_id; 390 lldb::user_id_t m_break_id; 391 DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information 392 uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for 393 mutable lldb_private::Mutex m_mutex; 394 lldb_private::Process::Notifications m_notification_callbacks; 395 396private: 397 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD); 398}; 399 400#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 401