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