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 
20 namespace lldb_private {
21 class 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.
31 class 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 
47 public:
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 
161 protected:
162   typedef std::list<SOEntry> SOEntryList;
163 
164 public:
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 
181 protected:
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