]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / DynamicLoader / POSIX-DYLD / DYLDRendezvous.h
1 //===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef liblldb_Rendezvous_H_
10 #define liblldb_Rendezvous_H_
11
12 #include <list>
13 #include <string>
14
15 #include "lldb/Utility/FileSpec.h"
16 #include "lldb/lldb-defines.h"
17 #include "lldb/lldb-types.h"
18
19 #include "lldb/Core/LoadedModuleInfoList.h"
20
21 using lldb_private::LoadedModuleInfoList;
22
23 namespace lldb_private {
24 class Process;
25 }
26
27 /// \class DYLDRendezvous
28 /// 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
32 /// provides an interface to this structure and maintains a consistent
33 /// snapshot of the 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
47     Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {}
48   };
49
50 public:
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 Resolve();
73
74   /// \returns true if this rendezvous has been located in the inferiors
75   /// address space and false otherwise.
76   bool IsValid();
77
78   /// \returns the address of the rendezvous structure in the inferiors
79   /// address space.
80   lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }
81
82   /// \returns the version of the rendezvous protocol being used.
83   uint64_t GetVersion() const { return m_current.version; }
84
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; }
88
89   /// A breakpoint should be set at this address and Resolve called on each
90   /// hit.
91   ///
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.
94   ///
95   /// \see Resolve()
96   lldb::addr_t GetBreakAddress() const { return m_current.brk; }
97
98   /// Returns the current state of the rendezvous structure.
99   uint64_t GetState() const { return m_current.state; }
100
101   /// \returns the base address of the runtime linker in the inferiors address
102   /// space.
103   lldb::addr_t GetLDBase() const { return m_current.ldbase; }
104
105   /// \returns the thread layout metadata from the inferiors thread library.
106   const ThreadInfo &GetThreadInfo();
107
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(); }
111
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(); }
115
116   void DumpToLog(lldb_private::Log *log) const;
117
118   /// Constants describing the state of the rendezvous.
119   ///
120   /// \see GetState().
121   enum RendezvousState { eConsistent, eAdd, eDelete };
122
123   /// Structure representing the shared objects currently loaded into the
124   /// inferior process.
125   ///
126   /// This object is a rough analogue to the struct link_map object which
127   /// actually lives in the inferiors memory.
128   struct SOEntry {
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.
136
137     SOEntry() { clear(); }
138
139     bool operator==(const SOEntry &entry) {
140       return file_spec == entry.file_spec;
141     }
142
143     void clear() {
144       link_addr = 0;
145       base_addr = 0;
146       path_addr = 0;
147       dyn_addr = 0;
148       next = 0;
149       prev = 0;
150       file_spec.Clear();
151     }
152   };
153
154 protected:
155   typedef std::list<SOEntry> SOEntryList;
156
157 public:
158   typedef SOEntryList::const_iterator iterator;
159
160   /// Iterators over all currently loaded modules.
161   iterator begin() const { return m_soentries.begin(); }
162   iterator end() const { return m_soentries.end(); }
163
164   /// Iterators over all modules loaded into the inferior since the last call
165   /// to Resolve().
166   iterator loaded_begin() const { return m_added_soentries.begin(); }
167   iterator loaded_end() const { return m_added_soentries.end(); }
168
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(); }
173
174 protected:
175   lldb_private::Process *m_process;
176
177   // Cached copy of executable file spec
178   lldb_private::FileSpec m_exe_file_spec;
179
180   /// Location of the r_debug structure in the inferiors address space.
181   lldb::addr_t m_rendezvous_addr;
182
183   /// Current and previous snapshots of the rendezvous structure.
184   Rendezvous m_current;
185   Rendezvous m_previous;
186
187   /// List of currently loaded SO modules
188   LoadedModuleInfoList m_loaded_modules;
189
190   /// List of SOEntry objects corresponding to the current link map state.
191   SOEntryList m_soentries;
192
193   /// List of SOEntry's added to the link map since the last call to
194   /// Resolve().
195   SOEntryList m_added_soentries;
196
197   /// List of SOEntry's removed from the link map since the last call to
198   /// Resolve().
199   SOEntryList m_removed_soentries;
200
201   /// Threading metadata read from the inferior.
202   ThreadInfo m_thread_info;
203
204   /// Reads an unsigned integer of \p size bytes from the inferior's address
205   /// space starting at \p addr.
206   ///
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);
209
210   /// Reads an address from the inferior's address space starting at \p addr.
211   ///
212   /// \returns addr + target address size if the read was successful and
213   /// 0 otherwise.
214   lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
215
216   /// Reads a null-terminated C string from the memory location starting at @p
217   /// addr.
218   std::string ReadStringFromMemory(lldb::addr_t addr);
219
220   /// Reads an SOEntry starting at \p addr.
221   bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
222
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);
226
227   bool FillSOEntryFromModuleInfo(
228       LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry);
229
230   bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
231
232   bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list);
233
234   bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
235
236   bool AddSOEntries();
237
238   bool RemoveSOEntries();
239
240   void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path);
241
242   bool SOEntryIsMainExecutable(const SOEntry &entry);
243
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);
247
248   enum PThreadField { eSize, eNElem, eOffset };
249
250   bool FindMetadata(const char *name, PThreadField field, uint32_t &value);
251 };
252
253 #endif