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