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