xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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