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