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