blob: 5035e9d8bb17aed9bc22eea017fe27b57b6192d9 [file] [log] [blame]
Deepak Panickalca238a72014-07-21 17:19:12 +00001//===-- HexagonDYLDRendezvous.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11// C++ Includes
12// Other libraries and framework includes
13#include "lldb/Core/ArchSpec.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Log.h"
16#include "lldb/Core/Module.h"
17#include "lldb/Symbol/Symbol.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
20
21#include "lldb/Symbol/ObjectFile.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
24
25#include "HexagonDYLDRendezvous.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30/// Locates the address of the rendezvous structure. Returns the address on
31/// success and LLDB_INVALID_ADDRESS on failure.
32static addr_t
33ResolveRendezvousAddress(Process *process)
34{
35 addr_t info_location;
36 addr_t info_addr;
37 Error error;
38
39 info_location = process->GetImageInfoAddress();
40
41 if (info_location == LLDB_INVALID_ADDRESS)
42 return LLDB_INVALID_ADDRESS;
43
44 info_addr = process->ReadPointerFromMemory(info_location, error);
45 if (error.Fail())
46 return LLDB_INVALID_ADDRESS;
47
48 if (info_addr == 0)
49 return LLDB_INVALID_ADDRESS;
50
51 return info_addr;
52}
53
54HexagonDYLDRendezvous::HexagonDYLDRendezvous(Process *process)
55 : m_process(process),
56 m_rendezvous_addr(LLDB_INVALID_ADDRESS),
57 m_current(),
58 m_previous(),
59 m_soentries(),
60 m_added_soentries(),
61 m_removed_soentries()
62{
63 m_thread_info.valid = false;
64
65 // Cache a copy of the executable path
66 if (m_process)
67 {
68 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
69 if (exe_mod)
70 exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
71 }
72}
73
74bool
75HexagonDYLDRendezvous::Resolve()
76{
77 const size_t word_size = 4;
78 Rendezvous info;
79 size_t address_size;
80 size_t padding;
81 addr_t info_addr;
82 addr_t cursor;
83
84 address_size = m_process->GetAddressByteSize();
85 padding = address_size - word_size;
86
87 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
88 cursor = info_addr = ResolveRendezvousAddress(m_process);
89 else
90 cursor = info_addr = m_rendezvous_addr;
91
92 if (cursor == LLDB_INVALID_ADDRESS)
93 return false;
94
95 if (!(cursor = ReadWord(cursor, &info.version, word_size)))
96 return false;
97
98 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
99 return false;
100
101 if (!(cursor = ReadPointer(cursor, &info.brk)))
102 return false;
103
104 if (!(cursor = ReadWord(cursor, &info.state, word_size)))
105 return false;
106
107 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
108 return false;
109
110 // The rendezvous was successfully read. Update our internal state.
111 m_rendezvous_addr = info_addr;
112 m_previous = m_current;
113 m_current = info;
114
115 return UpdateSOEntries();
116}
117
118void
119HexagonDYLDRendezvous::SetRendezvousAddress( lldb::addr_t addr )
120{
121 m_rendezvous_addr = addr;
122}
123
124bool
125HexagonDYLDRendezvous::IsValid()
126{
127 return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
128}
129
130bool
131HexagonDYLDRendezvous::UpdateSOEntries()
132{
133 SOEntry entry;
134
135 if (m_current.map_addr == 0)
136 return false;
137
138 // When the previous and current states are consistent this is the first
139 // time we have been asked to update. Just take a snapshot of the currently
140 // loaded modules.
141 if (m_previous.state == eConsistent && m_current.state == eConsistent)
142 return TakeSnapshot(m_soentries);
143
144 // If we are about to add or remove a shared object clear out the current
145 // state and take a snapshot of the currently loaded images.
146 if (m_current.state == eAdd || m_current.state == eDelete)
147 {
148 // this is a fudge so that we can clear the assert below.
149 m_previous.state = eConsistent;
150 // We hit this assert on the 2nd run of this function after running the calc example
151 assert(m_previous.state == eConsistent);
152 m_soentries.clear();
153 m_added_soentries.clear();
154 m_removed_soentries.clear();
155 return TakeSnapshot(m_soentries);
156 }
157 assert(m_current.state == eConsistent);
158
159 // Otherwise check the previous state to determine what to expect and update
160 // accordingly.
161 if (m_previous.state == eAdd)
162 return UpdateSOEntriesForAddition();
163 else if (m_previous.state == eDelete)
164 return UpdateSOEntriesForDeletion();
165
166 return false;
167}
168
169bool
170HexagonDYLDRendezvous::UpdateSOEntriesForAddition()
171{
172 SOEntry entry;
173 iterator pos;
174
175 assert(m_previous.state == eAdd);
176
177 if (m_current.map_addr == 0)
178 return false;
179
180 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
181 {
182 if (!ReadSOEntryFromMemory(cursor, entry))
183 return false;
184
185 // Only add shared libraries and not the executable.
186 // On Linux this is indicated by an empty path in the entry.
187 // On FreeBSD it is the name of the executable.
188 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
189 continue;
190
191 pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
192 if (pos == m_soentries.end())
193 {
194 m_soentries.push_back(entry);
195 m_added_soentries.push_back(entry);
196 }
197 }
198
199 return true;
200}
201
202bool
203HexagonDYLDRendezvous::UpdateSOEntriesForDeletion()
204{
205 SOEntryList entry_list;
206 iterator pos;
207
208 assert(m_previous.state == eDelete);
209
210 if (!TakeSnapshot(entry_list))
211 return false;
212
213 for (iterator I = begin(); I != end(); ++I)
214 {
215 pos = std::find(entry_list.begin(), entry_list.end(), *I);
216 if (pos == entry_list.end())
217 m_removed_soentries.push_back(*I);
218 }
219
220 m_soentries = entry_list;
221 return true;
222}
223
224bool
225HexagonDYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
226{
227 SOEntry entry;
228
229 if (m_current.map_addr == 0)
230 return false;
231
232 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
233 {
234 if (!ReadSOEntryFromMemory(cursor, entry))
235 return false;
236
237 // Only add shared libraries and not the executable.
238 // On Linux this is indicated by an empty path in the entry.
239 // On FreeBSD it is the name of the executable.
240 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
241 continue;
242
243 entry_list.push_back(entry);
244 }
245
246 return true;
247}
248
249addr_t
250HexagonDYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size)
251{
252 Error error;
253
254 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
255 if (error.Fail())
256 return 0;
257
258 return addr + size;
259}
260
261addr_t
262HexagonDYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst)
263{
264 Error error;
265
266 *dst = m_process->ReadPointerFromMemory(addr, error);
267 if (error.Fail())
268 return 0;
269
270 return addr + m_process->GetAddressByteSize();
271}
272
273std::string
274HexagonDYLDRendezvous::ReadStringFromMemory(addr_t addr)
275{
276 std::string str;
277 Error error;
278 size_t size;
279 char c;
280
281 if (addr == LLDB_INVALID_ADDRESS)
282 return std::string();
283
284 for (;;) {
285 size = m_process->DoReadMemory(addr, &c, 1, error);
286 if (size != 1 || error.Fail())
287 return std::string();
288 if (c == 0)
289 break;
290 else {
291 str.push_back(c);
292 addr++;
293 }
294 }
295
296 return str;
297}
298
299bool
300HexagonDYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
301{
302 entry.clear();
303 entry.link_addr = addr;
304
305 if (!(addr = ReadPointer(addr, &entry.base_addr)))
306 return false;
307
308 if (!(addr = ReadPointer(addr, &entry.path_addr)))
309 return false;
310
311 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
312 return false;
313
314 if (!(addr = ReadPointer(addr, &entry.next)))
315 return false;
316
317 if (!(addr = ReadPointer(addr, &entry.prev)))
318 return false;
319
320 entry.path = ReadStringFromMemory(entry.path_addr);
321
322 return true;
323}
324
325bool
326HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32_t& value)
327{
328 Target& target = m_process->GetTarget();
329
330 SymbolContextList list;
331 if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list))
332 return false;
333
334 Address address = list[0].symbol->GetAddress();
335 addr_t addr = address.GetLoadAddress (&target);
336 if (addr == LLDB_INVALID_ADDRESS)
337 return false;
338
339 Error error;
340 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(addr + field*sizeof(uint32_t), sizeof(uint32_t), 0, error);
341 if (error.Fail())
342 return false;
343
344 if (field == eSize)
345 value /= 8; // convert bits to bytes
346
347 return true;
348}
349
350const HexagonDYLDRendezvous::ThreadInfo&
351HexagonDYLDRendezvous::GetThreadInfo()
352{
353 if (!m_thread_info.valid)
354 {
355 bool ok = true;
356
357 ok &= FindMetadata ("_thread_db_pthread_dtvp", eOffset, m_thread_info.dtv_offset);
358 ok &= FindMetadata ("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
359 ok &= FindMetadata ("_thread_db_link_map_l_tls_modid", eOffset, m_thread_info.modid_offset);
360 ok &= FindMetadata ("_thread_db_dtv_t_pointer_val", eOffset, m_thread_info.tls_offset);
361
362 if (ok)
363 m_thread_info.valid = true;
364 }
365
366 return m_thread_info;
367}
368
369void
370HexagonDYLDRendezvous::DumpToLog(Log *log) const
371{
372 int state = GetState();
373
374 if (!log)
375 return;
376
377 log->PutCString("HexagonDYLDRendezvous:");
378 log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
379 log->Printf(" Version: %" PRIu64, GetVersion());
380 log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
381 log->Printf(" Break : %" PRIx64, GetBreakAddress());
382 log->Printf(" LDBase : %" PRIx64, GetLDBase());
383 log->Printf(" State : %s",
384 (state == eConsistent) ? "consistent" :
385 (state == eAdd) ? "add" :
386 (state == eDelete) ? "delete" : "unknown");
387
388 iterator I = begin();
389 iterator E = end();
390
391 if (I != E)
392 log->PutCString("HexagonDYLDRendezvous SOEntries:");
393
394 for (int i = 1; I != E; ++I, ++i)
395 {
396 log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
397 log->Printf(" Base : %" PRIx64, I->base_addr);
398 log->Printf(" Path : %" PRIx64, I->path_addr);
399 log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
400 log->Printf(" Next : %" PRIx64, I->next);
401 log->Printf(" Prev : %" PRIx64, I->prev);
402 }
403}