245 lines · c
1//===-- HexagonDYLDRendezvous.h ---------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_HEXAGON_DYLD_HEXAGONDYLDRENDEZVOUS_H10#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_HEXAGON_DYLD_HEXAGONDYLDRENDEZVOUS_H11 12#include <limits.h>13#include <list>14#include <map>15#include <string>16 17#include "lldb/lldb-defines.h"18#include "lldb/lldb-types.h"19 20namespace lldb_private {21class Process;22}23 24/// \class HexagonDYLDRendezvous25/// Interface to the runtime linker.26///27/// A structure is present in a processes memory space which is updated by the28/// runtime liker each time a module is loaded or unloaded. This class29/// provides an interface to this structure and maintains a consistent30/// snapshot of the currently loaded modules.31class HexagonDYLDRendezvous {32 33 // This structure is used to hold the contents of the debug rendezvous34 // information (struct r_debug) as found in the inferiors memory. Note that35 // the layout of this struct is not binary compatible, it is simply large36 // enough to hold the information on both 32 and 64 bit platforms.37 struct Rendezvous {38 uint64_t version = 0;39 lldb::addr_t map_addr = LLDB_INVALID_ADDRESS;40 lldb::addr_t brk = LLDB_INVALID_ADDRESS;41 uint64_t state = 0;42 lldb::addr_t ldbase = 0;43 44 Rendezvous() = default;45 };46 47public:48 // Various metadata supplied by the inferior's threading library to describe49 // the per-thread state.50 struct ThreadInfo {51 bool valid; // whether we read valid metadata52 uint32_t dtv_offset; // offset of DTV pointer within pthread53 uint32_t dtv_slot_size; // size of one DTV slot54 uint32_t modid_offset; // offset of module ID within link_map55 uint32_t tls_offset; // offset of TLS pointer within DTV slot56 };57 58 HexagonDYLDRendezvous(lldb_private::Process *process);59 60 /// Update the internal snapshot of runtime linker rendezvous and recompute61 /// the currently loaded modules.62 ///63 /// This method should be called once one start up, then once each time the64 /// runtime linker enters the function given by GetBreakAddress().65 ///66 /// \returns true on success and false on failure.67 ///68 /// \see GetBreakAddress().69 bool Resolve();70 71 /// \returns true if this rendezvous has been located in the inferiors72 /// address space and false otherwise.73 bool IsValid();74 75 /// \returns the address of the rendezvous structure in the inferiors76 /// address space.77 lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }78 79 /// Provide the dyld structure address80 void SetRendezvousAddress(lldb::addr_t);81 82 /// \returns the version of the rendezvous protocol being used.83 uint64_t GetVersion() const { return m_current.version; }84 85 /// \returns address in the inferiors address space containing the linked86 /// list of shared object descriptors.87 lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; }88 89 /// A breakpoint should be set at this address and Resolve called on each90 /// hit.91 ///92 /// \returns the address of a function called by the runtime linker each93 /// time a module is loaded/unloaded, or about to be loaded/unloaded.94 ///95 /// \see Resolve()96 lldb::addr_t GetBreakAddress() const { return m_current.brk; }97 98 /// In hexagon it is possible that we can know the dyld breakpoint without99 /// having to find it from the rendezvous structure100 ///101 void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; }102 103 /// Returns the current state of the rendezvous structure.104 uint64_t GetState() const { return m_current.state; }105 106 /// \returns the base address of the runtime linker in the inferiors address107 /// space.108 lldb::addr_t GetLDBase() const { return m_current.ldbase; }109 110 /// \returns the thread layout metadata from the inferiors thread library.111 const ThreadInfo &GetThreadInfo();112 113 /// \returns true if modules have been loaded into the inferior since the114 /// last call to Resolve().115 bool ModulesDidLoad() const { return !m_added_soentries.empty(); }116 117 /// \returns true if modules have been unloaded from the inferior since the118 /// last call to Resolve().119 bool ModulesDidUnload() const { return !m_removed_soentries.empty(); }120 121 void DumpToLog(lldb_private::Log *log) const;122 123 /// Constants describing the state of the rendezvous.124 ///125 /// \see GetState().126 enum RendezvousState {127 eConsistent = 0,128 eAdd,129 eDelete,130 };131 132 /// Structure representing the shared objects currently loaded into the133 /// inferior process.134 ///135 /// This object is a rough analogue to the struct link_map object which136 /// actually lives in the inferiors memory.137 struct SOEntry {138 lldb::addr_t link_addr; ///< Address of this link_map.139 lldb::addr_t base_addr; ///< Base address of the loaded object.140 lldb::addr_t path_addr; ///< String naming the shared object.141 lldb::addr_t dyn_addr; ///< Dynamic section of shared object.142 lldb::addr_t next; ///< Address of next so_entry.143 lldb::addr_t prev; ///< Address of previous so_entry.144 std::string path; ///< File name of shared object.145 146 SOEntry() { clear(); }147 148 bool operator==(const SOEntry &entry) { return this->path == entry.path; }149 150 void clear() {151 link_addr = 0;152 base_addr = 0;153 path_addr = 0;154 dyn_addr = 0;155 next = 0;156 prev = 0;157 path.clear();158 }159 };160 161protected:162 typedef std::list<SOEntry> SOEntryList;163 164public:165 typedef SOEntryList::const_iterator iterator;166 167 /// Iterators over all currently loaded modules.168 iterator begin() const { return m_soentries.begin(); }169 iterator end() const { return m_soentries.end(); }170 171 /// Iterators over all modules loaded into the inferior since the last call172 /// to Resolve().173 iterator loaded_begin() const { return m_added_soentries.begin(); }174 iterator loaded_end() const { return m_added_soentries.end(); }175 176 /// Iterators over all modules unloaded from the inferior since the last177 /// call to Resolve().178 iterator unloaded_begin() const { return m_removed_soentries.begin(); }179 iterator unloaded_end() const { return m_removed_soentries.end(); }180 181protected:182 lldb_private::Process *m_process;183 184 // Cached copy of executable pathname185 char m_exe_path[PATH_MAX];186 187 /// Location of the r_debug structure in the inferiors address space.188 lldb::addr_t m_rendezvous_addr;189 190 /// Current and previous snapshots of the rendezvous structure.191 Rendezvous m_current;192 Rendezvous m_previous;193 194 /// List of SOEntry objects corresponding to the current link map state.195 SOEntryList m_soentries;196 197 /// List of SOEntry's added to the link map since the last call to198 /// Resolve().199 SOEntryList m_added_soentries;200 201 /// List of SOEntry's removed from the link map since the last call to202 /// Resolve().203 SOEntryList m_removed_soentries;204 205 /// Threading metadata read from the inferior.206 ThreadInfo m_thread_info;207 208 /// Reads an unsigned integer of \p size bytes from the inferior's address209 /// space starting at \p addr.210 ///211 /// \returns addr + size if the read was successful and false otherwise.212 lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);213 214 /// Reads an address from the inferior's address space starting at \p addr.215 ///216 /// \returns addr + target address size if the read was successful and217 /// 0 otherwise.218 lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);219 220 /// Reads a null-terminated C string from the memory location starting at @p221 /// addr.222 std::string ReadStringFromMemory(lldb::addr_t addr);223 224 /// Reads an SOEntry starting at \p addr.225 bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);226 227 /// Updates the current set of SOEntries, the set of added entries, and the228 /// set of removed entries.229 bool UpdateSOEntries();230 231 bool UpdateSOEntriesForAddition();232 233 bool UpdateSOEntriesForDeletion();234 235 /// Reads the current list of shared objects according to the link map236 /// supplied by the runtime linker.237 bool TakeSnapshot(SOEntryList &entry_list);238 239 enum PThreadField { eSize, eNElem, eOffset };240 241 bool FindMetadata(const char *name, PThreadField field, uint32_t &value);242};243 244#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_HEXAGON_DYLD_HEXAGONDYLDRENDEZVOUS_H245