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