diff options
author | Johnny Chen <johnny.chen@apple.com> | 2012-01-05 19:17:38 +0000 |
---|---|---|
committer | Johnny Chen <johnny.chen@apple.com> | 2012-01-05 19:17:38 +0000 |
commit | 30213ffc28b97229c0d06b1332eaced3deba62d7 (patch) | |
tree | 32b27820081f772dedf9dcec828ab8aef3406c96 /lldb/source/Plugins/DynamicLoader | |
parent | 99ab273a778d4836981f71dd7c947785dc3816b8 (diff) | |
download | bcm5719-llvm-30213ffc28b97229c0d06b1332eaced3deba62d7.tar.gz bcm5719-llvm-30213ffc28b97229c0d06b1332eaced3deba62d7.zip |
This patch combines common code from Linux and FreeBSD into
a new POSIX platform. It also contains fixes for 64bit FreeBSD.
The patch is based on changes by Mark Peek <mp@FreeBSD.org> and
"K. Macy" <kmacy@freebsd.org> in their github repo located at
https://github.com/fbsd/lldb.
llvm-svn: 147609
Diffstat (limited to 'lldb/source/Plugins/DynamicLoader')
7 files changed, 0 insertions, 1439 deletions
diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp index 6954e4cac4d..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp @@ -1,191 +0,0 @@ -//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" - -#include "AuxVector.h" - -using namespace lldb; -using namespace lldb_private; - -static bool -GetMaxU64(DataExtractor &data, - uint32_t *offset, uint64_t *value, unsigned int byte_size) -{ - uint32_t saved_offset = *offset; - *value = data.GetMaxU64(offset, byte_size); - return *offset != saved_offset; -} - -static bool -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, - uint32_t *offset, unsigned int byte_size) -{ - if (!GetMaxU64(data, offset, &entry.type, byte_size)) - return false; - - if (!GetMaxU64(data, offset, &entry.value, byte_size)) - return false; - - return true; -} - -DataBufferSP -AuxVector::GetAuxvData() -{ - static const size_t path_size = 128; - static char path[path_size]; - DataBufferSP buf_sp; - int fd; - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) - return buf_sp; - - if ((fd = open(path, O_RDONLY, 0)) < 0) - return buf_sp; - - size_t bytes_read = 0; - std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); - for (;;) - { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - bytes_read += status; - - if (status == 0) - { - buf_ap->SetByteSize(bytes_read); - buf_sp.reset(buf_ap.release()); - break; - } - - if (avail - status == 0) - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); - } - - return buf_sp; -} - -void -AuxVector::ParseAuxv(DataExtractor &data) -{ - const unsigned int byte_size = m_process->GetAddressByteSize(); - uint32_t offset = 0; - - for (;;) - { - Entry entry; - - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) - break; - - if (entry.type == AT_NULL) - break; - - if (entry.type == AT_IGNORE) - continue; - - m_auxv.push_back(entry); - } -} - -AuxVector::AuxVector(Process *process) - : m_process(process) -{ - DataExtractor data; - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - data.SetData(GetAuxvData()); - data.SetByteOrder(m_process->GetByteOrder()); - data.SetAddressByteSize(m_process->GetAddressByteSize()); - - ParseAuxv(data); - - 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; - } - - return end(); -} - -void -AuxVector::DumpToLog(LogSP log) const -{ - if (!log) - return; - - log->PutCString("AuxVector: "); - for (iterator I = begin(); I != end(); ++I) - { - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); - } -} - -const char * -AuxVector::GetEntryName(EntryType type) -{ - const char *name; - -#define ENTRY_NAME(_type) _type: name = #_type - switch (type) - { - default: - name = "unkown"; - break; - - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - } -#undef ENTRY_NAME - - return name; -} - diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h index 7a5b3700fce..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h @@ -1,97 +0,0 @@ -//===-- AuxVector.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_AuxVector_H_ -#define liblldb_AuxVector_H_ - -// C Includes -// C++ Includes -#include <vector> - -// Other libraries and framework includes -#include "lldb/lldb-forward-rtti.h" - -namespace lldb_private { -class DataExtractor; -} - -/// @class AuxVector -/// @brief Represents a processes auxiliary vector. -/// -/// When a process is loaded on Linux a vector of values is placed onto the -/// stack communicating operating system specific information. On construction -/// this class locates and parses this information and provides a simple -/// read-only interface to the entries found. -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. - 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)). - }; - -private: - typedef std::vector<Entry> EntryVector; - -public: - typedef EntryVector::const_iterator iterator; - - iterator begin() const { return m_auxv.begin(); } - iterator end() const { return m_auxv.end(); } - - iterator - FindEntry(EntryType type) const; - - static const char * - GetEntryName(const Entry &entry) { - return GetEntryName(static_cast<EntryType>(entry.type)); - } - - static const char * - GetEntryName(EntryType type); - - void - DumpToLog(lldb::LogSP log) const; - -private: - lldb_private::Process *m_process; - EntryVector m_auxv; - - lldb::DataBufferSP - GetAuxvData(); - - void - ParseAuxv(lldb_private::DataExtractor &data); -}; - -#endif diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp index f10aedb63de..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp @@ -1,322 +0,0 @@ -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "DYLDRendezvous.h" - -using namespace lldb; -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) -{ - addr_t info_location; - addr_t info_addr; - Error error; - size_t size; - - info_location = process->GetImageInfoAddress(); - - if (info_location == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - info_addr = 0; - size = process->DoReadMemory(info_location, &info_addr, - process->GetAddressByteSize(), error); - if (size != process->GetAddressByteSize() || error.Fail()) - return LLDB_INVALID_ADDRESS; - - if (info_addr == 0) - 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_soentries(), - m_added_soentries(), - m_removed_soentries() -{ -} - -bool -DYLDRendezvous::Resolve() -{ - 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 (m_rendezvous_addr == LLDB_INVALID_ADDRESS) - cursor = info_addr = ResolveRendezvousAddress(m_process); - else - cursor = info_addr = m_rendezvous_addr; - - if (cursor == LLDB_INVALID_ADDRESS) - return false; - - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) - return false; - - // The rendezvous was successfully read. Update our internal state. - m_rendezvous_addr = info_addr; - m_previous = m_current; - m_current = info; - - return UpdateSOEntries(); -} - -bool -DYLDRendezvous::IsValid() -{ - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; -} - -bool -DYLDRendezvous::UpdateSOEntries() -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - // When the previous and current states are consistent this is the first - // time we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return TakeSnapshot(m_soentries); - - // If 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) - { - assert(m_previous.state == eConsistent); - m_soentries.clear(); - 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 UpdateSOEntriesForAddition(); - else if (m_previous.state == eDelete) - return UpdateSOEntriesForDeletion(); - - return false; -} - -bool -DYLDRendezvous::UpdateSOEntriesForAddition() -{ - SOEntry entry; - iterator pos; - - assert(m_previous.state == eAdd); - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - 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); - } - } - - return true; -} - -bool -DYLDRendezvous::UpdateSOEntriesForDeletion() -{ - SOEntryList entry_list; - iterator pos; - - assert(m_previous.state == eDelete); - - 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); - } - - m_soentries = entry_list; - return true; -} - -bool -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - entry_list.push_back(entry); - } - - return true; -} - -addr_t -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) -{ - size_t bytes_read; - Error error; - - bytes_read = m_process->DoReadMemory(addr, dst, size, error); - if (bytes_read != size || error.Fail()) - return 0; - - return addr + bytes_read; -} - -std::string -DYLDRendezvous::ReadStringFromMemory(addr_t addr) -{ - std::string str; - Error error; - size_t size; - char c; - - if (addr == LLDB_INVALID_ADDRESS) - return std::string(); - - for (;;) { - size = m_process->DoReadMemory(addr, &c, 1, error); - if (size != 1 || error.Fail()) - return std::string(); - if (c == 0) - break; - else { - str.push_back(c); - addr++; - } - } - - return str; -} - -bool -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) -{ - size_t address_size = m_process->GetAddressByteSize(); - - entry.clear(); - - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.next, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) - return false; - - entry.path = ReadStringFromMemory(entry.path_addr); - - return true; -} - -void -DYLDRendezvous::DumpToLog(LogSP log) const -{ - int state = GetState(); - - if (!log) - return; - - log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %lx", GetRendezvousAddress()); - log->Printf(" Version: %d", GetVersion()); - log->Printf(" Link : %lx", GetLinkMapAddress()); - log->Printf(" Break : %lx", GetBreakAddress()); - log->Printf(" LDBase : %lx", 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->path.c_str()); - log->Printf(" Base : %lx", I->base_addr); - log->Printf(" Path : %lx", I->path_addr); - log->Printf(" Dyn : %lx", I->dyn_addr); - log->Printf(" Next : %lx", I->next); - log->Printf(" Prev : %lx", I->prev); - } -} diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h index e8052ae5b3e..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h @@ -1,227 +0,0 @@ -//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Rendezvous_H_ -#define liblldb_Rendezvous_H_ - -// C Includes -// C++ Includes -#include <list> -#include <string> - -// Other libraries and framework includes -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -class Process; -} - -/// @class DYLDRendezvous -/// @brief Interface to the runtime linker. -/// -/// A structure is present in a processes memory space which is updated by the -/// runtime liker each time a module is loaded or unloaded. This class provides -/// an interface to this structure and maintains a consistent snapshot of the -/// 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) { } - }; - -public: - 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. - int - 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. - int - 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 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::LogSP 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 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. - std::string path; ///< File name of shared object. - - SOEntry() { clear(); } - - bool operator ==(const SOEntry &entry) { - return this->path == entry.path; - } - - void clear() { - base_addr = 0; - path_addr = 0; - dyn_addr = 0; - next = 0; - prev = 0; - path.clear(); - } - }; - -protected: - 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(); } - -protected: - lldb_private::Process *m_process; - - /// 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; - - /// 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 removed from the link map since the last call to - /// Resolve(). - SOEntryList m_removed_soentries; - - /// Reads @p size bytes from the inferiors address space starting at @p - /// addr. - /// - /// @returns addr + size if the read was successful and false otherwise. - lldb::addr_t - ReadMemory(lldb::addr_t addr, void *dst, size_t size); - - /// 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); - - /// Updates the current set of SOEntries, the set of added entries, and the - /// set of removed entries. - bool - UpdateSOEntries(); - - bool - UpdateSOEntriesForAddition(); - - bool - UpdateSOEntriesForDeletion(); - - /// Reads the current list of shared objects according to the link map - /// supplied by the runtime linker. - bool - TakeSnapshot(SOEntryList &entry_list); -}; - -#endif diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp index caad7a01f9a..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp @@ -1,423 +0,0 @@ -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" - -#include "AuxVector.h" -#include "DynamicLoaderLinuxDYLD.h" - -using namespace lldb; -using namespace lldb_private; - -void -DynamicLoaderLinuxDYLD::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); -} - -void -DynamicLoaderLinuxDYLD::Terminate() -{ -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginName() -{ - return "DynamicLoaderLinuxDYLD"; -} - -const char * -DynamicLoaderLinuxDYLD::GetShortPluginName() -{ - return "linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginNameStatic() -{ - return "dynamic-loader.linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() -{ - return "Dynamic loader plug-in that watches for shared library " - "loads/unloads in Linux processes."; -} - -void -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - -uint32_t -DynamicLoaderLinuxDYLD::GetPluginVersion() -{ - return 1; -} - -DynamicLoader * -DynamicLoaderLinuxDYLD::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) - create = true; - } - - if (create) - return new DynamicLoaderLinuxDYLD (process); - return NULL; -} - -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) - : DynamicLoader(process), - m_rendezvous(process), - m_load_offset(LLDB_INVALID_ADDRESS), - m_entry_point(LLDB_INVALID_ADDRESS), - m_auxv(NULL) -{ -} - -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() -{ -} - -void -DynamicLoaderLinuxDYLD::DidAttach() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -void -DynamicLoaderLinuxDYLD::DidLaunch() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - ProbeEntry(); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -Error -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - -Error -DynamicLoaderLinuxDYLD::CanLoadImage() -{ - return Error(); -} - -void -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) -{ - ObjectFile *obj_file = module->GetObjectFile(); - SectionList *sections = obj_file->GetSectionList(); - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); - const size_t num_sections = sections->GetSize(); - - for (unsigned i = 0; i < num_sections; ++i) - { - Section *section = sections->GetSectionAtIndex(i).get(); - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); - - // If the file address of the section is zero then this is not an - // allocatable/loadable section (property of ELF sh_addr). Skip it. - if (new_load_addr == base_addr) - continue; - - if (old_load_addr == LLDB_INVALID_ADDRESS || - old_load_addr != new_load_addr) - load_list.SetSectionLoadAddress(section, new_load_addr); - } -} - -void -DynamicLoaderLinuxDYLD::ProbeEntry() -{ - Breakpoint *entry_break; - addr_t entry; - - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return; - - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); -} - -// The runtime linker has run and initialized the rendezvous structure once the -// process has hit its entry point. When we hit the corresponding breakpoint we -// interrogate the rendezvous structure to get the load addresses of all -// 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 -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton); - dyld_instance->LoadAllCurrentModules(); - dyld_instance->SetRendezvousBreakpoint(); - return false; // Continue running. -} - -void -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() -{ - Breakpoint *dyld_break; - addr_t break_addr; - - break_addr = m_rendezvous.GetBreakAddress(); - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); -} - -bool -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton); - dyld_instance->RefreshModules(); - - // Return true to stop the target, false to just let the target run. - return dyld_instance->GetStopWhenImagesChange(); -} - -void -DynamicLoaderLinuxDYLD::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) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - new_modules.Append(module_sp); - } - 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) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); - if (module_sp.get()) - old_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidUnload(old_modules); - } -} - -ThreadPlanSP -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) -{ - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - 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; - - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); - if (!sym_name) - return thread_plan_sp; - - SymbolContextList target_symbols; - Target &target = thread.GetProcess().GetTarget(); - 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(); - - 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 -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() -{ - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - ModuleList module_list; - - if (!m_rendezvous.Resolve()) - return; - - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) - { - FileSpec file(I->path.c_str(), false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - module_list.Append(module_sp); - } - - m_process->GetTarget().ModulesDidLoad(module_list); -} - -ModuleSP -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) - { - UpdateLoadedSections(module_sp, base_addr); - } - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) - { - UpdateLoadedSections(module_sp, base_addr); - modules.Append(module_sp); - } - - return module_sp; -} - -addr_t -DynamicLoaderLinuxDYLD::ComputeLoadOffset() -{ - addr_t virt_entry; - - if (m_load_offset != LLDB_INVALID_ADDRESS) - return m_load_offset; - - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - ModuleSP module = m_process->GetTarget().GetExecutableModule(); - ObjectFile *exe = module->GetObjectFile(); - 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; -} - -addr_t -DynamicLoaderLinuxDYLD::GetEntryPoint() -{ - if (m_entry_point != LLDB_INVALID_ADDRESS) - return m_entry_point; - - if (m_auxv.get() == NULL) - return LLDB_INVALID_ADDRESS; - - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); - - if (I == m_auxv->end()) - return LLDB_INVALID_ADDRESS; - - m_entry_point = static_cast<addr_t>(I->value); - return m_entry_point; -} diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h index bead75c76dd..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h @@ -1,165 +0,0 @@ -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_DynamicLoaderLinux_H_ -#define liblldb_DynamicLoaderLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Target/DynamicLoader.h" - -#include "DYLDRendezvous.h" - -class AuxVector; - -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader -{ -public: - - static void - Initialize(); - - static void - Terminate(); - - static const char * - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - DynamicLoaderLinuxDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderLinuxDYLD(); - - //------------------------------------------------------------------ - // DynamicLoader protocol - //------------------------------------------------------------------ - - virtual void - DidAttach(); - - virtual void - DidLaunch(); - - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); - - virtual lldb_private::Error - CanLoadImage(); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual const char * - GetPluginName(); - - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - -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::auto_ptr<AuxVector> m_auxv; - - /// Enables a breakpoint on a function called by the runtime - /// linker each time a module is loaded or unloaded. - 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 base_addr The virtual base address @p module is loaded at. - void - UpdateLoadedSections(lldb::ModuleSP module, - lldb::addr_t base_addr = 0); - - /// Locates or creates a module given by @p file and updates/loads the - /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); - - /// 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. - 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(); - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); -}; - -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ diff --git a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/Makefile b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/Makefile index 94025dd3eba..e69de29bb2d 100644 --- a/lldb/source/Plugins/DynamicLoader/Linux-DYLD/Makefile +++ b/lldb/source/Plugins/DynamicLoader/Linux-DYLD/Makefile @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderLinux -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile |