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