DynamicLoaderMacOSXDYLD.h revision 20d338fad87eba91de65aa9bec76e01c04472848
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/Core/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); 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 //------------------------------------------------------------------ 66 // Process::Notifications callback functions 67 //------------------------------------------------------------------ 68 static void 69 Initialize (void *baton, 70 lldb_private::Process *process); 71 72 static void 73 ProcessStateChanged (void *baton, 74 lldb_private::Process *process, 75 lldb::StateType state); 76 77 virtual lldb::ThreadPlanSP 78 GetStepThroughTrampolinePlan (lldb_private::Thread &thread, 79 bool stop_others); 80 81 virtual lldb_private::Error 82 CanLoadImage (); 83 84 //------------------------------------------------------------------ 85 // PluginInterface protocol 86 //------------------------------------------------------------------ 87 virtual const char * 88 GetPluginName(); 89 90 virtual const char * 91 GetShortPluginName(); 92 93 virtual uint32_t 94 GetPluginVersion(); 95 96 virtual void 97 GetPluginCommandHelp (const char *command, lldb_private::Stream *strm); 98 99 virtual lldb_private::Error 100 ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm); 101 102 virtual lldb_private::Log * 103 EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command); 104 105 106 107protected: 108 void 109 PrivateInitialize (lldb_private::Process *process); 110 111 void 112 PrivateProcessStateChanged (lldb_private::Process *process, 113 lldb::StateType state); 114 bool 115 LocateDYLD (); 116 117 bool 118 DidSetNotificationBreakpoint () const; 119 120 void 121 Clear (bool clear_process); 122 123 void 124 PutToLog (lldb_private::Log *log) const; 125 126 bool 127 ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr); 128 129 uint32_t 130 UpdateAllImageInfos (); 131 132 static bool 133 NotifyBreakpointHit (void *baton, 134 lldb_private::StoppointCallbackContext *context, 135 lldb::user_id_t break_id, 136 lldb::user_id_t break_loc_id); 137 void 138 UpdateAllImageInfosHeaderAndLoadCommands (); 139 140 bool 141 UpdateCommPageLoadAddress (lldb_private::Module *module); 142 143 uint32_t 144 AddrByteSize() 145 { 146 switch (m_dyld.header.magic) 147 { 148 case llvm::MachO::HeaderMagic32: 149 case llvm::MachO::HeaderMagic32Swapped: 150 return 4; 151 152 case llvm::MachO::HeaderMagic64: 153 case llvm::MachO::HeaderMagic64Swapped: 154 return 8; 155 156 default: 157 break; 158 } 159 return 0; 160 } 161 162 static lldb::ByteOrder 163 GetByteOrderFromMagic (uint32_t magic) 164 { 165 switch (magic) 166 { 167 case llvm::MachO::HeaderMagic32: 168 case llvm::MachO::HeaderMagic64: 169 return lldb::eByteOrderHost; 170 171 case llvm::MachO::HeaderMagic32Swapped: 172 case llvm::MachO::HeaderMagic64Swapped: 173 if (lldb::eByteOrderHost == lldb::eByteOrderBig) 174 return lldb::eByteOrderLittle; 175 else 176 return lldb::eByteOrderBig; 177 178 default: 179 break; 180 } 181 return lldb::eByteOrderInvalid; 182 } 183 184 bool 185 ReadMachHeader (lldb::addr_t addr, 186 llvm::MachO::mach_header *header, 187 lldb_private::DataExtractor *load_command_data); 188 class Segment 189 { 190 public: 191 192 Segment() : 193 name(), 194 addr(LLDB_INVALID_ADDRESS), 195 size(0) 196 { 197 } 198 199 lldb_private::ConstString name; 200 lldb::addr_t addr; 201 lldb::addr_t size; 202 203 bool 204 operator==(const Segment& rhs) const 205 { 206 return name == rhs.name && addr == rhs.addr && size == rhs.size; 207 } 208 209 void 210 PutToLog (lldb_private::Log *log, 211 lldb::addr_t slide) const; 212 213 }; 214 215 struct DYLDImageInfo 216 { 217 lldb::addr_t address; // Address of mach header for this dylib 218 lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. 219 lldb::addr_t mod_date; // Modification date for this dylib 220 lldb_private::FileSpec file_spec; // Resolved path for this dylib 221 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros 222 llvm::MachO::mach_header header; // The mach header for this image 223 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) 224 225 DYLDImageInfo() : 226 address(LLDB_INVALID_ADDRESS), 227 slide(0), 228 mod_date(0), 229 file_spec(), 230 uuid(), 231 header(), 232 segments() 233 { 234 } 235 236 void 237 Clear(bool load_cmd_data_only) 238 { 239 if (!load_cmd_data_only) 240 { 241 address = LLDB_INVALID_ADDRESS; 242 slide = 0; 243 mod_date = 0; 244 file_spec.Clear(); 245 ::bzero (&header, sizeof(header)); 246 } 247 uuid.Clear(); 248 segments.clear(); 249 } 250 251 bool 252 operator == (const DYLDImageInfo& rhs) const 253 { 254 return address == rhs.address 255 && slide == rhs.slide 256 && mod_date == rhs.mod_date 257 && file_spec == rhs.file_spec 258 && uuid == rhs.uuid 259 && memcmp(&header, &rhs.header, sizeof(header)) == 0 260 && segments == rhs.segments; 261 } 262 263 bool 264 UUIDValid() const 265 { 266 return uuid.IsValid(); 267 } 268 269 uint32_t 270 GetAddressByteSize () 271 { 272 if (header.cputype) 273 { 274 if (header.cputype & llvm::MachO::CPUArchABI64) 275 return 8; 276 else 277 return 4; 278 } 279 return 0; 280 } 281 282 lldb::ByteOrder 283 GetByteOrder() 284 { 285 switch (header.magic) 286 { 287 case llvm::MachO::HeaderMagic32: // MH_MAGIC 288 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 289 return lldb::eByteOrderHost; 290 291 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM 292 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 293 if (lldb::eByteOrderHost == lldb::eByteOrderLittle) 294 return lldb::eByteOrderBig; 295 else 296 return lldb::eByteOrderLittle; 297 default: 298 assert (!"invalid header.magic value"); 299 break; 300 } 301 return lldb::eByteOrderHost; 302 } 303 304 const Segment * 305 FindSegment (const lldb_private::ConstString &name) const; 306 307 void 308 PutToLog (lldb_private::Log *log) const; 309 310 typedef std::vector<DYLDImageInfo> collection; 311 typedef collection::iterator iterator; 312 typedef collection::const_iterator const_iterator; 313 }; 314 315 struct DYLDAllImageInfos 316 { 317 uint32_t version; 318 uint32_t dylib_info_count; // Version >= 1 319 lldb::addr_t dylib_info_addr; // Version >= 1 320 lldb::addr_t notification; // Version >= 1 321 bool processDetachedFromSharedRegion; // Version >= 1 322 bool libSystemInitialized; // Version >= 2 323 lldb::addr_t dyldImageLoadAddress; // Version >= 2 324 325 DYLDAllImageInfos() : 326 version (0), 327 dylib_info_count (0), 328 dylib_info_addr (LLDB_INVALID_ADDRESS), 329 notification (LLDB_INVALID_ADDRESS), 330 processDetachedFromSharedRegion (false), 331 libSystemInitialized (false), 332 dyldImageLoadAddress (LLDB_INVALID_ADDRESS) 333 { 334 } 335 336 void 337 Clear() 338 { 339 version = 0; 340 dylib_info_count = 0; 341 dylib_info_addr = LLDB_INVALID_ADDRESS; 342 notification = LLDB_INVALID_ADDRESS; 343 processDetachedFromSharedRegion = false; 344 libSystemInitialized = false; 345 dyldImageLoadAddress = LLDB_INVALID_ADDRESS; 346 } 347 348 bool 349 IsValid() const 350 { 351 return version >= 1 || version <= 6; 352 } 353 }; 354 355 void 356 RegisterNotificationCallbacks(); 357 358 void 359 UnregisterNotificationCallbacks(); 360 361 uint32_t 362 ParseLoadCommands (const lldb_private::DataExtractor& data, 363 struct DYLDImageInfo& dylib_info, 364 lldb_private::FileSpec *lc_id_dylinker); 365 366 bool 367 UpdateImageLoadAddress(lldb_private::Module *module, 368 struct DYLDImageInfo& info); 369 370 bool 371 UnloadImageLoadAddress (lldb_private::Module *module, 372 struct DYLDImageInfo& info); 373 374 bool 375 NeedToLocateDYLD () const; 376 377 bool 378 SetNotificationBreakpoint (); 379 380 bool 381 ReadAllImageInfosStructure (); 382 383 DYLDImageInfo m_dyld; // Info about the curent dyld being used 384 lldb::addr_t m_dyld_all_image_infos_addr; 385 DYLDAllImageInfos m_dyld_all_image_infos; 386 uint32_t m_dyld_all_image_infos_stop_id; 387 lldb::user_id_t m_break_id; 388 DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information 389 uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for 390 mutable lldb_private::Mutex m_mutex; 391 lldb_private::Process::Notifications m_notification_callbacks; 392 393private: 394 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD); 395}; 396 397#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 398