1 //===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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/Target/Process.h"
18 #include "lldb/Target/Target.h"
20 #include "DYLDRendezvous.h"
23 using namespace lldb_private;
25 /// Locates the address of the rendezvous structure. Returns the address on
26 /// success and LLDB_INVALID_ADDRESS on failure.
28 ResolveRendezvousAddress(Process *process)
35 info_location = process->GetImageInfoAddress();
37 if (info_location == LLDB_INVALID_ADDRESS)
38 return LLDB_INVALID_ADDRESS;
41 size = process->DoReadMemory(info_location, &info_addr,
42 process->GetAddressByteSize(), error);
43 if (size != process->GetAddressByteSize() || error.Fail())
44 return LLDB_INVALID_ADDRESS;
47 return LLDB_INVALID_ADDRESS;
52 DYLDRendezvous::DYLDRendezvous(Process *process)
54 m_rendezvous_addr(LLDB_INVALID_ADDRESS),
61 // Cache a copy of the executable path
64 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
66 exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
71 DYLDRendezvous::Resolve()
73 const size_t word_size = 4;
80 address_size = m_process->GetAddressByteSize();
81 padding = address_size - word_size;
83 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
84 cursor = info_addr = ResolveRendezvousAddress(m_process);
86 cursor = info_addr = m_rendezvous_addr;
88 if (cursor == LLDB_INVALID_ADDRESS)
91 if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
94 if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
97 if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
100 if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
103 if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
106 // The rendezvous was successfully read. Update our internal state.
107 m_rendezvous_addr = info_addr;
108 m_previous = m_current;
111 return UpdateSOEntries();
115 DYLDRendezvous::IsValid()
117 return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
121 DYLDRendezvous::UpdateSOEntries()
125 if (m_current.map_addr == 0)
128 // When the previous and current states are consistent this is the first
129 // time we have been asked to update. Just take a snapshot of the currently
131 if (m_previous.state == eConsistent && m_current.state == eConsistent)
132 return TakeSnapshot(m_soentries);
134 // If we are about to add or remove a shared object clear out the current
135 // state and take a snapshot of the currently loaded images.
136 if (m_current.state == eAdd || m_current.state == eDelete)
138 assert(m_previous.state == eConsistent);
140 m_added_soentries.clear();
141 m_removed_soentries.clear();
142 return TakeSnapshot(m_soentries);
144 assert(m_current.state == eConsistent);
146 // Otherwise check the previous state to determine what to expect and update
148 if (m_previous.state == eAdd)
149 return UpdateSOEntriesForAddition();
150 else if (m_previous.state == eDelete)
151 return UpdateSOEntriesForDeletion();
157 DYLDRendezvous::UpdateSOEntriesForAddition()
162 assert(m_previous.state == eAdd);
164 if (m_current.map_addr == 0)
167 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
169 if (!ReadSOEntryFromMemory(cursor, entry))
172 // Only add shared libraries and not the executable.
173 // On Linux this is indicated by an empty path in the entry.
174 // On FreeBSD it is the name of the executable.
175 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
178 pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
179 if (pos == m_soentries.end())
181 m_soentries.push_back(entry);
182 m_added_soentries.push_back(entry);
190 DYLDRendezvous::UpdateSOEntriesForDeletion()
192 SOEntryList entry_list;
195 assert(m_previous.state == eDelete);
197 if (!TakeSnapshot(entry_list))
200 for (iterator I = begin(); I != end(); ++I)
202 pos = std::find(entry_list.begin(), entry_list.end(), *I);
203 if (pos == entry_list.end())
204 m_removed_soentries.push_back(*I);
207 m_soentries = entry_list;
212 DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
216 if (m_current.map_addr == 0)
219 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
221 if (!ReadSOEntryFromMemory(cursor, entry))
224 // Only add shared libraries and not the executable.
225 // On Linux this is indicated by an empty path in the entry.
226 // On FreeBSD it is the name of the executable.
227 if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
230 entry_list.push_back(entry);
237 DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
242 bytes_read = m_process->DoReadMemory(addr, dst, size, error);
243 if (bytes_read != size || error.Fail())
246 return addr + bytes_read;
250 DYLDRendezvous::ReadStringFromMemory(addr_t addr)
257 if (addr == LLDB_INVALID_ADDRESS)
258 return std::string();
261 size = m_process->DoReadMemory(addr, &c, 1, error);
262 if (size != 1 || error.Fail())
263 return std::string();
276 DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
278 size_t address_size = m_process->GetAddressByteSize();
282 if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
285 if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
288 if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
291 if (!(addr = ReadMemory(addr, &entry.next, address_size)))
294 if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
297 entry.path = ReadStringFromMemory(entry.path_addr);
303 DYLDRendezvous::DumpToLog(Log *log) const
305 int state = GetState();
310 log->PutCString("DYLDRendezvous:");
311 log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
312 log->Printf(" Version: %" PRIu64, GetVersion());
313 log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
314 log->Printf(" Break : %" PRIx64, GetBreakAddress());
315 log->Printf(" LDBase : %" PRIx64, GetLDBase());
316 log->Printf(" State : %s",
317 (state == eConsistent) ? "consistent" :
318 (state == eAdd) ? "add" :
319 (state == eDelete) ? "delete" : "unknown");
321 iterator I = begin();
325 log->PutCString("DYLDRendezvous SOEntries:");
327 for (int i = 1; I != E; ++I, ++i)
329 log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
330 log->Printf(" Base : %" PRIx64, I->base_addr);
331 log->Printf(" Path : %" PRIx64, I->path_addr);
332 log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
333 log->Printf(" Next : %" PRIx64, I->next);
334 log->Printf(" Prev : %" PRIx64, I->prev);