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 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 const char *
84     GetPluginName();
85 
86     virtual const char *
87     GetShortPluginName();
88 
89     virtual uint32_t
90     GetPluginVersion();
91 
92     virtual bool
93     AlwaysRelyOnEHUnwindInfo (lldb_private::SymbolContext &sym_ctx);
94 
95 protected:
96     void
97     PrivateInitialize (lldb_private::Process *process);
98 
99     void
100     PrivateProcessStateChanged (lldb_private::Process *process,
101                                 lldb::StateType state);
102     bool
103     LocateDYLD ();
104 
105     bool
106     DidSetNotificationBreakpoint () const;
107 
108     void
109     Clear (bool clear_process);
110 
111     void
112     PutToLog (lldb_private::Log *log) const;
113 
114     bool
115     ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
116 
117     static bool
118     NotifyBreakpointHit (void *baton,
119                          lldb_private::StoppointCallbackContext *context,
120                          lldb::user_id_t break_id,
121                          lldb::user_id_t break_loc_id);
122 
123     uint32_t
124     AddrByteSize();
125 
126     static lldb::ByteOrder
127     GetByteOrderFromMagic (uint32_t magic);
128 
129     bool
130     ReadMachHeader (lldb::addr_t addr,
131                     llvm::MachO::mach_header *header,
132                     lldb_private::DataExtractor *load_command_data);
133     class Segment
134     {
135     public:
136 
137         Segment() :
138             name(),
139             vmaddr(LLDB_INVALID_ADDRESS),
140             vmsize(0),
141             fileoff(0),
142             filesize(0),
143             maxprot(0),
144             initprot(0),
145             nsects(0),
146             flags(0)
147         {
148         }
149 
150         lldb_private::ConstString name;
151         lldb::addr_t vmaddr;
152         lldb::addr_t vmsize;
153         lldb::addr_t fileoff;
154         lldb::addr_t filesize;
155         uint32_t maxprot;
156         uint32_t initprot;
157         uint32_t nsects;
158         uint32_t flags;
159 
160         bool
161         operator==(const Segment& rhs) const
162         {
163             return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
164         }
165 
166         void
167         PutToLog (lldb_private::Log *log,
168                   lldb::addr_t slide) const;
169 
170     };
171 
172     struct DYLDImageInfo
173     {
174         lldb::addr_t address;               // Address of mach header for this dylib
175         lldb::addr_t slide;                 // The amount to slide all segments by if there is a global slide.
176         lldb::addr_t mod_date;              // Modification date for this dylib
177         lldb_private::FileSpec file_spec;   // Resolved path for this dylib
178         lldb_private::UUID uuid;            // UUID for this dylib if it has one, else all zeros
179         llvm::MachO::mach_header header;    // The mach header for this image
180         std::vector<Segment> segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
181         uint32_t load_stop_id;              // The process stop ID that the sections for this image were loadeded
182 
183         DYLDImageInfo() :
184             address(LLDB_INVALID_ADDRESS),
185             slide(0),
186             mod_date(0),
187             file_spec(),
188             uuid(),
189             header(),
190             segments(),
191             load_stop_id(0)
192         {
193         }
194 
195         void
196         Clear(bool load_cmd_data_only)
197         {
198             if (!load_cmd_data_only)
199             {
200                 address = LLDB_INVALID_ADDRESS;
201                 slide = 0;
202                 mod_date = 0;
203                 file_spec.Clear();
204                 ::memset (&header, 0, sizeof(header));
205             }
206             uuid.Clear();
207             segments.clear();
208             load_stop_id = 0;
209         }
210 
211         bool
212         operator == (const DYLDImageInfo& rhs) const
213         {
214             return  address == rhs.address
215                 && slide == rhs.slide
216                 && mod_date == rhs.mod_date
217                 && file_spec == rhs.file_spec
218                 && uuid == rhs.uuid
219                 && memcmp(&header, &rhs.header, sizeof(header)) == 0
220                 && segments == rhs.segments;
221         }
222 
223         bool
224         UUIDValid() const
225         {
226             return uuid.IsValid();
227         }
228 
229         uint32_t
230         GetAddressByteSize ()
231         {
232             if (header.cputype)
233             {
234                 if (header.cputype & llvm::MachO::CPUArchABI64)
235                     return 8;
236                 else
237                     return 4;
238             }
239             return 0;
240         }
241 
242         lldb::ByteOrder
243         GetByteOrder();
244 
245         lldb_private::ArchSpec
246         GetArchitecture () const
247         {
248             return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
249         }
250 
251         const Segment *
252         FindSegment (const lldb_private::ConstString &name) const;
253 
254         void
255         PutToLog (lldb_private::Log *log) const;
256 
257         typedef std::vector<DYLDImageInfo> collection;
258         typedef collection::iterator iterator;
259         typedef collection::const_iterator const_iterator;
260     };
261 
262     struct DYLDAllImageInfos
263     {
264         uint32_t version;
265         uint32_t dylib_info_count;              // Version >= 1
266         lldb::addr_t dylib_info_addr;           // Version >= 1
267         lldb::addr_t notification;              // Version >= 1
268         bool processDetachedFromSharedRegion;   // Version >= 1
269         bool libSystemInitialized;              // Version >= 2
270         lldb::addr_t dyldImageLoadAddress;      // Version >= 2
271 
272         DYLDAllImageInfos() :
273             version (0),
274             dylib_info_count (0),
275             dylib_info_addr (LLDB_INVALID_ADDRESS),
276             notification (LLDB_INVALID_ADDRESS),
277             processDetachedFromSharedRegion (false),
278             libSystemInitialized (false),
279             dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
280         {
281         }
282 
283         void
284         Clear()
285         {
286             version = 0;
287             dylib_info_count = 0;
288             dylib_info_addr = LLDB_INVALID_ADDRESS;
289             notification = LLDB_INVALID_ADDRESS;
290             processDetachedFromSharedRegion = false;
291             libSystemInitialized = false;
292             dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
293         }
294 
295         bool
296         IsValid() const
297         {
298             return version >= 1 || version <= 6;
299         }
300     };
301 
302     void
303     RegisterNotificationCallbacks();
304 
305     void
306     UnregisterNotificationCallbacks();
307 
308     uint32_t
309     ParseLoadCommands (const lldb_private::DataExtractor& data,
310                        DYLDImageInfo& dylib_info,
311                        lldb_private::FileSpec *lc_id_dylinker);
312 
313     bool
314     UpdateImageLoadAddress(lldb_private::Module *module,
315                            DYLDImageInfo& info);
316 
317     bool
318     UnloadImageLoadAddress (lldb_private::Module *module,
319                             DYLDImageInfo& info);
320 
321     lldb::ModuleSP
322     FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info,
323                                       bool can_create,
324                                       bool *did_create_ptr);
325 
326     DYLDImageInfo *
327     GetImageInfo (lldb_private::Module *module);
328 
329     bool
330     NeedToLocateDYLD () const;
331 
332     bool
333     SetNotificationBreakpoint ();
334 
335     // There is a little tricky bit where you might initially attach while dyld is updating
336     // the all_image_infos, and you can't read the infos, so you have to continue and pick it
337     // up when you hit the update breakpoint.  At that point, you need to run this initialize
338     // function, but when you do it that way you DON'T need to do the extra work you would at
339     // the breakpoint.
340     // So this function will only do actual work if the image infos haven't been read yet.
341     // If it does do any work, then it will return true, and false otherwise.  That way you can
342     // call it in the breakpoint action, and if it returns true you're done.
343     bool
344     InitializeFromAllImageInfos ();
345 
346     bool
347     ReadAllImageInfosStructure ();
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::addr_t m_dyld_all_image_infos_addr;
371     DYLDAllImageInfos m_dyld_all_image_infos;
372     uint32_t m_dyld_all_image_infos_stop_id;
373     lldb::user_id_t m_break_id;
374     DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
375     uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
376     mutable lldb_private::Mutex m_mutex;
377     lldb_private::Process::Notifications m_notification_callbacks;
378     bool m_process_image_addr_is_all_images_infos;
379 
380 private:
381     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
382 };
383 
384 #endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
385