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