HexagonDYLDRendezvous.h revision 344779
1275072Semaste//===-- HexagonDYLDRendezvous.h ---------------------------------*- C++ -*-===//
2275072Semaste//
3275072Semaste//                     The LLVM Compiler Infrastructure
4275072Semaste//
5275072Semaste// This file is distributed under the University of Illinois Open Source
6275072Semaste// License. See LICENSE.TXT for details.
7275072Semaste//
8275072Semaste//===----------------------------------------------------------------------===//
9275072Semaste
10275072Semaste#ifndef liblldb_HexagonDYLDRendezvous_H_
11275072Semaste#define liblldb_HexagonDYLDRendezvous_H_
12275072Semaste
13344779Sdim#include <limits.h>
14275072Semaste#include <list>
15341825Sdim#include <map>
16275072Semaste#include <string>
17275072Semaste
18275072Semaste#include "lldb/lldb-defines.h"
19275072Semaste#include "lldb/lldb-types.h"
20275072Semaste
21314564Sdimnamespace lldb_private {
22314564Sdimclass Process;
23275072Semaste}
24275072Semaste
25275072Semaste/// @class HexagonDYLDRendezvous
26341825Sdim/// Interface to the runtime linker.
27275072Semaste///
28275072Semaste/// A structure is present in a processes memory space which is updated by the
29341825Sdim/// runtime liker each time a module is loaded or unloaded.  This class
30341825Sdim/// provides an interface to this structure and maintains a consistent
31341825Sdim/// snapshot of the currently loaded modules.
32314564Sdimclass HexagonDYLDRendezvous {
33275072Semaste
34314564Sdim  // This structure is used to hold the contents of the debug rendezvous
35314564Sdim  // information (struct r_debug) as found in the inferiors memory.  Note that
36314564Sdim  // the layout of this struct is not binary compatible, it is simply large
37314564Sdim  // enough to hold the information on both 32 and 64 bit platforms.
38314564Sdim  struct Rendezvous {
39314564Sdim    uint64_t version;
40314564Sdim    lldb::addr_t map_addr;
41314564Sdim    lldb::addr_t brk;
42314564Sdim    uint64_t state;
43314564Sdim    lldb::addr_t ldbase;
44275072Semaste
45314564Sdim    Rendezvous()
46314564Sdim        : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS),
47314564Sdim          state(0), ldbase(0) {}
48314564Sdim  };
49275072Semaste
50275072Semastepublic:
51314564Sdim  // Various metadata supplied by the inferior's threading library to describe
52314564Sdim  // the per-thread state.
53314564Sdim  struct ThreadInfo {
54314564Sdim    bool valid;             // whether we read valid metadata
55314564Sdim    uint32_t dtv_offset;    // offset of DTV pointer within pthread
56314564Sdim    uint32_t dtv_slot_size; // size of one DTV slot
57314564Sdim    uint32_t modid_offset;  // offset of module ID within link_map
58314564Sdim    uint32_t tls_offset;    // offset of TLS pointer within DTV slot
59314564Sdim  };
60275072Semaste
61314564Sdim  HexagonDYLDRendezvous(lldb_private::Process *process);
62275072Semaste
63314564Sdim  /// Update the internal snapshot of runtime linker rendezvous and recompute
64314564Sdim  /// the currently loaded modules.
65314564Sdim  ///
66314564Sdim  /// This method should be called once one start up, then once each time the
67314564Sdim  /// runtime linker enters the function given by GetBreakAddress().
68314564Sdim  ///
69314564Sdim  /// @returns true on success and false on failure.
70314564Sdim  ///
71314564Sdim  /// @see GetBreakAddress().
72314564Sdim  bool Resolve();
73275072Semaste
74314564Sdim  /// @returns true if this rendezvous has been located in the inferiors
75314564Sdim  /// address space and false otherwise.
76314564Sdim  bool IsValid();
77275072Semaste
78314564Sdim  /// @returns the address of the rendezvous structure in the inferiors
79314564Sdim  /// address space.
80314564Sdim  lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }
81275072Semaste
82314564Sdim  /// Provide the dyld structure address
83314564Sdim  void SetRendezvousAddress(lldb::addr_t);
84275072Semaste
85314564Sdim  /// @returns the version of the rendezvous protocol being used.
86314564Sdim  uint64_t GetVersion() const { return m_current.version; }
87275072Semaste
88314564Sdim  /// @returns address in the inferiors address space containing the linked
89314564Sdim  /// list of shared object descriptors.
90314564Sdim  lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; }
91275072Semaste
92314564Sdim  /// A breakpoint should be set at this address and Resolve called on each
93314564Sdim  /// hit.
94314564Sdim  ///
95314564Sdim  /// @returns the address of a function called by the runtime linker each
96314564Sdim  /// time a module is loaded/unloaded, or about to be loaded/unloaded.
97314564Sdim  ///
98314564Sdim  /// @see Resolve()
99314564Sdim  lldb::addr_t GetBreakAddress() const { return m_current.brk; }
100275072Semaste
101314564Sdim  /// In hexagon it is possible that we can know the dyld breakpoint without
102314564Sdim  /// having to find it from the rendezvous structure
103314564Sdim  ///
104314564Sdim  void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; }
105275072Semaste
106314564Sdim  /// Returns the current state of the rendezvous structure.
107314564Sdim  uint64_t GetState() const { return m_current.state; }
108275072Semaste
109314564Sdim  /// @returns the base address of the runtime linker in the inferiors address
110314564Sdim  /// space.
111314564Sdim  lldb::addr_t GetLDBase() const { return m_current.ldbase; }
112275072Semaste
113314564Sdim  /// @returns the thread layout metadata from the inferiors thread library.
114314564Sdim  const ThreadInfo &GetThreadInfo();
115275072Semaste
116314564Sdim  /// @returns true if modules have been loaded into the inferior since the
117314564Sdim  /// last call to Resolve().
118314564Sdim  bool ModulesDidLoad() const { return !m_added_soentries.empty(); }
119275072Semaste
120314564Sdim  /// @returns true if modules have been unloaded from the inferior since the
121314564Sdim  /// last call to Resolve().
122314564Sdim  bool ModulesDidUnload() const { return !m_removed_soentries.empty(); }
123275072Semaste
124314564Sdim  void DumpToLog(lldb_private::Log *log) const;
125275072Semaste
126341825Sdim  /// Constants describing the state of the rendezvous.
127314564Sdim  ///
128314564Sdim  /// @see GetState().
129314564Sdim  enum RendezvousState {
130314564Sdim    eConsistent = 0,
131314564Sdim    eAdd,
132314564Sdim    eDelete,
133314564Sdim  };
134275072Semaste
135341825Sdim  /// Structure representing the shared objects currently loaded into the
136341825Sdim  /// inferior process.
137314564Sdim  ///
138314564Sdim  /// This object is a rough analogue to the struct link_map object which
139314564Sdim  /// actually lives in the inferiors memory.
140314564Sdim  struct SOEntry {
141314564Sdim    lldb::addr_t link_addr; ///< Address of this link_map.
142314564Sdim    lldb::addr_t base_addr; ///< Base address of the loaded object.
143314564Sdim    lldb::addr_t path_addr; ///< String naming the shared object.
144314564Sdim    lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
145314564Sdim    lldb::addr_t next;      ///< Address of next so_entry.
146314564Sdim    lldb::addr_t prev;      ///< Address of previous so_entry.
147314564Sdim    std::string path;       ///< File name of shared object.
148275072Semaste
149314564Sdim    SOEntry() { clear(); }
150275072Semaste
151314564Sdim    bool operator==(const SOEntry &entry) { return this->path == entry.path; }
152275072Semaste
153314564Sdim    void clear() {
154314564Sdim      link_addr = 0;
155314564Sdim      base_addr = 0;
156314564Sdim      path_addr = 0;
157314564Sdim      dyn_addr = 0;
158314564Sdim      next = 0;
159314564Sdim      prev = 0;
160314564Sdim      path.clear();
161314564Sdim    }
162314564Sdim  };
163314564Sdim
164275072Semasteprotected:
165314564Sdim  typedef std::list<SOEntry> SOEntryList;
166275072Semaste
167275072Semastepublic:
168314564Sdim  typedef SOEntryList::const_iterator iterator;
169275072Semaste
170314564Sdim  /// Iterators over all currently loaded modules.
171314564Sdim  iterator begin() const { return m_soentries.begin(); }
172314564Sdim  iterator end() const { return m_soentries.end(); }
173275072Semaste
174314564Sdim  /// Iterators over all modules loaded into the inferior since the last call
175314564Sdim  /// to Resolve().
176314564Sdim  iterator loaded_begin() const { return m_added_soentries.begin(); }
177314564Sdim  iterator loaded_end() const { return m_added_soentries.end(); }
178275072Semaste
179314564Sdim  /// Iterators over all modules unloaded from the inferior since the last
180314564Sdim  /// call to Resolve().
181314564Sdim  iterator unloaded_begin() const { return m_removed_soentries.begin(); }
182314564Sdim  iterator unloaded_end() const { return m_removed_soentries.end(); }
183314564Sdim
184275072Semasteprotected:
185314564Sdim  lldb_private::Process *m_process;
186275072Semaste
187314564Sdim  // Cached copy of executable pathname
188314564Sdim  char m_exe_path[PATH_MAX];
189275072Semaste
190314564Sdim  /// Location of the r_debug structure in the inferiors address space.
191314564Sdim  lldb::addr_t m_rendezvous_addr;
192275072Semaste
193314564Sdim  /// Current and previous snapshots of the rendezvous structure.
194314564Sdim  Rendezvous m_current;
195314564Sdim  Rendezvous m_previous;
196275072Semaste
197314564Sdim  /// List of SOEntry objects corresponding to the current link map state.
198314564Sdim  SOEntryList m_soentries;
199275072Semaste
200341825Sdim  /// List of SOEntry's added to the link map since the last call to
201341825Sdim  /// Resolve().
202314564Sdim  SOEntryList m_added_soentries;
203275072Semaste
204314564Sdim  /// List of SOEntry's removed from the link map since the last call to
205314564Sdim  /// Resolve().
206314564Sdim  SOEntryList m_removed_soentries;
207275072Semaste
208314564Sdim  /// Threading metadata read from the inferior.
209314564Sdim  ThreadInfo m_thread_info;
210275072Semaste
211314564Sdim  /// Reads an unsigned integer of @p size bytes from the inferior's address
212314564Sdim  /// space starting at @p addr.
213314564Sdim  ///
214314564Sdim  /// @returns addr + size if the read was successful and false otherwise.
215314564Sdim  lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
216275072Semaste
217314564Sdim  /// Reads an address from the inferior's address space starting at @p addr.
218314564Sdim  ///
219314564Sdim  /// @returns addr + target address size if the read was successful and
220314564Sdim  /// 0 otherwise.
221314564Sdim  lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
222275072Semaste
223314564Sdim  /// Reads a null-terminated C string from the memory location starting at @p
224314564Sdim  /// addr.
225314564Sdim  std::string ReadStringFromMemory(lldb::addr_t addr);
226275072Semaste
227314564Sdim  /// Reads an SOEntry starting at @p addr.
228314564Sdim  bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
229275072Semaste
230314564Sdim  /// Updates the current set of SOEntries, the set of added entries, and the
231314564Sdim  /// set of removed entries.
232314564Sdim  bool UpdateSOEntries();
233275072Semaste
234314564Sdim  bool UpdateSOEntriesForAddition();
235275072Semaste
236314564Sdim  bool UpdateSOEntriesForDeletion();
237275072Semaste
238314564Sdim  /// Reads the current list of shared objects according to the link map
239314564Sdim  /// supplied by the runtime linker.
240314564Sdim  bool TakeSnapshot(SOEntryList &entry_list);
241275072Semaste
242314564Sdim  enum PThreadField { eSize, eNElem, eOffset };
243275072Semaste
244314564Sdim  bool FindMetadata(const char *name, PThreadField field, uint32_t &value);
245275072Semaste};
246275072Semaste
247275072Semaste#endif // liblldb_HexagonDYLDRendezvous_H_
248