DYLDRendezvous.h revision 321369
1//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef liblldb_Rendezvous_H_ 11#define liblldb_Rendezvous_H_ 12 13// C Includes 14// C++ Includes 15#include <list> 16#include <string> 17 18// Other libraries and framework includes 19#include "lldb/Utility/FileSpec.h" 20#include "lldb/lldb-defines.h" 21#include "lldb/lldb-types.h" 22 23#include "lldb/Core/LoadedModuleInfoList.h" 24 25using lldb_private::LoadedModuleInfoList; 26 27namespace lldb_private { 28class Process; 29} 30 31/// @class DYLDRendezvous 32/// @brief Interface to the runtime linker. 33/// 34/// A structure is present in a processes memory space which is updated by the 35/// runtime liker each time a module is loaded or unloaded. This class provides 36/// an interface to this structure and maintains a consistent snapshot of the 37/// currently loaded modules. 38class DYLDRendezvous { 39 40 // This structure is used to hold the contents of the debug rendezvous 41 // information (struct r_debug) as found in the inferiors memory. Note that 42 // the layout of this struct is not binary compatible, it is simply large 43 // enough to hold the information on both 32 and 64 bit platforms. 44 struct Rendezvous { 45 uint64_t version; 46 lldb::addr_t map_addr; 47 lldb::addr_t brk; 48 uint64_t state; 49 lldb::addr_t ldbase; 50 51 Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {} 52 }; 53 54public: 55 // Various metadata supplied by the inferior's threading library to describe 56 // the per-thread state. 57 struct ThreadInfo { 58 bool valid; // whether we read valid metadata 59 uint32_t dtv_offset; // offset of DTV pointer within pthread 60 uint32_t dtv_slot_size; // size of one DTV slot 61 uint32_t modid_offset; // offset of module ID within link_map 62 uint32_t tls_offset; // offset of TLS pointer within DTV slot 63 }; 64 65 DYLDRendezvous(lldb_private::Process *process); 66 67 /// Update the internal snapshot of runtime linker rendezvous and recompute 68 /// the currently loaded modules. 69 /// 70 /// This method should be called once one start up, then once each time the 71 /// runtime linker enters the function given by GetBreakAddress(). 72 /// 73 /// @returns true on success and false on failure. 74 /// 75 /// @see GetBreakAddress(). 76 bool Resolve(); 77 78 /// @returns true if this rendezvous has been located in the inferiors 79 /// address space and false otherwise. 80 bool IsValid(); 81 82 /// @returns the address of the rendezvous structure in the inferiors 83 /// address space. 84 lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; } 85 86 /// @returns the version of the rendezvous protocol being used. 87 uint64_t GetVersion() const { return m_current.version; } 88 89 /// @returns address in the inferiors address space containing the linked 90 /// list of shared object descriptors. 91 lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; } 92 93 /// A breakpoint should be set at this address and Resolve called on each 94 /// hit. 95 /// 96 /// @returns the address of a function called by the runtime linker each 97 /// time a module is loaded/unloaded, or about to be loaded/unloaded. 98 /// 99 /// @see Resolve() 100 lldb::addr_t GetBreakAddress() const { return m_current.brk; } 101 102 /// Returns the current state of the rendezvous structure. 103 uint64_t GetState() const { return m_current.state; } 104 105 /// @returns the base address of the runtime linker in the inferiors address 106 /// space. 107 lldb::addr_t GetLDBase() const { return m_current.ldbase; } 108 109 /// @returns the thread layout metadata from the inferiors thread library. 110 const ThreadInfo &GetThreadInfo(); 111 112 /// @returns true if modules have been loaded into the inferior since the 113 /// last call to Resolve(). 114 bool ModulesDidLoad() const { return !m_added_soentries.empty(); } 115 116 /// @returns true if modules have been unloaded from the inferior since the 117 /// last call to Resolve(). 118 bool ModulesDidUnload() const { return !m_removed_soentries.empty(); } 119 120 void DumpToLog(lldb_private::Log *log) const; 121 122 /// @brief Constants describing the state of the rendezvous. 123 /// 124 /// @see GetState(). 125 enum RendezvousState { eConsistent, eAdd, eDelete }; 126 127 /// @brief Structure representing the shared objects currently loaded into 128 /// the inferior process. 129 /// 130 /// This object is a rough analogue to the struct link_map object which 131 /// actually lives in the inferiors memory. 132 struct SOEntry { 133 lldb::addr_t link_addr; ///< Address of this link_map. 134 lldb::addr_t base_addr; ///< Base address of the loaded object. 135 lldb::addr_t path_addr; ///< String naming the shared object. 136 lldb::addr_t dyn_addr; ///< Dynamic section of shared object. 137 lldb::addr_t next; ///< Address of next so_entry. 138 lldb::addr_t prev; ///< Address of previous so_entry. 139 lldb_private::FileSpec file_spec; ///< File spec of shared object. 140 141 SOEntry() { clear(); } 142 143 bool operator==(const SOEntry &entry) { 144 return file_spec == entry.file_spec; 145 } 146 147 void clear() { 148 link_addr = 0; 149 base_addr = 0; 150 path_addr = 0; 151 dyn_addr = 0; 152 next = 0; 153 prev = 0; 154 file_spec.Clear(); 155 } 156 }; 157 158protected: 159 typedef std::list<SOEntry> SOEntryList; 160 161public: 162 typedef SOEntryList::const_iterator iterator; 163 164 /// Iterators over all currently loaded modules. 165 iterator begin() const { return m_soentries.begin(); } 166 iterator end() const { return m_soentries.end(); } 167 168 /// Iterators over all modules loaded into the inferior since the last call 169 /// to Resolve(). 170 iterator loaded_begin() const { return m_added_soentries.begin(); } 171 iterator loaded_end() const { return m_added_soentries.end(); } 172 173 /// Iterators over all modules unloaded from the inferior since the last 174 /// call to Resolve(). 175 iterator unloaded_begin() const { return m_removed_soentries.begin(); } 176 iterator unloaded_end() const { return m_removed_soentries.end(); } 177 178protected: 179 lldb_private::Process *m_process; 180 181 // Cached copy of executable file spec 182 lldb_private::FileSpec m_exe_file_spec; 183 184 /// Location of the r_debug structure in the inferiors address space. 185 lldb::addr_t m_rendezvous_addr; 186 187 /// Current and previous snapshots of the rendezvous structure. 188 Rendezvous m_current; 189 Rendezvous m_previous; 190 191 /// List of currently loaded SO modules 192 LoadedModuleInfoList m_loaded_modules; 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 Resolve(). 198 SOEntryList m_added_soentries; 199 200 /// List of SOEntry's removed from the link map since the last call to 201 /// Resolve(). 202 SOEntryList m_removed_soentries; 203 204 /// Threading metadata read from the inferior. 205 ThreadInfo m_thread_info; 206 207 /// Reads an unsigned integer of @p size bytes from the inferior's address 208 /// space starting at @p addr. 209 /// 210 /// @returns addr + size if the read was successful and false otherwise. 211 lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); 212 213 /// Reads an address from the inferior's address space starting at @p addr. 214 /// 215 /// @returns addr + target address size if the read was successful and 216 /// 0 otherwise. 217 lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); 218 219 /// Reads a null-terminated C string from the memory location starting at @p 220 /// addr. 221 std::string ReadStringFromMemory(lldb::addr_t addr); 222 223 /// Reads an SOEntry starting at @p addr. 224 bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 225 226 /// Updates the current set of SOEntries, the set of added entries, and the 227 /// set of removed entries. 228 bool UpdateSOEntries(bool fromRemote = false); 229 230 bool FillSOEntryFromModuleInfo( 231 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry); 232 233 bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); 234 235 bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); 236 237 bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); 238 239 bool AddSOEntries(); 240 241 bool RemoveSOEntries(); 242 243 void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path); 244 245 bool SOEntryIsMainExecutable(const SOEntry &entry); 246 247 /// Reads the current list of shared objects according to the link map 248 /// supplied by the runtime linker. 249 bool TakeSnapshot(SOEntryList &entry_list); 250 251 enum PThreadField { eSize, eNElem, eOffset }; 252 253 bool FindMetadata(const char *name, PThreadField field, uint32_t &value); 254}; 255 256#endif 257