1 //===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_Rendezvous_H_
10 #define liblldb_Rendezvous_H_
15 #include "lldb/Utility/FileSpec.h"
16 #include "lldb/lldb-defines.h"
17 #include "lldb/lldb-types.h"
19 #include "lldb/Core/LoadedModuleInfoList.h"
21 using lldb_private::LoadedModuleInfoList;
23 namespace lldb_private {
27 /// \class DYLDRendezvous
28 /// Interface to the runtime linker.
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
32 /// provides an interface to this structure and maintains a consistent
33 /// snapshot of the currently loaded modules.
34 class DYLDRendezvous {
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.
42 lldb::addr_t map_addr;
47 Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {}
51 // Various metadata supplied by the inferior's threading library to describe
52 // the per-thread state.
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
61 DYLDRendezvous(lldb_private::Process *process);
63 /// Update the internal snapshot of runtime linker rendezvous and recompute
64 /// the currently loaded modules.
66 /// This method should be called once one start up, then once each time the
67 /// runtime linker enters the function given by GetBreakAddress().
69 /// \returns true on success and false on failure.
71 /// \see GetBreakAddress().
74 /// \returns true if this rendezvous has been located in the inferiors
75 /// address space and false otherwise.
78 /// \returns the address of the rendezvous structure in the inferiors
80 lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }
82 /// \returns the version of the rendezvous protocol being used.
83 uint64_t GetVersion() const { return m_current.version; }
85 /// \returns address in the inferiors address space containing the linked
86 /// list of shared object descriptors.
87 lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; }
89 /// A breakpoint should be set at this address and Resolve called on each
92 /// \returns the address of a function called by the runtime linker each
93 /// time a module is loaded/unloaded, or about to be loaded/unloaded.
96 lldb::addr_t GetBreakAddress() const { return m_current.brk; }
98 /// Returns the current state of the rendezvous structure.
99 uint64_t GetState() const { return m_current.state; }
101 /// \returns the base address of the runtime linker in the inferiors address
103 lldb::addr_t GetLDBase() const { return m_current.ldbase; }
105 /// \returns the thread layout metadata from the inferiors thread library.
106 const ThreadInfo &GetThreadInfo();
108 /// \returns true if modules have been loaded into the inferior since the
109 /// last call to Resolve().
110 bool ModulesDidLoad() const { return !m_added_soentries.empty(); }
112 /// \returns true if modules have been unloaded from the inferior since the
113 /// last call to Resolve().
114 bool ModulesDidUnload() const { return !m_removed_soentries.empty(); }
116 void DumpToLog(lldb_private::Log *log) const;
118 /// Constants describing the state of the rendezvous.
121 enum RendezvousState { eConsistent, eAdd, eDelete };
123 /// Structure representing the shared objects currently loaded into the
124 /// inferior process.
126 /// This object is a rough analogue to the struct link_map object which
127 /// actually lives in the inferiors memory.
129 lldb::addr_t link_addr; ///< Address of this link_map.
130 lldb::addr_t base_addr; ///< Base address of the loaded object.
131 lldb::addr_t path_addr; ///< String naming the shared object.
132 lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
133 lldb::addr_t next; ///< Address of next so_entry.
134 lldb::addr_t prev; ///< Address of previous so_entry.
135 lldb_private::FileSpec file_spec; ///< File spec of shared object.
137 SOEntry() { clear(); }
139 bool operator==(const SOEntry &entry) {
140 return file_spec == entry.file_spec;
155 typedef std::list<SOEntry> SOEntryList;
158 typedef SOEntryList::const_iterator iterator;
160 /// Iterators over all currently loaded modules.
161 iterator begin() const { return m_soentries.begin(); }
162 iterator end() const { return m_soentries.end(); }
164 /// Iterators over all modules loaded into the inferior since the last call
166 iterator loaded_begin() const { return m_added_soentries.begin(); }
167 iterator loaded_end() const { return m_added_soentries.end(); }
169 /// Iterators over all modules unloaded from the inferior since the last
170 /// call to Resolve().
171 iterator unloaded_begin() const { return m_removed_soentries.begin(); }
172 iterator unloaded_end() const { return m_removed_soentries.end(); }
175 lldb_private::Process *m_process;
177 // Cached copy of executable file spec
178 lldb_private::FileSpec m_exe_file_spec;
180 /// Location of the r_debug structure in the inferiors address space.
181 lldb::addr_t m_rendezvous_addr;
183 /// Current and previous snapshots of the rendezvous structure.
184 Rendezvous m_current;
185 Rendezvous m_previous;
187 /// List of currently loaded SO modules
188 LoadedModuleInfoList m_loaded_modules;
190 /// List of SOEntry objects corresponding to the current link map state.
191 SOEntryList m_soentries;
193 /// List of SOEntry's added to the link map since the last call to
195 SOEntryList m_added_soentries;
197 /// List of SOEntry's removed from the link map since the last call to
199 SOEntryList m_removed_soentries;
201 /// Threading metadata read from the inferior.
202 ThreadInfo m_thread_info;
204 /// Reads an unsigned integer of \p size bytes from the inferior's address
205 /// space starting at \p addr.
207 /// \returns addr + size if the read was successful and false otherwise.
208 lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
210 /// Reads an address from the inferior's address space starting at \p addr.
212 /// \returns addr + target address size if the read was successful and
214 lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
216 /// Reads a null-terminated C string from the memory location starting at @p
218 std::string ReadStringFromMemory(lldb::addr_t addr);
220 /// Reads an SOEntry starting at \p addr.
221 bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
223 /// Updates the current set of SOEntries, the set of added entries, and the
224 /// set of removed entries.
225 bool UpdateSOEntries(bool fromRemote = false);
227 bool FillSOEntryFromModuleInfo(
228 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry);
230 bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
232 bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list);
234 bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
238 bool RemoveSOEntries();
240 void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path);
242 bool SOEntryIsMainExecutable(const SOEntry &entry);
244 /// Reads the current list of shared objects according to the link map
245 /// supplied by the runtime linker.
246 bool TakeSnapshot(SOEntryList &entry_list);
248 enum PThreadField { eSize, eNElem, eOffset };
250 bool FindMetadata(const char *name, PThreadField field, uint32_t &value);