diff options
Diffstat (limited to 'source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp')
-rw-r--r-- | source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp | 979 |
1 files changed, 465 insertions, 514 deletions
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 443f97ed0ba1..136bf6561a21 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -30,631 +30,582 @@ using namespace lldb_private; /// Locates the address of the rendezvous structure. Returns the address on /// success and LLDB_INVALID_ADDRESS on failure. -static addr_t -ResolveRendezvousAddress(Process *process) -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - addr_t info_location; - addr_t info_addr; - Error error; - - if (!process) - { - if (log) - log->Printf ("%s null process provided", __FUNCTION__); - return LLDB_INVALID_ADDRESS; - } +static addr_t ResolveRendezvousAddress(Process *process) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + addr_t info_location; + addr_t info_addr; + Error error; - // Try to get it from our process. This might be a remote process and might - // grab it via some remote-specific mechanism. - info_location = process->GetImageInfoAddress(); + if (!process) { if (log) - log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); - - // If the process fails to return an address, fall back to seeing if the local object file can help us find it. - if (info_location == LLDB_INVALID_ADDRESS) - { - Target *target = &process->GetTarget(); - if (target) - { - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(target); - - if (addr.IsValid()) - { - info_location = addr.GetLoadAddress(target); - if (log) - log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location); - } - else - { - if (log) - log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__); - } - } - } - - if (info_location == LLDB_INVALID_ADDRESS) - { + log->Printf("%s null process provided", __FUNCTION__); + return LLDB_INVALID_ADDRESS; + } + + // Try to get it from our process. This might be a remote process and might + // grab it via some remote-specific mechanism. + info_location = process->GetImageInfoAddress(); + if (log) + log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); + + // If the process fails to return an address, fall back to seeing if the local + // object file can help us find it. + if (info_location == LLDB_INVALID_ADDRESS) { + Target *target = &process->GetTarget(); + if (target) { + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(target); + + if (addr.IsValid()) { + info_location = addr.GetLoadAddress(target); if (log) - log->Printf ("%s FAILED - invalid info address", __FUNCTION__); - return LLDB_INVALID_ADDRESS; + log->Printf( + "%s resolved via direct object file approach to 0x%" PRIx64, + __FUNCTION__, info_location); + } else { + if (log) + log->Printf("%s FAILED - direct object file approach did not yield a " + "valid address", + __FUNCTION__); + } } + } + if (info_location == LLDB_INVALID_ADDRESS) { if (log) - log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location); + log->Printf("%s FAILED - invalid info address", __FUNCTION__); + return LLDB_INVALID_ADDRESS; + } - info_addr = process->ReadPointerFromMemory(info_location, error); - if (error.Fail()) - { - if (log) - log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ()); - return LLDB_INVALID_ADDRESS; - } + if (log) + log->Printf("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, + __FUNCTION__, process->GetAddressByteSize(), info_location); - if (info_addr == 0) - { - if (log) - log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location); - return LLDB_INVALID_ADDRESS; - } + info_addr = process->ReadPointerFromMemory(info_location, error); + if (error.Fail()) { + if (log) + log->Printf("%s FAILED - could not read from the info location: %s", + __FUNCTION__, error.AsCString()); + return LLDB_INVALID_ADDRESS; + } - return info_addr; + if (info_addr == 0) { + if (log) + log->Printf("%s FAILED - the rendezvous address contained at 0x%" PRIx64 + " returned a null value", + __FUNCTION__, info_location); + return LLDB_INVALID_ADDRESS; + } + + return info_addr; } DYLDRendezvous::DYLDRendezvous(Process *process) - : m_process(process), - m_rendezvous_addr(LLDB_INVALID_ADDRESS), - m_current(), - m_previous(), - m_loaded_modules(), - m_soentries(), - m_added_soentries(), - m_removed_soentries() -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - m_thread_info.valid = false; - - // Cache a copy of the executable path - if (m_process) - { - Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); - if (exe_mod) - { - m_exe_file_spec = exe_mod->GetPlatformFileSpec(); - if (log) - log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'", - __FUNCTION__, m_exe_file_spec.GetCString()); - } - else - { - if (log) - log->Printf ("DYLDRendezvous::%s cannot cache exe module path: null executable module pointer", __FUNCTION__); - } + : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(), + m_previous(), m_loaded_modules(), m_soentries(), m_added_soentries(), + m_removed_soentries() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + m_thread_info.valid = false; + + // Cache a copy of the executable path + if (m_process) { + Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); + if (exe_mod) { + m_exe_file_spec = exe_mod->GetPlatformFileSpec(); + if (log) + log->Printf("DYLDRendezvous::%s exe module executable path set: '%s'", + __FUNCTION__, m_exe_file_spec.GetCString()); + } else { + if (log) + log->Printf("DYLDRendezvous::%s cannot cache exe module path: null " + "executable module pointer", + __FUNCTION__); } + } } -bool -DYLDRendezvous::Resolve() -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); +bool DYLDRendezvous::Resolve() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + const size_t word_size = 4; + Rendezvous info; + size_t address_size; + size_t padding; + addr_t info_addr; + addr_t cursor; + + address_size = m_process->GetAddressByteSize(); + padding = address_size - word_size; + if (log) + log->Printf("DYLDRendezvous::%s address size: %" PRIu64 + ", padding %" PRIu64, + __FUNCTION__, uint64_t(address_size), uint64_t(padding)); + + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) + cursor = info_addr = ResolveRendezvousAddress(m_process); + else + cursor = info_addr = m_rendezvous_addr; + if (log) + log->Printf("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor); + + if (cursor == LLDB_INVALID_ADDRESS) + return false; - const size_t word_size = 4; - Rendezvous info; - size_t address_size; - size_t padding; - addr_t info_addr; - addr_t cursor; + if (!(cursor = ReadWord(cursor, &info.version, word_size))) + return false; - address_size = m_process->GetAddressByteSize(); - padding = address_size - word_size; - if (log) - log->Printf ("DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, __FUNCTION__, uint64_t(address_size), uint64_t(padding)); + if (!(cursor = ReadPointer(cursor + padding, &info.map_addr))) + return false; - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) - cursor = info_addr = ResolveRendezvousAddress(m_process); - else - cursor = info_addr = m_rendezvous_addr; - if (log) - log->Printf ("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor); + if (!(cursor = ReadPointer(cursor, &info.brk))) + return false; - if (cursor == LLDB_INVALID_ADDRESS) - return false; + if (!(cursor = ReadWord(cursor, &info.state, word_size))) + return false; - if (!(cursor = ReadWord(cursor, &info.version, word_size))) - return false; + if (!(cursor = ReadPointer(cursor + padding, &info.ldbase))) + return false; - if (!(cursor = ReadPointer(cursor + padding, &info.map_addr))) - return false; + // The rendezvous was successfully read. Update our internal state. + m_rendezvous_addr = info_addr; + m_previous = m_current; + m_current = info; - if (!(cursor = ReadPointer(cursor, &info.brk))) - return false; + if (UpdateSOEntries(true)) + return true; - if (!(cursor = ReadWord(cursor, &info.state, word_size))) - return false; + return UpdateSOEntries(); +} - if (!(cursor = ReadPointer(cursor + padding, &info.ldbase))) - return false; +bool DYLDRendezvous::IsValid() { + return m_rendezvous_addr != LLDB_INVALID_ADDRESS; +} - // The rendezvous was successfully read. Update our internal state. - m_rendezvous_addr = info_addr; - m_previous = m_current; - m_current = info; +bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) { + SOEntry entry; + LoadedModuleInfoList module_list; - if (UpdateSOEntries (true)) - return true; + // If we can't get the SO info from the remote, return failure. + if (fromRemote && m_process->LoadModules(module_list) == 0) + return false; - return UpdateSOEntries(); -} + if (!fromRemote && m_current.map_addr == 0) + return false; -bool -DYLDRendezvous::IsValid() -{ - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; + // 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 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. + if (m_current.state == eAdd || m_current.state == eDelete) { + // Some versions of the android dynamic linker might send two + // notifications with state == eAdd back to back. Ignore them + // until we get an eConsistent notification. + if (!(m_previous.state == eConsistent || + (m_previous.state == eAdd && m_current.state == eDelete))) + return false; + + m_soentries.clear(); + if (fromRemote) + return SaveSOEntriesFromRemote(module_list); + + m_added_soentries.clear(); + m_removed_soentries.clear(); + return TakeSnapshot(m_soentries); + } + assert(m_current.state == eConsistent); + + // Otherwise check the previous state to determine what to expect and update + // accordingly. + if (m_previous.state == eAdd) + return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries(); + else if (m_previous.state == eDelete) + return fromRemote ? RemoveSOEntriesFromRemote(module_list) + : RemoveSOEntries(); + + return false; } -bool -DYLDRendezvous::UpdateSOEntries(bool fromRemote) -{ - SOEntry entry; - LoadedModuleInfoList module_list; +bool 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 we can't get the SO info from the remote, return failure. - if (fromRemote && m_process->LoadModules (module_list) == 0) - return false; + if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) || + !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name)) + return false; - if (!fromRemote && m_current.map_addr == 0) - return false; + entry.link_addr = link_map_addr; + entry.base_addr = base_addr; + entry.dyn_addr = dyn_addr; - // 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 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. - if (m_current.state == eAdd || m_current.state == eDelete) - { - // Some versions of the android dynamic linker might send two - // notifications with state == eAdd back to back. Ignore them - // until we get an eConsistent notification. - if (!(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete))) - return false; - - m_soentries.clear(); - if (fromRemote) - return SaveSOEntriesFromRemote(module_list); - - m_added_soentries.clear(); - m_removed_soentries.clear(); - return TakeSnapshot(m_soentries); - } - assert(m_current.state == eConsistent); + entry.file_spec.SetFile(name, false); - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries(); - else if (m_previous.state == eDelete) - return fromRemote ? RemoveSOEntriesFromRemote(module_list) : RemoveSOEntries(); + UpdateBaseAddrIfNecessary(entry, name); - return false; + // not needed if we're using ModuleInfos + entry.next = 0; + entry.prev = 0; + entry.path_addr = 0; + + return true; } -bool -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; +bool DYLDRendezvous::SaveSOEntriesFromRemote( + LoadedModuleInfoList &module_list) { + for (auto const &modInfo : module_list.m_list) { + SOEntry entry; + if (!FillSOEntryFromModuleInfo(modInfo, entry)) + return false; - entry.link_addr = link_map_addr; - entry.base_addr = base_addr; - entry.dyn_addr = dyn_addr; + // Only add shared libraries and not the executable. + if (!SOEntryIsMainExecutable(entry)) + m_soentries.push_back(entry); + } - entry.file_spec.SetFile(name, false); + m_loaded_modules = module_list; + return true; +} - UpdateBaseAddrIfNecessary(entry, name); +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; + } + } - // not needed if we're using ModuleInfos - entry.next = 0; - entry.prev = 0; - entry.path_addr = 0; + if (found) + continue; - return true; + 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::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); +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; + } } - m_loaded_modules = module_list; - return true; + 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; -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_soentries.erase(pos); } + } - m_loaded_modules = module_list; - return true; + 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); - } - } +bool DYLDRendezvous::AddSOEntries() { + SOEntry entry; + iterator pos; - m_loaded_modules = module_list; - return true; -} + assert(m_previous.state == eAdd); -bool -DYLDRendezvous::AddSOEntries() -{ - SOEntry entry; - iterator pos; + if (m_current.map_addr == 0) + return false; - assert(m_previous.state == eAdd); + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; - if (m_current.map_addr == 0) - return false; + // Only add shared libraries and not the executable. + if (SOEntryIsMainExecutable(entry)) + continue; - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - // Only add shared libraries and not the executable. - if (SOEntryIsMainExecutable(entry)) - continue; - - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) - { - m_soentries.push_back(entry); - m_added_soentries.push_back(entry); - } + pos = std::find(m_soentries.begin(), m_soentries.end(), entry); + if (pos == m_soentries.end()) { + m_soentries.push_back(entry); + m_added_soentries.push_back(entry); } + } - return true; + return true; } -bool -DYLDRendezvous::RemoveSOEntries() -{ - SOEntryList entry_list; - iterator pos; +bool DYLDRendezvous::RemoveSOEntries() { + SOEntryList entry_list; + iterator pos; - assert(m_previous.state == eDelete); + assert(m_previous.state == eDelete); - if (!TakeSnapshot(entry_list)) - return false; + if (!TakeSnapshot(entry_list)) + return false; - for (iterator I = begin(); I != end(); ++I) - { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) - m_removed_soentries.push_back(*I); - } + for (iterator I = begin(); I != end(); ++I) { + pos = std::find(entry_list.begin(), entry_list.end(), *I); + if (pos == entry_list.end()) + m_removed_soentries.push_back(*I); + } - m_soentries = entry_list; - return true; + m_soentries = entry_list; + return true; } -bool -DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) -{ - // On Linux the executable is indicated by an empty path in the entry. On - // FreeBSD and on Android it is the full path to the executable. - - auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); - switch (triple.getOS()) - { - case llvm::Triple::FreeBSD: - return entry.file_spec == m_exe_file_spec; - case llvm::Triple::Linux: - if (triple.isAndroid()) - return entry.file_spec == m_exe_file_spec; - return !entry.file_spec; - default: - return false; - } +bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { + // On Linux the executable is indicated by an empty path in the entry. On + // FreeBSD and on Android it is the full path to the executable. + + auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); + switch (triple.getOS()) { + case llvm::Triple::FreeBSD: + return entry.file_spec == m_exe_file_spec; + case llvm::Triple::Linux: + if (triple.isAndroid()) + return entry.file_spec == m_exe_file_spec; + return !entry.file_spec; + default: + return false; + } } -bool -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) -{ - SOEntry entry; +bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) { + SOEntry entry; - if (m_current.map_addr == 0) - return false; + if (m_current.map_addr == 0) + return false; - // Clear previous entries since we are about to obtain an up to date list. - entry_list.clear(); + // Clear previous entries since we are about to obtain an up to date list. + entry_list.clear(); - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; - // Only add shared libraries and not the executable. - if (SOEntryIsMainExecutable(entry)) - continue; + // Only add shared libraries and not the executable. + if (SOEntryIsMainExecutable(entry)) + continue; - entry_list.push_back(entry); - } + entry_list.push_back(entry); + } - return true; + return true; } -addr_t -DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) -{ - Error error; +addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) { + Error error; - *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error); - if (error.Fail()) - return 0; + *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error); + if (error.Fail()) + return 0; - return addr + size; + return addr + size; } -addr_t -DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) -{ - Error error; - - *dst = m_process->ReadPointerFromMemory(addr, error); - if (error.Fail()) - return 0; +addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) { + Error error; - return addr + m_process->GetAddressByteSize(); + *dst = m_process->ReadPointerFromMemory(addr, error); + if (error.Fail()) + return 0; + + return addr + m_process->GetAddressByteSize(); } -std::string -DYLDRendezvous::ReadStringFromMemory(addr_t addr) -{ - std::string str; - Error error; +std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) { + std::string str; + Error error; - if (addr == LLDB_INVALID_ADDRESS) - return std::string(); + if (addr == LLDB_INVALID_ADDRESS) + return std::string(); - m_process->ReadCStringFromMemory(addr, str, error); + m_process->ReadCStringFromMemory(addr, str, error); - return str; + return str; } -// Returns true if the load bias reported by the linker is incorrect for the given entry. This -// function is used to handle cases where we want to work around a bug in the system linker. -static bool -isLoadBiasIncorrect(Target& target, const std::string& file_path) -{ - // On Android L (API 21, 22) the load address of the "/system/bin/linker" isn't filled in - // correctly. - uint32_t os_major = 0, os_minor = 0, os_update = 0; - if (target.GetArchitecture().GetTriple().isAndroid() && - target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && - (os_major == 21 || os_major == 22) && - (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) - { - return true; - } +// Returns true if the load bias reported by the linker is incorrect for the +// given entry. This +// function is used to handle cases where we want to work around a bug in the +// system linker. +static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) { + // On Android L (API 21, 22) the load address of the "/system/bin/linker" + // isn't filled in + // correctly. + uint32_t os_major = 0, os_minor = 0, os_update = 0; + if (target.GetArchitecture().GetTriple().isAndroid() && + target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && + (os_major == 21 || os_major == 22) && + (file_path == "/system/bin/linker" || + file_path == "/system/bin/linker64")) { + return true; + } - return false; + 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; - } +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) -{ - entry.clear(); +bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { + entry.clear(); - entry.link_addr = addr; - - if (!(addr = ReadPointer(addr, &entry.base_addr))) - return false; + entry.link_addr = addr; - // mips adds an extra load offset field to the link map struct on - // FreeBSD and NetBSD (need to validate other OSes). - // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57 - const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); - if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD - || arch.GetTriple().getOS() == llvm::Triple::NetBSD) && - (arch.GetMachine() == llvm::Triple::mips || arch.GetMachine() == llvm::Triple::mipsel - || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::mips64el)) - { - addr_t mips_l_offs; - if (!(addr = ReadPointer(addr, &mips_l_offs))) - return false; - if (mips_l_offs != 0 && mips_l_offs != entry.base_addr) - return false; - } - - if (!(addr = ReadPointer(addr, &entry.path_addr))) - return false; - - if (!(addr = ReadPointer(addr, &entry.dyn_addr))) - return false; - - if (!(addr = ReadPointer(addr, &entry.next))) - return false; - - if (!(addr = ReadPointer(addr, &entry.prev))) - return false; + if (!(addr = ReadPointer(addr, &entry.base_addr))) + return false; - std::string file_path = ReadStringFromMemory(entry.path_addr); - entry.file_spec.SetFile(file_path, false); + // mips adds an extra load offset field to the link map struct on + // FreeBSD and NetBSD (need to validate other OSes). + // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57 + const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); + if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD || + arch.GetTriple().getOS() == llvm::Triple::NetBSD) && + (arch.GetMachine() == llvm::Triple::mips || + arch.GetMachine() == llvm::Triple::mipsel || + arch.GetMachine() == llvm::Triple::mips64 || + arch.GetMachine() == llvm::Triple::mips64el)) { + addr_t mips_l_offs; + if (!(addr = ReadPointer(addr, &mips_l_offs))) + return false; + if (mips_l_offs != 0 && mips_l_offs != entry.base_addr) + return false; + } + + if (!(addr = ReadPointer(addr, &entry.path_addr))) + return false; - UpdateBaseAddrIfNecessary(entry, file_path); + if (!(addr = ReadPointer(addr, &entry.dyn_addr))) + return false; - return true; -} + if (!(addr = ReadPointer(addr, &entry.next))) + return false; + if (!(addr = ReadPointer(addr, &entry.prev))) + return false; -bool -DYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32_t& value) -{ - Target& target = m_process->GetTarget(); + std::string file_path = ReadStringFromMemory(entry.path_addr); + entry.file_spec.SetFile(file_path, false); - SymbolContextList list; - if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list)) - return false; + UpdateBaseAddrIfNecessary(entry, file_path); - Address address = list[0].symbol->GetAddress(); - addr_t addr = address.GetLoadAddress (&target); - if (addr == LLDB_INVALID_ADDRESS) - return false; + return true; +} - Error error; - value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(addr + field*sizeof(uint32_t), sizeof(uint32_t), 0, error); - if (error.Fail()) - return false; +bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, + uint32_t &value) { + Target &target = m_process->GetTarget(); - if (field == eSize) - value /= 8; // convert bits to bytes + SymbolContextList list; + if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name), + eSymbolTypeAny, list)) + return false; - return true; + Address address = list[0].symbol->GetAddress(); + addr_t addr = address.GetLoadAddress(&target); + if (addr == LLDB_INVALID_ADDRESS) + return false; + + Error error; + value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory( + addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error); + if (error.Fail()) + return false; + + if (field == eSize) + value /= 8; // convert bits to bytes + + return true; } -const DYLDRendezvous::ThreadInfo& -DYLDRendezvous::GetThreadInfo() -{ - if (!m_thread_info.valid) - { - bool ok = true; +const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() { + if (!m_thread_info.valid) { + bool ok = true; - ok &= FindMetadata ("_thread_db_pthread_dtvp", eOffset, m_thread_info.dtv_offset); - ok &= FindMetadata ("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size); - ok &= FindMetadata ("_thread_db_link_map_l_tls_modid", eOffset, m_thread_info.modid_offset); - ok &= FindMetadata ("_thread_db_dtv_t_pointer_val", eOffset, m_thread_info.tls_offset); + ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset, + m_thread_info.dtv_offset); + ok &= + FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size); + ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset, + m_thread_info.modid_offset); + ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset, + m_thread_info.tls_offset); - if (ok) - m_thread_info.valid = true; - } + if (ok) + m_thread_info.valid = true; + } - return m_thread_info; + return m_thread_info; } -void -DYLDRendezvous::DumpToLog(Log *log) const -{ - int state = GetState(); - - if (!log) - return; - - log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); - log->Printf(" Version: %" PRIu64, GetVersion()); - log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); - log->Printf(" Break : %" PRIx64, GetBreakAddress()); - log->Printf(" LDBase : %" PRIx64, GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) ? "consistent" : - (state == eAdd) ? "add" : - (state == eDelete) ? "delete" : "unknown"); - - iterator I = begin(); - iterator E = end(); - - if (I != E) - log->PutCString("DYLDRendezvous SOEntries:"); - - for (int i = 1; I != E; ++I, ++i) - { - log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString()); - log->Printf(" Base : %" PRIx64, I->base_addr); - log->Printf(" Path : %" PRIx64, I->path_addr); - log->Printf(" Dyn : %" PRIx64, I->dyn_addr); - log->Printf(" Next : %" PRIx64, I->next); - log->Printf(" Prev : %" PRIx64, I->prev); - } +void DYLDRendezvous::DumpToLog(Log *log) const { + int state = GetState(); + + if (!log) + return; + + log->PutCString("DYLDRendezvous:"); + log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); + log->Printf(" Version: %" PRIu64, GetVersion()); + log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); + log->Printf(" Break : %" PRIx64, GetBreakAddress()); + log->Printf(" LDBase : %" PRIx64, GetLDBase()); + log->Printf(" State : %s", + (state == eConsistent) + ? "consistent" + : (state == eAdd) ? "add" : (state == eDelete) ? "delete" + : "unknown"); + + iterator I = begin(); + iterator E = end(); + + if (I != E) + log->PutCString("DYLDRendezvous SOEntries:"); + + for (int i = 1; I != E; ++I, ++i) { + log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString()); + log->Printf(" Base : %" PRIx64, I->base_addr); + log->Printf(" Path : %" PRIx64, I->path_addr); + log->Printf(" Dyn : %" PRIx64, I->dyn_addr); + log->Printf(" Next : %" PRIx64, I->next); + log->Printf(" Prev : %" PRIx64, I->prev); + } } |