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