1275072Semaste//===-- HexagonDYLDRendezvous.h ---------------------------------*- C++ -*-===// 2275072Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6275072Semaste// 7275072Semaste//===----------------------------------------------------------------------===// 8275072Semaste 9275072Semaste#ifndef liblldb_HexagonDYLDRendezvous_H_ 10275072Semaste#define liblldb_HexagonDYLDRendezvous_H_ 11275072Semaste 12344779Sdim#include <limits.h> 13275072Semaste#include <list> 14341825Sdim#include <map> 15275072Semaste#include <string> 16275072Semaste 17275072Semaste#include "lldb/lldb-defines.h" 18275072Semaste#include "lldb/lldb-types.h" 19275072Semaste 20314564Sdimnamespace lldb_private { 21314564Sdimclass Process; 22275072Semaste} 23275072Semaste 24353358Sdim/// \class HexagonDYLDRendezvous 25341825Sdim/// Interface to the runtime linker. 26275072Semaste/// 27275072Semaste/// A structure is present in a processes memory space which is updated by the 28341825Sdim/// runtime liker each time a module is loaded or unloaded. This class 29341825Sdim/// provides an interface to this structure and maintains a consistent 30341825Sdim/// snapshot of the currently loaded modules. 31314564Sdimclass HexagonDYLDRendezvous { 32275072Semaste 33314564Sdim // This structure is used to hold the contents of the debug rendezvous 34314564Sdim // information (struct r_debug) as found in the inferiors memory. Note that 35314564Sdim // the layout of this struct is not binary compatible, it is simply large 36314564Sdim // enough to hold the information on both 32 and 64 bit platforms. 37314564Sdim struct Rendezvous { 38314564Sdim uint64_t version; 39314564Sdim lldb::addr_t map_addr; 40314564Sdim lldb::addr_t brk; 41314564Sdim uint64_t state; 42314564Sdim lldb::addr_t ldbase; 43275072Semaste 44314564Sdim Rendezvous() 45314564Sdim : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS), 46314564Sdim state(0), ldbase(0) {} 47314564Sdim }; 48275072Semaste 49275072Semastepublic: 50314564Sdim // Various metadata supplied by the inferior's threading library to describe 51314564Sdim // the per-thread state. 52314564Sdim struct ThreadInfo { 53314564Sdim bool valid; // whether we read valid metadata 54314564Sdim uint32_t dtv_offset; // offset of DTV pointer within pthread 55314564Sdim uint32_t dtv_slot_size; // size of one DTV slot 56314564Sdim uint32_t modid_offset; // offset of module ID within link_map 57314564Sdim uint32_t tls_offset; // offset of TLS pointer within DTV slot 58314564Sdim }; 59275072Semaste 60314564Sdim HexagonDYLDRendezvous(lldb_private::Process *process); 61275072Semaste 62314564Sdim /// Update the internal snapshot of runtime linker rendezvous and recompute 63314564Sdim /// the currently loaded modules. 64314564Sdim /// 65314564Sdim /// This method should be called once one start up, then once each time the 66314564Sdim /// runtime linker enters the function given by GetBreakAddress(). 67314564Sdim /// 68353358Sdim /// \returns true on success and false on failure. 69314564Sdim /// 70353358Sdim /// \see GetBreakAddress(). 71314564Sdim bool Resolve(); 72275072Semaste 73353358Sdim /// \returns true if this rendezvous has been located in the inferiors 74314564Sdim /// address space and false otherwise. 75314564Sdim bool IsValid(); 76275072Semaste 77353358Sdim /// \returns the address of the rendezvous structure in the inferiors 78314564Sdim /// address space. 79314564Sdim lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; } 80275072Semaste 81314564Sdim /// Provide the dyld structure address 82314564Sdim void SetRendezvousAddress(lldb::addr_t); 83275072Semaste 84353358Sdim /// \returns the version of the rendezvous protocol being used. 85314564Sdim uint64_t GetVersion() const { return m_current.version; } 86275072Semaste 87353358Sdim /// \returns address in the inferiors address space containing the linked 88314564Sdim /// list of shared object descriptors. 89314564Sdim lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; } 90275072Semaste 91314564Sdim /// A breakpoint should be set at this address and Resolve called on each 92314564Sdim /// hit. 93314564Sdim /// 94353358Sdim /// \returns the address of a function called by the runtime linker each 95314564Sdim /// time a module is loaded/unloaded, or about to be loaded/unloaded. 96314564Sdim /// 97353358Sdim /// \see Resolve() 98314564Sdim lldb::addr_t GetBreakAddress() const { return m_current.brk; } 99275072Semaste 100314564Sdim /// In hexagon it is possible that we can know the dyld breakpoint without 101314564Sdim /// having to find it from the rendezvous structure 102314564Sdim /// 103314564Sdim void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; } 104275072Semaste 105314564Sdim /// Returns the current state of the rendezvous structure. 106314564Sdim uint64_t GetState() const { return m_current.state; } 107275072Semaste 108353358Sdim /// \returns the base address of the runtime linker in the inferiors address 109314564Sdim /// space. 110314564Sdim lldb::addr_t GetLDBase() const { return m_current.ldbase; } 111275072Semaste 112353358Sdim /// \returns the thread layout metadata from the inferiors thread library. 113314564Sdim const ThreadInfo &GetThreadInfo(); 114275072Semaste 115353358Sdim /// \returns true if modules have been loaded into the inferior since the 116314564Sdim /// last call to Resolve(). 117314564Sdim bool ModulesDidLoad() const { return !m_added_soentries.empty(); } 118275072Semaste 119353358Sdim /// \returns true if modules have been unloaded from the inferior since the 120314564Sdim /// last call to Resolve(). 121314564Sdim bool ModulesDidUnload() const { return !m_removed_soentries.empty(); } 122275072Semaste 123314564Sdim void DumpToLog(lldb_private::Log *log) const; 124275072Semaste 125341825Sdim /// Constants describing the state of the rendezvous. 126314564Sdim /// 127353358Sdim /// \see GetState(). 128314564Sdim enum RendezvousState { 129314564Sdim eConsistent = 0, 130314564Sdim eAdd, 131314564Sdim eDelete, 132314564Sdim }; 133275072Semaste 134341825Sdim /// Structure representing the shared objects currently loaded into the 135341825Sdim /// inferior process. 136314564Sdim /// 137314564Sdim /// This object is a rough analogue to the struct link_map object which 138314564Sdim /// actually lives in the inferiors memory. 139314564Sdim struct SOEntry { 140314564Sdim lldb::addr_t link_addr; ///< Address of this link_map. 141314564Sdim lldb::addr_t base_addr; ///< Base address of the loaded object. 142314564Sdim lldb::addr_t path_addr; ///< String naming the shared object. 143314564Sdim lldb::addr_t dyn_addr; ///< Dynamic section of shared object. 144314564Sdim lldb::addr_t next; ///< Address of next so_entry. 145314564Sdim lldb::addr_t prev; ///< Address of previous so_entry. 146314564Sdim std::string path; ///< File name of shared object. 147275072Semaste 148314564Sdim SOEntry() { clear(); } 149275072Semaste 150314564Sdim bool operator==(const SOEntry &entry) { return this->path == entry.path; } 151275072Semaste 152314564Sdim void clear() { 153314564Sdim link_addr = 0; 154314564Sdim base_addr = 0; 155314564Sdim path_addr = 0; 156314564Sdim dyn_addr = 0; 157314564Sdim next = 0; 158314564Sdim prev = 0; 159314564Sdim path.clear(); 160314564Sdim } 161314564Sdim }; 162314564Sdim 163275072Semasteprotected: 164314564Sdim typedef std::list<SOEntry> SOEntryList; 165275072Semaste 166275072Semastepublic: 167314564Sdim typedef SOEntryList::const_iterator iterator; 168275072Semaste 169314564Sdim /// Iterators over all currently loaded modules. 170314564Sdim iterator begin() const { return m_soentries.begin(); } 171314564Sdim iterator end() const { return m_soentries.end(); } 172275072Semaste 173314564Sdim /// Iterators over all modules loaded into the inferior since the last call 174314564Sdim /// to Resolve(). 175314564Sdim iterator loaded_begin() const { return m_added_soentries.begin(); } 176314564Sdim iterator loaded_end() const { return m_added_soentries.end(); } 177275072Semaste 178314564Sdim /// Iterators over all modules unloaded from the inferior since the last 179314564Sdim /// call to Resolve(). 180314564Sdim iterator unloaded_begin() const { return m_removed_soentries.begin(); } 181314564Sdim iterator unloaded_end() const { return m_removed_soentries.end(); } 182314564Sdim 183275072Semasteprotected: 184314564Sdim lldb_private::Process *m_process; 185275072Semaste 186314564Sdim // Cached copy of executable pathname 187314564Sdim char m_exe_path[PATH_MAX]; 188275072Semaste 189314564Sdim /// Location of the r_debug structure in the inferiors address space. 190314564Sdim lldb::addr_t m_rendezvous_addr; 191275072Semaste 192314564Sdim /// Current and previous snapshots of the rendezvous structure. 193314564Sdim Rendezvous m_current; 194314564Sdim Rendezvous m_previous; 195275072Semaste 196314564Sdim /// List of SOEntry objects corresponding to the current link map state. 197314564Sdim SOEntryList m_soentries; 198275072Semaste 199341825Sdim /// List of SOEntry's added to the link map since the last call to 200341825Sdim /// Resolve(). 201314564Sdim SOEntryList m_added_soentries; 202275072Semaste 203314564Sdim /// List of SOEntry's removed from the link map since the last call to 204314564Sdim /// Resolve(). 205314564Sdim SOEntryList m_removed_soentries; 206275072Semaste 207314564Sdim /// Threading metadata read from the inferior. 208314564Sdim ThreadInfo m_thread_info; 209275072Semaste 210353358Sdim /// Reads an unsigned integer of \p size bytes from the inferior's address 211353358Sdim /// space starting at \p addr. 212314564Sdim /// 213353358Sdim /// \returns addr + size if the read was successful and false otherwise. 214314564Sdim lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); 215275072Semaste 216353358Sdim /// Reads an address from the inferior's address space starting at \p addr. 217314564Sdim /// 218353358Sdim /// \returns addr + target address size if the read was successful and 219314564Sdim /// 0 otherwise. 220314564Sdim lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); 221275072Semaste 222314564Sdim /// Reads a null-terminated C string from the memory location starting at @p 223314564Sdim /// addr. 224314564Sdim std::string ReadStringFromMemory(lldb::addr_t addr); 225275072Semaste 226353358Sdim /// Reads an SOEntry starting at \p addr. 227314564Sdim bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); 228275072Semaste 229314564Sdim /// Updates the current set of SOEntries, the set of added entries, and the 230314564Sdim /// set of removed entries. 231314564Sdim bool UpdateSOEntries(); 232275072Semaste 233314564Sdim bool UpdateSOEntriesForAddition(); 234275072Semaste 235314564Sdim bool UpdateSOEntriesForDeletion(); 236275072Semaste 237314564Sdim /// Reads the current list of shared objects according to the link map 238314564Sdim /// supplied by the runtime linker. 239314564Sdim bool TakeSnapshot(SOEntryList &entry_list); 240275072Semaste 241314564Sdim enum PThreadField { eSize, eNElem, eOffset }; 242275072Semaste 243314564Sdim bool FindMetadata(const char *name, PThreadField field, uint32_t &value); 244275072Semaste}; 245275072Semaste 246275072Semaste#endif // liblldb_HexagonDYLDRendezvous_H_ 247