Home | History | Annotate | Download | only in POSIX-DYLD
      1 //===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef liblldb_Rendezvous_H_
     11 #define liblldb_Rendezvous_H_
     12 
     13 // C Includes
     14 // C++ Includes
     15 #include <list>
     16 #include <string>
     17 
     18 // Other libraries and framework includes
     19 #include "lldb/lldb-defines.h"
     20 #include "lldb/lldb-types.h"
     21 
     22 namespace lldb_private {
     23 class Process;
     24 }
     25 
     26 /// @class DYLDRendezvous
     27 /// @brief Interface to the runtime linker.
     28 ///
     29 /// A structure is present in a processes memory space which is updated by the
     30 /// runtime liker each time a module is loaded or unloaded.  This class provides
     31 /// an interface to this structure and maintains a consistent snapshot of the
     32 /// currently loaded modules.
     33 class DYLDRendezvous {
     34 
     35     // This structure is used to hold the contents of the debug rendezvous
     36     // information (struct r_debug) as found in the inferiors memory.  Note that
     37     // the layout of this struct is not binary compatible, it is simply large
     38     // enough to hold the information on both 32 and 64 bit platforms.
     39     struct Rendezvous {
     40         uint64_t     version;
     41         lldb::addr_t map_addr;
     42         lldb::addr_t brk;
     43         uint64_t     state;
     44         lldb::addr_t ldbase;
     45 
     46         Rendezvous()
     47             : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
     48     };
     49 
     50 public:
     51     DYLDRendezvous(lldb_private::Process *process);
     52 
     53     /// Update the internal snapshot of runtime linker rendezvous and recompute
     54     /// the currently loaded modules.
     55     ///
     56     /// This method should be called once one start up, then once each time the
     57     /// runtime linker enters the function given by GetBreakAddress().
     58     ///
     59     /// @returns true on success and false on failure.
     60     ///
     61     /// @see GetBreakAddress().
     62     bool
     63     Resolve();
     64 
     65     /// @returns true if this rendezvous has been located in the inferiors
     66     /// address space and false otherwise.
     67     bool
     68     IsValid();
     69 
     70     /// @returns the address of the rendezvous structure in the inferiors
     71     /// address space.
     72     lldb::addr_t
     73     GetRendezvousAddress() const { return m_rendezvous_addr; }
     74 
     75     /// @returns the version of the rendezvous protocol being used.
     76     uint64_t
     77     GetVersion() const { return m_current.version; }
     78 
     79     /// @returns address in the inferiors address space containing the linked
     80     /// list of shared object descriptors.
     81     lldb::addr_t
     82     GetLinkMapAddress() const { return m_current.map_addr; }
     83 
     84     /// A breakpoint should be set at this address and Resolve called on each
     85     /// hit.
     86     ///
     87     /// @returns the address of a function called by the runtime linker each
     88     /// time a module is loaded/unloaded, or about to be loaded/unloaded.
     89     ///
     90     /// @see Resolve()
     91     lldb::addr_t
     92     GetBreakAddress() const { return m_current.brk; }
     93 
     94     /// Returns the current state of the rendezvous structure.
     95     uint64_t
     96     GetState() const { return m_current.state; }
     97 
     98     /// @returns the base address of the runtime linker in the inferiors address
     99     /// space.
    100     lldb::addr_t
    101     GetLDBase() const { return m_current.ldbase; }
    102 
    103     /// @returns true if modules have been loaded into the inferior since the
    104     /// last call to Resolve().
    105     bool
    106     ModulesDidLoad() const { return !m_added_soentries.empty(); }
    107 
    108     /// @returns true if modules have been unloaded from the inferior since the
    109     /// last call to Resolve().
    110     bool
    111     ModulesDidUnload() const { return !m_removed_soentries.empty(); }
    112 
    113     void
    114     DumpToLog(lldb_private::Log *log) const;
    115 
    116     /// @brief Constants describing the state of the rendezvous.
    117     ///
    118     /// @see GetState().
    119     enum RendezvousState {
    120         eConsistent,
    121         eAdd,
    122         eDelete
    123     };
    124 
    125     /// @brief Structure representing the shared objects currently loaded into
    126     /// the inferior process.
    127     ///
    128     /// This object is a rough analogue to the struct link_map object which
    129     /// actually lives in the inferiors memory.
    130     struct SOEntry {
    131         lldb::addr_t base_addr; ///< Base address of the loaded object.
    132         lldb::addr_t path_addr; ///< String naming the shared object.
    133         lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
    134         lldb::addr_t next;      ///< Address of next so_entry.
    135         lldb::addr_t prev;      ///< Address of previous so_entry.
    136         std::string  path;      ///< File name of shared object.
    137 
    138         SOEntry() { clear(); }
    139 
    140         bool operator ==(const SOEntry &entry) {
    141             return this->path == entry.path;
    142         }
    143 
    144         void clear() {
    145             base_addr = 0;
    146             path_addr = 0;
    147             dyn_addr  = 0;
    148             next = 0;
    149             prev = 0;
    150             path.clear();
    151         }
    152     };
    153 
    154 protected:
    155     typedef std::list<SOEntry> SOEntryList;
    156 
    157 public:
    158     typedef SOEntryList::const_iterator iterator;
    159 
    160     /// Iterators over all currently loaded modules.
    161     iterator begin() const { return m_soentries.begin(); }
    162     iterator end() const { return m_soentries.end(); }
    163 
    164     /// Iterators over all modules loaded into the inferior since the last call
    165     /// to Resolve().
    166     iterator loaded_begin() const { return m_added_soentries.begin(); }
    167     iterator loaded_end() const { return m_added_soentries.end(); }
    168 
    169     /// Iterators over all modules unloaded from the inferior since the last
    170     /// call to Resolve().
    171     iterator unloaded_begin() const { return m_removed_soentries.begin(); }
    172     iterator unloaded_end() const { return m_removed_soentries.end(); }
    173 
    174 protected:
    175     lldb_private::Process *m_process;
    176 
    177     // Cached copy of executable pathname
    178     char m_exe_path[PATH_MAX];
    179 
    180     /// Location of the r_debug structure in the inferiors address space.
    181     lldb::addr_t m_rendezvous_addr;
    182 
    183     /// Current and previous snapshots of the rendezvous structure.
    184     Rendezvous m_current;
    185     Rendezvous m_previous;
    186 
    187     /// List of SOEntry objects corresponding to the current link map state.
    188     SOEntryList m_soentries;
    189 
    190     /// List of SOEntry's added to the link map since the last call to Resolve().
    191     SOEntryList m_added_soentries;
    192 
    193     /// List of SOEntry's removed from the link map since the last call to
    194     /// Resolve().
    195     SOEntryList m_removed_soentries;
    196 
    197     /// Reads @p size bytes from the inferiors address space starting at @p
    198     /// addr.
    199     ///
    200     /// @returns addr + size if the read was successful and false otherwise.
    201     lldb::addr_t
    202     ReadMemory(lldb::addr_t addr, void *dst, size_t size);
    203 
    204     /// Reads a null-terminated C string from the memory location starting at @p
    205     /// addr.
    206     std::string
    207     ReadStringFromMemory(lldb::addr_t addr);
    208 
    209     /// Reads an SOEntry starting at @p addr.
    210     bool
    211     ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
    212 
    213     /// Updates the current set of SOEntries, the set of added entries, and the
    214     /// set of removed entries.
    215     bool
    216     UpdateSOEntries();
    217 
    218     bool
    219     UpdateSOEntriesForAddition();
    220 
    221     bool
    222     UpdateSOEntriesForDeletion();
    223 
    224     /// Reads the current list of shared objects according to the link map
    225     /// supplied by the runtime linker.
    226     bool
    227     TakeSnapshot(SOEntryList &entry_list);
    228 };
    229 
    230 #endif
    231