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