Coverage Report

Created: 2022-01-22 13:19

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