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