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