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