HexagonDYLDRendezvous.h revision 344779
1275072Semaste//===-- HexagonDYLDRendezvous.h ---------------------------------*- C++ -*-===// 2275072Semaste// 3275072Semaste// The LLVM Compiler Infrastructure 4275072Semaste// 5275072Semaste// This file is distributed under the University of Illinois Open Source 6275072Semaste// License. See LICENSE.TXT for details. 7275072Semaste// 8275072Semaste//===----------------------------------------------------------------------===// 9275072Semaste 10275072Semaste#ifndef liblldb_HexagonDYLDRendezvous_H_ 11275072Semaste#define liblldb_HexagonDYLDRendezvous_H_ 12275072Semaste 13344779Sdim#include <limits.h> 14275072Semaste#include <list> 15341825Sdim#include <map> 16275072Semaste#include <string> 17275072Semaste 18275072Semaste#include "lldb/lldb-defines.h" 19275072Semaste#include "lldb/lldb-types.h" 20275072Semaste 21314564Sdimnamespace lldb_private { 22314564Sdimclass Process; 23275072Semaste} 24275072Semaste 25275072Semaste/// @class HexagonDYLDRendezvous 26341825Sdim/// Interface to the runtime linker. 27275072Semaste/// 28275072Semaste/// A structure is present in a processes memory space which is updated by the 29341825Sdim/// runtime liker each time a module is loaded or unloaded. This class 30341825Sdim/// provides an interface to this structure and maintains a consistent 31341825Sdim/// snapshot of the currently loaded modules. 32314564Sdimclass HexagonDYLDRendezvous { 33275072Semaste 34314564Sdim // This structure is used to hold the contents of the debug rendezvous 35314564Sdim // information (struct r_debug) as found in the inferiors memory. Note that 36314564Sdim // the layout of this struct is not binary compatible, it is simply large 37314564Sdim // enough to hold the information on both 32 and 64 bit platforms. 38314564Sdim struct Rendezvous { 39314564Sdim uint64_t version; 40314564Sdim lldb::addr_t map_addr; 41314564Sdim lldb::addr_t brk; 42314564Sdim uint64_t state; 43314564Sdim lldb::addr_t ldbase; 44275072Semaste 45314564Sdim Rendezvous() 46314564Sdim : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS), 47314564Sdim state(0), ldbase(0) {} 48314564Sdim }; 49275072Semaste 50275072Semastepublic: 51314564Sdim // Various metadata supplied by the inferior's threading library to describe 52314564Sdim // the per-thread state. 53314564Sdim struct ThreadInfo { 54314564Sdim bool valid; // whether we read valid metadata 55314564Sdim uint32_t dtv_offset; // offset of DTV pointer within pthread 56314564Sdim uint32_t dtv_slot_size; // size of one DTV slot 57314564Sdim uint32_t modid_offset; // offset of module ID within link_map 58314564Sdim uint32_t tls_offset; // offset of TLS pointer within DTV slot 59314564Sdim }; 60275072Semaste 61314564Sdim HexagonDYLDRendezvous(lldb_private::Process *process); 62275072Semaste 63314564Sdim /// Update the internal snapshot of runtime linker rendezvous and recompute 64314564Sdim /// the currently loaded modules. 65314564Sdim /// 66314564Sdim /// This method should be called once one start up, then once each time the 67314564Sdim /// runtime linker enters the function given by GetBreakAddress(). 68314564Sdim /// 69314564Sdim /// @returns true on success and false on failure. 70314564Sdim /// 71314564Sdim /// @see GetBreakAddress(). 72314564Sdim bool Resolve(); 73275072Semaste 74314564Sdim /// @returns true if this rendezvous has been located in the inferiors 75314564Sdim /// address space and false otherwise. 76314564Sdim bool IsValid(); 77275072Semaste 78314564Sdim /// @returns the address of the rendezvous structure in the inferiors 79314564Sdim /// address space. 80314564Sdim lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; } 81275072Semaste 82314564Sdim /// Provide the dyld structure address 83314564Sdim void SetRendezvousAddress(lldb::addr_t); 84275072Semaste 85314564Sdim /// @returns the version of the rendezvous protocol being used. 86314564Sdim uint64_t GetVersion() const { return m_current.version; } 87275072Semaste 88314564Sdim /// @returns address in the inferiors address space containing the linked 89314564Sdim /// list of shared object descriptors. 90314564Sdim lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; } 91275072Semaste 92314564Sdim /// A breakpoint should be set at this address and Resolve called on each 93314564Sdim /// hit. 94314564Sdim /// 95314564Sdim /// @returns the address of a function called by the runtime linker each 96314564Sdim /// time a module is loaded/unloaded, or about to be loaded/unloaded. 97314564Sdim /// 98314564Sdim /// @see Resolve() 99314564Sdim lldb::addr_t GetBreakAddress() const { return m_current.brk; } 100275072Semaste 101314564Sdim /// In hexagon it is possible that we can know the dyld breakpoint without 102314564Sdim /// having to find it from the rendezvous structure 103314564Sdim /// 104314564Sdim void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; } 105275072Semaste 106314564Sdim /// Returns the current state of the rendezvous structure. 107314564Sdim uint64_t GetState() const { return m_current.state; } 108275072Semaste 109314564Sdim /// @returns the base address of the runtime linker in the inferiors address 110314564Sdim /// space. 111314564Sdim lldb::addr_t GetLDBase() const { return m_current.ldbase; } 112275072Semaste 113314564Sdim /// @returns the thread layout metadata from the inferiors thread library. 114314564Sdim const ThreadInfo &GetThreadInfo(); 115275072Semaste 116314564Sdim /// @returns true if modules have been loaded into the inferior since the 117314564Sdim /// last call to Resolve(). 118314564Sdim bool ModulesDidLoad() const { return !m_added_soentries.empty(); } 119275072Semaste 120314564Sdim /// @returns true if modules have been unloaded from the inferior since the 121314564Sdim /// last call to Resolve(). 122314564Sdim bool ModulesDidUnload() const { return !m_removed_soentries.empty(); } 123275072Semaste 124314564Sdim void DumpToLog(lldb_private::Log *log) const; 125275072Semaste 126341825Sdim /// Constants describing the state of the rendezvous. 127314564Sdim /// 128314564Sdim /// @see GetState(). 129314564Sdim enum RendezvousState { 130314564Sdim eConsistent = 0, 131314564Sdim eAdd, 132314564Sdim eDelete, 133314564Sdim }; 134275072Semaste 135341825Sdim /// Structure representing the shared objects currently loaded into the 136341825Sdim /// inferior process. 137314564Sdim /// 138314564Sdim /// This object is a rough analogue to the struct link_map object which 139314564Sdim /// actually lives in the inferiors memory. 140314564Sdim struct SOEntry { 141314564Sdim lldb::addr_t link_addr; ///< Address of this link_map. 142314564Sdim lldb::addr_t base_addr; ///< Base address of the loaded object. 143314564Sdim lldb::addr_t path_addr; ///< String naming the shared object. 144314564Sdim lldb::addr_t dyn_addr; ///< Dynamic section of shared object. 145314564Sdim lldb::addr_t next; ///< Address of next so_entry. 146314564Sdim lldb::addr_t prev; ///< Address of previous so_entry. 147314564Sdim std::string path; ///< File name of shared object. 148275072Semaste 149314564Sdim SOEntry() { clear(); } 150275072Semaste 151314564Sdim bool operator==(const SOEntry &entry) { return this->path == entry.path; } 152275072Semaste 153314564Sdim void clear() { 154314564Sdim link_addr = 0; 155314564Sdim base_addr = 0; 156314564Sdim path_addr = 0; 157314564Sdim dyn_addr = 0; 158314564Sdim next = 0; 159314564Sdim prev = 0; 160314564Sdim path.clear(); 161314564Sdim } 162314564Sdim }; 163314564Sdim 164275072Semasteprotected: 165314564Sdim typedef std::list<SOEntry> SOEntryList; 166275072Semaste 167275072Semastepublic: 168314564Sdim typedef SOEntryList::const_iterator iterator; 169275072Semaste 170314564Sdim /// Iterators over all currently loaded modules. 171314564Sdim iterator begin() const { return m_soentries.begin(); } 172314564Sdim iterator end() const { return m_soentries.end(); } 173275072Semaste 174314564Sdim /// Iterators over all modules loaded into the inferior since the last call 175314564Sdim /// to Resolve(). 176314564Sdim iterator loaded_begin() const { return m_added_soentries.begin(); } 177314564Sdim iterator loaded_end() const { return m_added_soentries.end(); } 178275072Semaste 179314564Sdim /// Iterators over all modules unloaded from the inferior since the last 180314564Sdim /// call to Resolve(). 181314564Sdim iterator unloaded_begin() const { return m_removed_soentries.begin(); } 182314564Sdim iterator unloaded_end() const { return m_removed_soentries.end(); } 183314564Sdim 184275072Semasteprotected: 185314564Sdim lldb_private::Process *m_process; 186275072Semaste 187314564Sdim // Cached copy of executable pathname 188314564Sdim char m_exe_path[PATH_MAX]; 189275072Semaste 190314564Sdim /// Location of the r_debug structure in the inferiors address space. 191314564Sdim lldb::addr_t m_rendezvous_addr; 192275072Semaste 193314564Sdim /// Current and previous snapshots of the rendezvous structure. 194314564Sdim Rendezvous m_current; 195314564Sdim Rendezvous m_previous; 196275072Semaste 197314564Sdim /// List of SOEntry objects corresponding to the current link map state. 198314564Sdim SOEntryList m_soentries; 199275072Semaste 200341825Sdim /// List of SOEntry's added to the link map since the last call to 201341825Sdim /// Resolve(). 202314564Sdim SOEntryList m_added_soentries; 203275072Semaste 204314564Sdim /// List of SOEntry's removed from the link map since the last call to 205314564Sdim /// Resolve(). 206314564Sdim SOEntryList m_removed_soentries; 207275072Semaste 208314564Sdim /// Threading metadata read from the inferior. 209314564Sdim ThreadInfo m_thread_info; 210275072Semaste 211314564Sdim /// Reads an unsigned integer of @p size bytes from the inferior's address 212314564Sdim /// space starting at @p addr. 213314564Sdim /// 214314564Sdim /// @returns addr + size if the read was successful and false otherwise. 215314564Sdim lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); 216275072Semaste 217314564Sdim /// Reads an address from the inferior's address space starting at @p addr. 218314564Sdim /// 219314564Sdim /// @returns addr + target address size if the read was successful and 220314564Sdim /// 0 otherwise. 221314564Sdim lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); 222275072Semaste 223314564Sdim /// Reads a null-terminated C string from the memory location starting at @p 224314564Sdim /// addr. 225314564Sdim std::string ReadStringFromMemory(lldb::addr_t addr); 226275072Semaste 227314564Sdim /// Reads an SOEntry starting at @p addr. 228314564Sdim bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 229275072Semaste 230314564Sdim /// Updates the current set of SOEntries, the set of added entries, and the 231314564Sdim /// set of removed entries. 232314564Sdim bool UpdateSOEntries(); 233275072Semaste 234314564Sdim bool UpdateSOEntriesForAddition(); 235275072Semaste 236314564Sdim bool UpdateSOEntriesForDeletion(); 237275072Semaste 238314564Sdim /// Reads the current list of shared objects according to the link map 239314564Sdim /// supplied by the runtime linker. 240314564Sdim bool TakeSnapshot(SOEntryList &entry_list); 241275072Semaste 242314564Sdim enum PThreadField { eSize, eNElem, eOffset }; 243275072Semaste 244314564Sdim bool FindMetadata(const char *name, PThreadField field, uint32_t &value); 245275072Semaste}; 246275072Semaste 247275072Semaste#endif // liblldb_HexagonDYLDRendezvous_H_ 248