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 #ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
11 #define liblldb_DynamicLoaderMacOSXDYLD_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <mutex>
16 #include <vector>
17 
18 // Other libraries and framework includes
19 // Project includes
20 #include "lldb/Target/DynamicLoader.h"
21 #include "lldb/Host/FileSpec.h"
22 #include "lldb/Core/StructuredData.h"
23 #include "lldb/Core/UUID.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Utility/SafeMachO.h"
26 
27 class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
28 {
29 public:
30     DynamicLoaderMacOSXDYLD(lldb_private::Process *process);
31 
32     ~DynamicLoaderMacOSXDYLD() override;
33 
34     //------------------------------------------------------------------
35     // Static Functions
36     //------------------------------------------------------------------
37     static void
38     Initialize();
39 
40     static void
41     Terminate();
42 
43     static lldb_private::ConstString
44     GetPluginNameStatic();
45 
46     static const char *
47     GetPluginDescriptionStatic();
48 
49     static lldb_private::DynamicLoader *
50     CreateInstance (lldb_private::Process *process, bool force);
51 
52     //------------------------------------------------------------------
53     /// Called after attaching a process.
54     ///
55     /// Allow DynamicLoader plug-ins to execute some code after
56     /// attaching to a process.
57     //------------------------------------------------------------------
58     void
59     DidAttach() override;
60 
61     void
62     DidLaunch() override;
63 
64     bool
65     ProcessDidExec() override;
66 
67     lldb::ThreadPlanSP
68     GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
69                                  bool stop_others) override;
70 
71     size_t
72     FindEquivalentSymbols(lldb_private::Symbol *original_symbol,
73                           lldb_private::ModuleList &module_list,
74                           lldb_private::SymbolContextList &equivalent_symbols) override;
75 
76     lldb_private::Error
77     CanLoadImage() override;
78 
79     //------------------------------------------------------------------
80     // PluginInterface protocol
81     //------------------------------------------------------------------
82     lldb_private::ConstString
83     GetPluginName() override;
84 
85     uint32_t
86     GetPluginVersion() override;
87 
88     bool
89     AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override;
90 
91 protected:
92     void
93     PrivateInitialize (lldb_private::Process *process);
94 
95     void
96     PrivateProcessStateChanged (lldb_private::Process *process,
97                                 lldb::StateType state);
98 
99     bool
100     LocateDYLD ();
101 
102     bool
103     DidSetNotificationBreakpoint () const;
104 
105     void
106     Clear (bool clear_process);
107 
108     void
109     PutToLog (lldb_private::Log *log) const;
110 
111     bool
112     ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
113 
114     static bool
115     NotifyBreakpointHit (void *baton,
116                          lldb_private::StoppointCallbackContext *context,
117                          lldb::user_id_t break_id,
118                          lldb::user_id_t break_loc_id);
119 
120     uint32_t
121     AddrByteSize();
122 
123     static lldb::ByteOrder
124     GetByteOrderFromMagic (uint32_t magic);
125 
126     bool
127     ReadMachHeader (lldb::addr_t addr,
128                     llvm::MachO::mach_header *header,
129                     lldb_private::DataExtractor *load_command_data);
130 
131     class Segment
132     {
133     public:
134         Segment() :
135             name(),
136             vmaddr(LLDB_INVALID_ADDRESS),
137             vmsize(0),
138             fileoff(0),
139             filesize(0),
140             maxprot(0),
141             initprot(0),
142             nsects(0),
143             flags(0)
144         {
145         }
146 
147         lldb_private::ConstString name;
148         lldb::addr_t vmaddr;
149         lldb::addr_t vmsize;
150         lldb::addr_t fileoff;
151         lldb::addr_t filesize;
152         uint32_t maxprot;
153         uint32_t initprot;
154         uint32_t nsects;
155         uint32_t flags;
156 
157         bool
158         operator==(const Segment& rhs) const
159         {
160             return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
161         }
162 
163         void
164         PutToLog (lldb_private::Log *log,
165                   lldb::addr_t slide) const;
166 
167     };
168 
169     struct DYLDImageInfo
170     {
171         lldb::addr_t address;               // Address of mach header for this dylib
172         lldb::addr_t slide;                 // The amount to slide all segments by if there is a global slide.
173         lldb::addr_t mod_date;              // Modification date for this dylib
174         lldb_private::FileSpec file_spec;   // Resolved path for this dylib
175         lldb_private::UUID uuid;            // UUID for this dylib if it has one, else all zeros
176         llvm::MachO::mach_header header;    // The mach header for this image
177         std::vector<Segment> segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
178         uint32_t load_stop_id;              // The process stop ID that the sections for this image were loaded
179 
180         DYLDImageInfo() :
181             address(LLDB_INVALID_ADDRESS),
182             slide(0),
183             mod_date(0),
184             file_spec(),
185             uuid(),
186             header(),
187             segments(),
188             load_stop_id(0)
189         {
190         }
191 
192         void
193         Clear(bool load_cmd_data_only)
194         {
195             if (!load_cmd_data_only)
196             {
197                 address = LLDB_INVALID_ADDRESS;
198                 slide = 0;
199                 mod_date = 0;
200                 file_spec.Clear();
201                 ::memset (&header, 0, sizeof(header));
202             }
203             uuid.Clear();
204             segments.clear();
205             load_stop_id = 0;
206         }
207 
208         bool
209         operator == (const DYLDImageInfo& rhs) const
210         {
211             return  address == rhs.address
212                 && slide == rhs.slide
213                 && mod_date == rhs.mod_date
214                 && file_spec == rhs.file_spec
215                 && uuid == rhs.uuid
216                 && memcmp(&header, &rhs.header, sizeof(header)) == 0
217                 && segments == rhs.segments;
218         }
219 
220         bool
221         UUIDValid() const
222         {
223             return uuid.IsValid();
224         }
225 
226         uint32_t
227         GetAddressByteSize ()
228         {
229             if (header.cputype)
230             {
231                 if (header.cputype & llvm::MachO::CPU_ARCH_ABI64)
232                     return 8;
233                 else
234                     return 4;
235             }
236             return 0;
237         }
238 
239         lldb::ByteOrder
240         GetByteOrder();
241 
242         lldb_private::ArchSpec
243         GetArchitecture () const
244         {
245             return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
246         }
247 
248         const Segment *
249         FindSegment (const lldb_private::ConstString &name) const;
250 
251         void
252         PutToLog (lldb_private::Log *log) const;
253 
254         typedef std::vector<DYLDImageInfo> collection;
255         typedef collection::iterator iterator;
256         typedef collection::const_iterator const_iterator;
257     };
258 
259     struct DYLDAllImageInfos
260     {
261         uint32_t version;
262         uint32_t dylib_info_count;              // Version >= 1
263         lldb::addr_t dylib_info_addr;           // Version >= 1
264         lldb::addr_t notification;              // Version >= 1
265         bool processDetachedFromSharedRegion;   // Version >= 1
266         bool libSystemInitialized;              // Version >= 2
267         lldb::addr_t dyldImageLoadAddress;      // Version >= 2
268 
269         DYLDAllImageInfos() :
270             version (0),
271             dylib_info_count (0),
272             dylib_info_addr (LLDB_INVALID_ADDRESS),
273             notification (LLDB_INVALID_ADDRESS),
274             processDetachedFromSharedRegion (false),
275             libSystemInitialized (false),
276             dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
277         {
278         }
279 
280         void
281         Clear()
282         {
283             version = 0;
284             dylib_info_count = 0;
285             dylib_info_addr = LLDB_INVALID_ADDRESS;
286             notification = LLDB_INVALID_ADDRESS;
287             processDetachedFromSharedRegion = false;
288             libSystemInitialized = false;
289             dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
290         }
291 
292         bool
293         IsValid() const
294         {
295             return version >= 1 || version <= 6;
296         }
297     };
298 
299     void
300     RegisterNotificationCallbacks();
301 
302     void
303     UnregisterNotificationCallbacks();
304 
305     uint32_t
306     ParseLoadCommands (const lldb_private::DataExtractor& data,
307                        DYLDImageInfo& dylib_info,
308                        lldb_private::FileSpec *lc_id_dylinker);
309 
310     bool
311     UpdateImageLoadAddress(lldb_private::Module *module,
312                            DYLDImageInfo& info);
313 
314     bool
315     UnloadImageLoadAddress (lldb_private::Module *module,
316                             DYLDImageInfo& info);
317 
318     lldb::ModuleSP
319     FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info,
320                                       bool can_create,
321                                       bool *did_create_ptr);
322 
323     DYLDImageInfo *
324     GetImageInfo (lldb_private::Module *module);
325 
326     bool
327     NeedToLocateDYLD () const;
328 
329     bool
330     SetNotificationBreakpoint ();
331 
332     // There is a little tricky bit where you might initially attach while dyld is updating
333     // the all_image_infos, and you can't read the infos, so you have to continue and pick it
334     // up when you hit the update breakpoint.  At that point, you need to run this initialize
335     // function, but when you do it that way you DON'T need to do the extra work you would at
336     // the breakpoint.
337     // So this function will only do actual work if the image infos haven't been read yet.
338     // If it does do any work, then it will return true, and false otherwise.  That way you can
339     // call it in the breakpoint action, and if it returns true you're done.
340     bool
341     InitializeFromAllImageInfos ();
342 
343     bool
344     ReadAllImageInfosStructure ();
345 
346     bool
347     AddModulesUsingInfosFromDebugserver (lldb_private::StructuredData::ObjectSP image_details, DYLDImageInfo::collection &image_infos);
348 
349     bool
350     AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
351 
352     bool
353     AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos);
354 
355     bool
356     RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
357 
358     void
359     UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
360                                           uint32_t infos_count,
361                                           bool update_executable);
362 
363     bool
364     ReadImageInfos (lldb::addr_t image_infos_addr,
365                     uint32_t image_infos_count,
366                     DYLDImageInfo::collection &image_infos);
367 
368 
369     DYLDImageInfo m_dyld;               // Info about the current dyld being used
370     lldb::ModuleWP m_dyld_module_wp;
371     lldb::addr_t m_dyld_all_image_infos_addr;
372     DYLDAllImageInfos m_dyld_all_image_infos;
373     uint32_t m_dyld_all_image_infos_stop_id;
374     lldb::user_id_t m_break_id;
375     DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
376     uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
377     mutable std::recursive_mutex m_mutex;
378     lldb_private::Process::Notifications m_notification_callbacks;
379     bool m_process_image_addr_is_all_images_infos;
380 
381 private:
382     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
383 };
384 
385 #endif // liblldb_DynamicLoaderMacOSXDYLD_h_
386