DynamicLoaderMacOSXDYLD.h revision 24bc5d9bfad2a1c562c27e7cf37e1c56d85c45e7
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
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, 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
84protected:
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    uint32_t
107    UpdateAllImageInfos ();
108
109    static bool
110    NotifyBreakpointHit (void *baton,
111                         lldb_private::StoppointCallbackContext *context,
112                         lldb::user_id_t break_id,
113                         lldb::user_id_t break_loc_id);
114    void
115    UpdateAllImageInfosHeaderAndLoadCommands ();
116
117    bool
118    UpdateCommPageLoadAddress (lldb_private::Module *module);
119
120    uint32_t
121    AddrByteSize()
122    {
123        switch (m_dyld.header.magic)
124        {
125            case llvm::MachO::HeaderMagic32:
126            case llvm::MachO::HeaderMagic32Swapped:
127                return 4;
128
129            case llvm::MachO::HeaderMagic64:
130            case llvm::MachO::HeaderMagic64Swapped:
131                return 8;
132
133            default:
134                break;
135        }
136        return 0;
137    }
138
139    static lldb::ByteOrder
140    GetByteOrderFromMagic (uint32_t magic)
141    {
142        switch (magic)
143        {
144            case llvm::MachO::HeaderMagic32:
145            case llvm::MachO::HeaderMagic64:
146                return lldb::endian::InlHostByteOrder();
147
148            case llvm::MachO::HeaderMagic32Swapped:
149            case llvm::MachO::HeaderMagic64Swapped:
150                if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
151                    return lldb::eByteOrderLittle;
152                else
153                    return lldb::eByteOrderBig;
154
155            default:
156                break;
157        }
158        return lldb::eByteOrderInvalid;
159    }
160
161    bool
162    ReadMachHeader (lldb::addr_t addr,
163                    llvm::MachO::mach_header *header,
164                    lldb_private::DataExtractor *load_command_data);
165    class Segment
166    {
167    public:
168
169        Segment() :
170            name(),
171            addr(LLDB_INVALID_ADDRESS),
172            size(0)
173        {
174        }
175
176        lldb_private::ConstString name;
177        lldb::addr_t addr;
178        lldb::addr_t size;
179
180        bool
181        operator==(const Segment& rhs) const
182        {
183            return name == rhs.name && addr == rhs.addr && size == rhs.size;
184        }
185
186        void
187        PutToLog (lldb_private::Log *log,
188                  lldb::addr_t slide) const;
189
190    };
191
192    struct DYLDImageInfo
193    {
194        lldb::addr_t address;               // Address of mach header for this dylib
195        lldb::addr_t slide;                 // The amount to slide all segments by if there is a global slide.
196        lldb::addr_t mod_date;              // Modification date for this dylib
197        lldb_private::FileSpec file_spec;   // Resolved path for this dylib
198        lldb_private::UUID uuid;            // UUID for this dylib if it has one, else all zeros
199        llvm::MachO::mach_header header;    // The mach header for this image
200        std::vector<Segment> segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
201
202        DYLDImageInfo() :
203            address(LLDB_INVALID_ADDRESS),
204            slide(0),
205            mod_date(0),
206            file_spec(),
207            uuid(),
208            header(),
209            segments()
210        {
211        }
212
213        void
214        Clear(bool load_cmd_data_only)
215        {
216            if (!load_cmd_data_only)
217            {
218                address = LLDB_INVALID_ADDRESS;
219                slide = 0;
220                mod_date = 0;
221                file_spec.Clear();
222                ::memset (&header, 0, sizeof(header));
223            }
224            uuid.Clear();
225            segments.clear();
226        }
227
228        bool
229        operator == (const DYLDImageInfo& rhs) const
230        {
231            return  address == rhs.address
232                && slide == rhs.slide
233                && mod_date == rhs.mod_date
234                && file_spec == rhs.file_spec
235                && uuid == rhs.uuid
236                && memcmp(&header, &rhs.header, sizeof(header)) == 0
237                && segments == rhs.segments;
238        }
239
240        bool
241        UUIDValid() const
242        {
243            return uuid.IsValid();
244        }
245
246        uint32_t
247        GetAddressByteSize ()
248        {
249            if (header.cputype)
250            {
251                if (header.cputype & llvm::MachO::CPUArchABI64)
252                    return 8;
253                else
254                    return 4;
255            }
256            return 0;
257        }
258
259        lldb::ByteOrder
260        GetByteOrder()
261        {
262            switch (header.magic)
263            {
264            case llvm::MachO::HeaderMagic32:        // MH_MAGIC
265            case llvm::MachO::HeaderMagic64:        // MH_MAGIC_64
266                return lldb::endian::InlHostByteOrder();
267
268            case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
269            case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
270                if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
271                    return lldb::eByteOrderBig;
272                else
273                    return lldb::eByteOrderLittle;
274            default:
275                assert (!"invalid header.magic value");
276                break;
277            }
278            return lldb::endian::InlHostByteOrder();
279        }
280
281        lldb_private::ArchSpec
282        GetArchitecture () const
283        {
284            return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
285        }
286
287        const Segment *
288        FindSegment (const lldb_private::ConstString &name) const;
289
290        void
291        PutToLog (lldb_private::Log *log) const;
292
293        typedef std::vector<DYLDImageInfo> collection;
294        typedef collection::iterator iterator;
295        typedef collection::const_iterator const_iterator;
296    };
297
298    struct DYLDAllImageInfos
299    {
300        uint32_t version;
301        uint32_t dylib_info_count;              // Version >= 1
302        lldb::addr_t dylib_info_addr;           // Version >= 1
303        lldb::addr_t notification;              // Version >= 1
304        bool processDetachedFromSharedRegion;   // Version >= 1
305        bool libSystemInitialized;              // Version >= 2
306        lldb::addr_t dyldImageLoadAddress;      // Version >= 2
307
308        DYLDAllImageInfos() :
309            version (0),
310            dylib_info_count (0),
311            dylib_info_addr (LLDB_INVALID_ADDRESS),
312            notification (LLDB_INVALID_ADDRESS),
313            processDetachedFromSharedRegion (false),
314            libSystemInitialized (false),
315            dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
316        {
317        }
318
319        void
320        Clear()
321        {
322            version = 0;
323            dylib_info_count = 0;
324            dylib_info_addr = LLDB_INVALID_ADDRESS;
325            notification = LLDB_INVALID_ADDRESS;
326            processDetachedFromSharedRegion = false;
327            libSystemInitialized = false;
328            dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
329        }
330
331        bool
332        IsValid() const
333        {
334            return version >= 1 || version <= 6;
335        }
336    };
337
338    void
339    RegisterNotificationCallbacks();
340
341    void
342    UnregisterNotificationCallbacks();
343
344    uint32_t
345    ParseLoadCommands (const lldb_private::DataExtractor& data,
346                       DYLDImageInfo& dylib_info,
347                       lldb_private::FileSpec *lc_id_dylinker);
348
349    bool
350    UpdateImageLoadAddress(lldb_private::Module *module,
351                           DYLDImageInfo& info);
352
353    bool
354    UnloadImageLoadAddress (lldb_private::Module *module,
355                            DYLDImageInfo& info);
356
357    lldb::ModuleSP
358    FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info,
359                                      bool can_create,
360                                      bool *did_create_ptr);
361
362    DYLDImageInfo *
363    GetImageInfo (lldb_private::Module *module);
364
365    bool
366    NeedToLocateDYLD () const;
367
368    bool
369    SetNotificationBreakpoint ();
370
371    bool
372    ReadAllImageInfosStructure ();
373
374    DYLDImageInfo m_dyld;               // Info about the current dyld being used
375    lldb::addr_t m_dyld_all_image_infos_addr;
376    DYLDAllImageInfos m_dyld_all_image_infos;
377    uint32_t m_dyld_all_image_infos_stop_id;
378    lldb::user_id_t m_break_id;
379    DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
380    uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
381    mutable lldb_private::Mutex m_mutex;
382    lldb_private::Process::Notifications m_notification_callbacks;
383
384private:
385    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
386};
387
388#endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
389