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