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 lldb_private::ConstString
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 bool
66     ProcessDidExec ();
67 
68     virtual lldb::ThreadPlanSP
69     GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
70                                   bool stop_others);
71 
72     virtual size_t
73     FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
74                            lldb_private::ModuleList &module_list,
75                            lldb_private::SymbolContextList &equivalent_symbols);
76 
77     virtual lldb_private::Error
78     CanLoadImage ();
79 
80     //------------------------------------------------------------------
81     // PluginInterface protocol
82     //------------------------------------------------------------------
83     virtual lldb_private::ConstString
84     GetPluginName();
85 
86     virtual uint32_t
87     GetPluginVersion();
88 
89     virtual bool
90     AlwaysRelyOnEHUnwindInfo (lldb_private::SymbolContext &sym_ctx);
91 
92 protected:
93     void
94     PrivateInitialize (lldb_private::Process *process);
95 
96     void
97     PrivateProcessStateChanged (lldb_private::Process *process,
98                                 lldb::StateType state);
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     class Segment
131     {
132     public:
133 
Segment()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 loadeded
179 
DYLDImageInfoDYLDImageInfo180         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
ClearDYLDImageInfo193         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
UUIDValidDYLDImageInfo221         UUIDValid() const
222         {
223             return uuid.IsValid();
224         }
225 
226         uint32_t
GetAddressByteSizeDYLDImageInfo227         GetAddressByteSize ()
228         {
229             if (header.cputype)
230             {
231                 if (header.cputype & llvm::MachO::CPUArchABI64)
232                     return 8;
233                 else
234                     return 4;
235             }
236             return 0;
237         }
238 
239         lldb::ByteOrder
240         GetByteOrder();
241 
242         lldb_private::ArchSpec
GetArchitectureDYLDImageInfo243         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 
DYLDAllImageInfosDYLDAllImageInfos269         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
ClearDYLDAllImageInfos281         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
IsValidDYLDAllImageInfos293         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     AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
348 
349     bool
350     AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos);
351 
352     bool
353     RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
354 
355     void
356     UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
357                                           uint32_t infos_count,
358                                           bool update_executable);
359 
360     bool
361     ReadImageInfos (lldb::addr_t image_infos_addr,
362                     uint32_t image_infos_count,
363                     DYLDImageInfo::collection &image_infos);
364 
365 
366     DYLDImageInfo m_dyld;               // Info about the current dyld being used
367     lldb::addr_t m_dyld_all_image_infos_addr;
368     DYLDAllImageInfos m_dyld_all_image_infos;
369     uint32_t m_dyld_all_image_infos_stop_id;
370     lldb::user_id_t m_break_id;
371     DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
372     uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
373     mutable lldb_private::Mutex m_mutex;
374     lldb_private::Process::Notifications m_notification_callbacks;
375     bool m_process_image_addr_is_all_images_infos;
376 
377 private:
378     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
379 };
380 
381 #endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
382