DynamicLoaderMacOSXDYLD.h revision 0bce9a22354df3f00e68ffd912119a0741753b7f
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 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 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 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 182 DYLDImageInfo() : 183 address(LLDB_INVALID_ADDRESS), 184 slide(0), 185 mod_date(0), 186 file_spec(), 187 uuid(), 188 header(), 189 segments() 190 { 191 } 192 193 void 194 Clear(bool load_cmd_data_only) 195 { 196 if (!load_cmd_data_only) 197 { 198 address = LLDB_INVALID_ADDRESS; 199 slide = 0; 200 mod_date = 0; 201 file_spec.Clear(); 202 ::memset (&header, 0, sizeof(header)); 203 } 204 uuid.Clear(); 205 segments.clear(); 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 221 UUIDValid() const 222 { 223 return uuid.IsValid(); 224 } 225 226 uint32_t 227 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 243 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 269 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 281 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 293 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 (const 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 UpdateCommPageLoadAddress (lldb_private::Module *module); 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 380private: 381 DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD); 382}; 383 384#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 385