|
|
@@ -0,0 +1,279 @@ |
|
|
//===-- HexagonDYLDRendezvous.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_HexagonDYLDRendezvous_H_ |
|
|
#define liblldb_HexagonDYLDRendezvous_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 HexagonDYLDRendezvous |
|
|
/// @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 HexagonDYLDRendezvous |
|
|
{ |
|
|
|
|
|
// 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(LLDB_INVALID_ADDRESS) |
|
|
, brk (LLDB_INVALID_ADDRESS) |
|
|
, 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 |
|
|
}; |
|
|
|
|
|
HexagonDYLDRendezvous(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; } |
|
|
|
|
|
/// Provide the dyld structure address |
|
|
void |
|
|
SetRendezvousAddress( lldb::addr_t ); |
|
|
|
|
|
/// @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; } |
|
|
|
|
|
/// In hexagon it is possible that we can know the dyld breakpoint without |
|
|
/// having to find it from the rendezvous structure |
|
|
/// |
|
|
void |
|
|
SetBreakAddress( lldb::addr_t addr ) { m_current.brk = addr; } |
|
|
|
|
|
/// 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 = 0, |
|
|
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. |
|
|
std::string path; ///< File name of shared object. |
|
|
|
|
|
SOEntry() { clear(); } |
|
|
|
|
|
bool operator ==(const SOEntry &entry) { |
|
|
return this->path == entry.path; |
|
|
} |
|
|
|
|
|
void clear() { |
|
|
link_addr = 0; |
|
|
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; |
|
|
|
|
|
// Cached copy of executable pathname |
|
|
char m_exe_path[PATH_MAX]; |
|
|
|
|
|
/// 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; |
|
|
|
|
|
/// 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 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 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); |
|
|
|
|
|
enum PThreadField { eSize, eNElem, eOffset }; |
|
|
|
|
|
bool FindMetadata(const char *name, PThreadField field, uint32_t& value); |
|
|
}; |
|
|
|
|
|
#endif // liblldb_HexagonDYLDRendezvous_H_ |