xref: /llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h (revision 5f2cf99e146ce99d4e148038d9bdd012331b4821)
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 llvm::StringRef GetPluginNameStatic() { return "macosx-dyld"; }
47 
48   static llvm::StringRef GetPluginDescriptionStatic();
49 
50   static lldb_private::DynamicLoader *
51   CreateInstance(lldb_private::Process *process, bool force);
52 
53   static void DebuggerInitialize(lldb_private::Debugger &debugger);
54 
55   /// Called after attaching a process.
56   ///
57   /// Allow DynamicLoader plug-ins to execute some code after
58   /// attaching to a process.
59   bool ProcessDidExec() override;
60 
61   lldb_private::Status CanLoadImage() override;
62 
63   bool GetSharedCacheInformation(
64       lldb::addr_t &base_address, lldb_private::UUID &uuid,
65       lldb_private::LazyBool &using_shared_cache,
66       lldb_private::LazyBool &private_shared_cache) override;
67 
68   // PluginInterface protocol
69   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
70 
71   bool IsFullyInitialized() override;
72 
73 protected:
74   void PutToLog(lldb_private::Log *log) const;
75 
76   void DoInitialImageFetch() override;
77 
78   bool NeedToDoInitialImageFetch() override;
79 
80   bool DidSetNotificationBreakpoint() override;
81 
82   void DoClear() override;
83 
84   bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr);
85 
86   static bool
87   NotifyBreakpointHit(void *baton,
88                       lldb_private::StoppointCallbackContext *context,
89                       lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
90 
91   uint32_t AddrByteSize();
92 
93   bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header,
94                       lldb_private::DataExtractor *load_command_data);
95 
96   uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data,
97                              ImageInfo &dylib_info,
98                              lldb_private::FileSpec *lc_id_dylinker);
99 
100   struct DYLDAllImageInfos {
101     uint32_t version = 0;
102     uint32_t dylib_info_count = 0;                            // Version >= 1
103     lldb::addr_t dylib_info_addr = LLDB_INVALID_ADDRESS;      // Version >= 1
104     lldb::addr_t notification = LLDB_INVALID_ADDRESS;         // Version >= 1
105     bool processDetachedFromSharedRegion = false;             // Version >= 1
106     bool libSystemInitialized = false;                        // Version >= 2
107     lldb::addr_t dyldImageLoadAddress = LLDB_INVALID_ADDRESS; // Version >= 2
108 
109     DYLDAllImageInfos() = default;
110 
111     void Clear() {
112       version = 0;
113       dylib_info_count = 0;
114       dylib_info_addr = LLDB_INVALID_ADDRESS;
115       notification = LLDB_INVALID_ADDRESS;
116       processDetachedFromSharedRegion = false;
117       libSystemInitialized = false;
118       dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
119     }
120 
121     bool IsValid() const { return version >= 1 && version <= 6; }
122   };
123 
124   static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic);
125 
126   bool SetNotificationBreakpoint() override;
127 
128   void ClearNotificationBreakpoint() override;
129 
130   // There is a little tricky bit where you might initially attach while dyld is
131   // updating
132   // the all_image_infos, and you can't read the infos, so you have to continue
133   // and pick it
134   // up when you hit the update breakpoint.  At that point, you need to run this
135   // initialize
136   // function, but when you do it that way you DON'T need to do the extra work
137   // you would at
138   // the breakpoint.
139   // So this function will only do actual work if the image infos haven't been
140   // read yet.
141   // If it does do any work, then it will return true, and false otherwise.
142   // That way you can
143   // call it in the breakpoint action, and if it returns true you're done.
144   bool InitializeFromAllImageInfos();
145 
146   bool ReadAllImageInfosStructure();
147 
148   bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
149                                         uint32_t image_infos_count);
150 
151   bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
152                                            uint32_t image_infos_count);
153 
154   void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos,
155                                              uint32_t infos_count,
156                                              bool update_executable);
157 
158   bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count,
159                       ImageInfo::collection &image_infos);
160 
161   lldb::addr_t m_dyld_all_image_infos_addr;
162   DYLDAllImageInfos m_dyld_all_image_infos;
163   uint32_t m_dyld_all_image_infos_stop_id;
164   lldb::user_id_t m_break_id;
165   mutable std::recursive_mutex m_mutex;
166   bool m_process_image_addr_is_all_images_infos;
167 
168 private:
169   DynamicLoaderMacOSXDYLD(const DynamicLoaderMacOSXDYLD &) = delete;
170   const DynamicLoaderMacOSXDYLD &
171   operator=(const DynamicLoaderMacOSXDYLD &) = delete;
172 };
173 
174 #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H
175