| //===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / |
| // watchOS / BridgeOS) |
| // platforms earlier than 2016, where lldb would read the "dyld_all_image_infos" |
| // dyld internal structure to understand where things were loaded and the |
| // solib loaded/unloaded notification function we put a breakpoint on gives us |
| // an array of (load address, mod time, file path) tuples. |
| // |
| // As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses |
| // dyld SPI functions to get the same information without reading internal dyld |
| // data structures. |
| |
| #ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H |
| #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H |
| |
| #include <mutex> |
| #include <vector> |
| |
| #include "lldb/Host/SafeMachO.h" |
| #include "lldb/Target/DynamicLoader.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Utility/FileSpec.h" |
| #include "lldb/Utility/StructuredData.h" |
| #include "lldb/Utility/UUID.h" |
| |
| #include "DynamicLoaderDarwin.h" |
| |
| class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { |
| public: |
| DynamicLoaderMacOSXDYLD(lldb_private::Process *process); |
| |
| ~DynamicLoaderMacOSXDYLD() override; |
| |
| // Static Functions |
| static void Initialize(); |
| |
| static void Terminate(); |
| |
| static lldb_private::ConstString GetPluginNameStatic(); |
| |
| static const char *GetPluginDescriptionStatic(); |
| |
| static lldb_private::DynamicLoader * |
| CreateInstance(lldb_private::Process *process, bool force); |
| |
| /// Called after attaching a process. |
| /// |
| /// Allow DynamicLoader plug-ins to execute some code after |
| /// attaching to a process. |
| bool ProcessDidExec() override; |
| |
| lldb_private::Status CanLoadImage() override; |
| |
| bool GetSharedCacheInformation( |
| lldb::addr_t &base_address, lldb_private::UUID &uuid, |
| lldb_private::LazyBool &using_shared_cache, |
| lldb_private::LazyBool &private_shared_cache) override; |
| |
| // PluginInterface protocol |
| lldb_private::ConstString GetPluginName() override; |
| |
| uint32_t GetPluginVersion() override; |
| |
| bool IsFullyInitialized() override; |
| |
| protected: |
| void PutToLog(lldb_private::Log *log) const; |
| |
| void DoInitialImageFetch() override; |
| |
| bool NeedToDoInitialImageFetch() override; |
| |
| bool DidSetNotificationBreakpoint() override; |
| |
| void DoClear() override; |
| |
| bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr); |
| |
| static bool |
| NotifyBreakpointHit(void *baton, |
| lldb_private::StoppointCallbackContext *context, |
| lldb::user_id_t break_id, lldb::user_id_t break_loc_id); |
| |
| uint32_t AddrByteSize(); |
| |
| bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header, |
| lldb_private::DataExtractor *load_command_data); |
| |
| uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data, |
| ImageInfo &dylib_info, |
| lldb_private::FileSpec *lc_id_dylinker); |
| |
| struct DYLDAllImageInfos { |
| uint32_t version = 0; |
| uint32_t dylib_info_count = 0; // Version >= 1 |
| lldb::addr_t dylib_info_addr = LLDB_INVALID_ADDRESS; // Version >= 1 |
| lldb::addr_t notification = LLDB_INVALID_ADDRESS; // Version >= 1 |
| bool processDetachedFromSharedRegion = false; // Version >= 1 |
| bool libSystemInitialized = false; // Version >= 2 |
| lldb::addr_t dyldImageLoadAddress = LLDB_INVALID_ADDRESS; // Version >= 2 |
| |
| DYLDAllImageInfos() = default; |
| |
| void Clear() { |
| version = 0; |
| dylib_info_count = 0; |
| dylib_info_addr = LLDB_INVALID_ADDRESS; |
| notification = LLDB_INVALID_ADDRESS; |
| processDetachedFromSharedRegion = false; |
| libSystemInitialized = false; |
| dyldImageLoadAddress = LLDB_INVALID_ADDRESS; |
| } |
| |
| bool IsValid() const { return version >= 1 && version <= 6; } |
| }; |
| |
| static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); |
| |
| bool SetNotificationBreakpoint() override; |
| |
| void ClearNotificationBreakpoint() override; |
| |
| // There is a little tricky bit where you might initially attach while dyld is |
| // updating |
| // the all_image_infos, and you can't read the infos, so you have to continue |
| // and pick it |
| // up when you hit the update breakpoint. At that point, you need to run this |
| // initialize |
| // function, but when you do it that way you DON'T need to do the extra work |
| // you would at |
| // the breakpoint. |
| // So this function will only do actual work if the image infos haven't been |
| // read yet. |
| // If it does do any work, then it will return true, and false otherwise. |
| // That way you can |
| // call it in the breakpoint action, and if it returns true you're done. |
| bool InitializeFromAllImageInfos(); |
| |
| bool ReadAllImageInfosStructure(); |
| |
| bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, |
| uint32_t image_infos_count); |
| |
| bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, |
| uint32_t image_infos_count); |
| |
| void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, |
| uint32_t infos_count, |
| bool update_executable); |
| |
| bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count, |
| ImageInfo::collection &image_infos); |
| |
| lldb::addr_t m_dyld_all_image_infos_addr; |
| DYLDAllImageInfos m_dyld_all_image_infos; |
| uint32_t m_dyld_all_image_infos_stop_id; |
| lldb::user_id_t m_break_id; |
| mutable std::recursive_mutex m_mutex; |
| bool m_process_image_addr_is_all_images_infos; |
| |
| private: |
| DynamicLoaderMacOSXDYLD(const DynamicLoaderMacOSXDYLD &) = delete; |
| const DynamicLoaderMacOSXDYLD & |
| operator=(const DynamicLoaderMacOSXDYLD &) = delete; |
| }; |
| |
| #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H |