1061da546Spatrick //===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick // This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / 10061da546Spatrick // watchOS / BridgeOS) 11061da546Spatrick // platforms earlier than 2016, where lldb would read the "dyld_all_image_infos" 12061da546Spatrick // dyld internal structure to understand where things were loaded and the 13061da546Spatrick // solib loaded/unloaded notification function we put a breakpoint on gives us 14061da546Spatrick // an array of (load address, mod time, file path) tuples. 15061da546Spatrick // 16061da546Spatrick // As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses 17061da546Spatrick // dyld SPI functions to get the same information without reading internal dyld 18061da546Spatrick // data structures. 19061da546Spatrick 20dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H 21dda28197Spatrick #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H 22061da546Spatrick 23061da546Spatrick #include <mutex> 24061da546Spatrick #include <vector> 25061da546Spatrick 26061da546Spatrick #include "lldb/Host/SafeMachO.h" 27061da546Spatrick #include "lldb/Target/DynamicLoader.h" 28061da546Spatrick #include "lldb/Target/Process.h" 29061da546Spatrick #include "lldb/Utility/FileSpec.h" 30061da546Spatrick #include "lldb/Utility/StructuredData.h" 31061da546Spatrick #include "lldb/Utility/UUID.h" 32061da546Spatrick 33061da546Spatrick #include "DynamicLoaderDarwin.h" 34061da546Spatrick 35061da546Spatrick class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { 36061da546Spatrick public: 37061da546Spatrick DynamicLoaderMacOSXDYLD(lldb_private::Process *process); 38061da546Spatrick 39061da546Spatrick ~DynamicLoaderMacOSXDYLD() override; 40061da546Spatrick 41061da546Spatrick // Static Functions 42061da546Spatrick static void Initialize(); 43061da546Spatrick 44061da546Spatrick static void Terminate(); 45061da546Spatrick GetPluginNameStatic()46*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "macosx-dyld"; } 47061da546Spatrick 48*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic(); 49061da546Spatrick 50061da546Spatrick static lldb_private::DynamicLoader * 51061da546Spatrick CreateInstance(lldb_private::Process *process, bool force); 52061da546Spatrick 53061da546Spatrick /// Called after attaching a process. 54061da546Spatrick /// 55061da546Spatrick /// Allow DynamicLoader plug-ins to execute some code after 56061da546Spatrick /// attaching to a process. 57061da546Spatrick bool ProcessDidExec() override; 58061da546Spatrick 59061da546Spatrick lldb_private::Status CanLoadImage() override; 60061da546Spatrick 61061da546Spatrick bool GetSharedCacheInformation( 62061da546Spatrick lldb::addr_t &base_address, lldb_private::UUID &uuid, 63061da546Spatrick lldb_private::LazyBool &using_shared_cache, 64061da546Spatrick lldb_private::LazyBool &private_shared_cache) override; 65061da546Spatrick 66061da546Spatrick // PluginInterface protocol GetPluginName()67*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 68061da546Spatrick 69be691f3bSpatrick bool IsFullyInitialized() override; 70be691f3bSpatrick 71061da546Spatrick protected: 72061da546Spatrick void PutToLog(lldb_private::Log *log) const; 73061da546Spatrick 74061da546Spatrick void DoInitialImageFetch() override; 75061da546Spatrick 76061da546Spatrick bool NeedToDoInitialImageFetch() override; 77061da546Spatrick 78061da546Spatrick bool DidSetNotificationBreakpoint() override; 79061da546Spatrick 80061da546Spatrick void DoClear() override; 81061da546Spatrick 82061da546Spatrick bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr); 83061da546Spatrick 84061da546Spatrick static bool 85061da546Spatrick NotifyBreakpointHit(void *baton, 86061da546Spatrick lldb_private::StoppointCallbackContext *context, 87061da546Spatrick lldb::user_id_t break_id, lldb::user_id_t break_loc_id); 88061da546Spatrick 89061da546Spatrick uint32_t AddrByteSize(); 90061da546Spatrick 91061da546Spatrick bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header, 92061da546Spatrick lldb_private::DataExtractor *load_command_data); 93061da546Spatrick 94061da546Spatrick uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data, 95061da546Spatrick ImageInfo &dylib_info, 96061da546Spatrick lldb_private::FileSpec *lc_id_dylinker); 97061da546Spatrick 98061da546Spatrick struct DYLDAllImageInfos { 99be691f3bSpatrick uint32_t version = 0; 100be691f3bSpatrick uint32_t dylib_info_count = 0; // Version >= 1 101be691f3bSpatrick lldb::addr_t dylib_info_addr = LLDB_INVALID_ADDRESS; // Version >= 1 102be691f3bSpatrick lldb::addr_t notification = LLDB_INVALID_ADDRESS; // Version >= 1 103be691f3bSpatrick bool processDetachedFromSharedRegion = false; // Version >= 1 104be691f3bSpatrick bool libSystemInitialized = false; // Version >= 2 105be691f3bSpatrick lldb::addr_t dyldImageLoadAddress = LLDB_INVALID_ADDRESS; // Version >= 2 106061da546Spatrick 107be691f3bSpatrick DYLDAllImageInfos() = default; 108061da546Spatrick ClearDYLDAllImageInfos109061da546Spatrick void Clear() { 110061da546Spatrick version = 0; 111061da546Spatrick dylib_info_count = 0; 112061da546Spatrick dylib_info_addr = LLDB_INVALID_ADDRESS; 113061da546Spatrick notification = LLDB_INVALID_ADDRESS; 114061da546Spatrick processDetachedFromSharedRegion = false; 115061da546Spatrick libSystemInitialized = false; 116061da546Spatrick dyldImageLoadAddress = LLDB_INVALID_ADDRESS; 117061da546Spatrick } 118061da546Spatrick IsValidDYLDAllImageInfos119061da546Spatrick bool IsValid() const { return version >= 1 && version <= 6; } 120061da546Spatrick }; 121061da546Spatrick 122061da546Spatrick static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); 123061da546Spatrick 124061da546Spatrick bool SetNotificationBreakpoint() override; 125061da546Spatrick 126061da546Spatrick void ClearNotificationBreakpoint() override; 127061da546Spatrick 128061da546Spatrick // There is a little tricky bit where you might initially attach while dyld is 129061da546Spatrick // updating 130061da546Spatrick // the all_image_infos, and you can't read the infos, so you have to continue 131061da546Spatrick // and pick it 132061da546Spatrick // up when you hit the update breakpoint. At that point, you need to run this 133061da546Spatrick // initialize 134061da546Spatrick // function, but when you do it that way you DON'T need to do the extra work 135061da546Spatrick // you would at 136061da546Spatrick // the breakpoint. 137061da546Spatrick // So this function will only do actual work if the image infos haven't been 138061da546Spatrick // read yet. 139061da546Spatrick // If it does do any work, then it will return true, and false otherwise. 140061da546Spatrick // That way you can 141061da546Spatrick // call it in the breakpoint action, and if it returns true you're done. 142061da546Spatrick bool InitializeFromAllImageInfos(); 143061da546Spatrick 144061da546Spatrick bool ReadAllImageInfosStructure(); 145061da546Spatrick 146061da546Spatrick bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, 147061da546Spatrick uint32_t image_infos_count); 148061da546Spatrick 149061da546Spatrick bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, 150061da546Spatrick uint32_t image_infos_count); 151061da546Spatrick 152061da546Spatrick void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, 153061da546Spatrick uint32_t infos_count, 154061da546Spatrick bool update_executable); 155061da546Spatrick 156061da546Spatrick bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count, 157061da546Spatrick ImageInfo::collection &image_infos); 158061da546Spatrick 159061da546Spatrick lldb::addr_t m_dyld_all_image_infos_addr; 160061da546Spatrick DYLDAllImageInfos m_dyld_all_image_infos; 161061da546Spatrick uint32_t m_dyld_all_image_infos_stop_id; 162061da546Spatrick lldb::user_id_t m_break_id; 163061da546Spatrick mutable std::recursive_mutex m_mutex; 164061da546Spatrick bool m_process_image_addr_is_all_images_infos; 165061da546Spatrick 166061da546Spatrick private: 167dda28197Spatrick DynamicLoaderMacOSXDYLD(const DynamicLoaderMacOSXDYLD &) = delete; 168dda28197Spatrick const DynamicLoaderMacOSXDYLD & 169dda28197Spatrick operator=(const DynamicLoaderMacOSXDYLD &) = delete; 170061da546Spatrick }; 171061da546Spatrick 172dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H 173