summaryrefslogtreecommitdiffstats
path: root/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp')
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp177
1 files changed, 157 insertions, 20 deletions
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 09e874a..443f97e 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -107,6 +107,7 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_rendezvous_addr(LLDB_INVALID_ADDRESS),
m_current(),
m_previous(),
+ m_loaded_modules(),
m_soentries(),
m_added_soentries(),
m_removed_soentries()
@@ -181,6 +182,9 @@ DYLDRendezvous::Resolve()
m_previous = m_current;
m_current = info;
+ if (UpdateSOEntries (true))
+ return true;
+
return UpdateSOEntries();
}
@@ -191,18 +195,23 @@ DYLDRendezvous::IsValid()
}
bool
-DYLDRendezvous::UpdateSOEntries()
+DYLDRendezvous::UpdateSOEntries(bool fromRemote)
{
SOEntry entry;
+ LoadedModuleInfoList module_list;
- if (m_current.map_addr == 0)
+ // If we can't get the SO info from the remote, return failure.
+ if (fromRemote && m_process->LoadModules (module_list) == 0)
+ return false;
+
+ if (!fromRemote && m_current.map_addr == 0)
return false;
// When the previous and current states are consistent this is the first
// time we have been asked to update. Just take a snapshot of the currently
// loaded modules.
- if (m_previous.state == eConsistent && m_current.state == eConsistent)
- return TakeSnapshot(m_soentries);
+ if (m_previous.state == eConsistent && m_current.state == eConsistent)
+ return fromRemote ? SaveSOEntriesFromRemote(module_list) : TakeSnapshot(m_soentries);
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
@@ -215,6 +224,9 @@ DYLDRendezvous::UpdateSOEntries()
return false;
m_soentries.clear();
+ if (fromRemote)
+ return SaveSOEntriesFromRemote(module_list);
+
m_added_soentries.clear();
m_removed_soentries.clear();
return TakeSnapshot(m_soentries);
@@ -224,15 +236,133 @@ DYLDRendezvous::UpdateSOEntries()
// Otherwise check the previous state to determine what to expect and update
// accordingly.
if (m_previous.state == eAdd)
- return UpdateSOEntriesForAddition();
+ return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries();
else if (m_previous.state == eDelete)
- return UpdateSOEntriesForDeletion();
+ return fromRemote ? RemoveSOEntriesFromRemote(module_list) : RemoveSOEntries();
return false;
}
-
+
bool
-DYLDRendezvous::UpdateSOEntriesForAddition()
+DYLDRendezvous::FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo,
+ SOEntry &entry)
+{
+ addr_t link_map_addr;
+ addr_t base_addr;
+ addr_t dyn_addr;
+ std::string name;
+
+ if (!modInfo.get_link_map (link_map_addr) ||
+ !modInfo.get_base (base_addr) ||
+ !modInfo.get_dynamic (dyn_addr) ||
+ !modInfo.get_name (name))
+ return false;
+
+ entry.link_addr = link_map_addr;
+ entry.base_addr = base_addr;
+ entry.dyn_addr = dyn_addr;
+
+ entry.file_spec.SetFile(name, false);
+
+ UpdateBaseAddrIfNecessary(entry, name);
+
+ // not needed if we're using ModuleInfos
+ entry.next = 0;
+ entry.prev = 0;
+ entry.path_addr = 0;
+
+ return true;
+}
+
+bool
+DYLDRendezvous::SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+
+}
+
+bool
+DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ bool found = false;
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ bool found = false;
+ for (auto const & modInfo : module_list.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(existing, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ {
+ auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ return false;
+
+ m_soentries.erase(pos);
+ }
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::AddSOEntries()
{
SOEntry entry;
iterator pos;
@@ -263,7 +393,7 @@ DYLDRendezvous::UpdateSOEntriesForAddition()
}
bool
-DYLDRendezvous::UpdateSOEntriesForDeletion()
+DYLDRendezvous::RemoveSOEntries()
{
SOEntryList entry_list;
iterator pos;
@@ -291,7 +421,8 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
// FreeBSD and on Android it is the full path to the executable.
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
- switch (triple.getOS()) {
+ switch (triple.getOS())
+ {
case llvm::Triple::FreeBSD:
return entry.file_spec == m_exe_file_spec;
case llvm::Triple::Linux:
@@ -386,6 +517,21 @@ isLoadBiasIncorrect(Target& target, const std::string& file_path)
return false;
}
+void
+DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path)
+{
+ // If the load bias reported by the linker is incorrect then fetch the load address of the file
+ // from the proc file system.
+ if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
+ {
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ bool is_loaded = false;
+ Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ entry.base_addr = load_addr;
+ }
+}
+
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
@@ -427,16 +573,7 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
std::string file_path = ReadStringFromMemory(entry.path_addr);
entry.file_spec.SetFile(file_path, false);
- // If the load bias reported by the linker is incorrect then fetch the load address of the file
- // from the proc file system.
- if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
- {
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- bool is_loaded = false;
- Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
- if (error.Success() && is_loaded)
- entry.base_addr = load_addr;
- }
+ UpdateBaseAddrIfNecessary(entry, file_path);
return true;
}
OpenPOWER on IntegriCloud