1 //===-- GDBRemoteRegisterContext.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 lldb_GDBRemoteRegisterContext_h_
11 #define lldb_GDBRemoteRegisterContext_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <vector>
16 
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/lldb-private.h"
20 #include "lldb/lldb-enumerations.h"
21 #include "lldb/Core/ConstString.h"
22 #include "lldb/Core/DataExtractor.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "GDBRemoteCommunicationClient.h"
25 
26 class ThreadGDBRemote;
27 class ProcessGDBRemote;
28 class StringExtractor;
29 
30 class GDBRemoteDynamicRegisterInfo
31 {
32 public:
GDBRemoteDynamicRegisterInfo()33     GDBRemoteDynamicRegisterInfo () :
34         m_regs (),
35         m_sets (),
36         m_set_reg_nums (),
37         m_reg_names (),
38         m_reg_alt_names (),
39         m_set_names (),
40         m_reg_data_byte_size (0)
41     {
42     }
43 
~GDBRemoteDynamicRegisterInfo()44     ~GDBRemoteDynamicRegisterInfo ()
45     {
46     }
47 
48     void
AddRegister(lldb_private::RegisterInfo reg_info,lldb_private::ConstString & reg_name,lldb_private::ConstString & reg_alt_name,lldb_private::ConstString & set_name)49     AddRegister (lldb_private::RegisterInfo reg_info,
50                  lldb_private::ConstString &reg_name,
51                  lldb_private::ConstString &reg_alt_name,
52                  lldb_private::ConstString &set_name)
53     {
54         const uint32_t reg_num = (uint32_t)m_regs.size();
55         m_reg_names.push_back (reg_name);
56         m_reg_alt_names.push_back (reg_alt_name);
57         reg_info.name = reg_name.AsCString();
58         assert (reg_info.name);
59         reg_info.alt_name = reg_alt_name.AsCString(NULL);
60         uint32_t i;
61         if (reg_info.value_regs)
62         {
63             for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
64                 m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
65             m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
66             reg_info.value_regs = m_value_regs_map[reg_num].data();
67         }
68         if (reg_info.invalidate_regs)
69         {
70             for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
71                 m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
72             m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
73             reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
74         }
75         m_regs.push_back (reg_info);
76         uint32_t set = GetRegisterSetIndexByName (set_name);
77         assert (set < m_sets.size());
78         assert (set < m_set_reg_nums.size());
79         assert (set < m_set_names.size());
80         m_set_reg_nums[set].push_back(reg_num);
81         size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
82         if (m_reg_data_byte_size < end_reg_offset)
83             m_reg_data_byte_size = end_reg_offset;
84     }
85 
86     void
Finalize()87     Finalize ()
88     {
89         for (uint32_t set = 0; set < m_sets.size(); ++set)
90         {
91             assert (m_sets.size() == m_set_reg_nums.size());
92             m_sets[set].num_registers = m_set_reg_nums[set].size();
93             m_sets[set].registers = &m_set_reg_nums[set][0];
94         }
95     }
96 
97     size_t
GetNumRegisters()98     GetNumRegisters() const
99     {
100         return m_regs.size();
101     }
102 
103     size_t
GetNumRegisterSets()104     GetNumRegisterSets() const
105     {
106         return m_sets.size();
107     }
108 
109     size_t
GetRegisterDataByteSize()110     GetRegisterDataByteSize() const
111     {
112         return m_reg_data_byte_size;
113     }
114 
115     const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex(uint32_t i)116     GetRegisterInfoAtIndex (uint32_t i) const
117     {
118         if (i < m_regs.size())
119             return &m_regs[i];
120         return NULL;
121     }
122 
123     const lldb_private::RegisterSet *
GetRegisterSet(uint32_t i)124     GetRegisterSet (uint32_t i) const
125     {
126         if (i < m_sets.size())
127             return &m_sets[i];
128         return NULL;
129     }
130 
131     uint32_t
GetRegisterSetIndexByName(lldb_private::ConstString & set_name)132     GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
133     {
134         name_collection::iterator pos, end = m_set_names.end();
135         for (pos = m_set_names.begin(); pos != end; ++pos)
136         {
137             if (*pos == set_name)
138                 return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
139         }
140 
141         m_set_names.push_back(set_name);
142         m_set_reg_nums.resize(m_set_reg_nums.size()+1);
143         lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
144         m_sets.push_back (new_set);
145         return static_cast<uint32_t>(m_sets.size() - 1);
146     }
147 
148     uint32_t
ConvertRegisterKindToRegisterNumber(uint32_t kind,uint32_t num)149     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
150     {
151         reg_collection::const_iterator pos, end = m_regs.end();
152         for (pos = m_regs.begin(); pos != end; ++pos)
153         {
154             if (pos->kinds[kind] == num)
155                 return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
156         }
157 
158         return LLDB_INVALID_REGNUM;
159     }
160     void
Clear()161     Clear()
162     {
163         m_regs.clear();
164         m_sets.clear();
165         m_set_reg_nums.clear();
166         m_reg_names.clear();
167         m_reg_alt_names.clear();
168         m_set_names.clear();
169     }
170 
171     void
172     HardcodeARMRegisters(bool from_scratch);
173 
174 protected:
175     //------------------------------------------------------------------
176     // Classes that inherit from GDBRemoteRegisterContext can see and modify these
177     //------------------------------------------------------------------
178     typedef std::vector <lldb_private::RegisterInfo> reg_collection;
179     typedef std::vector <lldb_private::RegisterSet> set_collection;
180     typedef std::vector <uint32_t> reg_num_collection;
181     typedef std::vector <reg_num_collection> set_reg_num_collection;
182     typedef std::vector <lldb_private::ConstString> name_collection;
183     typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
184 
185     reg_collection m_regs;
186     set_collection m_sets;
187     set_reg_num_collection m_set_reg_nums;
188     name_collection m_reg_names;
189     name_collection m_reg_alt_names;
190     name_collection m_set_names;
191     reg_to_regs_map m_value_regs_map;
192     reg_to_regs_map m_invalidate_regs_map;
193     size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
194 };
195 
196 class GDBRemoteRegisterContext : public lldb_private::RegisterContext
197 {
198 public:
199     //------------------------------------------------------------------
200     // Constructors and Destructors
201     //------------------------------------------------------------------
202     GDBRemoteRegisterContext (ThreadGDBRemote &thread,
203                               uint32_t concrete_frame_idx,
204                               GDBRemoteDynamicRegisterInfo &reg_info,
205                               bool read_all_at_once);
206 
207     virtual
208     ~GDBRemoteRegisterContext ();
209 
210     //------------------------------------------------------------------
211     // Subclasses must override these functions
212     //------------------------------------------------------------------
213     virtual void
214     InvalidateAllRegisters ();
215 
216     virtual size_t
217     GetRegisterCount ();
218 
219     virtual const lldb_private::RegisterInfo *
220     GetRegisterInfoAtIndex (size_t reg);
221 
222     virtual size_t
223     GetRegisterSetCount ();
224 
225     virtual const lldb_private::RegisterSet *
226     GetRegisterSet (size_t reg_set);
227 
228     virtual bool
229     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
230 
231     virtual bool
232     WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
233 
234     virtual bool
235     ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
236 
237     virtual bool
238     WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
239 
240     virtual uint32_t
241     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
242 
243 protected:
244     friend class ThreadGDBRemote;
245 
246     bool
247     ReadRegisterBytes (const lldb_private::RegisterInfo *reg_info,
248                        lldb_private::DataExtractor &data);
249 
250     bool
251     WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info,
252                         lldb_private::DataExtractor &data,
253                         uint32_t data_offset);
254 
255     bool
256     PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
257 
258     void
259     SetAllRegisterValid (bool b);
260 
261     bool
GetRegisterIsValid(uint32_t reg)262     GetRegisterIsValid (uint32_t reg) const
263     {
264 #if defined (LLDB_CONFIGURATION_DEBUG)
265         assert (reg < m_reg_valid.size());
266 #endif
267         if (reg < m_reg_valid.size())
268             return m_reg_valid[reg];
269         return false;
270     }
271 
272     void
SetRegisterIsValid(const lldb_private::RegisterInfo * reg_info,bool valid)273     SetRegisterIsValid (const lldb_private::RegisterInfo *reg_info, bool valid)
274     {
275         if (reg_info)
276             return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid);
277     }
278 
279     void
SetRegisterIsValid(uint32_t reg,bool valid)280     SetRegisterIsValid (uint32_t reg, bool valid)
281     {
282 #if defined (LLDB_CONFIGURATION_DEBUG)
283         assert (reg < m_reg_valid.size());
284 #endif
285         if (reg < m_reg_valid.size())
286             m_reg_valid[reg] = valid;
287     }
288 
289     void
290     SyncThreadState(lldb_private::Process *process);  // Assumes the sequence mutex has already been acquired.
291 
292     GDBRemoteDynamicRegisterInfo &m_reg_info;
293     std::vector<bool> m_reg_valid;
294     lldb_private::DataExtractor m_reg_data;
295     bool m_read_all_at_once;
296 
297 private:
298     // Helper function for ReadRegisterBytes().
299     bool GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
300                                GDBRemoteCommunicationClient &gdb_comm);
301     // Helper function for WriteRegisterBytes().
302     bool SetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
303                                GDBRemoteCommunicationClient &gdb_comm);
304 
305     //------------------------------------------------------------------
306     // For GDBRemoteRegisterContext only
307     //------------------------------------------------------------------
308     DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
309 };
310 
311 #endif  // lldb_GDBRemoteRegisterContext_h_
312