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