HexagonDYLDRendezvous.h revision 276479
128257Smsmith//===-- HexagonDYLDRendezvous.h ---------------------------------*- C++ -*-===//
255939Snsouch//
328257Smsmith//                     The LLVM Compiler Infrastructure
428257Smsmith//
528257Smsmith// This file is distributed under the University of Illinois Open Source
628257Smsmith// License. See LICENSE.TXT for details.
728257Smsmith//
828257Smsmith//===----------------------------------------------------------------------===//
928257Smsmith
1028257Smsmith#ifndef liblldb_HexagonDYLDRendezvous_H_
1128257Smsmith#define liblldb_HexagonDYLDRendezvous_H_
1228257Smsmith
1328257Smsmith// C Includes
1428257Smsmith// C++ Includes
1528257Smsmith#include <list>
1628257Smsmith#include <string>
1728257Smsmith
1828257Smsmith// Other libraries and framework includes
1928257Smsmith#include "lldb/lldb-defines.h"
2028257Smsmith#include "lldb/lldb-types.h"
2128257Smsmith
2228257Smsmithnamespace lldb_private
2328257Smsmith{
2428257Smsmith    class Process;
2528257Smsmith}
26119418Sobrien
27119418Sobrien/// @class HexagonDYLDRendezvous
28119418Sobrien/// @brief Interface to the runtime linker.
29119418Sobrien///
3028257Smsmith/// A structure is present in a processes memory space which is updated by the
31187576Sjhb/// runtime liker each time a module is loaded or unloaded.  This class provides
3228257Smsmith/// an interface to this structure and maintains a consistent snapshot of the
3355939Snsouch/// currently loaded modules.
34187576Sjhbclass HexagonDYLDRendezvous
35187576Sjhb{
3655939Snsouch
3755939Snsouch    // This structure is used to hold the contents of the debug rendezvous
3828257Smsmith    // information (struct r_debug) as found in the inferiors memory.  Note that
39185003Sjhb    // the layout of this struct is not binary compatible, it is simply large
4055939Snsouch    // enough to hold the information on both 32 and 64 bit platforms.
4128257Smsmith    struct Rendezvous {
4255939Snsouch        uint64_t     version;
43185003Sjhb        lldb::addr_t map_addr;
44119284Simp        lldb::addr_t brk;
45119284Simp        uint64_t     state;
4655939Snsouch        lldb::addr_t ldbase;
47185003Sjhb
4828257Smsmith        Rendezvous()
4955939Snsouch        : version (0)
5028257Smsmith        , map_addr(LLDB_INVALID_ADDRESS)
5155939Snsouch        , brk     (LLDB_INVALID_ADDRESS)
5228257Smsmith        , state   (0)
5328257Smsmith        , ldbase  (0)
5428257Smsmith        { }
5528257Smsmith
5655939Snsouch    };
5755939Snsouch
5828257Smsmithpublic:
59187576Sjhb    // Various metadata supplied by the inferior's threading library to describe
6042475Snsouch    // the per-thread state.
6142475Snsouch    struct ThreadInfo {
6228257Smsmith        bool     valid;         // whether we read valid metadata
63187576Sjhb        uint32_t dtv_offset;    // offset of DTV pointer within pthread
64187576Sjhb        uint32_t dtv_slot_size; // size of one DTV slot
6542475Snsouch        uint32_t modid_offset;  // offset of module ID within link_map
6642475Snsouch        uint32_t tls_offset;    // offset of TLS pointer within DTV slot
6742475Snsouch    };
6855939Snsouch
6942475Snsouch    HexagonDYLDRendezvous(lldb_private::Process *process);
7042475Snsouch
7142475Snsouch    /// Update the internal snapshot of runtime linker rendezvous and recompute
7242475Snsouch    /// the currently loaded modules.
7342475Snsouch    ///
7442475Snsouch    /// This method should be called once one start up, then once each time the
7542475Snsouch    /// runtime linker enters the function given by GetBreakAddress().
7642475Snsouch    ///
7755939Snsouch    /// @returns true on success and false on failure.
7828257Smsmith    ///
7928257Smsmith    /// @see GetBreakAddress().
80187576Sjhb    bool
81187576Sjhb    Resolve();
82187576Sjhb
83187576Sjhb    /// @returns true if this rendezvous has been located in the inferiors
84187576Sjhb    /// address space and false otherwise.
8542475Snsouch    bool
8628257Smsmith    IsValid();
8728257Smsmith
8828257Smsmith    /// @returns the address of the rendezvous structure in the inferiors
8928257Smsmith    /// address space.
9028257Smsmith    lldb::addr_t
9128257Smsmith    GetRendezvousAddress() const { return m_rendezvous_addr; }
9255939Snsouch
9338061Smsmith    /// Provide the dyld structure address
9455939Snsouch    void
9538061Smsmith    SetRendezvousAddress( lldb::addr_t );
9638061Smsmith
9755939Snsouch    /// @returns the version of the rendezvous protocol being used.
9838061Smsmith    uint64_t
99187576Sjhb    GetVersion() const { return m_current.version; }
100187576Sjhb
101187576Sjhb    /// @returns address in the inferiors address space containing the linked
10255939Snsouch    /// list of shared object descriptors.
10338061Smsmith    lldb::addr_t
104187576Sjhb    GetLinkMapAddress() const { return m_current.map_addr; }
10555939Snsouch
10638061Smsmith    /// A breakpoint should be set at this address and Resolve called on each
10755939Snsouch    /// hit.
10855939Snsouch    ///
10955939Snsouch    /// @returns the address of a function called by the runtime linker each
11055939Snsouch    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
11155939Snsouch    ///
11255939Snsouch    /// @see Resolve()
11355939Snsouch    lldb::addr_t
11455939Snsouch    GetBreakAddress() const { return m_current.brk; }
11555939Snsouch
11655939Snsouch    /// In hexagon it is possible that we can know the dyld breakpoint without
11755939Snsouch    /// having to find it from the rendezvous structure
11855939Snsouch    ///
11938061Smsmith    void
120187576Sjhb    SetBreakAddress( lldb::addr_t addr ) { m_current.brk = addr; }
12155939Snsouch
12255939Snsouch    /// Returns the current state of the rendezvous structure.
12338061Smsmith    uint64_t
12455939Snsouch    GetState() const { return m_current.state; }
12555939Snsouch
12655939Snsouch    /// @returns the base address of the runtime linker in the inferiors address
12755939Snsouch    /// space.
12855939Snsouch    lldb::addr_t
12955939Snsouch    GetLDBase() const { return m_current.ldbase; }
13055939Snsouch
13155939Snsouch    /// @returns the thread layout metadata from the inferiors thread library.
13255939Snsouch    const ThreadInfo&
13355939Snsouch    GetThreadInfo();
13455939Snsouch
135187576Sjhb    /// @returns true if modules have been loaded into the inferior since the
13663458Sn_hibma    /// last call to Resolve().
137185003Sjhb    bool
13855939Snsouch    ModulesDidLoad() const { return !m_added_soentries.empty(); }
13963458Sn_hibma
14063458Sn_hibma    /// @returns true if modules have been unloaded from the inferior since the
14163458Sn_hibma    /// last call to Resolve().
14238061Smsmith    bool
14338061Smsmith    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
14438061Smsmith
14538061Smsmith    void
14642475Snsouch    DumpToLog(lldb_private::Log *log) const;
14742475Snsouch
14842475Snsouch    /// @brief Constants describing the state of the rendezvous.
14942475Snsouch    ///
15042475Snsouch    /// @see GetState().
15155939Snsouch    enum RendezvousState
15242475Snsouch    {
153187576Sjhb        eConsistent	= 0,
154187576Sjhb        eAdd		,
155187576Sjhb        eDelete		,
156187576Sjhb    };
157187576Sjhb
15855939Snsouch    /// @brief Structure representing the shared objects currently loaded into
15942475Snsouch    /// the inferior process.
16042475Snsouch    ///
16142475Snsouch    /// This object is a rough analogue to the struct link_map object which
16228257Smsmith    /// actually lives in the inferiors memory.
16328257Smsmith    struct SOEntry {
16438061Smsmith        lldb::addr_t link_addr; ///< Address of this link_map.
16528257Smsmith        lldb::addr_t base_addr; ///< Base address of the loaded object.
16628257Smsmith        lldb::addr_t path_addr; ///< String naming the shared object.
16755939Snsouch        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
16828257Smsmith        lldb::addr_t next;      ///< Address of next so_entry.
169187576Sjhb        lldb::addr_t prev;      ///< Address of previous so_entry.
170187576Sjhb        std::string  path;      ///< File name of shared object.
171187576Sjhb
172187576Sjhb        SOEntry() { clear(); }
173187576Sjhb
17455939Snsouch        bool operator ==(const SOEntry &entry) {
17528257Smsmith            return this->path == entry.path;
17628257Smsmith        }
17728257Smsmith
17828257Smsmith        void clear() {
17928257Smsmith            link_addr = 0;
18038061Smsmith            base_addr = 0;
18128257Smsmith            path_addr = 0;
18228257Smsmith            dyn_addr  = 0;
18355939Snsouch            next = 0;
18428257Smsmith            prev = 0;
185187576Sjhb            path.clear();
186187576Sjhb        }
187187576Sjhb    };
188187576Sjhb
189187576Sjhbprotected:
19055939Snsouch    typedef std::list<SOEntry> SOEntryList;
19128257Smsmith
19228257Smsmithpublic:
19328257Smsmith    typedef SOEntryList::const_iterator iterator;
19428257Smsmith
19528257Smsmith    /// Iterators over all currently loaded modules.
19638061Smsmith    iterator begin() const { return m_soentries.begin(); }
19728257Smsmith    iterator end() const { return m_soentries.end(); }
19828257Smsmith
19955939Snsouch    /// Iterators over all modules loaded into the inferior since the last call
20028257Smsmith    /// to Resolve().
201187576Sjhb    iterator loaded_begin() const { return m_added_soentries.begin(); }
202187576Sjhb    iterator loaded_end() const { return m_added_soentries.end(); }
203187576Sjhb
20428257Smsmith    /// Iterators over all modules unloaded from the inferior since the last
20528257Smsmith    /// call to Resolve().
206187576Sjhb    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
207187576Sjhb    iterator unloaded_end() const { return m_removed_soentries.end(); }
20855939Snsouch
20928257Smsmithprotected:
21028257Smsmith    lldb_private::Process *m_process;
21128257Smsmith
21228257Smsmith    // Cached copy of executable pathname
21339134Snsouch    char m_exe_path[PATH_MAX];
21428257Smsmith
21528257Smsmith    /// Location of the r_debug structure in the inferiors address space.
21628257Smsmith    lldb::addr_t m_rendezvous_addr;
21728257Smsmith
21828257Smsmith    /// Current and previous snapshots of the rendezvous structure.
219187576Sjhb    Rendezvous m_current;
220187576Sjhb    Rendezvous m_previous;
221187576Sjhb
222187576Sjhb    /// List of SOEntry objects corresponding to the current link map state.
223187576Sjhb    SOEntryList m_soentries;
224187576Sjhb
225187576Sjhb    /// List of SOEntry's added to the link map since the last call to Resolve().
226187576Sjhb    SOEntryList m_added_soentries;
227187576Sjhb
228187576Sjhb    /// List of SOEntry's removed from the link map since the last call to
229187576Sjhb    /// Resolve().
230187576Sjhb    SOEntryList m_removed_soentries;
231187576Sjhb
232187576Sjhb    /// Threading metadata read from the inferior.
233187576Sjhb    ThreadInfo  m_thread_info;
234187576Sjhb
235187576Sjhb    /// Reads an unsigned integer of @p size bytes from the inferior's address
236187576Sjhb    /// space starting at @p addr.
237187576Sjhb    ///
238187576Sjhb    /// @returns addr + size if the read was successful and false otherwise.
239187576Sjhb    lldb::addr_t
240230799Sattilio    ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
241187576Sjhb
242187576Sjhb    /// Reads an address from the inferior's address space starting at @p addr.
243187576Sjhb    ///
244187576Sjhb    /// @returns addr + target address size if the read was successful and
245187576Sjhb    /// 0 otherwise.
246187576Sjhb    lldb::addr_t
247187576Sjhb    ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
248187576Sjhb
249187576Sjhb    /// Reads a null-terminated C string from the memory location starting at @p
250187576Sjhb    /// addr.
251187576Sjhb    std::string
252187576Sjhb    ReadStringFromMemory(lldb::addr_t addr);
253187576Sjhb
254187576Sjhb    /// Reads an SOEntry starting at @p addr.
255187576Sjhb    bool
256187576Sjhb    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
257187576Sjhb
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