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