LLDB mainline
HexagonDYLDRendezvous.cpp
Go to the documentation of this file.
1//===-- HexagonDYLDRendezvous.cpp -----------------------------------------===//
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#include "lldb/Core/Module.h"
11#include "lldb/Symbol/Symbol.h"
13#include "lldb/Target/Process.h"
14#include "lldb/Target/Target.h"
15#include "lldb/Utility/Log.h"
16#include "lldb/Utility/Status.h"
17
18#include "llvm/Support/Error.h"
19
21
22using namespace lldb;
23using namespace lldb_private;
24
25/// Locates the address of the rendezvous structure. Returns the address on
26/// success and LLDB_INVALID_ADDRESS on failure.
28 addr_t info_location;
29 addr_t info_addr;
30
31 info_location = process->GetImageInfoAddress();
32
33 if (info_location == LLDB_INVALID_ADDRESS)
35
36 llvm::Expected<lldb::addr_t> info_addr_or_err =
37 process->ReadPointerFromMemory(info_location);
38 if (!info_addr_or_err) {
39 llvm::consumeError(info_addr_or_err.takeError());
41 }
42 info_addr = *info_addr_or_err;
43
44 if (info_addr == 0)
46
47 return info_addr;
48}
49
53 m_thread_info.valid = false;
54 m_thread_info.dtv_offset = 0;
55 m_thread_info.dtv_slot_size = 0;
56 m_thread_info.modid_offset = 0;
57 m_thread_info.tls_offset = 0;
58
59 // Cache a copy of the executable path
60 if (m_process) {
61 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
62 if (exe_mod)
64 }
65}
66
68 const size_t word_size = 4;
69 Rendezvous info;
70 size_t address_size;
71 size_t padding;
72 addr_t info_addr;
73 addr_t cursor;
74
75 address_size = m_process->GetAddressByteSize();
76 padding = address_size - word_size;
77
79 cursor = info_addr = ResolveRendezvousAddress(m_process);
80 else
81 cursor = info_addr = m_rendezvous_addr;
82
83 if (cursor == LLDB_INVALID_ADDRESS)
84 return false;
85
86 if (!(cursor = ReadWord(cursor, &info.version, word_size)))
87 return false;
88
89 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
90 return false;
91
92 if (!(cursor = ReadPointer(cursor, &info.brk)))
93 return false;
94
95 if (!(cursor = ReadWord(cursor, &info.state, word_size)))
96 return false;
97
98 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
99 return false;
100
101 // The rendezvous was successfully read. Update our internal state.
102 m_rendezvous_addr = info_addr;
104 m_current = info;
105
106 return UpdateSOEntries();
107}
108
112
116
118 SOEntry entry;
119
120 if (m_current.map_addr == 0)
121 return false;
122
123 // When the previous and current states are consistent this is the first time
124 // we have been asked to update. Just take a snapshot of the currently
125 // loaded modules.
126 if (m_previous.state == eConsistent && m_current.state == eConsistent)
128
129 // If we are about to add or remove a shared object clear out the current
130 // state and take a snapshot of the currently loaded images.
131 if (m_current.state == eAdd || m_current.state == eDelete) {
132 // this is a fudge so that we can clear the assert below.
133 m_previous.state = eConsistent;
134 // We hit this assert on the 2nd run of this function after running the
135 // calc example
136 assert(m_previous.state == eConsistent);
137 m_soentries.clear();
138 m_added_soentries.clear();
139 m_removed_soentries.clear();
141 }
142 assert(m_current.state == eConsistent);
143
144 // Otherwise check the previous state to determine what to expect and update
145 // accordingly.
146 if (m_previous.state == eAdd)
148 else if (m_previous.state == eDelete)
150
151 return false;
152}
153
155 SOEntry entry;
156
157 assert(m_previous.state == eAdd);
158
159 if (m_current.map_addr == 0)
160 return false;
161
162 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
163 if (!ReadSOEntryFromMemory(cursor, entry))
164 return false;
165
166 // Only add shared libraries and not the executable. On Linux this is
167 // indicated by an empty path in the entry. On FreeBSD it is the name of
168 // the executable.
169 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
170 continue;
171
172 if (!llvm::is_contained(m_soentries, entry)) {
173 m_soentries.push_back(entry);
174 m_added_soentries.push_back(entry);
175 }
176 }
177
178 return true;
179}
180
182 SOEntryList entry_list;
183
184 assert(m_previous.state == eDelete);
185
186 if (!TakeSnapshot(entry_list))
187 return false;
188
189 for (iterator I = begin(); I != end(); ++I) {
190 if (!llvm::is_contained(entry_list, *I))
191 m_removed_soentries.push_back(*I);
192 }
193
194 m_soentries = entry_list;
195 return true;
196}
197
199 SOEntry entry;
200
201 if (m_current.map_addr == 0)
202 return false;
203
204 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
205 if (!ReadSOEntryFromMemory(cursor, entry))
206 return false;
207
208 // Only add shared libraries and not the executable. On Linux this is
209 // indicated by an empty path in the entry. On FreeBSD it is the name of
210 // the executable.
211 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
212 continue;
213
214 entry_list.push_back(entry);
215 }
216
217 return true;
218}
219
221 size_t size) {
223
224 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
225 if (error.Fail())
226 return 0;
227
228 return addr + size;
229}
230
232 llvm::Expected<lldb::addr_t> dst_or_err =
233 m_process->ReadPointerFromMemory(addr);
234 if (!dst_or_err) {
235 llvm::consumeError(dst_or_err.takeError());
236 return 0;
237 }
238 *dst = *dst_or_err;
239
240 return addr + m_process->GetAddressByteSize();
241}
242
244 std::string str;
246 size_t size;
247 char c;
248
249 if (addr == LLDB_INVALID_ADDRESS)
250 return std::string();
251
252 for (;;) {
253 size = m_process->ReadMemory(addr, &c, 1, error);
254 if (size != 1 || error.Fail())
255 return std::string();
256 if (c == 0)
257 break;
258 else {
259 str.push_back(c);
260 addr++;
261 }
262 }
263
264 return str;
265}
266
268 SOEntry &entry) {
269 entry.clear();
270 entry.link_addr = addr;
271
272 if (!(addr = ReadPointer(addr, &entry.base_addr)))
273 return false;
274
275 if (!(addr = ReadPointer(addr, &entry.path_addr)))
276 return false;
277
278 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
279 return false;
280
281 if (!(addr = ReadPointer(addr, &entry.next)))
282 return false;
283
284 if (!(addr = ReadPointer(addr, &entry.prev)))
285 return false;
286
287 entry.path = ReadStringFromMemory(entry.path_addr);
288
289 return true;
290}
291
293 uint32_t &value) {
294 Target &target = m_process->GetTarget();
295
298 eSymbolTypeAny, list);
299 if (list.IsEmpty())
300 return false;
301
302 Address address = list[0].symbol->GetAddress();
303 addr_t addr = address.GetLoadAddress(&target);
304 if (addr == LLDB_INVALID_ADDRESS)
305 return false;
306
308 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
309 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
310 if (error.Fail())
311 return false;
312
313 if (field == eSize)
314 value /= 8; // convert bits to bytes
315
316 return true;
317}
318
321 if (!m_thread_info.valid) {
322 bool ok = true;
323
324 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
325 m_thread_info.dtv_offset);
326 ok &=
327 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
328 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
329 m_thread_info.modid_offset);
330 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
331 m_thread_info.tls_offset);
332
333 if (ok)
334 m_thread_info.valid = true;
335 }
336
337 return m_thread_info;
338}
339
341 int state = GetState();
342
343 if (!log)
344 return;
345
346 log->PutCString("HexagonDYLDRendezvous:");
347 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress());
348 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion());
349 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress());
350 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress());
351 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase());
352 LLDB_LOGF(log, " State : %s",
353 (state == eConsistent)
354 ? "consistent"
355 : (state == eAdd) ? "add"
356 : (state == eDelete) ? "delete" : "unknown");
357
358 iterator I = begin();
359 iterator E = end();
360
361 if (I != E)
362 log->PutCString("HexagonDYLDRendezvous SOEntries:");
363
364 for (int i = 1; I != E; ++I, ++i) {
365 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->path.c_str());
366 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr);
367 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr);
368 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr);
369 LLDB_LOGF(log, " Next : %" PRIx64, I->next);
370 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev);
371 }
372}
static const size_t word_size
static llvm::raw_ostream & error(Stream &strm)
static addr_t ResolveRendezvousAddress(Process *process)
Locates the address of the rendezvous structure.
#define LLDB_LOGF(log,...)
Definition Log.h:389
Rendezvous m_current
Current and previous snapshots of the rendezvous structure.
std::list< SOEntry > SOEntryList
SOEntryList m_added_soentries
List of SOEntry's added to the link map since the last call to Resolve().
void DumpToLog(lldb_private::Log *log) const
lldb_private::Process * m_process
lldb::addr_t GetLinkMapAddress() const
SOEntryList m_soentries
List of SOEntry objects corresponding to the current link map state.
lldb::addr_t m_rendezvous_addr
Location of the r_debug structure in the inferiors address space.
bool Resolve()
Update the internal snapshot of runtime linker rendezvous and recompute the currently loaded modules.
HexagonDYLDRendezvous(lldb_private::Process *process)
bool UpdateSOEntries()
Updates the current set of SOEntries, the set of added entries, and the set of removed entries.
uint64_t GetState() const
Returns the current state of the rendezvous structure.
bool TakeSnapshot(SOEntryList &entry_list)
Reads the current list of shared objects according to the link map supplied by the runtime linker.
const ThreadInfo & GetThreadInfo()
lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst)
Reads an address from the inferior's address space starting at addr.
SOEntryList::const_iterator iterator
lldb::addr_t GetBreakAddress() const
A breakpoint should be set at this address and Resolve called on each hit.
std::string ReadStringFromMemory(lldb::addr_t addr)
Reads a null-terminated C string from the memory location starting at addr.
lldb::addr_t GetLDBase() const
bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
Reads an SOEntry starting at addr.
SOEntryList m_removed_soentries
List of SOEntry's removed from the link map since the last call to Resolve().
lldb::addr_t GetRendezvousAddress() const
iterator begin() const
Iterators over all currently loaded modules.
void SetRendezvousAddress(lldb::addr_t)
Provide the dyld structure address.
ThreadInfo m_thread_info
Threading metadata read from the inferior.
bool FindMetadata(const char *name, PThreadField field, uint32_t &value)
lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size)
Reads an unsigned integer of size bytes from the inferior's address space starting at addr.
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition Address.cpp:303
A uniqued constant string class.
Definition ConstString.h:40
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
void PutCString(const char *cstr)
Definition Log.cpp:162
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:91
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition Module.h:447
A plug-in interface definition class for debugging a process.
Definition Process.h:367
llvm::Expected< lldb::addr_t > ReadPointerFromMemory(lldb::addr_t vm_addr)
Definition Process.cpp:2563
virtual lldb::addr_t GetImageInfoAddress()
Get the image information address for the current process.
Definition Process.cpp:1504
An error handling class.
Definition Status.h:118
Defines a list of symbol context objects.
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1254
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
uint64_t addr_t
Definition lldb-types.h:80
Structure representing the shared objects currently loaded into the inferior process.
lldb::addr_t path_addr
String naming the shared object.
lldb::addr_t dyn_addr
Dynamic section of shared object.
std::string path
File name of shared object.
lldb::addr_t base_addr
Base address of the loaded object.
lldb::addr_t next
Address of next so_entry.
lldb::addr_t prev
Address of previous so_entry.
lldb::addr_t link_addr
Address of this link_map.
#define PATH_MAX