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 22 namespace lldb_private { 23 class Process; 24 } 25 26 /// @class DYLDRendezvous 27 /// @brief Interface to the runtime linker. 28 /// 29 /// A structure is present in a processes memory space which is updated by the 30 /// runtime liker each time a module is loaded or unloaded. This class provides 31 /// an interface to this structure and maintains a consistent snapshot of the 32 /// currently loaded modules. 33 class DYLDRendezvous { 34 35 // This structure is used to hold the contents of the debug rendezvous 36 // information (struct r_debug) as found in the inferiors memory. Note that 37 // the layout of this struct is not binary compatible, it is simply large 38 // enough to hold the information on both 32 and 64 bit platforms. 39 struct Rendezvous { 40 uint64_t version; 41 lldb::addr_t map_addr; 42 lldb::addr_t brk; 43 uint64_t state; 44 lldb::addr_t ldbase; 45 RendezvousRendezvous46 Rendezvous() 47 : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } 48 }; 49 50 public: 51 DYLDRendezvous(lldb_private::Process *process); 52 53 /// Update the internal snapshot of runtime linker rendezvous and recompute 54 /// the currently loaded modules. 55 /// 56 /// This method should be called once one start up, then once each time the 57 /// runtime linker enters the function given by GetBreakAddress(). 58 /// 59 /// @returns true on success and false on failure. 60 /// 61 /// @see GetBreakAddress(). 62 bool 63 Resolve(); 64 65 /// @returns true if this rendezvous has been located in the inferiors 66 /// address space and false otherwise. 67 bool 68 IsValid(); 69 70 /// @returns the address of the rendezvous structure in the inferiors 71 /// address space. 72 lldb::addr_t GetRendezvousAddress()73 GetRendezvousAddress() const { return m_rendezvous_addr; } 74 75 /// @returns the version of the rendezvous protocol being used. 76 uint64_t GetVersion()77 GetVersion() const { return m_current.version; } 78 79 /// @returns address in the inferiors address space containing the linked 80 /// list of shared object descriptors. 81 lldb::addr_t GetLinkMapAddress()82 GetLinkMapAddress() const { return m_current.map_addr; } 83 84 /// A breakpoint should be set at this address and Resolve called on each 85 /// hit. 86 /// 87 /// @returns the address of a function called by the runtime linker each 88 /// time a module is loaded/unloaded, or about to be loaded/unloaded. 89 /// 90 /// @see Resolve() 91 lldb::addr_t GetBreakAddress()92 GetBreakAddress() const { return m_current.brk; } 93 94 /// Returns the current state of the rendezvous structure. 95 uint64_t GetState()96 GetState() const { return m_current.state; } 97 98 /// @returns the base address of the runtime linker in the inferiors address 99 /// space. 100 lldb::addr_t GetLDBase()101 GetLDBase() const { return m_current.ldbase; } 102 103 /// @returns true if modules have been loaded into the inferior since the 104 /// last call to Resolve(). 105 bool ModulesDidLoad()106 ModulesDidLoad() const { return !m_added_soentries.empty(); } 107 108 /// @returns true if modules have been unloaded from the inferior since the 109 /// last call to Resolve(). 110 bool ModulesDidUnload()111 ModulesDidUnload() const { return !m_removed_soentries.empty(); } 112 113 void 114 DumpToLog(lldb_private::Log *log) const; 115 116 /// @brief Constants describing the state of the rendezvous. 117 /// 118 /// @see GetState(). 119 enum RendezvousState { 120 eConsistent, 121 eAdd, 122 eDelete 123 }; 124 125 /// @brief Structure representing the shared objects currently loaded into 126 /// the inferior process. 127 /// 128 /// This object is a rough analogue to the struct link_map object which 129 /// actually lives in the inferiors memory. 130 struct SOEntry { 131 lldb::addr_t base_addr; ///< Base address of the loaded object. 132 lldb::addr_t path_addr; ///< String naming the shared object. 133 lldb::addr_t dyn_addr; ///< Dynamic section of shared object. 134 lldb::addr_t next; ///< Address of next so_entry. 135 lldb::addr_t prev; ///< Address of previous so_entry. 136 std::string path; ///< File name of shared object. 137 SOEntrySOEntry138 SOEntry() { clear(); } 139 140 bool operator ==(const SOEntry &entry) { 141 return this->path == entry.path; 142 } 143 clearSOEntry144 void clear() { 145 base_addr = 0; 146 path_addr = 0; 147 dyn_addr = 0; 148 next = 0; 149 prev = 0; 150 path.clear(); 151 } 152 }; 153 154 protected: 155 typedef std::list<SOEntry> SOEntryList; 156 157 public: 158 typedef SOEntryList::const_iterator iterator; 159 160 /// Iterators over all currently loaded modules. begin()161 iterator begin() const { return m_soentries.begin(); } end()162 iterator end() const { return m_soentries.end(); } 163 164 /// Iterators over all modules loaded into the inferior since the last call 165 /// to Resolve(). loaded_begin()166 iterator loaded_begin() const { return m_added_soentries.begin(); } loaded_end()167 iterator loaded_end() const { return m_added_soentries.end(); } 168 169 /// Iterators over all modules unloaded from the inferior since the last 170 /// call to Resolve(). unloaded_begin()171 iterator unloaded_begin() const { return m_removed_soentries.begin(); } unloaded_end()172 iterator unloaded_end() const { return m_removed_soentries.end(); } 173 174 protected: 175 lldb_private::Process *m_process; 176 177 // Cached copy of executable pathname 178 char m_exe_path[PATH_MAX]; 179 180 /// Location of the r_debug structure in the inferiors address space. 181 lldb::addr_t m_rendezvous_addr; 182 183 /// Current and previous snapshots of the rendezvous structure. 184 Rendezvous m_current; 185 Rendezvous m_previous; 186 187 /// List of SOEntry objects corresponding to the current link map state. 188 SOEntryList m_soentries; 189 190 /// List of SOEntry's added to the link map since the last call to Resolve(). 191 SOEntryList m_added_soentries; 192 193 /// List of SOEntry's removed from the link map since the last call to 194 /// Resolve(). 195 SOEntryList m_removed_soentries; 196 197 /// Reads @p size bytes from the inferiors address space starting at @p 198 /// addr. 199 /// 200 /// @returns addr + size if the read was successful and false otherwise. 201 lldb::addr_t 202 ReadMemory(lldb::addr_t addr, void *dst, size_t size); 203 204 /// Reads a null-terminated C string from the memory location starting at @p 205 /// addr. 206 std::string 207 ReadStringFromMemory(lldb::addr_t addr); 208 209 /// Reads an SOEntry starting at @p addr. 210 bool 211 ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 212 213 /// Updates the current set of SOEntries, the set of added entries, and the 214 /// set of removed entries. 215 bool 216 UpdateSOEntries(); 217 218 bool 219 UpdateSOEntriesForAddition(); 220 221 bool 222 UpdateSOEntriesForDeletion(); 223 224 /// Reads the current list of shared objects according to the link map 225 /// supplied by the runtime linker. 226 bool 227 TakeSnapshot(SOEntryList &entry_list); 228 }; 229 230 #endif 231