DYLDRendezvous.h revision 263363
1//===-- DYLDRendezvous.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_Rendezvous_H_
11#define liblldb_Rendezvous_H_
12
13// C Includes
14// C++ Includes
15#include <list>
16#include <string>
17
18// Other libraries and framework includes
19#include "lldb/lldb-defines.h"
20#include "lldb/lldb-types.h"
21
22namespace lldb_private {
23class Process;
24}
25
26/// @class DYLDRendezvous
27/// @brief Interface to the runtime linker.
28///
29/// A structure is present in a processes memory space which is updated by the
30/// runtime liker each time a module is loaded or unloaded.  This class provides
31/// an interface to this structure and maintains a consistent snapshot of the
32/// currently loaded modules.
33class DYLDRendezvous {
34
35    // This structure is used to hold the contents of the debug rendezvous
36    // information (struct r_debug) as found in the inferiors memory.  Note that
37    // the layout of this struct is not binary compatible, it is simply large
38    // enough to hold the information on both 32 and 64 bit platforms.
39    struct Rendezvous {
40        uint64_t     version;
41        lldb::addr_t map_addr;
42        lldb::addr_t brk;
43        uint64_t     state;
44        lldb::addr_t ldbase;
45
46        Rendezvous()
47            : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
48    };
49
50public:
51    // Various metadata supplied by the inferior's threading library to describe
52    // the per-thread state.
53    struct ThreadInfo {
54        bool     valid;         // whether we read valid metadata
55        uint32_t dtv_offset;    // offset of DTV pointer within pthread
56        uint32_t dtv_slot_size; // size of one DTV slot
57        uint32_t modid_offset;  // offset of module ID within link_map
58        uint32_t tls_offset;    // offset of TLS pointer within DTV slot
59    };
60
61    DYLDRendezvous(lldb_private::Process *process);
62
63    /// Update the internal snapshot of runtime linker rendezvous and recompute
64    /// the currently loaded modules.
65    ///
66    /// This method should be called once one start up, then once each time the
67    /// runtime linker enters the function given by GetBreakAddress().
68    ///
69    /// @returns true on success and false on failure.
70    ///
71    /// @see GetBreakAddress().
72    bool
73    Resolve();
74
75    /// @returns true if this rendezvous has been located in the inferiors
76    /// address space and false otherwise.
77    bool
78    IsValid();
79
80    /// @returns the address of the rendezvous structure in the inferiors
81    /// address space.
82    lldb::addr_t
83    GetRendezvousAddress() const { return m_rendezvous_addr; }
84
85    /// @returns the version of the rendezvous protocol being used.
86    uint64_t
87    GetVersion() const { return m_current.version; }
88
89    /// @returns address in the inferiors address space containing the linked
90    /// list of shared object descriptors.
91    lldb::addr_t
92    GetLinkMapAddress() const { return m_current.map_addr; }
93
94    /// A breakpoint should be set at this address and Resolve called on each
95    /// hit.
96    ///
97    /// @returns the address of a function called by the runtime linker each
98    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
99    ///
100    /// @see Resolve()
101    lldb::addr_t
102    GetBreakAddress() const { return m_current.brk; }
103
104    /// Returns the current state of the rendezvous structure.
105    uint64_t
106    GetState() const { return m_current.state; }
107
108    /// @returns the base address of the runtime linker in the inferiors address
109    /// space.
110    lldb::addr_t
111    GetLDBase() const { return m_current.ldbase; }
112
113    /// @returns the thread layout metadata from the inferiors thread library.
114    const ThreadInfo&
115    GetThreadInfo();
116
117    /// @returns true if modules have been loaded into the inferior since the
118    /// last call to Resolve().
119    bool
120    ModulesDidLoad() const { return !m_added_soentries.empty(); }
121
122    /// @returns true if modules have been unloaded from the inferior since the
123    /// last call to Resolve().
124    bool
125    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
126
127    void
128    DumpToLog(lldb_private::Log *log) const;
129
130    /// @brief Constants describing the state of the rendezvous.
131    ///
132    /// @see GetState().
133    enum RendezvousState {
134        eConsistent,
135        eAdd,
136        eDelete
137    };
138
139    /// @brief Structure representing the shared objects currently loaded into
140    /// the inferior process.
141    ///
142    /// This object is a rough analogue to the struct link_map object which
143    /// actually lives in the inferiors memory.
144    struct SOEntry {
145        lldb::addr_t link_addr; ///< Address of this link_map.
146        lldb::addr_t base_addr; ///< Base address of the loaded object.
147        lldb::addr_t path_addr; ///< String naming the shared object.
148        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
149        lldb::addr_t next;      ///< Address of next so_entry.
150        lldb::addr_t prev;      ///< Address of previous so_entry.
151        std::string  path;      ///< File name of shared object.
152
153        SOEntry() { clear(); }
154
155        bool operator ==(const SOEntry &entry) {
156            return this->path == entry.path;
157        }
158
159        void clear() {
160            link_addr = 0;
161            base_addr = 0;
162            path_addr = 0;
163            dyn_addr  = 0;
164            next = 0;
165            prev = 0;
166            path.clear();
167        }
168    };
169
170protected:
171    typedef std::list<SOEntry> SOEntryList;
172
173public:
174    typedef SOEntryList::const_iterator iterator;
175
176    /// Iterators over all currently loaded modules.
177    iterator begin() const { return m_soentries.begin(); }
178    iterator end() const { return m_soentries.end(); }
179
180    /// Iterators over all modules loaded into the inferior since the last call
181    /// to Resolve().
182    iterator loaded_begin() const { return m_added_soentries.begin(); }
183    iterator loaded_end() const { return m_added_soentries.end(); }
184
185    /// Iterators over all modules unloaded from the inferior since the last
186    /// call to Resolve().
187    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
188    iterator unloaded_end() const { return m_removed_soentries.end(); }
189
190protected:
191    lldb_private::Process *m_process;
192
193    // Cached copy of executable pathname
194    char m_exe_path[PATH_MAX];
195
196    /// Location of the r_debug structure in the inferiors address space.
197    lldb::addr_t m_rendezvous_addr;
198
199    /// Current and previous snapshots of the rendezvous structure.
200    Rendezvous m_current;
201    Rendezvous m_previous;
202
203    /// List of SOEntry objects corresponding to the current link map state.
204    SOEntryList m_soentries;
205
206    /// List of SOEntry's added to the link map since the last call to Resolve().
207    SOEntryList m_added_soentries;
208
209    /// List of SOEntry's removed from the link map since the last call to
210    /// Resolve().
211    SOEntryList m_removed_soentries;
212
213    /// Threading metadata read from the inferior.
214    ThreadInfo  m_thread_info;
215
216    /// Reads an unsigned integer of @p size bytes from the inferior's address
217    /// space starting at @p addr.
218    ///
219    /// @returns addr + size if the read was successful and false otherwise.
220    lldb::addr_t
221    ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
222
223    /// Reads an address from the inferior's address space starting at @p addr.
224    ///
225    /// @returns addr + target address size if the read was successful and
226    /// 0 otherwise.
227    lldb::addr_t
228    ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
229
230    /// Reads a null-terminated C string from the memory location starting at @p
231    /// addr.
232    std::string
233    ReadStringFromMemory(lldb::addr_t addr);
234
235    /// Reads an SOEntry starting at @p addr.
236    bool
237    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
238
239    /// Updates the current set of SOEntries, the set of added entries, and the
240    /// set of removed entries.
241    bool
242    UpdateSOEntries();
243
244    bool
245    UpdateSOEntriesForAddition();
246
247    bool
248    UpdateSOEntriesForDeletion();
249
250    /// Reads the current list of shared objects according to the link map
251    /// supplied by the runtime linker.
252    bool
253    TakeSnapshot(SOEntryList &entry_list);
254
255    enum PThreadField { eSize, eNElem, eOffset };
256
257    bool FindMetadata(const char *name, PThreadField field, uint32_t& value);
258};
259
260#endif
261