DynamicLoaderMacOSXDYLD.h revision 84985174d8b0fe4913caf446f7789f1531317650
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 size_t
70    FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
71                           lldb_private::ModuleList &module_list,
72                           lldb_private::SymbolContextList &equivalent_symbols);
73
74    virtual lldb_private::Error
75    CanLoadImage ();
76
77    //------------------------------------------------------------------
78    // PluginInterface protocol
79    //------------------------------------------------------------------
80    virtual const char *
81    GetPluginName();
82
83    virtual const char *
84    GetShortPluginName();
85
86    virtual uint32_t
87    GetPluginVersion();
88
89    virtual bool
90    AlwaysRelyOnEHUnwindInfo (lldb_private::SymbolContext &sym_ctx);
91
92protected:
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        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            vmaddr(LLDB_INVALID_ADDRESS),
172            vmsize(0),
173            fileoff(0),
174            filesize(0),
175            maxprot(0),
176            initprot(0),
177            nsects(0),
178            flags(0)
179        {
180        }
181
182        lldb_private::ConstString name;
183        lldb::addr_t vmaddr;
184        lldb::addr_t vmsize;
185        lldb::addr_t fileoff;
186        lldb::addr_t filesize;
187        uint32_t maxprot;
188        uint32_t initprot;
189        uint32_t nsects;
190        uint32_t flags;
191
192        bool
193        operator==(const Segment& rhs) const
194        {
195            return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
196        }
197
198        void
199        PutToLog (lldb_private::Log *log,
200                  lldb::addr_t slide) const;
201
202    };
203
204    struct DYLDImageInfo
205    {
206        lldb::addr_t address;               // Address of mach header for this dylib
207        lldb::addr_t slide;                 // The amount to slide all segments by if there is a global slide.
208        lldb::addr_t mod_date;              // Modification date for this dylib
209        lldb_private::FileSpec file_spec;   // Resolved path for this dylib
210        lldb_private::UUID uuid;            // UUID for this dylib if it has one, else all zeros
211        llvm::MachO::mach_header header;    // The mach header for this image
212        std::vector<Segment> segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
213
214        DYLDImageInfo() :
215            address(LLDB_INVALID_ADDRESS),
216            slide(0),
217            mod_date(0),
218            file_spec(),
219            uuid(),
220            header(),
221            segments()
222        {
223        }
224
225        void
226        Clear(bool load_cmd_data_only)
227        {
228            if (!load_cmd_data_only)
229            {
230                address = LLDB_INVALID_ADDRESS;
231                slide = 0;
232                mod_date = 0;
233                file_spec.Clear();
234                ::memset (&header, 0, sizeof(header));
235            }
236            uuid.Clear();
237            segments.clear();
238        }
239
240        bool
241        operator == (const DYLDImageInfo& rhs) const
242        {
243            return  address == rhs.address
244                && slide == rhs.slide
245                && mod_date == rhs.mod_date
246                && file_spec == rhs.file_spec
247                && uuid == rhs.uuid
248                && memcmp(&header, &rhs.header, sizeof(header)) == 0
249                && segments == rhs.segments;
250        }
251
252        bool
253        UUIDValid() const
254        {
255            return uuid.IsValid();
256        }
257
258        uint32_t
259        GetAddressByteSize ()
260        {
261            if (header.cputype)
262            {
263                if (header.cputype & llvm::MachO::CPUArchABI64)
264                    return 8;
265                else
266                    return 4;
267            }
268            return 0;
269        }
270
271        lldb::ByteOrder
272        GetByteOrder()
273        {
274            switch (header.magic)
275            {
276            case llvm::MachO::HeaderMagic32:        // MH_MAGIC
277            case llvm::MachO::HeaderMagic64:        // MH_MAGIC_64
278                return lldb::endian::InlHostByteOrder();
279
280            case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
281            case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
282                if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
283                    return lldb::eByteOrderBig;
284                else
285                    return lldb::eByteOrderLittle;
286            default:
287                assert (!"invalid header.magic value");
288                break;
289            }
290            return lldb::endian::InlHostByteOrder();
291        }
292
293        lldb_private::ArchSpec
294        GetArchitecture () const
295        {
296            return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
297        }
298
299        const Segment *
300        FindSegment (const lldb_private::ConstString &name) const;
301
302        void
303        PutToLog (lldb_private::Log *log) const;
304
305        typedef std::vector<DYLDImageInfo> collection;
306        typedef collection::iterator iterator;
307        typedef collection::const_iterator const_iterator;
308    };
309
310    struct DYLDAllImageInfos
311    {
312        uint32_t version;
313        uint32_t dylib_info_count;              // Version >= 1
314        lldb::addr_t dylib_info_addr;           // Version >= 1
315        lldb::addr_t notification;              // Version >= 1
316        bool processDetachedFromSharedRegion;   // Version >= 1
317        bool libSystemInitialized;              // Version >= 2
318        lldb::addr_t dyldImageLoadAddress;      // Version >= 2
319
320        DYLDAllImageInfos() :
321            version (0),
322            dylib_info_count (0),
323            dylib_info_addr (LLDB_INVALID_ADDRESS),
324            notification (LLDB_INVALID_ADDRESS),
325            processDetachedFromSharedRegion (false),
326            libSystemInitialized (false),
327            dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
328        {
329        }
330
331        void
332        Clear()
333        {
334            version = 0;
335            dylib_info_count = 0;
336            dylib_info_addr = LLDB_INVALID_ADDRESS;
337            notification = LLDB_INVALID_ADDRESS;
338            processDetachedFromSharedRegion = false;
339            libSystemInitialized = false;
340            dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
341        }
342
343        bool
344        IsValid() const
345        {
346            return version >= 1 || version <= 6;
347        }
348    };
349
350    void
351    RegisterNotificationCallbacks();
352
353    void
354    UnregisterNotificationCallbacks();
355
356    uint32_t
357    ParseLoadCommands (const lldb_private::DataExtractor& data,
358                       DYLDImageInfo& dylib_info,
359                       lldb_private::FileSpec *lc_id_dylinker);
360
361    bool
362    UpdateImageLoadAddress(lldb_private::Module *module,
363                           DYLDImageInfo& info);
364
365    bool
366    UnloadImageLoadAddress (lldb_private::Module *module,
367                            DYLDImageInfo& info);
368
369    lldb::ModuleSP
370    FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info,
371                                      bool can_create,
372                                      bool *did_create_ptr);
373
374    DYLDImageInfo *
375    GetImageInfo (lldb_private::Module *module);
376
377    bool
378    NeedToLocateDYLD () const;
379
380    bool
381    SetNotificationBreakpoint ();
382
383    // There is a little tricky bit where you might initially attach while dyld is updating
384    // the all_image_infos, and you can't read the infos, so you have to continue and pick it
385    // up when you hit the update breakpoint.  At that point, you need to run this initialize
386    // function, but when you do it that way you DON'T need to do the extra work you would at
387    // the breakpoint.
388    // So this function will only do actual work if the image infos haven't been read yet.
389    // If it does do any work, then it will return true, and false otherwise.  That way you can
390    // call it in the breakpoint action, and if it returns true you're done.
391    bool
392    InitializeFromAllImageInfos ();
393
394    bool
395    ReadAllImageInfosStructure ();
396
397    bool
398    AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
399
400    bool
401    AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos);
402
403    bool
404    RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
405
406    void
407    UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
408                                          uint32_t infos_count,
409                                          bool update_executable);
410
411    bool
412    UpdateCommPageLoadAddress (lldb_private::Module *module);
413
414    bool
415    ReadImageInfos (lldb::addr_t image_infos_addr,
416                    uint32_t image_infos_count,
417                    DYLDImageInfo::collection &image_infos);
418
419
420    DYLDImageInfo m_dyld;               // Info about the current dyld being used
421    lldb::addr_t m_dyld_all_image_infos_addr;
422    DYLDAllImageInfos m_dyld_all_image_infos;
423    uint32_t m_dyld_all_image_infos_stop_id;
424    lldb::user_id_t m_break_id;
425    DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
426    uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
427    mutable lldb_private::Mutex m_mutex;
428    lldb_private::Process::Notifications m_notification_callbacks;
429
430private:
431    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
432};
433
434#endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
435