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"
10#include "lldb/Symbol/Symbol.h"
12#include "lldb/Target/Process.h"
13#include "lldb/Target/Target.h"
14#include "lldb/Utility/Log.h"
15#include "lldb/Utility/Status.h"
16
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
20
22
23using namespace lldb;
24using namespace lldb_private;
25
26/// Locates the address of the rendezvous structure. Returns the address on
27/// success and LLDB_INVALID_ADDRESS on failure.
29 addr_t info_location;
30 addr_t info_addr;
32
33 info_location = process->GetImageInfoAddress();
34
35 if (info_location == LLDB_INVALID_ADDRESS)
37
38 info_addr = process->ReadPointerFromMemory(info_location, error);
39 if (error.Fail())
41
42 if (info_addr == 0)
44
45 return info_addr;
46}
47
49 : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(),
50 m_previous(), m_soentries(), m_added_soentries(), m_removed_soentries() {
51 m_thread_info.valid = false;
56
57 // Cache a copy of the executable path
58 if (m_process) {
60 if (exe_mod)
62 }
63}
64
66 const size_t word_size = 4;
67 Rendezvous info;
68 size_t address_size;
69 size_t padding;
70 addr_t info_addr;
71 addr_t cursor;
72
73 address_size = m_process->GetAddressByteSize();
74 padding = address_size - word_size;
75
77 cursor = info_addr = ResolveRendezvousAddress(m_process);
78 else
79 cursor = info_addr = m_rendezvous_addr;
80
81 if (cursor == LLDB_INVALID_ADDRESS)
82 return false;
83
84 if (!(cursor = ReadWord(cursor, &info.version, word_size)))
85 return false;
86
87 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
88 return false;
89
90 if (!(cursor = ReadPointer(cursor, &info.brk)))
91 return false;
92
93 if (!(cursor = ReadWord(cursor, &info.state, word_size)))
94 return false;
95
96 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
97 return false;
98
99 // The rendezvous was successfully read. Update our internal state.
100 m_rendezvous_addr = info_addr;
102 m_current = info;
103
104 return UpdateSOEntries();
105}
106
108 m_rendezvous_addr = addr;
109}
110
113}
114
116 SOEntry entry;
117
118 if (m_current.map_addr == 0)
119 return false;
120
121 // When the previous and current states are consistent this is the first time
122 // we have been asked to update. Just take a snapshot of the currently
123 // loaded modules.
126
127 // If we are about to add or remove a shared object clear out the current
128 // state and take a snapshot of the currently loaded images.
129 if (m_current.state == eAdd || m_current.state == eDelete) {
130 // this is a fudge so that we can clear the assert below.
132 // We hit this assert on the 2nd run of this function after running the
133 // calc example
134 assert(m_previous.state == eConsistent);
135 m_soentries.clear();
136 m_added_soentries.clear();
137 m_removed_soentries.clear();
139 }
140 assert(m_current.state == eConsistent);
141
142 // Otherwise check the previous state to determine what to expect and update
143 // accordingly.
144 if (m_previous.state == eAdd)
146 else if (m_previous.state == eDelete)
148
149 return false;
150}
151
153 SOEntry entry;
154 iterator pos;
155
156 assert(m_previous.state == eAdd);
157
158 if (m_current.map_addr == 0)
159 return false;
160
161 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
162 if (!ReadSOEntryFromMemory(cursor, entry))
163 return false;
164
165 // Only add shared libraries and not the executable. On Linux this is
166 // indicated by an empty path in the entry. On FreeBSD it is the name of
167 // the executable.
168 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
169 continue;
170
171 if (!llvm::is_contained(m_soentries, entry)) {
172 m_soentries.push_back(entry);
173 m_added_soentries.push_back(entry);
174 }
175 }
176
177 return true;
178}
179
181 SOEntryList entry_list;
182 iterator pos;
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
233
235 if (error.Fail())
236 return 0;
237
238 return addr + m_process->GetAddressByteSize();
239}
240
242 std::string str;
244 size_t size;
245 char c;
246
247 if (addr == LLDB_INVALID_ADDRESS)
248 return std::string();
249
250 for (;;) {
251 size = m_process->ReadMemory(addr, &c, 1, error);
252 if (size != 1 || error.Fail())
253 return std::string();
254 if (c == 0)
255 break;
256 else {
257 str.push_back(c);
258 addr++;
259 }
260 }
261
262 return str;
263}
264
266 SOEntry &entry) {
267 entry.clear();
268 entry.link_addr = addr;
269
270 if (!(addr = ReadPointer(addr, &entry.base_addr)))
271 return false;
272
273 if (!(addr = ReadPointer(addr, &entry.path_addr)))
274 return false;
275
276 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
277 return false;
278
279 if (!(addr = ReadPointer(addr, &entry.next)))
280 return false;
281
282 if (!(addr = ReadPointer(addr, &entry.prev)))
283 return false;
284
285 entry.path = ReadStringFromMemory(entry.path_addr);
286
287 return true;
288}
289
291 uint32_t &value) {
292 Target &target = m_process->GetTarget();
293
296 eSymbolTypeAny, list);
297 if (list.IsEmpty())
298 return false;
299
300 Address address = list[0].symbol->GetAddress();
301 addr_t addr = address.GetLoadAddress(&target);
302 if (addr == LLDB_INVALID_ADDRESS)
303 return false;
304
306 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
307 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
308 if (error.Fail())
309 return false;
310
311 if (field == eSize)
312 value /= 8; // convert bits to bytes
313
314 return true;
315}
316
319 if (!m_thread_info.valid) {
320 bool ok = true;
321
322 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
324 ok &=
325 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
326 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
328 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
330
331 if (ok)
332 m_thread_info.valid = true;
333 }
334
335 return m_thread_info;
336}
337
339 int state = GetState();
340
341 if (!log)
342 return;
343
344 log->PutCString("HexagonDYLDRendezvous:");
345 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress());
346 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion());
347 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress());
348 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress());
349 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase());
350 LLDB_LOGF(log, " State : %s",
351 (state == eConsistent)
352 ? "consistent"
353 : (state == eAdd) ? "add"
354 : (state == eDelete) ? "delete" : "unknown");
355
356 iterator I = begin();
357 iterator E = end();
358
359 if (I != E)
360 log->PutCString("HexagonDYLDRendezvous SOEntries:");
361
362 for (int i = 1; I != E; ++I, ++i) {
363 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->path.c_str());
364 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr);
365 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr);
366 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr);
367 LLDB_LOGF(log, " Next : %" PRIx64, I->next);
368 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev);
369 }
370}
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:349
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:313
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:367
void PutCString(const char *cstr)
Definition: Log.cpp:134
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
Definition: ModuleList.cpp:527
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:88
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:452
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
Definition: Process.cpp:1939
uint64_t ReadUnsignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Status &error)
Reads an unsigned integer of the specified byte size from process memory.
Definition: Process.cpp:2080
virtual lldb::addr_t GetImageInfoAddress()
Get the image information address for the current process.
Definition: Process.cpp:1495
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
Definition: Process.cpp:2102
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3404
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1277
An error handling class.
Definition: Status.h:44
Defines a list of symbol context objects.
Module * GetExecutableModulePointer()
Definition: Target.cpp:1436
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:972
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
uint64_t addr_t
Definition: lldb-types.h:79
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