1254721Semaste//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#ifndef liblldb_Rendezvous_H_
11254721Semaste#define liblldb_Rendezvous_H_
12254721Semaste
13254721Semaste// C Includes
14254721Semaste// C++ Includes
15254721Semaste#include <list>
16254721Semaste#include <string>
17254721Semaste
18254721Semaste// Other libraries and framework includes
19254721Semaste#include "lldb/lldb-defines.h"
20254721Semaste#include "lldb/lldb-types.h"
21254721Semaste
22254721Semastenamespace lldb_private {
23254721Semasteclass Process;
24254721Semaste}
25254721Semaste
26254721Semaste/// @class DYLDRendezvous
27254721Semaste/// @brief Interface to the runtime linker.
28254721Semaste///
29254721Semaste/// A structure is present in a processes memory space which is updated by the
30254721Semaste/// runtime liker each time a module is loaded or unloaded.  This class provides
31254721Semaste/// an interface to this structure and maintains a consistent snapshot of the
32254721Semaste/// currently loaded modules.
33254721Semasteclass DYLDRendezvous {
34254721Semaste
35254721Semaste    // This structure is used to hold the contents of the debug rendezvous
36254721Semaste    // information (struct r_debug) as found in the inferiors memory.  Note that
37254721Semaste    // the layout of this struct is not binary compatible, it is simply large
38254721Semaste    // enough to hold the information on both 32 and 64 bit platforms.
39254721Semaste    struct Rendezvous {
40254721Semaste        uint64_t     version;
41254721Semaste        lldb::addr_t map_addr;
42254721Semaste        lldb::addr_t brk;
43254721Semaste        uint64_t     state;
44254721Semaste        lldb::addr_t ldbase;
45254721Semaste
46254721Semaste        Rendezvous()
47254721Semaste            : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
48254721Semaste    };
49254721Semaste
50254721Semastepublic:
51254721Semaste    DYLDRendezvous(lldb_private::Process *process);
52254721Semaste
53254721Semaste    /// Update the internal snapshot of runtime linker rendezvous and recompute
54254721Semaste    /// the currently loaded modules.
55254721Semaste    ///
56254721Semaste    /// This method should be called once one start up, then once each time the
57254721Semaste    /// runtime linker enters the function given by GetBreakAddress().
58254721Semaste    ///
59254721Semaste    /// @returns true on success and false on failure.
60254721Semaste    ///
61254721Semaste    /// @see GetBreakAddress().
62254721Semaste    bool
63254721Semaste    Resolve();
64254721Semaste
65254721Semaste    /// @returns true if this rendezvous has been located in the inferiors
66254721Semaste    /// address space and false otherwise.
67254721Semaste    bool
68254721Semaste    IsValid();
69254721Semaste
70254721Semaste    /// @returns the address of the rendezvous structure in the inferiors
71254721Semaste    /// address space.
72254721Semaste    lldb::addr_t
73254721Semaste    GetRendezvousAddress() const { return m_rendezvous_addr; }
74254721Semaste
75254721Semaste    /// @returns the version of the rendezvous protocol being used.
76254721Semaste    uint64_t
77254721Semaste    GetVersion() const { return m_current.version; }
78254721Semaste
79254721Semaste    /// @returns address in the inferiors address space containing the linked
80254721Semaste    /// list of shared object descriptors.
81254721Semaste    lldb::addr_t
82254721Semaste    GetLinkMapAddress() const { return m_current.map_addr; }
83254721Semaste
84254721Semaste    /// A breakpoint should be set at this address and Resolve called on each
85254721Semaste    /// hit.
86254721Semaste    ///
87254721Semaste    /// @returns the address of a function called by the runtime linker each
88254721Semaste    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
89254721Semaste    ///
90254721Semaste    /// @see Resolve()
91254721Semaste    lldb::addr_t
92254721Semaste    GetBreakAddress() const { return m_current.brk; }
93254721Semaste
94254721Semaste    /// Returns the current state of the rendezvous structure.
95254721Semaste    uint64_t
96254721Semaste    GetState() const { return m_current.state; }
97254721Semaste
98254721Semaste    /// @returns the base address of the runtime linker in the inferiors address
99254721Semaste    /// space.
100254721Semaste    lldb::addr_t
101254721Semaste    GetLDBase() const { return m_current.ldbase; }
102254721Semaste
103254721Semaste    /// @returns true if modules have been loaded into the inferior since the
104254721Semaste    /// last call to Resolve().
105254721Semaste    bool
106254721Semaste    ModulesDidLoad() const { return !m_added_soentries.empty(); }
107254721Semaste
108254721Semaste    /// @returns true if modules have been unloaded from the inferior since the
109254721Semaste    /// last call to Resolve().
110254721Semaste    bool
111254721Semaste    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
112254721Semaste
113254721Semaste    void
114254721Semaste    DumpToLog(lldb_private::Log *log) const;
115254721Semaste
116254721Semaste    /// @brief Constants describing the state of the rendezvous.
117254721Semaste    ///
118254721Semaste    /// @see GetState().
119254721Semaste    enum RendezvousState {
120254721Semaste        eConsistent,
121254721Semaste        eAdd,
122254721Semaste        eDelete
123254721Semaste    };
124254721Semaste
125254721Semaste    /// @brief Structure representing the shared objects currently loaded into
126254721Semaste    /// the inferior process.
127254721Semaste    ///
128254721Semaste    /// This object is a rough analogue to the struct link_map object which
129254721Semaste    /// actually lives in the inferiors memory.
130254721Semaste    struct SOEntry {
131254721Semaste        lldb::addr_t base_addr; ///< Base address of the loaded object.
132254721Semaste        lldb::addr_t path_addr; ///< String naming the shared object.
133254721Semaste        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
134254721Semaste        lldb::addr_t next;      ///< Address of next so_entry.
135254721Semaste        lldb::addr_t prev;      ///< Address of previous so_entry.
136254721Semaste        std::string  path;      ///< File name of shared object.
137254721Semaste
138254721Semaste        SOEntry() { clear(); }
139254721Semaste
140254721Semaste        bool operator ==(const SOEntry &entry) {
141254721Semaste            return this->path == entry.path;
142254721Semaste        }
143254721Semaste
144254721Semaste        void clear() {
145254721Semaste            base_addr = 0;
146254721Semaste            path_addr = 0;
147254721Semaste            dyn_addr  = 0;
148254721Semaste            next = 0;
149254721Semaste            prev = 0;
150254721Semaste            path.clear();
151254721Semaste        }
152254721Semaste    };
153254721Semaste
154254721Semasteprotected:
155254721Semaste    typedef std::list<SOEntry> SOEntryList;
156254721Semaste
157254721Semastepublic:
158254721Semaste    typedef SOEntryList::const_iterator iterator;
159254721Semaste
160254721Semaste    /// Iterators over all currently loaded modules.
161254721Semaste    iterator begin() const { return m_soentries.begin(); }
162254721Semaste    iterator end() const { return m_soentries.end(); }
163254721Semaste
164254721Semaste    /// Iterators over all modules loaded into the inferior since the last call
165254721Semaste    /// to Resolve().
166254721Semaste    iterator loaded_begin() const { return m_added_soentries.begin(); }
167254721Semaste    iterator loaded_end() const { return m_added_soentries.end(); }
168254721Semaste
169254721Semaste    /// Iterators over all modules unloaded from the inferior since the last
170254721Semaste    /// call to Resolve().
171254721Semaste    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
172254721Semaste    iterator unloaded_end() const { return m_removed_soentries.end(); }
173254721Semaste
174254721Semasteprotected:
175254721Semaste    lldb_private::Process *m_process;
176254721Semaste
177254721Semaste    // Cached copy of executable pathname
178254721Semaste    char m_exe_path[PATH_MAX];
179254721Semaste
180254721Semaste    /// Location of the r_debug structure in the inferiors address space.
181254721Semaste    lldb::addr_t m_rendezvous_addr;
182254721Semaste
183254721Semaste    /// Current and previous snapshots of the rendezvous structure.
184254721Semaste    Rendezvous m_current;
185254721Semaste    Rendezvous m_previous;
186254721Semaste
187254721Semaste    /// List of SOEntry objects corresponding to the current link map state.
188254721Semaste    SOEntryList m_soentries;
189254721Semaste
190254721Semaste    /// List of SOEntry's added to the link map since the last call to Resolve().
191254721Semaste    SOEntryList m_added_soentries;
192254721Semaste
193254721Semaste    /// List of SOEntry's removed from the link map since the last call to
194254721Semaste    /// Resolve().
195254721Semaste    SOEntryList m_removed_soentries;
196254721Semaste
197254721Semaste    /// Reads @p size bytes from the inferiors address space starting at @p
198254721Semaste    /// addr.
199254721Semaste    ///
200254721Semaste    /// @returns addr + size if the read was successful and false otherwise.
201254721Semaste    lldb::addr_t
202254721Semaste    ReadMemory(lldb::addr_t addr, void *dst, size_t size);
203254721Semaste
204254721Semaste    /// Reads a null-terminated C string from the memory location starting at @p
205254721Semaste    /// addr.
206254721Semaste    std::string
207254721Semaste    ReadStringFromMemory(lldb::addr_t addr);
208254721Semaste
209254721Semaste    /// Reads an SOEntry starting at @p addr.
210254721Semaste    bool
211254721Semaste    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
212254721Semaste
213254721Semaste    /// Updates the current set of SOEntries, the set of added entries, and the
214254721Semaste    /// set of removed entries.
215254721Semaste    bool
216254721Semaste    UpdateSOEntries();
217254721Semaste
218254721Semaste    bool
219254721Semaste    UpdateSOEntriesForAddition();
220254721Semaste
221254721Semaste    bool
222254721Semaste    UpdateSOEntriesForDeletion();
223254721Semaste
224254721Semaste    /// Reads the current list of shared objects according to the link map
225254721Semaste    /// supplied by the runtime linker.
226254721Semaste    bool
227254721Semaste    TakeSnapshot(SOEntryList &entry_list);
228254721Semaste};
229254721Semaste
230254721Semaste#endif
231