DYLDRendezvous.h revision 296417
1238384Sjkim//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===// 2238384Sjkim// 3238384Sjkim// The LLVM Compiler Infrastructure 4238384Sjkim// 5238384Sjkim// This file is distributed under the University of Illinois Open Source 6238384Sjkim// License. See LICENSE.TXT for details. 7238384Sjkim// 8238384Sjkim//===----------------------------------------------------------------------===// 9238384Sjkim 10238384Sjkim#ifndef liblldb_Rendezvous_H_ 11238384Sjkim#define liblldb_Rendezvous_H_ 12238384Sjkim 13238384Sjkim// C Includes 14238384Sjkim// C++ Includes 15238384Sjkim#include <list> 16238384Sjkim#include <string> 17238384Sjkim 18238384Sjkim// Other libraries and framework includes 19238384Sjkim#include "lldb/lldb-defines.h" 20238384Sjkim#include "lldb/lldb-types.h" 21238384Sjkim#include "lldb/Host/FileSpec.h" 22238384Sjkim 23238384Sjkim#include "lldb/Core/LoadedModuleInfoList.h" 24238384Sjkim 25238384Sjkimusing lldb_private::LoadedModuleInfoList; 26238384Sjkim 27238384Sjkimnamespace lldb_private { 28238384Sjkimclass Process; 29238384Sjkim} 30238384Sjkim 31238384Sjkim/// @class DYLDRendezvous 32238384Sjkim/// @brief Interface to the runtime linker. 33238384Sjkim/// 34238384Sjkim/// A structure is present in a processes memory space which is updated by the 35238384Sjkim/// runtime liker each time a module is loaded or unloaded. This class provides 36246772Sjkim/// an interface to this structure and maintains a consistent snapshot of the 37238384Sjkim/// currently loaded modules. 38238384Sjkimclass DYLDRendezvous { 39238384Sjkim 40238384Sjkim // This structure is used to hold the contents of the debug rendezvous 41238384Sjkim // information (struct r_debug) as found in the inferiors memory. Note that 42238384Sjkim // the layout of this struct is not binary compatible, it is simply large 43238384Sjkim // enough to hold the information on both 32 and 64 bit platforms. 44238384Sjkim struct Rendezvous { 45238384Sjkim uint64_t version; 46238384Sjkim lldb::addr_t map_addr; 47238384Sjkim lldb::addr_t brk; 48238384Sjkim uint64_t state; 49238384Sjkim lldb::addr_t ldbase; 50238384Sjkim 51238384Sjkim Rendezvous() 52238384Sjkim : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } 53238384Sjkim }; 54238384Sjkim 55238384Sjkimpublic: 56238384Sjkim // Various metadata supplied by the inferior's threading library to describe 57238384Sjkim // the per-thread state. 58238384Sjkim struct ThreadInfo { 59238384Sjkim bool valid; // whether we read valid metadata 60238384Sjkim uint32_t dtv_offset; // offset of DTV pointer within pthread 61238384Sjkim uint32_t dtv_slot_size; // size of one DTV slot 62238384Sjkim uint32_t modid_offset; // offset of module ID within link_map 63238384Sjkim uint32_t tls_offset; // offset of TLS pointer within DTV slot 64238384Sjkim }; 65238384Sjkim 66238384Sjkim DYLDRendezvous(lldb_private::Process *process); 67238384Sjkim 68238384Sjkim /// Update the internal snapshot of runtime linker rendezvous and recompute 69238384Sjkim /// the currently loaded modules. 70238384Sjkim /// 71238384Sjkim /// This method should be called once one start up, then once each time the 72238384Sjkim /// runtime linker enters the function given by GetBreakAddress(). 73238384Sjkim /// 74238384Sjkim /// @returns true on success and false on failure. 75238384Sjkim /// 76238384Sjkim /// @see GetBreakAddress(). 77238384Sjkim bool 78238384Sjkim Resolve(); 79238384Sjkim 80238384Sjkim /// @returns true if this rendezvous has been located in the inferiors 81238384Sjkim /// address space and false otherwise. 82238384Sjkim bool 83238384Sjkim IsValid(); 84238384Sjkim 85238384Sjkim /// @returns the address of the rendezvous structure in the inferiors 86238384Sjkim /// address space. 87238384Sjkim lldb::addr_t 88238384Sjkim GetRendezvousAddress() const { return m_rendezvous_addr; } 89238384Sjkim 90238384Sjkim /// @returns the version of the rendezvous protocol being used. 91238384Sjkim uint64_t 92238384Sjkim GetVersion() const { return m_current.version; } 93238384Sjkim 94238384Sjkim /// @returns address in the inferiors address space containing the linked 95238384Sjkim /// list of shared object descriptors. 96238384Sjkim lldb::addr_t 97238384Sjkim GetLinkMapAddress() const { return m_current.map_addr; } 98238384Sjkim 99238384Sjkim /// A breakpoint should be set at this address and Resolve called on each 100238384Sjkim /// hit. 101238384Sjkim /// 102238384Sjkim /// @returns the address of a function called by the runtime linker each 103238384Sjkim /// time a module is loaded/unloaded, or about to be loaded/unloaded. 104238384Sjkim /// 105238384Sjkim /// @see Resolve() 106238384Sjkim lldb::addr_t 107238384Sjkim GetBreakAddress() const { return m_current.brk; } 108238384Sjkim 109238384Sjkim /// Returns the current state of the rendezvous structure. 110238384Sjkim uint64_t 111238384Sjkim GetState() const { return m_current.state; } 112238384Sjkim 113238384Sjkim /// @returns the base address of the runtime linker in the inferiors address 114238384Sjkim /// space. 115238384Sjkim lldb::addr_t 116238384Sjkim GetLDBase() const { return m_current.ldbase; } 117238384Sjkim 118238384Sjkim /// @returns the thread layout metadata from the inferiors thread library. 119238384Sjkim const ThreadInfo& 120238384Sjkim GetThreadInfo(); 121238384Sjkim 122238384Sjkim /// @returns true if modules have been loaded into the inferior since the 123238384Sjkim /// last call to Resolve(). 124238384Sjkim bool 125238384Sjkim ModulesDidLoad() const { return !m_added_soentries.empty(); } 126238384Sjkim 127238384Sjkim /// @returns true if modules have been unloaded from the inferior since the 128238384Sjkim /// last call to Resolve(). 129238384Sjkim bool 130238384Sjkim ModulesDidUnload() const { return !m_removed_soentries.empty(); } 131238384Sjkim 132238384Sjkim void 133238384Sjkim DumpToLog(lldb_private::Log *log) const; 134238384Sjkim 135238384Sjkim /// @brief Constants describing the state of the rendezvous. 136238384Sjkim /// 137238384Sjkim /// @see GetState(). 138238384Sjkim enum RendezvousState { 139238384Sjkim eConsistent, 140238384Sjkim eAdd, 141238384Sjkim eDelete 142238384Sjkim }; 143238384Sjkim 144238384Sjkim /// @brief Structure representing the shared objects currently loaded into 145238384Sjkim /// the inferior process. 146238384Sjkim /// 147238384Sjkim /// This object is a rough analogue to the struct link_map object which 148238384Sjkim /// actually lives in the inferiors memory. 149238384Sjkim struct SOEntry { 150238384Sjkim lldb::addr_t link_addr; ///< Address of this link_map. 151238384Sjkim lldb::addr_t base_addr; ///< Base address of the loaded object. 152238384Sjkim lldb::addr_t path_addr; ///< String naming the shared object. 153238384Sjkim lldb::addr_t dyn_addr; ///< Dynamic section of shared object. 154238384Sjkim lldb::addr_t next; ///< Address of next so_entry. 155238384Sjkim lldb::addr_t prev; ///< Address of previous so_entry. 156238384Sjkim lldb_private::FileSpec file_spec; ///< File spec of shared object. 157238384Sjkim 158238384Sjkim SOEntry() { clear(); } 159238384Sjkim 160238384Sjkim bool operator ==(const SOEntry &entry) { 161238384Sjkim return file_spec == entry.file_spec; 162238384Sjkim } 163238384Sjkim 164238384Sjkim void clear() { 165238384Sjkim link_addr = 0; 166238384Sjkim base_addr = 0; 167238384Sjkim path_addr = 0; 168238384Sjkim dyn_addr = 0; 169238384Sjkim next = 0; 170238384Sjkim prev = 0; 171238384Sjkim file_spec.Clear(); 172238384Sjkim } 173238384Sjkim }; 174238384Sjkim 175238384Sjkimprotected: 176238384Sjkim typedef std::list<SOEntry> SOEntryList; 177238384Sjkim 178238384Sjkimpublic: 179238384Sjkim typedef SOEntryList::const_iterator iterator; 180238384Sjkim 181238384Sjkim /// Iterators over all currently loaded modules. 182238384Sjkim iterator begin() const { return m_soentries.begin(); } 183238384Sjkim iterator end() const { return m_soentries.end(); } 184238384Sjkim 185238384Sjkim /// Iterators over all modules loaded into the inferior since the last call 186238384Sjkim /// to Resolve(). 187238384Sjkim iterator loaded_begin() const { return m_added_soentries.begin(); } 188238384Sjkim iterator loaded_end() const { return m_added_soentries.end(); } 189238384Sjkim 190238384Sjkim /// Iterators over all modules unloaded from the inferior since the last 191238384Sjkim /// call to Resolve(). 192238384Sjkim iterator unloaded_begin() const { return m_removed_soentries.begin(); } 193238384Sjkim iterator unloaded_end() const { return m_removed_soentries.end(); } 194238384Sjkim 195238384Sjkimprotected: 196238384Sjkim lldb_private::Process *m_process; 197238384Sjkim 198238384Sjkim // Cached copy of executable file spec 199 lldb_private::FileSpec m_exe_file_spec; 200 201 /// Location of the r_debug structure in the inferiors address space. 202 lldb::addr_t m_rendezvous_addr; 203 204 /// Current and previous snapshots of the rendezvous structure. 205 Rendezvous m_current; 206 Rendezvous m_previous; 207 208 /// List of currently loaded SO modules 209 LoadedModuleInfoList m_loaded_modules; 210 211 /// List of SOEntry objects corresponding to the current link map state. 212 SOEntryList m_soentries; 213 214 /// List of SOEntry's added to the link map since the last call to Resolve(). 215 SOEntryList m_added_soentries; 216 217 /// List of SOEntry's removed from the link map since the last call to 218 /// Resolve(). 219 SOEntryList m_removed_soentries; 220 221 /// Threading metadata read from the inferior. 222 ThreadInfo m_thread_info; 223 224 /// Reads an unsigned integer of @p size bytes from the inferior's address 225 /// space starting at @p addr. 226 /// 227 /// @returns addr + size if the read was successful and false otherwise. 228 lldb::addr_t 229 ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); 230 231 /// Reads an address from the inferior's address space starting at @p addr. 232 /// 233 /// @returns addr + target address size if the read was successful and 234 /// 0 otherwise. 235 lldb::addr_t 236 ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); 237 238 /// Reads a null-terminated C string from the memory location starting at @p 239 /// addr. 240 std::string 241 ReadStringFromMemory(lldb::addr_t addr); 242 243 /// Reads an SOEntry starting at @p addr. 244 bool 245 ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 246 247 /// Updates the current set of SOEntries, the set of added entries, and the 248 /// set of removed entries. 249 bool 250 UpdateSOEntries(bool fromRemote = false); 251 252 bool 253 FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo, 254 SOEntry &entry); 255 256 bool 257 SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); 258 259 bool 260 AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); 261 262 bool 263 RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); 264 265 bool 266 AddSOEntries(); 267 268 bool 269 RemoveSOEntries(); 270 271 void 272 UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path); 273 274 bool 275 SOEntryIsMainExecutable(const SOEntry &entry); 276 277 /// Reads the current list of shared objects according to the link map 278 /// supplied by the runtime linker. 279 bool 280 TakeSnapshot(SOEntryList &entry_list); 281 282 enum PThreadField { eSize, eNElem, eOffset }; 283 284 bool FindMetadata(const char *name, PThreadField field, uint32_t& value); 285}; 286 287#endif 288