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

source code of lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h