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 // This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / 11 // watchOS) 12 // platforms earlier than 2016, where lldb would read the "dyld_all_image_infos" 13 // dyld internal structure to understand where things were loaded and the 14 // solib loaded/unloaded notification function we put a breakpoint on gives us 15 // an array of (load address, mod time, file path) tuples. 16 // 17 // As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses 18 // dyld SPI functions to get the same information without reading internal dyld 19 // data structures. 20 21 #ifndef liblldb_DynamicLoaderMacOSXDYLD_h_ 22 #define liblldb_DynamicLoaderMacOSXDYLD_h_ 23 24 // C Includes 25 // C++ Includes 26 #include <mutex> 27 #include <vector> 28 29 // Other libraries and framework includes 30 // Project includes 31 #include "lldb/Core/StructuredData.h" 32 #include "lldb/Core/UUID.h" 33 #include "lldb/Host/FileSpec.h" 34 #include "lldb/Target/DynamicLoader.h" 35 #include "lldb/Target/Process.h" 36 #include "lldb/Utility/SafeMachO.h" 37 38 #include "DynamicLoaderDarwin.h" 39 40 class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { 41 public: 42 DynamicLoaderMacOSXDYLD(lldb_private::Process *process); 43 44 virtual ~DynamicLoaderMacOSXDYLD() override; 45 46 //------------------------------------------------------------------ 47 // Static Functions 48 //------------------------------------------------------------------ 49 static void Initialize(); 50 51 static void Terminate(); 52 53 static lldb_private::ConstString GetPluginNameStatic(); 54 55 static const char *GetPluginDescriptionStatic(); 56 57 static lldb_private::DynamicLoader * 58 CreateInstance(lldb_private::Process *process, bool force); 59 60 //------------------------------------------------------------------ 61 /// Called after attaching a process. 62 /// 63 /// Allow DynamicLoader plug-ins to execute some code after 64 /// attaching to a process. 65 //------------------------------------------------------------------ 66 bool ProcessDidExec() override; 67 68 lldb_private::Error CanLoadImage() override; 69 70 bool GetSharedCacheInformation( 71 lldb::addr_t &base_address, lldb_private::UUID &uuid, 72 lldb_private::LazyBool &using_shared_cache, 73 lldb_private::LazyBool &private_shared_cache) override; 74 75 //------------------------------------------------------------------ 76 // PluginInterface protocol 77 //------------------------------------------------------------------ 78 lldb_private::ConstString GetPluginName() override; 79 80 uint32_t GetPluginVersion() override; 81 82 protected: 83 void PutToLog(lldb_private::Log *log) const; 84 85 void DoInitialImageFetch() override; 86 87 bool NeedToDoInitialImageFetch() override; 88 89 bool DidSetNotificationBreakpoint() override; 90 91 void DoClear() override; 92 93 bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr); 94 95 static bool 96 NotifyBreakpointHit(void *baton, 97 lldb_private::StoppointCallbackContext *context, 98 lldb::user_id_t break_id, lldb::user_id_t break_loc_id); 99 100 uint32_t AddrByteSize(); 101 102 bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header, 103 lldb_private::DataExtractor *load_command_data); 104 105 uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data, 106 ImageInfo &dylib_info, 107 lldb_private::FileSpec *lc_id_dylinker); 108 109 struct DYLDAllImageInfos { 110 uint32_t version; 111 uint32_t dylib_info_count; // Version >= 1 112 lldb::addr_t dylib_info_addr; // Version >= 1 113 lldb::addr_t notification; // Version >= 1 114 bool processDetachedFromSharedRegion; // Version >= 1 115 bool libSystemInitialized; // Version >= 2 116 lldb::addr_t dyldImageLoadAddress; // Version >= 2 117 118 DYLDAllImageInfos() 119 : version(0), dylib_info_count(0), 120 dylib_info_addr(LLDB_INVALID_ADDRESS), 121 notification(LLDB_INVALID_ADDRESS), 122 processDetachedFromSharedRegion(false), libSystemInitialized(false), 123 dyldImageLoadAddress(LLDB_INVALID_ADDRESS) {} 124 125 void Clear() { 126 version = 0; 127 dylib_info_count = 0; 128 dylib_info_addr = LLDB_INVALID_ADDRESS; 129 notification = LLDB_INVALID_ADDRESS; 130 processDetachedFromSharedRegion = false; 131 libSystemInitialized = false; 132 dyldImageLoadAddress = LLDB_INVALID_ADDRESS; 133 } 134 135 bool IsValid() const { return version >= 1 || version <= 6; } 136 }; 137 138 static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); 139 140 bool SetNotificationBreakpoint() override; 141 142 void ClearNotificationBreakpoint() override; 143 144 // There is a little tricky bit where you might initially attach while dyld is 145 // updating 146 // the all_image_infos, and you can't read the infos, so you have to continue 147 // and pick it 148 // up when you hit the update breakpoint. At that point, you need to run this 149 // initialize 150 // function, but when you do it that way you DON'T need to do the extra work 151 // you would at 152 // the breakpoint. 153 // So this function will only do actual work if the image infos haven't been 154 // read yet. 155 // If it does do any work, then it will return true, and false otherwise. 156 // That way you can 157 // call it in the breakpoint action, and if it returns true you're done. 158 bool InitializeFromAllImageInfos(); 159 160 bool ReadAllImageInfosStructure(); 161 162 bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, 163 uint32_t image_infos_count); 164 165 bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, 166 uint32_t image_infos_count); 167 168 void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, 169 uint32_t infos_count, 170 bool update_executable); 171 172 bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count, 173 ImageInfo::collection &image_infos); 174 175 lldb::addr_t m_dyld_all_image_infos_addr; 176 DYLDAllImageInfos m_dyld_all_image_infos; 177 uint32_t m_dyld_all_image_infos_stop_id; 178 lldb::user_id_t m_break_id; 179 mutable std::recursive_mutex m_mutex; 180 bool m_process_image_addr_is_all_images_infos; 181 182 private: 183 DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOSXDYLD); 184 }; 185 186 #endif // liblldb_DynamicLoaderMacOSXDYLD_h_ 187