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