diff options
Diffstat (limited to 'lldb/source/Plugins/DynamicLoader/POSIX-DYLD')
6 files changed, 1445 insertions, 1590 deletions
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp index 04a6792fbf0..ec655c6f9b3 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp @@ -28,113 +28,92 @@ using namespace lldb; using namespace lldb_private; -static bool -GetMaxU64(DataExtractor &data, - lldb::offset_t *offset_ptr, - uint64_t *value, - unsigned int byte_size) -{ - lldb::offset_t saved_offset = *offset_ptr; - *value = data.GetMaxU64(offset_ptr, byte_size); - return *offset_ptr != saved_offset; +static bool GetMaxU64(DataExtractor &data, lldb::offset_t *offset_ptr, + uint64_t *value, unsigned int byte_size) { + lldb::offset_t saved_offset = *offset_ptr; + *value = data.GetMaxU64(offset_ptr, byte_size); + return *offset_ptr != saved_offset; } -static bool -ParseAuxvEntry(DataExtractor &data, - AuxVector::Entry &entry, - lldb::offset_t *offset_ptr, - unsigned int byte_size) -{ - if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size)) - return false; +static bool ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, + lldb::offset_t *offset_ptr, unsigned int byte_size) { + if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size)) + return false; - if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size)) - return false; + if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size)) + return false; - return true; + return true; } -DataBufferSP -AuxVector::GetAuxvData() -{ - if (m_process) - return m_process->GetAuxvData (); - else - return DataBufferSP (); +DataBufferSP AuxVector::GetAuxvData() { + if (m_process) + return m_process->GetAuxvData(); + else + return DataBufferSP(); } -void -AuxVector::ParseAuxv(DataExtractor &data) -{ - const unsigned int byte_size = m_process->GetAddressByteSize(); - lldb::offset_t offset = 0; +void AuxVector::ParseAuxv(DataExtractor &data) { + const unsigned int byte_size = m_process->GetAddressByteSize(); + lldb::offset_t offset = 0; - for (;;) - { - Entry entry; + for (;;) { + Entry entry; - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) - break; + if (!ParseAuxvEntry(data, entry, &offset, byte_size)) + break; - if (entry.type == AT_NULL) - break; + if (entry.type == AT_NULL) + break; - if (entry.type == AT_IGNORE) - continue; + if (entry.type == AT_IGNORE) + continue; - m_auxv.push_back(entry); - } + m_auxv.push_back(entry); + } } -AuxVector::AuxVector(Process *process) - : m_process(process) -{ - DataExtractor data; - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); +AuxVector::AuxVector(Process *process) : m_process(process) { + DataExtractor data; + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + data.SetData(GetAuxvData()); + data.SetByteOrder(m_process->GetByteOrder()); + data.SetAddressByteSize(m_process->GetAddressByteSize()); - data.SetData(GetAuxvData()); - data.SetByteOrder(m_process->GetByteOrder()); - data.SetAddressByteSize(m_process->GetAddressByteSize()); - - ParseAuxv(data); + ParseAuxv(data); - if (log) - DumpToLog(log); + if (log) + DumpToLog(log); } -AuxVector::iterator -AuxVector::FindEntry(EntryType type) const -{ - for (iterator I = begin(); I != end(); ++I) - { - if (I->type == static_cast<uint64_t>(type)) - return I; - } +AuxVector::iterator AuxVector::FindEntry(EntryType type) const { + for (iterator I = begin(); I != end(); ++I) { + if (I->type == static_cast<uint64_t>(type)) + return I; + } - return end(); + return end(); } -void -AuxVector::DumpToLog(Log *log) const -{ - if (!log) - return; +void AuxVector::DumpToLog(Log *log) const { + if (!log) + return; - log->PutCString("AuxVector: "); - for (iterator I = begin(); I != end(); ++I) - { - log->Printf(" %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type, I->value); - } + log->PutCString("AuxVector: "); + for (iterator I = begin(); I != end(); ++I) { + log->Printf(" %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type, + I->value); + } } -const char * -AuxVector::GetEntryName(EntryType type) -{ - const char *name = "AT_???"; +const char *AuxVector::GetEntryName(EntryType type) { + const char *name = "AT_???"; -#define ENTRY_NAME(_type) _type: name = #_type - switch (type) - { +#define ENTRY_NAME(_type) \ + _type: \ + name = #_type + switch (type) { case ENTRY_NAME(AT_NULL); break; case ENTRY_NAME(AT_IGNORE); break; case ENTRY_NAME(AT_EXECFD); break; @@ -173,4 +152,3 @@ AuxVector::GetEntryName(EntryType type) return name; } - diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h index 2d39eddcacc..9c3e1b002a2 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h @@ -19,7 +19,7 @@ namespace lldb_private { class DataExtractor; -} +} /// @class AuxVector /// @brief Represents a processes auxiliary vector. @@ -31,85 +31,80 @@ class DataExtractor; class AuxVector { public: - AuxVector(lldb_private::Process *process); - - struct Entry { - uint64_t type; - uint64_t value; - - Entry() : type(0), value(0) { } - }; - - /// Constants describing the type of entry. - /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information. - enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). - AT_PLATFORM = 15, ///< String identifying platform. - AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. - AT_FPUCW = 18, ///< Used FPU control word. - AT_DCACHEBSIZE = 19, ///< Data cache block size. - AT_ICACHEBSIZE = 20, ///< Instruction cache block size. - AT_UCACHEBSIZE = 21, ///< Unified cache block size. - AT_IGNOREPPC = 22, ///< Entry should be ignored. - AT_SECURE = 23, ///< Boolean, was exec setuid-like? - AT_BASE_PLATFORM = 24, ///< String identifying real platforms. - AT_RANDOM = 25, ///< Address of 16 random bytes. - AT_EXECFN = 31, ///< Filename of executable. - AT_SYSINFO = 32, ///< Pointer to the global system page used for system calls and other nice things. - AT_SYSINFO_EHDR = 33, - AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. - AT_L1D_CACHESHAPE = 35, - AT_L2_CACHESHAPE = 36, - AT_L3_CACHESHAPE = 37, - }; + AuxVector(lldb_private::Process *process); + + struct Entry { + uint64_t type; + uint64_t value; + + Entry() : type(0), value(0) {} + }; + + /// Constants describing the type of entry. + /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information. + enum EntryType { + AT_NULL = 0, ///< End of auxv. + AT_IGNORE = 1, ///< Ignore entry. + AT_EXECFD = 2, ///< File descriptor of program. + AT_PHDR = 3, ///< Program headers. + AT_PHENT = 4, ///< Size of program header. + AT_PHNUM = 5, ///< Number of program headers. + AT_PAGESZ = 6, ///< Page size. + AT_BASE = 7, ///< Interpreter base address. + AT_FLAGS = 8, ///< Flags. + AT_ENTRY = 9, ///< Program entry point. + AT_NOTELF = 10, ///< Set if program is not an ELF. + AT_UID = 11, ///< UID. + AT_EUID = 12, ///< Effective UID. + AT_GID = 13, ///< GID. + AT_EGID = 14, ///< Effective GID. + AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). + AT_PLATFORM = 15, ///< String identifying platform. + AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. + AT_FPUCW = 18, ///< Used FPU control word. + AT_DCACHEBSIZE = 19, ///< Data cache block size. + AT_ICACHEBSIZE = 20, ///< Instruction cache block size. + AT_UCACHEBSIZE = 21, ///< Unified cache block size. + AT_IGNOREPPC = 22, ///< Entry should be ignored. + AT_SECURE = 23, ///< Boolean, was exec setuid-like? + AT_BASE_PLATFORM = 24, ///< String identifying real platforms. + AT_RANDOM = 25, ///< Address of 16 random bytes. + AT_EXECFN = 31, ///< Filename of executable. + AT_SYSINFO = 32, ///< Pointer to the global system page used for system + ///calls and other nice things. + AT_SYSINFO_EHDR = 33, + AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. + AT_L1D_CACHESHAPE = 35, + AT_L2_CACHESHAPE = 36, + AT_L3_CACHESHAPE = 37, + }; private: - typedef std::vector<Entry> EntryVector; + typedef std::vector<Entry> EntryVector; public: - typedef EntryVector::const_iterator iterator; + typedef EntryVector::const_iterator iterator; - iterator begin() const { return m_auxv.begin(); } - iterator end() const { return m_auxv.end(); } + iterator begin() const { return m_auxv.begin(); } + iterator end() const { return m_auxv.end(); } - iterator - FindEntry(EntryType type) const; + iterator FindEntry(EntryType type) const; - static const char * - GetEntryName(const Entry &entry) { - return GetEntryName(static_cast<EntryType>(entry.type)); - } + static const char *GetEntryName(const Entry &entry) { + return GetEntryName(static_cast<EntryType>(entry.type)); + } - static const char * - GetEntryName(EntryType type); + static const char *GetEntryName(EntryType type); - void - DumpToLog(lldb_private::Log *log) const; + void DumpToLog(lldb_private::Log *log) const; private: - lldb_private::Process *m_process; - EntryVector m_auxv; + lldb_private::Process *m_process; + EntryVector m_auxv; - lldb::DataBufferSP - GetAuxvData(); + lldb::DataBufferSP GetAuxvData(); - void - ParseAuxv(lldb_private::DataExtractor &data); + void ParseAuxv(lldb_private::DataExtractor &data); }; #endif diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 443f97ed0ba..136bf6561a2 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/lldb/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); + } } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 8498116c808..55b8bd7fb49 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -16,9 +16,9 @@ #include <string> // Other libraries and framework includes +#include "lldb/Host/FileSpec.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Core/LoadedModuleInfoList.h" @@ -37,251 +37,220 @@ class Process; /// currently loaded modules. class DYLDRendezvous { - // This structure is used to hold the contents of the debug rendezvous - // information (struct r_debug) as found in the inferiors memory. Note that - // the layout of this struct is not binary compatible, it is simply large - // enough to hold the information on both 32 and 64 bit platforms. - struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; - - Rendezvous() - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } - }; + // This structure is used to hold the contents of the debug rendezvous + // information (struct r_debug) as found in the inferiors memory. Note that + // the layout of this struct is not binary compatible, it is simply large + // enough to hold the information on both 32 and 64 bit platforms. + struct Rendezvous { + uint64_t version; + lldb::addr_t map_addr; + lldb::addr_t brk; + uint64_t state; + lldb::addr_t ldbase; + + Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {} + }; public: - // Various metadata supplied by the inferior's threading library to describe - // the per-thread state. - struct ThreadInfo { - bool valid; // whether we read valid metadata - uint32_t dtv_offset; // offset of DTV pointer within pthread - uint32_t dtv_slot_size; // size of one DTV slot - uint32_t modid_offset; // offset of module ID within link_map - uint32_t tls_offset; // offset of TLS pointer within DTV slot - }; - - DYLDRendezvous(lldb_private::Process *process); - - /// Update the internal snapshot of runtime linker rendezvous and recompute - /// the currently loaded modules. - /// - /// This method should be called once one start up, then once each time the - /// runtime linker enters the function given by GetBreakAddress(). - /// - /// @returns true on success and false on failure. - /// - /// @see GetBreakAddress(). - bool - Resolve(); - - /// @returns true if this rendezvous has been located in the inferiors - /// address space and false otherwise. - bool - IsValid(); - - /// @returns the address of the rendezvous structure in the inferiors - /// address space. - lldb::addr_t - GetRendezvousAddress() const { return m_rendezvous_addr; } - - /// @returns the version of the rendezvous protocol being used. - uint64_t - GetVersion() const { return m_current.version; } - - /// @returns address in the inferiors address space containing the linked - /// list of shared object descriptors. - lldb::addr_t - GetLinkMapAddress() const { return m_current.map_addr; } - - /// A breakpoint should be set at this address and Resolve called on each - /// hit. - /// - /// @returns the address of a function called by the runtime linker each - /// time a module is loaded/unloaded, or about to be loaded/unloaded. - /// - /// @see Resolve() - lldb::addr_t - GetBreakAddress() const { return m_current.brk; } - - /// Returns the current state of the rendezvous structure. - uint64_t - GetState() const { return m_current.state; } - - /// @returns the base address of the runtime linker in the inferiors address - /// space. - lldb::addr_t - GetLDBase() const { return m_current.ldbase; } - - /// @returns the thread layout metadata from the inferiors thread library. - const ThreadInfo& - GetThreadInfo(); - - /// @returns true if modules have been loaded into the inferior since the - /// last call to Resolve(). - bool - ModulesDidLoad() const { return !m_added_soentries.empty(); } - - /// @returns true if modules have been unloaded from the inferior since the - /// last call to Resolve(). - bool - ModulesDidUnload() const { return !m_removed_soentries.empty(); } - - void - DumpToLog(lldb_private::Log *log) const; - - /// @brief Constants describing the state of the rendezvous. - /// - /// @see GetState(). - enum RendezvousState { - eConsistent, - eAdd, - eDelete - }; - - /// @brief Structure representing the shared objects currently loaded into - /// the inferior process. - /// - /// This object is a rough analogue to the struct link_map object which - /// actually lives in the inferiors memory. - struct SOEntry { - lldb::addr_t link_addr; ///< Address of this link_map. - lldb::addr_t base_addr; ///< Base address of the loaded object. - lldb::addr_t path_addr; ///< String naming the shared object. - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. - lldb::addr_t next; ///< Address of next so_entry. - lldb::addr_t prev; ///< Address of previous so_entry. - lldb_private::FileSpec file_spec; ///< File spec of shared object. - - SOEntry() { clear(); } - - bool operator ==(const SOEntry &entry) { - return file_spec == entry.file_spec; - } - - void clear() { - link_addr = 0; - base_addr = 0; - path_addr = 0; - dyn_addr = 0; - next = 0; - prev = 0; - file_spec.Clear(); - } - }; + // Various metadata supplied by the inferior's threading library to describe + // the per-thread state. + struct ThreadInfo { + bool valid; // whether we read valid metadata + uint32_t dtv_offset; // offset of DTV pointer within pthread + uint32_t dtv_slot_size; // size of one DTV slot + uint32_t modid_offset; // offset of module ID within link_map + uint32_t tls_offset; // offset of TLS pointer within DTV slot + }; + + DYLDRendezvous(lldb_private::Process *process); + + /// Update the internal snapshot of runtime linker rendezvous and recompute + /// the currently loaded modules. + /// + /// This method should be called once one start up, then once each time the + /// runtime linker enters the function given by GetBreakAddress(). + /// + /// @returns true on success and false on failure. + /// + /// @see GetBreakAddress(). + bool Resolve(); + + /// @returns true if this rendezvous has been located in the inferiors + /// address space and false otherwise. + bool IsValid(); + + /// @returns the address of the rendezvous structure in the inferiors + /// address space. + lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; } + + /// @returns the version of the rendezvous protocol being used. + uint64_t GetVersion() const { return m_current.version; } + + /// @returns address in the inferiors address space containing the linked + /// list of shared object descriptors. + lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; } + + /// A breakpoint should be set at this address and Resolve called on each + /// hit. + /// + /// @returns the address of a function called by the runtime linker each + /// time a module is loaded/unloaded, or about to be loaded/unloaded. + /// + /// @see Resolve() + lldb::addr_t GetBreakAddress() const { return m_current.brk; } + + /// Returns the current state of the rendezvous structure. + uint64_t GetState() const { return m_current.state; } + + /// @returns the base address of the runtime linker in the inferiors address + /// space. + lldb::addr_t GetLDBase() const { return m_current.ldbase; } + + /// @returns the thread layout metadata from the inferiors thread library. + const ThreadInfo &GetThreadInfo(); + + /// @returns true if modules have been loaded into the inferior since the + /// last call to Resolve(). + bool ModulesDidLoad() const { return !m_added_soentries.empty(); } + + /// @returns true if modules have been unloaded from the inferior since the + /// last call to Resolve(). + bool ModulesDidUnload() const { return !m_removed_soentries.empty(); } + + void DumpToLog(lldb_private::Log *log) const; + + /// @brief Constants describing the state of the rendezvous. + /// + /// @see GetState(). + enum RendezvousState { eConsistent, eAdd, eDelete }; + + /// @brief Structure representing the shared objects currently loaded into + /// the inferior process. + /// + /// This object is a rough analogue to the struct link_map object which + /// actually lives in the inferiors memory. + struct SOEntry { + lldb::addr_t link_addr; ///< Address of this link_map. + lldb::addr_t base_addr; ///< Base address of the loaded object. + lldb::addr_t path_addr; ///< String naming the shared object. + lldb::addr_t dyn_addr; ///< Dynamic section of shared object. + lldb::addr_t next; ///< Address of next so_entry. + lldb::addr_t prev; ///< Address of previous so_entry. + lldb_private::FileSpec file_spec; ///< File spec of shared object. + + SOEntry() { clear(); } + + bool operator==(const SOEntry &entry) { + return file_spec == entry.file_spec; + } + + void clear() { + link_addr = 0; + base_addr = 0; + path_addr = 0; + dyn_addr = 0; + next = 0; + prev = 0; + file_spec.Clear(); + } + }; protected: - typedef std::list<SOEntry> SOEntryList; + typedef std::list<SOEntry> SOEntryList; public: - typedef SOEntryList::const_iterator iterator; - - /// Iterators over all currently loaded modules. - iterator begin() const { return m_soentries.begin(); } - iterator end() const { return m_soentries.end(); } - - /// Iterators over all modules loaded into the inferior since the last call - /// to Resolve(). - iterator loaded_begin() const { return m_added_soentries.begin(); } - iterator loaded_end() const { return m_added_soentries.end(); } - - /// Iterators over all modules unloaded from the inferior since the last - /// call to Resolve(). - iterator unloaded_begin() const { return m_removed_soentries.begin(); } - iterator unloaded_end() const { return m_removed_soentries.end(); } - + typedef SOEntryList::const_iterator iterator; + + /// Iterators over all currently loaded modules. + iterator begin() const { return m_soentries.begin(); } + iterator end() const { return m_soentries.end(); } + + /// Iterators over all modules loaded into the inferior since the last call + /// to Resolve(). + iterator loaded_begin() const { return m_added_soentries.begin(); } + iterator loaded_end() const { return m_added_soentries.end(); } + + /// Iterators over all modules unloaded from the inferior since the last + /// call to Resolve(). + iterator unloaded_begin() const { return m_removed_soentries.begin(); } + iterator unloaded_end() const { return m_removed_soentries.end(); } + protected: - lldb_private::Process *m_process; + lldb_private::Process *m_process; - // Cached copy of executable file spec - lldb_private::FileSpec m_exe_file_spec; + // Cached copy of executable file spec + lldb_private::FileSpec m_exe_file_spec; - /// Location of the r_debug structure in the inferiors address space. - lldb::addr_t m_rendezvous_addr; + /// Location of the r_debug structure in the inferiors address space. + lldb::addr_t m_rendezvous_addr; - /// Current and previous snapshots of the rendezvous structure. - Rendezvous m_current; - Rendezvous m_previous; + /// Current and previous snapshots of the rendezvous structure. + Rendezvous m_current; + Rendezvous m_previous; - /// List of currently loaded SO modules - LoadedModuleInfoList m_loaded_modules; + /// List of currently loaded SO modules + LoadedModuleInfoList m_loaded_modules; - /// List of SOEntry objects corresponding to the current link map state. - SOEntryList m_soentries; + /// List of SOEntry objects corresponding to the current link map state. + SOEntryList m_soentries; - /// List of SOEntry's added to the link map since the last call to Resolve(). - SOEntryList m_added_soentries; + /// List of SOEntry's added to the link map since the last call to Resolve(). + SOEntryList m_added_soentries; - /// List of SOEntry's removed from the link map since the last call to - /// Resolve(). - SOEntryList m_removed_soentries; + /// List of SOEntry's removed from the link map since the last call to + /// Resolve(). + SOEntryList m_removed_soentries; - /// Threading metadata read from the inferior. - ThreadInfo m_thread_info; + /// Threading metadata read from the inferior. + ThreadInfo m_thread_info; - /// Reads an unsigned integer of @p size bytes from the inferior's address - /// space starting at @p addr. - /// - /// @returns addr + size if the read was successful and false otherwise. - lldb::addr_t - ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); + /// Reads an unsigned integer of @p size bytes from the inferior's address + /// space starting at @p addr. + /// + /// @returns addr + size if the read was successful and false otherwise. + lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size); - /// Reads an address from the inferior's address space starting at @p addr. - /// - /// @returns addr + target address size if the read was successful and - /// 0 otherwise. - lldb::addr_t - ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); + /// Reads an address from the inferior's address space starting at @p addr. + /// + /// @returns addr + target address size if the read was successful and + /// 0 otherwise. + lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst); - /// Reads a null-terminated C string from the memory location starting at @p - /// addr. - std::string - ReadStringFromMemory(lldb::addr_t addr); + /// Reads a null-terminated C string from the memory location starting at @p + /// addr. + std::string ReadStringFromMemory(lldb::addr_t addr); - /// Reads an SOEntry starting at @p addr. - bool - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); + /// Reads an SOEntry starting at @p addr. + bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); - /// Updates the current set of SOEntries, the set of added entries, and the - /// set of removed entries. - bool - UpdateSOEntries(bool fromRemote = false); + /// Updates the current set of SOEntries, the set of added entries, and the + /// set of removed entries. + bool UpdateSOEntries(bool fromRemote = false); - bool - FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo, - SOEntry &entry); + bool FillSOEntryFromModuleInfo( + LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry); - bool - SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); - bool - AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); - bool - RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); - bool - AddSOEntries(); + bool AddSOEntries(); - bool - RemoveSOEntries(); + bool RemoveSOEntries(); - void - UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path); + void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path); - bool - SOEntryIsMainExecutable(const SOEntry &entry); + bool SOEntryIsMainExecutable(const SOEntry &entry); - /// Reads the current list of shared objects according to the link map - /// supplied by the runtime linker. - bool - TakeSnapshot(SOEntryList &entry_list); + /// Reads the current list of shared objects according to the link map + /// supplied by the runtime linker. + bool TakeSnapshot(SOEntryList &entry_list); - enum PThreadField { eSize, eNElem, eOffset }; + enum PThreadField { eSize, eNElem, eOffset }; - bool FindMetadata(const char *name, PThreadField field, uint32_t& value); + bool FindMetadata(const char *name, PThreadField field, uint32_t &value); }; #endif diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 772efc17c1e..cb27190cf33 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -14,19 +14,19 @@ #include "AuxVector.h" // Other libraries and framework includes -#include "lldb/Core/PluginManager.h" +#include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Target/Platform.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Symbol/Function.h" // C++ Includes // C Includes @@ -34,258 +34,240 @@ using namespace lldb; using namespace lldb_private; -void -DynamicLoaderPOSIXDYLD::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); -} - -void -DynamicLoaderPOSIXDYLD::Terminate() -{ +void DynamicLoaderPOSIXDYLD::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); } -lldb_private::ConstString -DynamicLoaderPOSIXDYLD::GetPluginName() -{ - return GetPluginNameStatic(); -} +void DynamicLoaderPOSIXDYLD::Terminate() {} -lldb_private::ConstString -DynamicLoaderPOSIXDYLD::GetPluginNameStatic() -{ - static ConstString g_name("linux-dyld"); - return g_name; +lldb_private::ConstString DynamicLoaderPOSIXDYLD::GetPluginName() { + return GetPluginNameStatic(); } -const char * -DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() -{ - return "Dynamic loader plug-in that watches for shared library " - "loads/unloads in POSIX processes."; +lldb_private::ConstString DynamicLoaderPOSIXDYLD::GetPluginNameStatic() { + static ConstString g_name("linux-dyld"); + return g_name; } -uint32_t -DynamicLoaderPOSIXDYLD::GetPluginVersion() -{ - return 1; +const char *DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() { + return "Dynamic loader plug-in that watches for shared library " + "loads/unloads in POSIX processes."; } -DynamicLoader * -DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) -{ - bool create = force; - if (!create) - { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Linux || - triple_ref.getOS() == llvm::Triple::FreeBSD) - create = true; - } - - if (create) - return new DynamicLoaderPOSIXDYLD (process); - return NULL; +uint32_t DynamicLoaderPOSIXDYLD::GetPluginVersion() { return 1; } + +DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, + bool force) { + bool create = force; + if (!create) { + const llvm::Triple &triple_ref = + process->GetTarget().GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::Linux || + triple_ref.getOS() == llvm::Triple::FreeBSD) + create = true; + } + + if (create) + return new DynamicLoaderPOSIXDYLD(process); + return NULL; } DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) - : DynamicLoader(process), - m_rendezvous(process), - m_load_offset(LLDB_INVALID_ADDRESS), - m_entry_point(LLDB_INVALID_ADDRESS), - m_auxv(), - m_dyld_bid(LLDB_INVALID_BREAK_ID), - m_vdso_base(LLDB_INVALID_ADDRESS) -{ + : DynamicLoader(process), m_rendezvous(process), + m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS), + m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID), + m_vdso_base(LLDB_INVALID_ADDRESS) {} + +DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() { + if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { + m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid); + m_dyld_bid = LLDB_INVALID_BREAK_ID; + } } -DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() -{ - if (m_dyld_bid != LLDB_INVALID_BREAK_ID) - { - m_process->GetTarget().RemoveBreakpointByID (m_dyld_bid); - m_dyld_bid = LLDB_INVALID_BREAK_ID; +void DynamicLoaderPOSIXDYLD::DidAttach() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + + m_auxv.reset(new AuxVector(m_process)); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + + // ask the process if it can load any of its own modules + m_process->LoadModules(); + + ModuleSP executable_sp = GetTargetExecutable(); + ResolveExecutableModule(executable_sp); + + // find the main process load offset + addr_t load_offset = ComputeLoadOffset(); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " executable '%s', load_offset 0x%" PRIx64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() + : "<null executable>", + load_offset); + + EvalVdsoStatus(); + + // if we dont have a load address we cant re-base + bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; + + // if we have a valid executable + if (executable_sp.get()) { + lldb_private::ObjectFile *obj = executable_sp->GetObjectFile(); + if (obj) { + // don't rebase if the module already has a load address + Target &target = m_process->GetTarget(); + Address addr = obj->GetImageInfoAddress(&target); + if (addr.GetLoadAddress(&target) != LLDB_INVALID_ADDRESS) + rebase_exec = false; } -} - -void -DynamicLoaderPOSIXDYLD::DidAttach() -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - - m_auxv.reset(new AuxVector(m_process)); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); + } else { + // no executable, nothing to re-base + rebase_exec = false; + } - // ask the process if it can load any of its own modules - m_process->LoadModules (); - - ModuleSP executable_sp = GetTargetExecutable (); - ResolveExecutableModule (executable_sp); + // if the target executable should be re-based + if (rebase_exec) { + ModuleList module_list; - // find the main process load offset - addr_t load_offset = ComputeLoadOffset (); + module_list.Append(executable_sp); if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset); - - EvalVdsoStatus(); - - // if we dont have a load address we cant re-base - bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; - - // if we have a valid executable - if (executable_sp.get()) - { - lldb_private::ObjectFile * obj = executable_sp->GetObjectFile(); - if (obj) - { - // don't rebase if the module already has a load address - Target & target = m_process->GetTarget (); - Address addr = obj->GetImageInfoAddress (&target); - if (addr.GetLoadAddress (&target) != LLDB_INVALID_ADDRESS) - rebase_exec = false; - } - } - else - { - // no executable, nothing to re-base - rebase_exec = false; + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " added executable '%s' to module load list", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp->GetFileSpec().GetPath().c_str()); + + UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, + true); + + // When attaching to a target, there are two possible states: + // (1) We already crossed the entry point and therefore the rendezvous + // structure is ready to be used and we can load the list of modules + // and place the rendezvous breakpoint. + // (2) We didn't cross the entry point yet, so these structures are not + // ready; we should behave as if we just launched the target and + // call ProbeEntry(). This will place a breakpoint on the entry + // point which itself will be hit after the rendezvous structure is + // set up and will perform actions described in (1). + if (m_rendezvous.Resolve()) { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 + " rendezvous could resolve: attach assuming dynamic loader " + "info is available now", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LoadAllCurrentModules(); + SetRendezvousBreakpoint(); + } else { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 + " rendezvous could not yet resolve: adding breakpoint to " + "catch future rendezvous setup", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + ProbeEntry(); } - // if the target executable should be re-based - if (rebase_exec) - { - ModuleList module_list; - - module_list.Append(executable_sp); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " added executable '%s' to module load list", - __FUNCTION__, - m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, - executable_sp->GetFileSpec().GetPath().c_str ()); - - UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); - - // When attaching to a target, there are two possible states: - // (1) We already crossed the entry point and therefore the rendezvous - // structure is ready to be used and we can load the list of modules - // and place the rendezvous breakpoint. - // (2) We didn't cross the entry point yet, so these structures are not - // ready; we should behave as if we just launched the target and - // call ProbeEntry(). This will place a breakpoint on the entry - // point which itself will be hit after the rendezvous structure is - // set up and will perform actions described in (1). - if (m_rendezvous.Resolve()) - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could resolve: attach assuming dynamic loader info is available now", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - LoadAllCurrentModules(); - SetRendezvousBreakpoint(); - } - else - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could not yet resolve: adding breakpoint to catch future rendezvous setup", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - ProbeEntry(); - } - - m_process->GetTarget().ModulesDidLoad(module_list); - if (log) - { - log->Printf ("DynamicLoaderPOSIXDYLD::%s told the target about the modules that loaded:", __FUNCTION__); - for (auto module_sp : module_list.Modules ()) - { - log->Printf ("-- [module] %s (pid %" PRIu64 ")", - module_sp ? module_sp->GetFileSpec().GetPath().c_str () : "<null>", - m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - } - } + m_process->GetTarget().ModulesDidLoad(module_list); + if (log) { + log->Printf("DynamicLoaderPOSIXDYLD::%s told the target about the " + "modules that loaded:", + __FUNCTION__); + for (auto module_sp : module_list.Modules()) { + log->Printf("-- [module] %s (pid %" PRIu64 ")", + module_sp ? module_sp->GetFileSpec().GetPath().c_str() + : "<null>", + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + } } + } } -void -DynamicLoaderPOSIXDYLD::DidLaunch() -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); +void DynamicLoaderPOSIXDYLD::DidLaunch() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); - ModuleSP executable; - addr_t load_offset; + ModuleSP executable; + addr_t load_offset; - m_auxv.reset(new AuxVector(m_process)); + m_auxv.reset(new AuxVector(m_process)); - executable = GetTargetExecutable(); - load_offset = ComputeLoadOffset(); - EvalVdsoStatus(); + executable = GetTargetExecutable(); + load_offset = ComputeLoadOffset(); + EvalVdsoStatus(); - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) { + ModuleList module_list; + module_list.Append(executable); + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); - ProbeEntry(); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", + __FUNCTION__); + ProbeEntry(); - m_process->GetTarget().ModulesDidLoad(module_list); - } + m_process->GetTarget().ModulesDidLoad(module_list); + } } -Error -DynamicLoaderPOSIXDYLD::CanLoadImage() -{ - return Error(); -} +Error DynamicLoaderPOSIXDYLD::CanLoadImage() { return Error(); } -void -DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, - addr_t link_map_addr, - addr_t base_addr, - bool base_addr_is_offset) -{ - m_loaded_modules[module] = link_map_addr; - UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); +void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { + m_loaded_modules[module] = link_map_addr; + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } -void -DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) -{ - m_loaded_modules.erase(module); +void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { + m_loaded_modules.erase(module); - UnloadSectionsCommon(module); + UnloadSectionsCommon(module); } -void -DynamicLoaderPOSIXDYLD::ProbeEntry() -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - const addr_t entry = GetEntryPoint(); - if (entry == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned no address, not setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - return; - } +void DynamicLoaderPOSIXDYLD::ProbeEntry() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + const addr_t entry = GetEntryPoint(); + if (entry == LLDB_INVALID_ADDRESS) { if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned address 0x%" PRIx64 ", setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, entry); - - if (m_process) - { - Breakpoint *const entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); - entry_break->SetBreakpointKind("shared-library-event"); - - // Shoudn't hit this more than once. - entry_break->SetOneShot (true); - } + log->Printf( + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned no address, not setting entry breakpoint", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + return; + } + + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned address 0x%" PRIx64 + ", setting entry breakpoint", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + entry); + + if (m_process) { + Breakpoint *const entry_break = + m_process->GetTarget().CreateBreakpoint(entry, true, false).get(); + entry_break->SetCallback(EntryBreakpointHit, this, true); + entry_break->SetBreakpointKind("shared-library-event"); + + // Shoudn't hit this more than once. + entry_break->SetOneShot(true); + } } // The runtime linker has run and initialized the rendezvous structure once the @@ -294,419 +276,422 @@ DynamicLoaderPOSIXDYLD::ProbeEntry() // dependent modules for the process. Similarly, we can discover the runtime // linker function and setup a breakpoint to notify us of any dynamically loaded // modules (via dlopen). -bool -DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - assert(baton && "null baton"); - if (!baton) - return false; - - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton); - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID); - - // Disable the breakpoint --- if a stop happens right after this, which we've seen on occasion, we don't - // want the breakpoint stepping thread-plan logic to show a breakpoint instruction at the disassembled - // entry point to the program. Disabling it prevents it. (One-shot is not enough - one-shot removal logic - // only happens after the breakpoint goes public, which wasn't happening in our scenario). - if (dyld_instance->m_process) - { - BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID (break_id); - if (breakpoint_sp) - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " disabling breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id); - breakpoint_sp->SetEnabled (false); - } - else - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " failed to find breakpoint for breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id); - } - } - else - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 " no Process instance! Cannot disable breakpoint", __FUNCTION__, break_id); +bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( + void *baton, StoppointCallbackContext *context, user_id_t break_id, + user_id_t break_loc_id) { + assert(baton && "null baton"); + if (!baton) + return false; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + DynamicLoaderPOSIXDYLD *const dyld_instance = + static_cast<DynamicLoaderPOSIXDYLD *>(baton); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); + + // Disable the breakpoint --- if a stop happens right after this, which we've + // seen on occasion, we don't + // want the breakpoint stepping thread-plan logic to show a breakpoint + // instruction at the disassembled + // entry point to the program. Disabling it prevents it. (One-shot is not + // enough - one-shot removal logic + // only happens after the breakpoint goes public, which wasn't happening in + // our scenario). + if (dyld_instance->m_process) { + BreakpointSP breakpoint_sp = + dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id); + if (breakpoint_sp) { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " disabling breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); + breakpoint_sp->SetEnabled(false); + } else { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " failed to find breakpoint for breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); } - - dyld_instance->LoadAllCurrentModules(); - dyld_instance->SetRendezvousBreakpoint(); - return false; // Continue running. + } else { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 + " no Process instance! Cannot disable breakpoint", + __FUNCTION__, break_id); + } + + dyld_instance->LoadAllCurrentModules(); + dyld_instance->SetRendezvousBreakpoint(); + return false; // Continue running. } -void -DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - addr_t break_addr = m_rendezvous.GetBreakAddress(); - Target &target = m_process->GetTarget(); - - if (m_dyld_bid == LLDB_INVALID_BREAK_ID) - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " setting rendezvous break address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, break_addr); - Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true, false).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); - dyld_break->SetBreakpointKind ("shared-library-event"); - m_dyld_bid = dyld_break->GetID(); - } - else - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reusing break id %" PRIu32 ", address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, m_dyld_bid, break_addr); - } +void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - // Make sure our breakpoint is at the right address. - assert (target.GetBreakpointByID(m_dyld_bid)->FindLocationByAddress(break_addr)->GetBreakpoint().GetID() == m_dyld_bid); -} + addr_t break_addr = m_rendezvous.GetBreakAddress(); + Target &target = m_process->GetTarget(); -bool -DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - assert (baton && "null baton"); - if (!baton) - return false; - - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton); + if (m_dyld_bid == LLDB_INVALID_BREAK_ID) { if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID); - - dyld_instance->RefreshModules(); - - // Return true to stop the target, false to just let the target run. - const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " setting rendezvous break address at 0x%" PRIx64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + break_addr); + Breakpoint *dyld_break = + target.CreateBreakpoint(break_addr, true, false).get(); + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); + dyld_break->SetBreakpointKind("shared-library-event"); + m_dyld_bid = dyld_break->GetID(); + } else { if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " stop_when_images_change=%s", __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID, stop_when_images_change ? "true" : "false"); - return stop_when_images_change; + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " reusing break id %" PRIu32 ", address at 0x%" PRIx64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + m_dyld_bid, break_addr); + } + + // Make sure our breakpoint is at the right address. + assert(target.GetBreakpointByID(m_dyld_bid) + ->FindLocationByAddress(break_addr) + ->GetBreakpoint() + .GetID() == m_dyld_bid); } -void -DynamicLoaderPOSIXDYLD::RefreshModules() -{ - if (!m_rendezvous.Resolve()) - return; - - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); - - if (m_rendezvous.ModulesDidLoad()) - { - ModuleList new_modules; - - E = m_rendezvous.loaded_end(); - for (I = m_rendezvous.loaded_begin(); I != E; ++I) - { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); - if (module_sp.get()) - { - loaded_modules.AppendIfNeeded(module_sp); - new_modules.Append(module_sp); - } - } - m_process->GetTarget().ModulesDidLoad(new_modules); +bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit( + void *baton, StoppointCallbackContext *context, user_id_t break_id, + user_id_t break_loc_id) { + assert(baton && "null baton"); + if (!baton) + return false; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + DynamicLoaderPOSIXDYLD *const dyld_instance = + static_cast<DynamicLoaderPOSIXDYLD *>(baton); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); + + dyld_instance->RefreshModules(); + + // Return true to stop the target, false to just let the target run. + const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " stop_when_images_change=%s", + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID, + stop_when_images_change ? "true" : "false"); + return stop_when_images_change; +} + +void DynamicLoaderPOSIXDYLD::RefreshModules() { + if (!m_rendezvous.Resolve()) + return; + + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + if (m_rendezvous.ModulesDidLoad()) { + ModuleList new_modules; + + E = m_rendezvous.loaded_end(); + for (I = m_rendezvous.loaded_begin(); I != E; ++I) { + ModuleSP module_sp = + LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); + if (module_sp.get()) { + loaded_modules.AppendIfNeeded(module_sp); + new_modules.Append(module_sp); + } } - - if (m_rendezvous.ModulesDidUnload()) - { - ModuleList old_modules; - - E = m_rendezvous.unloaded_end(); - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) - { - ModuleSpec module_spec{I->file_spec}; - ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec); - - if (module_sp.get()) - { - old_modules.Append(module_sp); - UnloadSections(module_sp); - } - } - loaded_modules.Remove(old_modules); - m_process->GetTarget().ModulesDidUnload(old_modules, false); + m_process->GetTarget().ModulesDidLoad(new_modules); + } + + if (m_rendezvous.ModulesDidUnload()) { + ModuleList old_modules; + + E = m_rendezvous.unloaded_end(); + for (I = m_rendezvous.unloaded_begin(); I != E; ++I) { + ModuleSpec module_spec{I->file_spec}; + ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec); + + if (module_sp.get()) { + old_modules.Append(module_sp); + UnloadSections(module_sp); + } } + loaded_modules.Remove(old_modules); + m_process->GetTarget().ModulesDidUnload(old_modules, false); + } } ThreadPlanSP -DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) -{ - ThreadPlanSP thread_plan_sp; - - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *sym = context.symbol; - - if (sym == NULL || !sym->IsTrampoline()) - return thread_plan_sp; - - ConstString sym_name = sym->GetName(); - if (!sym_name) - return thread_plan_sp; - - SymbolContextList target_symbols; - Target &target = thread.GetProcess()->GetTarget(); - const ModuleList &images = target.GetImages(); - - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); - size_t num_targets = target_symbols.GetSize(); - if (!num_targets) - return thread_plan_sp; - - typedef std::vector<lldb::addr_t> AddressVector; - AddressVector addrs; - for (size_t i = 0; i < num_targets; ++i) - { - SymbolContext context; - AddressRange range; - if (target_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange(eSymbolContextEverything, 0, false, range); - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); - if (addr != LLDB_INVALID_ADDRESS) - addrs.push_back(addr); - } - } +DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, + bool stop) { + ThreadPlanSP thread_plan_sp; - if (addrs.size() > 0) - { - AddressVector::iterator start = addrs.begin(); - AddressVector::iterator end = addrs.end(); + StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); + const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); + Symbol *sym = context.symbol; - std::sort(start, end); - addrs.erase(std::unique(start, end), end); - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); - } + if (sym == NULL || !sym->IsTrampoline()) + return thread_plan_sp; + ConstString sym_name = sym->GetName(); + if (!sym_name) return thread_plan_sp; -} -void -DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() -{ - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - ModuleList module_list; - - if (!m_rendezvous.Resolve()) - { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD rendezvous address", - __FUNCTION__); - return; + SymbolContextList target_symbols; + Target &target = thread.GetProcess()->GetTarget(); + const ModuleList &images = target.GetImages(); + + images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); + size_t num_targets = target_symbols.GetSize(); + if (!num_targets) + return thread_plan_sp; + + typedef std::vector<lldb::addr_t> AddressVector; + AddressVector addrs; + for (size_t i = 0; i < num_targets; ++i) { + SymbolContext context; + AddressRange range; + if (target_symbols.GetContextAtIndex(i, context)) { + context.GetAddressRange(eSymbolContextEverything, 0, false, range); + lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); + if (addr != LLDB_INVALID_ADDRESS) + addrs.push_back(addr); } + } + + if (addrs.size() > 0) { + AddressVector::iterator start = addrs.begin(); + AddressVector::iterator end = addrs.end(); - // The rendezvous class doesn't enumerate the main module, so track - // that ourselves here. - ModuleSP executable = GetTargetExecutable(); - m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - if (m_vdso_base != LLDB_INVALID_ADDRESS) - { - FileSpec file_spec("[vdso]", false); - ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false); - if (module_sp.get()) - { - module_list.Append(module_sp); - } + std::sort(start, end); + addrs.erase(std::unique(start, end), end); + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); + } + + return thread_plan_sp; +} + +void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + ModuleList module_list; + + if (!m_rendezvous.Resolve()) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " + "rendezvous address", + __FUNCTION__); + return; + } + + // The rendezvous class doesn't enumerate the main module, so track + // that ourselves here. + ModuleSP executable = GetTargetExecutable(); + m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); + if (m_vdso_base != LLDB_INVALID_ADDRESS) { + FileSpec file_spec("[vdso]", false); + ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, + m_vdso_base, false); + if (module_sp.get()) { + module_list.Append(module_sp); } - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) - { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); - if (module_sp.get()) - { - module_list.Append(module_sp); - } - else - { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, - __FUNCTION__, I->file_spec.GetCString(), I->base_addr); - } + } + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { + ModuleSP module_sp = + LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); + if (module_sp.get()) { + module_list.Append(module_sp); + } else { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf( + "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, + __FUNCTION__, I->file_spec.GetCString(), I->base_addr); } + } - m_process->GetTarget().ModulesDidLoad(module_list); + m_process->GetTarget().ModulesDidLoad(module_list); } -addr_t -DynamicLoaderPOSIXDYLD::ComputeLoadOffset() -{ - addr_t virt_entry; +addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { + addr_t virt_entry; - if (m_load_offset != LLDB_INVALID_ADDRESS) - return m_load_offset; + if (m_load_offset != LLDB_INVALID_ADDRESS) + return m_load_offset; - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; - ModuleSP module = m_process->GetTarget().GetExecutableModule(); - if (!module) - return LLDB_INVALID_ADDRESS; + ModuleSP module = m_process->GetTarget().GetExecutableModule(); + if (!module) + return LLDB_INVALID_ADDRESS; - ObjectFile *exe = module->GetObjectFile(); - if (!exe) - return LLDB_INVALID_ADDRESS; + ObjectFile *exe = module->GetObjectFile(); + if (!exe) + return LLDB_INVALID_ADDRESS; - Address file_entry = exe->GetEntryPointAddress(); + Address file_entry = exe->GetEntryPointAddress(); - if (!file_entry.IsValid()) - return LLDB_INVALID_ADDRESS; - - m_load_offset = virt_entry - file_entry.GetFileAddress(); - return m_load_offset; -} + if (!file_entry.IsValid()) + return LLDB_INVALID_ADDRESS; -void -DynamicLoaderPOSIXDYLD::EvalVdsoStatus() -{ - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + m_load_offset = virt_entry - file_entry.GetFileAddress(); + return m_load_offset; +} - if (I != m_auxv->end()) - m_vdso_base = I->value; +void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() { + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + if (I != m_auxv->end()) + m_vdso_base = I->value; } -addr_t -DynamicLoaderPOSIXDYLD::GetEntryPoint() -{ - if (m_entry_point != LLDB_INVALID_ADDRESS) - return m_entry_point; +addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { + if (m_entry_point != LLDB_INVALID_ADDRESS) + return m_entry_point; - if (m_auxv.get() == NULL) - return LLDB_INVALID_ADDRESS; + if (m_auxv.get() == NULL) + return LLDB_INVALID_ADDRESS; - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); - if (I == m_auxv->end()) - return LLDB_INVALID_ADDRESS; + if (I == m_auxv->end()) + return LLDB_INVALID_ADDRESS; - m_entry_point = static_cast<addr_t>(I->value); + m_entry_point = static_cast<addr_t>(I->value); - const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); + const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); - // On ppc64, the entry point is actually a descriptor. Dereference it. - if (arch.GetMachine() == llvm::Triple::ppc64) - m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8); + // On ppc64, the entry point is actually a descriptor. Dereference it. + if (arch.GetMachine() == llvm::Triple::ppc64) + m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8); - return m_entry_point; + return m_entry_point; } lldb::addr_t -DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread, - lldb::addr_t tls_file_addr) -{ - auto it = m_loaded_modules.find (module_sp); - if (it == m_loaded_modules.end()) - return LLDB_INVALID_ADDRESS; - - addr_t link_map = it->second; - if (link_map == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo(); - if (!metadata.valid) - return LLDB_INVALID_ADDRESS; - - // Get the thread pointer. - addr_t tp = thread->GetThreadPointer (); - if (tp == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - // Find the module's modid. - int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit - int64_t modid = ReadUnsignedIntWithSizeInBytes (link_map + metadata.modid_offset, modid_size); - if (modid == -1) - return LLDB_INVALID_ADDRESS; - - // Lookup the DTV structure for this thread. - addr_t dtv_ptr = tp + metadata.dtv_offset; - addr_t dtv = ReadPointer (dtv_ptr); - if (dtv == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - // Find the TLS block for this module. - addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid; - addr_t tls_block = ReadPointer (dtv_slot + metadata.tls_offset); - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", - module_sp->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); - - if (tls_block == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - else - return tls_block + tls_file_addr; +DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, + const lldb::ThreadSP thread, + lldb::addr_t tls_file_addr) { + auto it = m_loaded_modules.find(module_sp); + if (it == m_loaded_modules.end()) + return LLDB_INVALID_ADDRESS; + + addr_t link_map = it->second; + if (link_map == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo(); + if (!metadata.valid) + return LLDB_INVALID_ADDRESS; + + // Get the thread pointer. + addr_t tp = thread->GetThreadPointer(); + if (tp == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + // Find the module's modid. + int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit + int64_t modid = ReadUnsignedIntWithSizeInBytes( + link_map + metadata.modid_offset, modid_size); + if (modid == -1) + return LLDB_INVALID_ADDRESS; + + // Lookup the DTV structure for this thread. + addr_t dtv_ptr = tp + metadata.dtv_offset; + addr_t dtv = ReadPointer(dtv_ptr); + if (dtv == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + // Find the TLS block for this module. + addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid; + addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset); + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 + ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", + module_sp->GetObjectName().AsCString(""), link_map, tp, + (int64_t)modid, tls_block); + + if (tls_block == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + else + return tls_block + tls_file_addr; } -void -DynamicLoaderPOSIXDYLD::ResolveExecutableModule (lldb::ModuleSP &module_sp) -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); +void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( + lldb::ModuleSP &module_sp) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (m_process == nullptr) - return; + if (m_process == nullptr) + return; - auto &target = m_process->GetTarget (); - const auto platform_sp = target.GetPlatform (); + auto &target = m_process->GetTarget(); + const auto platform_sp = target.GetPlatform(); - ProcessInstanceInfo process_info; - if (!m_process->GetProcessInfo(process_info)) - { - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s - failed to get process info for pid %" PRIu64, - __FUNCTION__, m_process->GetID ()); - return; - } + ProcessInstanceInfo process_info; + if (!m_process->GetProcessInfo(process_info)) { + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to get process info for " + "pid %" PRIu64, + __FUNCTION__, m_process->GetID()); + return; + } + + if (log) + log->Printf("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 + ": %s", + __FUNCTION__, m_process->GetID(), + process_info.GetExecutableFile().GetPath().c_str()); + + ModuleSpec module_spec(process_info.GetExecutableFile(), + process_info.GetArchitecture()); + if (module_sp && module_sp->MatchesModuleSpec(module_spec)) + return; + + const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths()); + auto error = platform_sp->ResolveExecutable( + module_spec, module_sp, + !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr); + if (error.Fail()) { + StreamString stream; + module_spec.Dump(stream); if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", - __FUNCTION__, m_process->GetID (), process_info.GetExecutableFile ().GetPath ().c_str ()); - - ModuleSpec module_spec (process_info.GetExecutableFile (), process_info.GetArchitecture ()); - if (module_sp && module_sp->MatchesModuleSpec (module_spec)) - return; - - const auto executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - auto error = platform_sp->ResolveExecutable ( - module_spec, module_sp, !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr); - if (error.Fail ()) - { - StreamString stream; - module_spec.Dump (stream); - - if (log) - log->Printf ("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable with module spec \"%s\": %s", - __FUNCTION__, stream.GetString ().c_str (), error.AsCString ()); - return; - } + log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " + "with module spec \"%s\": %s", + __FUNCTION__, stream.GetString().c_str(), error.AsCString()); + return; + } - target.SetExecutableModule (module_sp, false); + target.SetExecutableModule(module_sp, false); } -bool -DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) -{ - ModuleSP module_sp; - if (sym_ctx.symbol) - module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); - if (!module_sp && sym_ctx.function) - module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); - if (!module_sp) - return false; - - return module_sp->GetFileSpec().GetPath() == "[vdso]"; +bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo( + lldb_private::SymbolContext &sym_ctx) { + ModuleSP module_sp; + if (sym_ctx.symbol) + module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); + if (!module_sp && sym_ctx.function) + module_sp = + sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); + if (!module_sp) + return false; + + return module_sp->GetFileSpec().GetPath() == "[vdso]"; } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 1049e543256..1e8333fb099 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -21,162 +21,139 @@ class AuxVector; -class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader -{ +class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { public: - DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); - ~DynamicLoaderPOSIXDYLD() override; + ~DynamicLoaderPOSIXDYLD() override; - static void - Initialize(); + static void Initialize(); - static void - Terminate(); + static void Terminate(); - static lldb_private::ConstString - GetPluginNameStatic(); + static lldb_private::ConstString GetPluginNameStatic(); - static const char * - GetPluginDescriptionStatic(); + static const char *GetPluginDescriptionStatic(); - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); + static lldb_private::DynamicLoader * + CreateInstance(lldb_private::Process *process, bool force); - //------------------------------------------------------------------ - // DynamicLoader protocol - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // DynamicLoader protocol + //------------------------------------------------------------------ - void - DidAttach() override; + void DidAttach() override; - void - DidLaunch() override; + void DidLaunch() override; - lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others) override; + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override; - lldb_private::Error - CanLoadImage() override; + lldb_private::Error CanLoadImage() override; - lldb::addr_t - GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override; + lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module, + const lldb::ThreadSP thread, + lldb::addr_t tls_file_addr) override; - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString - GetPluginName() override; + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; - uint32_t - GetPluginVersion() override; + uint32_t GetPluginVersion() override; protected: - /// Runtime linker rendezvous structure. - DYLDRendezvous m_rendezvous; - - /// Virtual load address of the inferior process. - lldb::addr_t m_load_offset; - - /// Virtual entry address of the inferior process. - lldb::addr_t m_entry_point; - - /// Auxiliary vector of the inferior process. - std::unique_ptr<AuxVector> m_auxv; - - /// Rendezvous breakpoint. - lldb::break_id_t m_dyld_bid; - - /// Contains AT_SYSINFO_EHDR, which means a vDSO has been - /// mapped to the address space - lldb::addr_t m_vdso_base; - - /// Loaded module list. (link map for each module) - std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules; - - /// Enables a breakpoint on a function called by the runtime - /// linker each time a module is loaded or unloaded. - virtual void - SetRendezvousBreakpoint(); - - /// Callback routine which updates the current list of loaded modules based - /// on the information supplied by the runtime linker. - static bool - RendezvousBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set - /// of loaded modules. - void - RefreshModules(); - - /// Updates the load address of every allocatable section in @p module. - /// - /// @param module The module to traverse. - /// - /// @param link_map_addr The virtual address of the link map for the @p module. - /// - /// @param base_addr The virtual base address @p module is loaded at. - void - UpdateLoadedSections(lldb::ModuleSP module, - lldb::addr_t link_map_addr, - lldb::addr_t base_addr, - bool base_addr_is_offset) override; - - /// Removes the loaded sections from the target in @p module. - /// - /// @param module The module to traverse. - void - UnloadSections(const lldb::ModuleSP module) override; - - /// Resolves the entry point for the current inferior process and sets a - /// breakpoint at that address. - void - ProbeEntry(); - - /// Callback routine invoked when we hit the breakpoint on process entry. - /// - /// This routine is responsible for resolving the load addresses of all - /// dependent modules required by the inferior and setting up the rendezvous - /// breakpoint. - static bool - EntryBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper for the entry breakpoint callback. Resolves the load addresses - /// of all dependent modules. - virtual void - LoadAllCurrentModules(); - - /// Computes a value for m_load_offset returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - ComputeLoadOffset(); - - /// Computes a value for m_entry_point returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - GetEntryPoint(); - - /// Evaluate if Aux vectors contain vDSO information - /// in case they do, read and assign the address to m_vdso_base - void - EvalVdsoStatus(); - - /// Loads Module from inferior process. - void - ResolveExecutableModule(lldb::ModuleSP &module_sp); - - bool - AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; + /// Runtime linker rendezvous structure. + DYLDRendezvous m_rendezvous; + + /// Virtual load address of the inferior process. + lldb::addr_t m_load_offset; + + /// Virtual entry address of the inferior process. + lldb::addr_t m_entry_point; + + /// Auxiliary vector of the inferior process. + std::unique_ptr<AuxVector> m_auxv; + + /// Rendezvous breakpoint. + lldb::break_id_t m_dyld_bid; + + /// Contains AT_SYSINFO_EHDR, which means a vDSO has been + /// mapped to the address space + lldb::addr_t m_vdso_base; + + /// Loaded module list. (link map for each module) + std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> + m_loaded_modules; + + /// Enables a breakpoint on a function called by the runtime + /// linker each time a module is loaded or unloaded. + virtual void SetRendezvousBreakpoint(); + + /// Callback routine which updates the current list of loaded modules based + /// on the information supplied by the runtime linker. + static bool RendezvousBreakpointHit( + void *baton, lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set + /// of loaded modules. + void RefreshModules(); + + /// Updates the load address of every allocatable section in @p module. + /// + /// @param module The module to traverse. + /// + /// @param link_map_addr The virtual address of the link map for the @p + /// module. + /// + /// @param base_addr The virtual base address @p module is loaded at. + void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset) override; + + /// Removes the loaded sections from the target in @p module. + /// + /// @param module The module to traverse. + void UnloadSections(const lldb::ModuleSP module) override; + + /// Resolves the entry point for the current inferior process and sets a + /// breakpoint at that address. + void ProbeEntry(); + + /// Callback routine invoked when we hit the breakpoint on process entry. + /// + /// This routine is responsible for resolving the load addresses of all + /// dependent modules required by the inferior and setting up the rendezvous + /// breakpoint. + static bool + EntryBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + /// Helper for the entry breakpoint callback. Resolves the load addresses + /// of all dependent modules. + virtual void LoadAllCurrentModules(); + + /// Computes a value for m_load_offset returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t ComputeLoadOffset(); + + /// Computes a value for m_entry_point returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t GetEntryPoint(); + + /// Evaluate if Aux vectors contain vDSO information + /// in case they do, read and assign the address to m_vdso_base + void EvalVdsoStatus(); + + /// Loads Module from inferior process. + void ResolveExecutableModule(lldb::ModuleSP &module_sp); + + bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); }; #endif // liblldb_DynamicLoaderPOSIXDYLD_h_ |