DynamicLoaderMacOSXDYLD.h revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
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#include <mach-o/loader.h>
15
16// C++ Includes
17#include <map>
18#include <vector>
19#include <string>
20
21// Other libraries and framework includes
22#include "lldb/Target/DynamicLoader.h"
23#include "lldb/Core/FileSpec.h"
24#include "lldb/Core/UUID.h"
25#include "lldb/Host/Mutex.h"
26#include "lldb/Target/Process.h"
27#include "ObjCTrampolineHandler.h"
28
29class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
30{
31public:
32    //------------------------------------------------------------------
33    // Static Functions
34    //------------------------------------------------------------------
35    static void
36    Initialize();
37
38    static void
39    Terminate();
40
41    static const char *
42    GetPluginNameStatic();
43
44    static const char *
45    GetPluginDescriptionStatic();
46
47    static lldb_private::DynamicLoader *
48    CreateInstance (lldb_private::Process *process);
49
50    DynamicLoaderMacOSXDYLD (lldb_private::Process *process);
51
52    virtual
53    ~DynamicLoaderMacOSXDYLD ();
54    //------------------------------------------------------------------
55    /// Called after attaching a process.
56    ///
57    /// Allow DynamicLoader plug-ins to execute some code after
58    /// attaching to a process.
59    //------------------------------------------------------------------
60    virtual void
61    DidAttach ();
62
63    virtual void
64    DidLaunch ();
65
66    //------------------------------------------------------------------
67    // Process::Notifications callback functions
68    //------------------------------------------------------------------
69    static void
70    Initialize (void *baton,
71                lldb_private::Process *process);
72
73    static void
74    ProcessStateChanged (void *baton,
75                         lldb_private::Process *process,
76                         lldb::StateType state);
77
78    virtual lldb::ThreadPlanSP
79    GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
80                                  bool stop_others);
81
82
83    //------------------------------------------------------------------
84    // PluginInterface protocol
85    //------------------------------------------------------------------
86    virtual const char *
87    GetPluginName();
88
89    virtual const char *
90    GetShortPluginName();
91
92    virtual uint32_t
93    GetPluginVersion();
94
95    virtual void
96    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
97
98    virtual lldb_private::Error
99    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
100
101    virtual lldb_private::Log *
102    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
103
104
105
106protected:
107    void
108    PrivateInitialize (lldb_private::Process *process);
109
110    void
111    PrivateProcessStateChanged (lldb_private::Process *process,
112                                lldb::StateType state);
113    bool
114    LocateDYLD ();
115
116    bool
117    DidSetNotificationBreakpoint () const;
118
119    void
120    Clear (bool clear_process);
121
122    void
123    PutToLog (lldb_private::Log *log) const;
124
125    bool
126    ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
127
128    uint32_t
129    UpdateAllImageInfos ();
130
131    static bool
132    NotifyBreakpointHit (void *baton,
133                         lldb_private::StoppointCallbackContext *context,
134                         lldb::user_id_t break_id,
135                         lldb::user_id_t break_loc_id);
136    void
137    UpdateAllImageInfosHeaderAndLoadCommands ();
138
139    bool
140    UpdateCommPageLoadAddress (lldb_private::Module *module);
141
142    uint32_t
143    AddrByteSize()
144    {
145        switch (m_dyld.header.magic)
146        {
147            case MH_MAGIC:
148            case MH_CIGAM:
149                return 4;
150
151            case MH_MAGIC_64:
152            case MH_CIGAM_64:
153                return 8;
154
155            default:
156                break;
157        }
158        return 0;
159    }
160
161    static lldb::ByteOrder
162    GetByteOrderFromMagic (uint32_t magic)
163    {
164        switch (magic)
165        {
166            case MH_MAGIC:
167            case MH_MAGIC_64:
168                return lldb::eByteOrderHost;
169
170            case MH_CIGAM:
171            case MH_CIGAM_64:
172                if (lldb::eByteOrderHost == lldb::eByteOrderBig)
173                    return lldb::eByteOrderLittle;
174                else
175                    return lldb::eByteOrderBig;
176
177            default:
178                break;
179        }
180        return lldb::eByteOrderInvalid;
181    }
182
183    bool
184    ReadMachHeader (lldb::addr_t addr,
185                    struct mach_header *header,
186                    lldb_private::DataExtractor *load_command_data);
187    class Segment
188    {
189    public:
190
191        Segment() :
192            name(),
193            addr(LLDB_INVALID_ADDRESS),
194            size(0)
195        {
196        }
197
198        lldb_private::ConstString name;
199        lldb::addr_t addr;
200        lldb::addr_t size;
201
202        bool
203        operator==(const Segment& rhs) const
204        {
205            return name == rhs.name && addr == rhs.addr && size == rhs.size;
206        }
207
208        void
209        PutToLog (lldb_private::Log *log,
210                  lldb::addr_t slide) const;
211
212    };
213
214    struct DYLDImageInfo
215    {
216        lldb::addr_t address;           // Address of mach header for this dylib
217        lldb::addr_t slide;             // The amount to slide all segments by if there is a global slide.
218        lldb::addr_t mod_date;          // Modification date for this dylib
219        lldb_private::FileSpec file_spec;       // Resolved path for this dylib
220        lldb_private::UUID uuid;                // UUID for this dylib if it has one, else all zeros
221        struct mach_header header;      // The mach header for this image
222        std::vector<Segment> segments;  // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
223
224        DYLDImageInfo() :
225            address(LLDB_INVALID_ADDRESS),
226            slide(0),
227            mod_date(0),
228            file_spec(),
229            uuid(),
230            header(),
231            segments()
232        {
233        }
234
235        void
236        Clear(bool load_cmd_data_only)
237        {
238            if (!load_cmd_data_only)
239            {
240                address = LLDB_INVALID_ADDRESS;
241                slide = 0;
242                mod_date = 0;
243                file_spec.Clear();
244                ::bzero (&header, sizeof(header));
245            }
246            uuid.Clear();
247            segments.clear();
248        }
249
250        bool
251        operator == (const DYLDImageInfo& rhs) const
252        {
253            return  address == rhs.address
254                && slide == rhs.slide
255                && mod_date == rhs.mod_date
256                && file_spec == rhs.file_spec
257                && uuid == rhs.uuid
258                && memcmp(&header, &rhs.header, sizeof(header)) == 0
259                && segments == rhs.segments;
260        }
261
262        bool
263        UUIDValid() const
264        {
265            return uuid.IsValid();
266        }
267
268        const Segment *
269        FindSegment (const lldb_private::ConstString &name) const;
270
271        void
272        PutToLog (lldb_private::Log *log) const;
273
274        typedef std::vector<DYLDImageInfo> collection;
275        typedef collection::iterator iterator;
276        typedef collection::const_iterator const_iterator;
277    };
278
279    struct DYLDAllImageInfos
280    {
281        uint32_t version;
282        uint32_t dylib_info_count;              // Version >= 1
283        lldb::addr_t dylib_info_addr;           // Version >= 1
284        lldb::addr_t notification;              // Version >= 1
285        bool processDetachedFromSharedRegion;   // Version >= 1
286        bool libSystemInitialized;              // Version >= 2
287        lldb::addr_t dyldImageLoadAddress;      // Version >= 2
288
289        DYLDAllImageInfos() :
290            version (0),
291            dylib_info_count (0),
292            dylib_info_addr (LLDB_INVALID_ADDRESS),
293            notification (LLDB_INVALID_ADDRESS),
294            processDetachedFromSharedRegion (false),
295            libSystemInitialized (false),
296            dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
297        {
298        }
299
300        void
301        Clear()
302        {
303            version = 0;
304            dylib_info_count = 0;
305            dylib_info_addr = LLDB_INVALID_ADDRESS;
306            notification = LLDB_INVALID_ADDRESS;
307            processDetachedFromSharedRegion = false;
308            libSystemInitialized = false;
309            dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
310        }
311
312        bool
313        IsValid() const
314        {
315            return version >= 1 || version <= 6;
316        }
317    };
318
319    void
320    RegisterNotificationCallbacks();
321
322    void
323    UnregisterNotificationCallbacks();
324
325    uint32_t
326    ParseLoadCommands (const lldb_private::DataExtractor& data,
327                       struct DYLDImageInfo& dylib_info,
328                       lldb_private::FileSpec *lc_id_dylinker);
329
330    bool
331    UpdateImageLoadAddress(lldb_private::Module *module,
332                           struct DYLDImageInfo& info);
333
334    bool
335    UnloadImageLoadAddress (lldb_private::Module *module,
336                            struct DYLDImageInfo& info);
337
338    bool
339    NeedToLocateDYLD () const;
340
341    bool
342    SetNotificationBreakpoint ();
343
344    bool
345    ReadAllImageInfosStructure ();
346
347    DYLDImageInfo m_dyld;               // Info about the curent dyld being used
348    lldb::addr_t m_dyld_all_image_infos_addr;
349    DYLDAllImageInfos m_dyld_all_image_infos;
350    lldb::user_id_t m_break_id;
351    DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
352    mutable lldb_private::Mutex m_mutex;
353    lldb_private::Process::Notifications m_notification_callbacks;
354    std::auto_ptr<lldb_private::ObjCTrampolineHandler> m_objc_trampoline_handler_ap;
355
356private:
357    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
358};
359
360#endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
361