Coverage Report

Created: 2022-01-22 13:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
Line
Count
Source (jump to first uncovered line)
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_HEXAGON_DYLD_HEXAGONDYLDRENDEZVOUS_H
10
#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_HEXAGON_DYLD_HEXAGONDYLDRENDEZVOUS_H
11
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
20
namespace lldb_private {
21
class Process;
22
}
23
24
/// \class HexagonDYLDRendezvous
25
/// Interface to the runtime linker.
26
///
27
/// A structure is present in a processes memory space which is updated by the
28
/// runtime liker each time a module is loaded or unloaded.  This class
29
/// provides an interface to this structure and maintains a consistent
30
/// snapshot of the currently loaded modules.
31
class HexagonDYLDRendezvous {
32
33
  // This structure is used to hold the contents of the debug rendezvous
34
  // information (struct r_debug) as found in the inferiors memory.  Note that
35
  // the layout of this struct is not binary compatible, it is simply large
36
  // 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
0
    Rendezvous() = default;
45
  };
46
47
public:
48
  // Various metadata supplied by the inferior's threading library to describe
49
  // the per-thread state.
50
  struct ThreadInfo {
51
    bool valid;             // whether we read valid metadata
52
    uint32_t dtv_offset;    // offset of DTV pointer within pthread
53
    uint32_t dtv_slot_size; // size of one DTV slot
54
    uint32_t modid_offset;  // offset of module ID within link_map
55
    uint32_t tls_offset;    // offset of TLS pointer within DTV slot
56
  };
57
58
  HexagonDYLDRendezvous(lldb_private::Process *process);
59
60
  /// Update the internal snapshot of runtime linker rendezvous and recompute
61
  /// the currently loaded modules.
62
  ///
63
  /// This method should be called once one start up, then once each time the
64
  /// 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 inferiors
72
  /// address space and false otherwise.
73
  bool IsValid();
74
75
  /// \returns the address of the rendezvous structure in the inferiors
76
  /// address space.
77
0
  lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }
78
79
  /// Provide the dyld structure address
80
  void SetRendezvousAddress(lldb::addr_t);
81
82
  /// \returns the version of the rendezvous protocol being used.
83
0
  uint64_t GetVersion() const { return m_current.version; }
84
85
  /// \returns address in the inferiors address space containing the linked
86
  /// list of shared object descriptors.
87
0
  lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; }
88
89
  /// A breakpoint should be set at this address and Resolve called on each
90
  /// hit.
91
  ///
92
  /// \returns the address of a function called by the runtime linker each
93
  /// time a module is loaded/unloaded, or about to be loaded/unloaded.
94
  ///
95
  /// \see Resolve()
96
0
  lldb::addr_t GetBreakAddress() const { return m_current.brk; }
97
98
  /// In hexagon it is possible that we can know the dyld breakpoint without
99
  /// having to find it from the rendezvous structure
100
  ///
101
0
  void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; }
102
103
  /// Returns the current state of the rendezvous structure.
104
0
  uint64_t GetState() const { return m_current.state; }
105
106
  /// \returns the base address of the runtime linker in the inferiors address
107
  /// space.
108
0
  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 the
114
  /// last call to Resolve().
115
0
  bool ModulesDidLoad() const { return !m_added_soentries.empty(); }
116
117
  /// \returns true if modules have been unloaded from the inferior since the
118
  /// last call to Resolve().
119
0
  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 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
    std::string path;       ///< File name of shared object.
145
146
0
    SOEntry() { clear(); }
147
148
0
    bool operator==(const SOEntry &entry) { return this->path == entry.path; }
149
150
0
    void clear() {
151
0
      link_addr = 0;
152
0
      base_addr = 0;
153
0
      path_addr = 0;
154
0
      dyn_addr = 0;
155
0
      next = 0;
156
0
      prev = 0;
157
0
      path.clear();
158
0
    }
159
  };
160
161
protected:
162
  typedef std::list<SOEntry> SOEntryList;
163
164
public:
165
  typedef SOEntryList::const_iterator iterator;
166
167
  /// Iterators over all currently loaded modules.
168
0
  iterator begin() const { return m_soentries.begin(); }
169
0
  iterator end() const { return m_soentries.end(); }
170
171
  /// Iterators over all modules loaded into the inferior since the last call
172
  /// to Resolve().
173
0
  iterator loaded_begin() const { return m_added_soentries.begin(); }
174
0
  iterator loaded_end() const { return m_added_soentries.end(); }
175
176
  /// Iterators over all modules unloaded from the inferior since the last
177
  /// call to Resolve().
178
0
  iterator unloaded_begin() const { return m_removed_soentries.begin(); }
179
0
  iterator unloaded_end() const { return m_removed_soentries.end(); }
180
181
protected:
182
  lldb_private::Process *m_process;
183
184
  // Cached copy of executable pathname
185
  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 to
198
  /// Resolve().
199
  SOEntryList m_added_soentries;
200
201
  /// List of SOEntry's removed from the link map since the last call to
202
  /// 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 address
209
  /// 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 and
217
  /// 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 @p
221
  /// 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 the
228
  /// 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 map
236
  /// 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_H