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