DynamicLoaderMacOSXDYLD.h revision 20d338fad87eba91de65aa9bec76e01c04472848
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/Core/FileSpec.h"
24#include "lldb/Core/UUID.h"
25#include "lldb/Host/Mutex.h"
26#include "lldb/Target/Process.h"
27
28class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
29{
30public:
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);
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    //------------------------------------------------------------------
66    // Process::Notifications callback functions
67    //------------------------------------------------------------------
68    static void
69    Initialize (void *baton,
70                lldb_private::Process *process);
71
72    static void
73    ProcessStateChanged (void *baton,
74                         lldb_private::Process *process,
75                         lldb::StateType state);
76
77    virtual lldb::ThreadPlanSP
78    GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
79                                  bool stop_others);
80
81    virtual lldb_private::Error
82    CanLoadImage ();
83
84    //------------------------------------------------------------------
85    // PluginInterface protocol
86    //------------------------------------------------------------------
87    virtual const char *
88    GetPluginName();
89
90    virtual const char *
91    GetShortPluginName();
92
93    virtual uint32_t
94    GetPluginVersion();
95
96    virtual void
97    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
98
99    virtual lldb_private::Error
100    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
101
102    virtual lldb_private::Log *
103    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
104
105
106
107protected:
108    void
109    PrivateInitialize (lldb_private::Process *process);
110
111    void
112    PrivateProcessStateChanged (lldb_private::Process *process,
113                                lldb::StateType state);
114    bool
115    LocateDYLD ();
116
117    bool
118    DidSetNotificationBreakpoint () const;
119
120    void
121    Clear (bool clear_process);
122
123    void
124    PutToLog (lldb_private::Log *log) const;
125
126    bool
127    ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
128
129    uint32_t
130    UpdateAllImageInfos ();
131
132    static bool
133    NotifyBreakpointHit (void *baton,
134                         lldb_private::StoppointCallbackContext *context,
135                         lldb::user_id_t break_id,
136                         lldb::user_id_t break_loc_id);
137    void
138    UpdateAllImageInfosHeaderAndLoadCommands ();
139
140    bool
141    UpdateCommPageLoadAddress (lldb_private::Module *module);
142
143    uint32_t
144    AddrByteSize()
145    {
146        switch (m_dyld.header.magic)
147        {
148            case llvm::MachO::HeaderMagic32:
149            case llvm::MachO::HeaderMagic32Swapped:
150                return 4;
151
152            case llvm::MachO::HeaderMagic64:
153            case llvm::MachO::HeaderMagic64Swapped:
154                return 8;
155
156            default:
157                break;
158        }
159        return 0;
160    }
161
162    static lldb::ByteOrder
163    GetByteOrderFromMagic (uint32_t magic)
164    {
165        switch (magic)
166        {
167            case llvm::MachO::HeaderMagic32:
168            case llvm::MachO::HeaderMagic64:
169                return lldb::eByteOrderHost;
170
171            case llvm::MachO::HeaderMagic32Swapped:
172            case llvm::MachO::HeaderMagic64Swapped:
173                if (lldb::eByteOrderHost == lldb::eByteOrderBig)
174                    return lldb::eByteOrderLittle;
175                else
176                    return lldb::eByteOrderBig;
177
178            default:
179                break;
180        }
181        return lldb::eByteOrderInvalid;
182    }
183
184    bool
185    ReadMachHeader (lldb::addr_t addr,
186                    llvm::MachO::mach_header *header,
187                    lldb_private::DataExtractor *load_command_data);
188    class Segment
189    {
190    public:
191
192        Segment() :
193            name(),
194            addr(LLDB_INVALID_ADDRESS),
195            size(0)
196        {
197        }
198
199        lldb_private::ConstString name;
200        lldb::addr_t addr;
201        lldb::addr_t size;
202
203        bool
204        operator==(const Segment& rhs) const
205        {
206            return name == rhs.name && addr == rhs.addr && size == rhs.size;
207        }
208
209        void
210        PutToLog (lldb_private::Log *log,
211                  lldb::addr_t slide) const;
212
213    };
214
215    struct DYLDImageInfo
216    {
217        lldb::addr_t address;           // Address of mach header for this dylib
218        lldb::addr_t slide;             // The amount to slide all segments by if there is a global slide.
219        lldb::addr_t mod_date;          // Modification date for this dylib
220        lldb_private::FileSpec file_spec;       // Resolved path for this dylib
221        lldb_private::UUID uuid;                // UUID for this dylib if it has one, else all zeros
222        llvm::MachO::mach_header header;      // The mach header for this image
223        std::vector<Segment> segments;  // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
224
225        DYLDImageInfo() :
226            address(LLDB_INVALID_ADDRESS),
227            slide(0),
228            mod_date(0),
229            file_spec(),
230            uuid(),
231            header(),
232            segments()
233        {
234        }
235
236        void
237        Clear(bool load_cmd_data_only)
238        {
239            if (!load_cmd_data_only)
240            {
241                address = LLDB_INVALID_ADDRESS;
242                slide = 0;
243                mod_date = 0;
244                file_spec.Clear();
245                ::bzero (&header, sizeof(header));
246            }
247            uuid.Clear();
248            segments.clear();
249        }
250
251        bool
252        operator == (const DYLDImageInfo& rhs) const
253        {
254            return  address == rhs.address
255                && slide == rhs.slide
256                && mod_date == rhs.mod_date
257                && file_spec == rhs.file_spec
258                && uuid == rhs.uuid
259                && memcmp(&header, &rhs.header, sizeof(header)) == 0
260                && segments == rhs.segments;
261        }
262
263        bool
264        UUIDValid() const
265        {
266            return uuid.IsValid();
267        }
268
269        uint32_t
270        GetAddressByteSize ()
271        {
272            if (header.cputype)
273            {
274                if (header.cputype & llvm::MachO::CPUArchABI64)
275                    return 8;
276                else
277                    return 4;
278            }
279            return 0;
280        }
281
282        lldb::ByteOrder
283        GetByteOrder()
284        {
285            switch (header.magic)
286            {
287            case llvm::MachO::HeaderMagic32:        // MH_MAGIC
288            case llvm::MachO::HeaderMagic64:        // MH_MAGIC_64
289                return lldb::eByteOrderHost;
290
291            case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
292            case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
293                if (lldb::eByteOrderHost == lldb::eByteOrderLittle)
294                    return lldb::eByteOrderBig;
295                else
296                    return lldb::eByteOrderLittle;
297            default:
298                assert (!"invalid header.magic value");
299                break;
300            }
301            return lldb::eByteOrderHost;
302        }
303
304        const Segment *
305        FindSegment (const lldb_private::ConstString &name) const;
306
307        void
308        PutToLog (lldb_private::Log *log) const;
309
310        typedef std::vector<DYLDImageInfo> collection;
311        typedef collection::iterator iterator;
312        typedef collection::const_iterator const_iterator;
313    };
314
315    struct DYLDAllImageInfos
316    {
317        uint32_t version;
318        uint32_t dylib_info_count;              // Version >= 1
319        lldb::addr_t dylib_info_addr;           // Version >= 1
320        lldb::addr_t notification;              // Version >= 1
321        bool processDetachedFromSharedRegion;   // Version >= 1
322        bool libSystemInitialized;              // Version >= 2
323        lldb::addr_t dyldImageLoadAddress;      // Version >= 2
324
325        DYLDAllImageInfos() :
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
336        void
337        Clear()
338        {
339            version = 0;
340            dylib_info_count = 0;
341            dylib_info_addr = LLDB_INVALID_ADDRESS;
342            notification = LLDB_INVALID_ADDRESS;
343            processDetachedFromSharedRegion = false;
344            libSystemInitialized = false;
345            dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
346        }
347
348        bool
349        IsValid() const
350        {
351            return version >= 1 || version <= 6;
352        }
353    };
354
355    void
356    RegisterNotificationCallbacks();
357
358    void
359    UnregisterNotificationCallbacks();
360
361    uint32_t
362    ParseLoadCommands (const lldb_private::DataExtractor& data,
363                       struct DYLDImageInfo& dylib_info,
364                       lldb_private::FileSpec *lc_id_dylinker);
365
366    bool
367    UpdateImageLoadAddress(lldb_private::Module *module,
368                           struct DYLDImageInfo& info);
369
370    bool
371    UnloadImageLoadAddress (lldb_private::Module *module,
372                            struct DYLDImageInfo& info);
373
374    bool
375    NeedToLocateDYLD () const;
376
377    bool
378    SetNotificationBreakpoint ();
379
380    bool
381    ReadAllImageInfosStructure ();
382
383    DYLDImageInfo m_dyld;               // Info about the curent dyld being used
384    lldb::addr_t m_dyld_all_image_infos_addr;
385    DYLDAllImageInfos m_dyld_all_image_infos;
386    uint32_t m_dyld_all_image_infos_stop_id;
387    lldb::user_id_t m_break_id;
388    DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
389    uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
390    mutable lldb_private::Mutex m_mutex;
391    lldb_private::Process::Notifications m_notification_callbacks;
392
393private:
394    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
395};
396
397#endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
398