HexagonDYLDRendezvous.h revision 275072
1//===-- HexagonDYLDRendezvous.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_HexagonDYLDRendezvous_H_
11#define liblldb_HexagonDYLDRendezvous_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
22namespace lldb_private
23{
24    class Process;
25}
26
27/// @class HexagonDYLDRendezvous
28/// @brief Interface to the runtime linker.
29///
30/// A structure is present in a processes memory space which is updated by the
31/// runtime liker each time a module is loaded or unloaded.  This class provides
32/// an interface to this structure and maintains a consistent snapshot of the
33/// currently loaded modules.
34class HexagonDYLDRendezvous
35{
36
37    // This structure is used to hold the contents of the debug rendezvous
38    // information (struct r_debug) as found in the inferiors memory.  Note that
39    // the layout of this struct is not binary compatible, it is simply large
40    // enough to hold the information on both 32 and 64 bit platforms.
41    struct Rendezvous {
42        uint64_t     version;
43        lldb::addr_t map_addr;
44        lldb::addr_t brk;
45        uint64_t     state;
46        lldb::addr_t ldbase;
47
48        Rendezvous()
49        : version (0)
50        , map_addr(LLDB_INVALID_ADDRESS)
51        , brk     (LLDB_INVALID_ADDRESS)
52        , state   (0)
53        , ldbase  (0)
54        { }
55
56    };
57
58public:
59    // Various metadata supplied by the inferior's threading library to describe
60    // the per-thread state.
61    struct ThreadInfo {
62        bool     valid;         // whether we read valid metadata
63        uint32_t dtv_offset;    // offset of DTV pointer within pthread
64        uint32_t dtv_slot_size; // size of one DTV slot
65        uint32_t modid_offset;  // offset of module ID within link_map
66        uint32_t tls_offset;    // offset of TLS pointer within DTV slot
67    };
68
69    HexagonDYLDRendezvous(lldb_private::Process *process);
70
71    /// Update the internal snapshot of runtime linker rendezvous and recompute
72    /// the currently loaded modules.
73    ///
74    /// This method should be called once one start up, then once each time the
75    /// runtime linker enters the function given by GetBreakAddress().
76    ///
77    /// @returns true on success and false on failure.
78    ///
79    /// @see GetBreakAddress().
80    bool
81    Resolve();
82
83    /// @returns true if this rendezvous has been located in the inferiors
84    /// address space and false otherwise.
85    bool
86    IsValid();
87
88    /// @returns the address of the rendezvous structure in the inferiors
89    /// address space.
90    lldb::addr_t
91    GetRendezvousAddress() const { return m_rendezvous_addr; }
92
93    /// Provide the dyld structure address
94    void
95    SetRendezvousAddress( lldb::addr_t );
96
97    /// @returns the version of the rendezvous protocol being used.
98    uint64_t
99    GetVersion() const { return m_current.version; }
100
101    /// @returns address in the inferiors address space containing the linked
102    /// list of shared object descriptors.
103    lldb::addr_t
104    GetLinkMapAddress() const { return m_current.map_addr; }
105
106    /// A breakpoint should be set at this address and Resolve called on each
107    /// hit.
108    ///
109    /// @returns the address of a function called by the runtime linker each
110    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
111    ///
112    /// @see Resolve()
113    lldb::addr_t
114    GetBreakAddress() const { return m_current.brk; }
115
116    /// In hexagon it is possible that we can know the dyld breakpoint without
117    /// having to find it from the rendezvous structure
118    ///
119    void
120    SetBreakAddress( lldb::addr_t addr ) { m_current.brk = addr; }
121
122    /// Returns the current state of the rendezvous structure.
123    uint64_t
124    GetState() const { return m_current.state; }
125
126    /// @returns the base address of the runtime linker in the inferiors address
127    /// space.
128    lldb::addr_t
129    GetLDBase() const { return m_current.ldbase; }
130
131    /// @returns the thread layout metadata from the inferiors thread library.
132    const ThreadInfo&
133    GetThreadInfo();
134
135    /// @returns true if modules have been loaded into the inferior since the
136    /// last call to Resolve().
137    bool
138    ModulesDidLoad() const { return !m_added_soentries.empty(); }
139
140    /// @returns true if modules have been unloaded from the inferior since the
141    /// last call to Resolve().
142    bool
143    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
144
145    void
146    DumpToLog(lldb_private::Log *log) const;
147
148    /// @brief Constants describing the state of the rendezvous.
149    ///
150    /// @see GetState().
151    enum RendezvousState
152    {
153        eConsistent	= 0,
154        eAdd		,
155        eDelete		,
156    };
157
158    /// @brief Structure representing the shared objects currently loaded into
159    /// the inferior process.
160    ///
161    /// This object is a rough analogue to the struct link_map object which
162    /// actually lives in the inferiors memory.
163    struct SOEntry {
164        lldb::addr_t link_addr; ///< Address of this link_map.
165        lldb::addr_t base_addr; ///< Base address of the loaded object.
166        lldb::addr_t path_addr; ///< String naming the shared object.
167        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
168        lldb::addr_t next;      ///< Address of next so_entry.
169        lldb::addr_t prev;      ///< Address of previous so_entry.
170        std::string  path;      ///< File name of shared object.
171
172        SOEntry() { clear(); }
173
174        bool operator ==(const SOEntry &entry) {
175            return this->path == entry.path;
176        }
177
178        void clear() {
179            link_addr = 0;
180            base_addr = 0;
181            path_addr = 0;
182            dyn_addr  = 0;
183            next = 0;
184            prev = 0;
185            path.clear();
186        }
187    };
188
189protected:
190    typedef std::list<SOEntry> SOEntryList;
191
192public:
193    typedef SOEntryList::const_iterator iterator;
194
195    /// Iterators over all currently loaded modules.
196    iterator begin() const { return m_soentries.begin(); }
197    iterator end() const { return m_soentries.end(); }
198
199    /// Iterators over all modules loaded into the inferior since the last call
200    /// to Resolve().
201    iterator loaded_begin() const { return m_added_soentries.begin(); }
202    iterator loaded_end() const { return m_added_soentries.end(); }
203
204    /// Iterators over all modules unloaded from the inferior since the last
205    /// call to Resolve().
206    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
207    iterator unloaded_end() const { return m_removed_soentries.end(); }
208
209protected:
210    lldb_private::Process *m_process;
211
212    // Cached copy of executable pathname
213    char m_exe_path[PATH_MAX];
214
215    /// Location of the r_debug structure in the inferiors address space.
216    lldb::addr_t m_rendezvous_addr;
217
218    /// Current and previous snapshots of the rendezvous structure.
219    Rendezvous m_current;
220    Rendezvous m_previous;
221
222    /// List of SOEntry objects corresponding to the current link map state.
223    SOEntryList m_soentries;
224
225    /// List of SOEntry's added to the link map since the last call to Resolve().
226    SOEntryList m_added_soentries;
227
228    /// List of SOEntry's removed from the link map since the last call to
229    /// Resolve().
230    SOEntryList m_removed_soentries;
231
232    /// Threading metadata read from the inferior.
233    ThreadInfo  m_thread_info;
234
235    /// Reads an unsigned integer of @p size bytes from the inferior's address
236    /// space starting at @p addr.
237    ///
238    /// @returns addr + size if the read was successful and false otherwise.
239    lldb::addr_t
240    ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
241
242    /// Reads an address from the inferior's address space starting at @p addr.
243    ///
244    /// @returns addr + target address size if the read was successful and
245    /// 0 otherwise.
246    lldb::addr_t
247    ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
248
249    /// Reads a null-terminated C string from the memory location starting at @p
250    /// addr.
251    std::string
252    ReadStringFromMemory(lldb::addr_t addr);
253
254    /// Reads an SOEntry starting at @p addr.
255    bool
256    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
257
258    /// Updates the current set of SOEntries, the set of added entries, and the
259    /// set of removed entries.
260    bool
261    UpdateSOEntries();
262
263    bool
264    UpdateSOEntriesForAddition();
265
266    bool
267    UpdateSOEntriesForDeletion();
268
269    /// Reads the current list of shared objects according to the link map
270    /// supplied by the runtime linker.
271    bool
272    TakeSnapshot(SOEntryList &entry_list);
273
274    enum PThreadField { eSize, eNElem, eOffset };
275
276    bool FindMetadata(const char *name, PThreadField field, uint32_t& value);
277};
278
279#endif // liblldb_HexagonDYLDRendezvous_H_
280