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