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 LLDB_SOURCE_PLUGINS_DYNAMICLOADER_POSIX_DYLD_DYLDRENDEZVOUS_H 10 #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_POSIX_DYLD_DYLDRENDEZVOUS_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 = 0; 42 lldb::addr_t map_addr = 0; 43 lldb::addr_t brk = 0; 44 uint64_t state = 0; 45 lldb::addr_t ldbase = 0; 46 47 Rendezvous() = default; 48 }; 49 50 /// Locates the address of the rendezvous structure. It updates 51 /// m_executable_interpreter if address is extracted from _r_debug. 52 /// 53 /// \returns address on success and LLDB_INVALID_ADDRESS on failure. 54 lldb::addr_t ResolveRendezvousAddress(); 55 56 public: 57 // Various metadata supplied by the inferior's threading library to describe 58 // the per-thread state. 59 struct ThreadInfo { 60 bool valid; // whether we read valid metadata 61 uint32_t dtv_offset; // offset of DTV pointer within pthread 62 uint32_t dtv_slot_size; // size of one DTV slot 63 uint32_t modid_offset; // offset of module ID within link_map 64 uint32_t tls_offset; // offset of TLS pointer within DTV slot 65 }; 66 67 DYLDRendezvous(lldb_private::Process *process); 68 69 /// Update the cached executable path. 70 void UpdateExecutablePath(); 71 72 /// Update the internal snapshot of runtime linker rendezvous and recompute 73 /// the currently loaded modules. 74 /// 75 /// This method should be called once one start up, then once each time the 76 /// runtime linker enters the function given by GetBreakAddress(). 77 /// 78 /// \returns true on success and false on failure. 79 /// 80 /// \see GetBreakAddress(). 81 bool Resolve(); 82 83 /// \returns true if this rendezvous has been located in the inferiors 84 /// address space and false otherwise. 85 bool IsValid(); 86 87 /// \returns the address of the rendezvous structure in the inferiors 88 /// address space. 89 lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; } 90 91 /// \returns the version of the rendezvous protocol being used. 92 uint64_t GetVersion() const { return m_current.version; } 93 94 /// \returns address in the inferiors address space containing the linked 95 /// list of shared object descriptors. 96 lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; } 97 98 /// A breakpoint should be set at this address and Resolve called on each 99 /// hit. 100 /// 101 /// \returns the address of a function called by the runtime linker each 102 /// time a module is loaded/unloaded, or about to be loaded/unloaded. 103 /// 104 /// \see Resolve() 105 lldb::addr_t GetBreakAddress() const { return m_current.brk; } 106 107 /// Returns the current state of the rendezvous structure. 108 uint64_t GetState() const { return m_current.state; } 109 110 /// \returns the base address of the runtime linker in the inferiors address 111 /// space. 112 lldb::addr_t GetLDBase() const { return m_current.ldbase; } 113 114 /// \returns the thread layout metadata from the inferiors thread library. 115 const ThreadInfo &GetThreadInfo(); 116 117 /// \returns true if modules have been loaded into the inferior since the 118 /// last call to Resolve(). 119 bool ModulesDidLoad() const { return !m_added_soentries.empty(); } 120 121 /// \returns true if modules have been unloaded from the inferior since the 122 /// last call to Resolve(). 123 bool ModulesDidUnload() const { return !m_removed_soentries.empty(); } 124 125 void DumpToLog(lldb_private::Log *log) const; 126 127 /// Constants describing the state of the rendezvous. 128 /// 129 /// \see GetState(). 130 enum RendezvousState { eConsistent, eAdd, eDelete }; 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 lldb_private::FileSpec file_spec; ///< File spec of shared object. 145 146 SOEntry() { clear(); } 147 148 bool operator==(const SOEntry &entry) { 149 return file_spec == entry.file_spec; 150 } 151 152 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 file_spec.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. 170 iterator begin() const { return m_soentries.begin(); } 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(). 175 iterator loaded_begin() const { return m_added_soentries.begin(); } 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(). 180 iterator unloaded_begin() const { return m_removed_soentries.begin(); } 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 file spec 187 lldb_private::FileSpec m_exe_file_spec; 188 189 /// Location of the r_debug structure in the inferiors address space. 190 lldb::addr_t m_rendezvous_addr; 191 192 // True if the main program is the dynamic linker/loader/program interpreter. 193 bool m_executable_interpreter; 194 195 /// Current and previous snapshots of the rendezvous structure. 196 Rendezvous m_current; 197 Rendezvous m_previous; 198 199 /// List of currently loaded SO modules 200 LoadedModuleInfoList m_loaded_modules; 201 202 /// List of SOEntry objects corresponding to the current link map state. 203 SOEntryList m_soentries; 204 205 /// List of SOEntry's added to the link map since the last call to 206 /// Resolve(). 207 SOEntryList m_added_soentries; 208 209 /// List of SOEntry's removed from the link map since the last call to 210 /// Resolve(). 211 SOEntryList m_removed_soentries; 212 213 /// Threading metadata read from the inferior. 214 ThreadInfo m_thread_info; 215 216 /// Reads an unsigned integer of \p size bytes from the inferior's address 217 /// space starting at \p addr. 218 /// 219 /// \returns addr + size if the read was successful and false otherwise. 220 lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); 221 222 /// Reads an address from the inferior's address space starting at \p addr. 223 /// 224 /// \returns addr + target address size if the read was successful and 225 /// 0 otherwise. 226 lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); 227 228 /// Reads a null-terminated C string from the memory location starting at @p 229 /// addr. 230 std::string ReadStringFromMemory(lldb::addr_t addr); 231 232 /// Reads an SOEntry starting at \p addr. 233 bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 234 235 /// Updates the current set of SOEntries, the set of added entries, and the 236 /// set of removed entries. 237 bool UpdateSOEntries(); 238 239 /// Same as UpdateSOEntries but it gets the list of loaded modules from the 240 /// remote debug server (faster when supported). 241 bool UpdateSOEntriesFromRemote(); 242 243 bool FillSOEntryFromModuleInfo( 244 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry); 245 246 bool SaveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); 247 248 bool AddSOEntriesFromRemote(const LoadedModuleInfoList &module_list); 249 250 bool RemoveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); 251 252 bool AddSOEntries(); 253 254 bool RemoveSOEntries(); 255 256 void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path); 257 258 void UpdateFileSpecIfNecessary(SOEntry &entry); 259 260 bool SOEntryIsMainExecutable(const SOEntry &entry); 261 262 /// Reads the current list of shared objects according to the link map 263 /// supplied by the runtime linker. 264 bool TakeSnapshot(SOEntryList &entry_list); 265 266 enum PThreadField { eSize, eNElem, eOffset }; 267 268 bool FindMetadata(const char *name, PThreadField field, uint32_t &value); 269 270 bool IsCoreFile() const; 271 272 enum RendezvousAction { 273 eNoAction, 274 eTakeSnapshot, 275 eAddModules, 276 eRemoveModules 277 }; 278 279 /// Returns the current action to be taken given the current and previous 280 /// state 281 RendezvousAction GetAction() const; 282 }; 283 284 #endif 285