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