DynamicLoaderMacOSXDYLD.h revision e6bd142d9fa7ed149bd37efd8a75637375f165b7
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 static bool 107 NotifyBreakpointHit (void *baton, 108 lldb_private::StoppointCallbackContext *context, 109 lldb::user_id_t break_id, 110 lldb::user_id_t break_loc_id); 111 112 uint32_t 113 AddrByteSize() 114 { 115 switch (m_dyld.header.magic) 116 { 117 case llvm::MachO::HeaderMagic32: 118 case llvm::MachO::HeaderMagic32Swapped: 119 return 4; 120 121 case llvm::MachO::HeaderMagic64: 122 case llvm::MachO::HeaderMagic64Swapped: 123 return 8; 124 125 default: 126 break; 127 } 128 return 0; 129 } 130 131 static lldb::ByteOrder 132 GetByteOrderFromMagic (uint32_t magic) 133 { 134 switch (magic) 135 { 136 case llvm::MachO::HeaderMagic32: 137 case llvm::MachO::HeaderMagic64: 138 return lldb::endian::InlHostByteOrder(); 139 140 case llvm::MachO::HeaderMagic32Swapped: 141 case llvm::MachO::HeaderMagic64Swapped: 142 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig) 143 return lldb::eByteOrderLittle; 144 else 145 return lldb::eByteOrderBig; 146 147 default: 148 break; 149 } 150 return lldb::eByteOrderInvalid; 151 } 152 153 bool 154 ReadMachHeader (lldb::addr_t addr, 155 llvm::MachO::mach_header *header, 156 lldb_private::DataExtractor *load_command_data); 157 class Segment 158 { 159 public: 160 161 Segment() : 162 name(), 163 vmaddr(LLDB_INVALID_ADDRESS), 164 vmsize(0), 165 fileoff(0), 166 filesize(0), 167 maxprot(0), 168 initprot(0), 169 nsects(0), 170 flags(0) 171 { 172 } 173 174 lldb_private::ConstString name; 175 lldb::addr_t vmaddr; 176 lldb::addr_t vmsize; 177 lldb::addr_t fileoff; 178 lldb::addr_t filesize; 179 uint32_t maxprot; 180 uint32_t initprot; 181 uint32_t nsects; 182 uint32_t flags; 183 184 bool 185 operator==(const Segment& rhs) const 186 { 187 return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; 188 } 189 190 void 191 PutToLog (lldb_private::Log *log, 192 lldb::addr_t slide) const; 193 194 }; 195 196 struct DYLDImageInfo 197 { 198 lldb::addr_t address; // Address of mach header for this dylib 199 lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. 200 lldb::addr_t mod_date; // Modification date for this dylib 201 lldb_private::FileSpec file_spec; // Resolved path for this dylib 202 lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros 203 llvm::MachO::mach_header header; // The mach header for this image 204 std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) 205 206 DYLDImageInfo() : 207 address(LLDB_INVALID_ADDRESS), 208 slide(0), 209 mod_date(0), 210 file_spec(), 211 uuid(), 212 header(), 213 segments() 214 { 215 } 216 217 void 218 Clear(bool load_cmd_data_only) 219 { 220 if (!load_cmd_data_only) 221 { 222 address = LLDB_INVALID_ADDRESS; 223 slide = 0; 224 mod_date = 0; 225 file_spec.Clear(); 226 ::memset (&header, 0, sizeof(header)); 227 } 228 uuid.Clear(); 229 segments.clear(); 230 } 231 232 bool 233 operator == (const DYLDImageInfo& rhs) const 234 { 235 return address == rhs.address 236 && slide == rhs.slide 237 && mod_date == rhs.mod_date 238 && file_spec == rhs.file_spec 239 && uuid == rhs.uuid 240 && memcmp(&header, &rhs.header, sizeof(header)) == 0 241 && segments == rhs.segments; 242 } 243 244 bool 245 UUIDValid() const 246 { 247 return uuid.IsValid(); 248 } 249 250 uint32_t 251 GetAddressByteSize () 252 { 253 if (header.cputype) 254 { 255 if (header.cputype & llvm::MachO::CPUArchABI64) 256 return 8; 257 else 258 return 4; 259 } 260 return 0; 261 } 262 263 lldb::ByteOrder 264 GetByteOrder() 265 { 266 switch (header.magic) 267 { 268 case llvm::MachO::HeaderMagic32: // MH_MAGIC 269 case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 270 return lldb::endian::InlHostByteOrder(); 271 272 case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM 273 case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 274 if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) 275 return lldb::eByteOrderBig; 276 else 277 return lldb::eByteOrderLittle; 278 default: 279 assert (!"invalid header.magic value"); 280 break; 281 } 282 return lldb::endian::InlHostByteOrder(); 283 } 284 285 lldb_private::ArchSpec 286 GetArchitecture () const 287 { 288 return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); 289 } 290 291 const Segment * 292 FindSegment (const lldb_private::ConstString &name) const; 293 294 void 295 PutToLog (lldb_private::Log *log) const; 296 297 typedef std::vector<DYLDImageInfo> collection; 298 typedef collection::iterator iterator; 299 typedef collection::const_iterator const_iterator; 300 }; 301 302 struct DYLDAllImageInfos 303 { 304 uint32_t version; 305 uint32_t dylib_info_count; // Version >= 1 306 lldb::addr_t dylib_info_addr; // Version >= 1 307 lldb::addr_t notification; // Version >= 1 308 bool processDetachedFromSharedRegion; // Version >= 1 309 bool libSystemInitialized; // Version >= 2 310 lldb::addr_t dyldImageLoadAddress; // Version >= 2 311 312 DYLDAllImageInfos() : 313 version (0), 314 dylib_info_count (0), 315 dylib_info_addr (LLDB_INVALID_ADDRESS), 316 notification (LLDB_INVALID_ADDRESS), 317 processDetachedFromSharedRegion (false), 318 libSystemInitialized (false), 319 dyldImageLoadAddress (LLDB_INVALID_ADDRESS) 320 { 321 } 322 323 void 324 Clear() 325 { 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 bool 336 IsValid() const 337 { 338 return version >= 1 || version <= 6; 339 } 340 }; 341 342 void 343 RegisterNotificationCallbacks(); 344 345 void 346 UnregisterNotificationCallbacks(); 347 348 uint32_t 349 ParseLoadCommands (const lldb_private::DataExtractor& data, 350 DYLDImageInfo& dylib_info, 351 lldb_private::FileSpec *lc_id_dylinker); 352 353 bool 354 UpdateImageLoadAddress(lldb_private::Module *module, 355 DYLDImageInfo& info); 356 357 bool 358 UnloadImageLoadAddress (lldb_private::Module *module, 359 DYLDImageInfo& info); 360 361 lldb::ModuleSP 362 FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, 363 bool can_create, 364 bool *did_create_ptr); 365 366 DYLDImageInfo * 367 GetImageInfo (lldb_private::Module *module); 368 369 bool 370 NeedToLocateDYLD () const; 371 372 bool 373 SetNotificationBreakpoint (); 374 375 // There is a little tricky bit where you might initially attach while dyld is updating 376 // the all_image_infos, and you can't read the infos, so you have to continue and pick it 377 // up when you hit the update breakpoint. At that point, you need to run this initialize 378 // function, but when you do it that way you DON'T need to do the extra work you would at 379 // the breakpoint. 380 // So this function will only do actual work if the image infos haven't been read yet. 381 // If it does do any work, then it will return true, and false otherwise. That way you can 382 // call it in the breakpoint action, and if it returns true you're done. 383 bool 384 InitializeFromAllImageInfos (); 385 386 bool 387 ReadAllImageInfosStructure (); 388 389 bool 390 AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); 391 392 bool 393 AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos); 394 395 bool 396 RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); 397 398 void 399 UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, 400 uint32_t infos_count, 401 bool update_executable); 402 403 bool 404 UpdateCommPageLoadAddress (lldb_private::Module *module); 405 406 bool 407 ReadImageInfos (lldb::addr_t image_infos_addr, 408 uint32_t image_infos_count, 409 DYLDImageInfo::collection &image_infos); 410 411 412 DYLDImageInfo m_dyld; // Info about the current dyld being used 413 lldb::addr_t m_dyld_all_image_infos_addr; 414 DYLDAllImageInfos m_dyld_all_image_infos; 415 uint32_t m_dyld_all_image_infos_stop_id; 416 lldb::user_id_t m_break_id; 417 DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information 418 uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for 419 mutable lldb_private::Mutex m_mutex; 420 lldb_private::Process::Notifications m_notification_callbacks; 421 422private: 423 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD); 424}; 425 426#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 427