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 
25 
26 class ThreadGDBRemote;
27 class ProcessGDBRemote;
28 class StringExtractor;
29 
30 class GDBRemoteDynamicRegisterInfo
31 {
32 public:
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 
44     ~GDBRemoteDynamicRegisterInfo ()
45     {
46     }
47 
48     void
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 = 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         m_regs.push_back (reg_info);
61         uint32_t set = GetRegisterSetIndexByName (set_name, true);
62         assert (set < m_sets.size());
63         assert (set < m_set_reg_nums.size());
64         assert (set < m_set_names.size());
65         m_set_reg_nums[set].push_back(reg_num);
66         size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
67         if (m_reg_data_byte_size < end_reg_offset)
68             m_reg_data_byte_size = end_reg_offset;
69     }
70 
71     void
72     Finalize ()
73     {
74         for (uint32_t set = 0; set < m_sets.size(); ++set)
75         {
76             assert (m_sets.size() == m_set_reg_nums.size());
77             m_sets[set].num_registers = m_set_reg_nums[set].size();
78             m_sets[set].registers = &m_set_reg_nums[set][0];
79         }
80     }
81 
82     size_t
83     GetNumRegisters() const
84     {
85         return m_regs.size();
86     }
87 
88     size_t
89     GetNumRegisterSets() const
90     {
91         return m_sets.size();
92     }
93 
94     size_t
95     GetRegisterDataByteSize() const
96     {
97         return m_reg_data_byte_size;
98     }
99 
100     const lldb_private::RegisterInfo *
101     GetRegisterInfoAtIndex (uint32_t i) const
102     {
103         if (i < m_regs.size())
104             return &m_regs[i];
105         return NULL;
106     }
107 
108     const lldb_private::RegisterSet *
109     GetRegisterSet (uint32_t i) const
110     {
111         if (i < m_sets.size())
112             return &m_sets[i];
113         return NULL;
114     }
115 
116     uint32_t
117     GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create)
118     {
119         name_collection::iterator pos, end = m_set_names.end();
120         for (pos = m_set_names.begin(); pos != end; ++pos)
121         {
122             if (*pos == set_name)
123                 return std::distance (m_set_names.begin(), pos);
124         }
125 
126         m_set_names.push_back(set_name);
127         m_set_reg_nums.resize(m_set_reg_nums.size()+1);
128         lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
129         m_sets.push_back (new_set);
130         return m_sets.size() - 1;
131     }
132 
133     uint32_t
134     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
135     {
136         reg_collection::const_iterator pos, end = m_regs.end();
137         for (pos = m_regs.begin(); pos != end; ++pos)
138         {
139             if (pos->kinds[kind] == num)
140                 return std::distance (m_regs.begin(), pos);
141         }
142 
143         return LLDB_INVALID_REGNUM;
144     }
145     void
146     Clear()
147     {
148         m_regs.clear();
149         m_sets.clear();
150         m_set_reg_nums.clear();
151         m_reg_names.clear();
152         m_reg_alt_names.clear();
153         m_set_names.clear();
154     }
155 
156     void
157     HardcodeARMRegisters();
158 
159 protected:
160     //------------------------------------------------------------------
161     // Classes that inherit from GDBRemoteRegisterContext can see and modify these
162     //------------------------------------------------------------------
163     typedef std::vector <lldb_private::RegisterInfo> reg_collection;
164     typedef std::vector <lldb_private::RegisterSet> set_collection;
165     typedef std::vector <uint32_t> reg_num_collection;
166     typedef std::vector <reg_num_collection> set_reg_num_collection;
167     typedef std::vector <lldb_private::ConstString> name_collection;
168 
169     reg_collection m_regs;
170     set_collection m_sets;
171     set_reg_num_collection m_set_reg_nums;
172     name_collection m_reg_names;
173     name_collection m_reg_alt_names;
174     name_collection m_set_names;
175     size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
176 };
177 
178 class GDBRemoteRegisterContext : public lldb_private::RegisterContext
179 {
180 public:
181     //------------------------------------------------------------------
182     // Constructors and Destructors
183     //------------------------------------------------------------------
184     GDBRemoteRegisterContext (ThreadGDBRemote &thread,
185                               uint32_t concrete_frame_idx,
186                               GDBRemoteDynamicRegisterInfo &reg_info,
187                               bool read_all_at_once);
188 
189     virtual
190     ~GDBRemoteRegisterContext ();
191 
192     //------------------------------------------------------------------
193     // Subclasses must override these functions
194     //------------------------------------------------------------------
195     virtual void
196     InvalidateAllRegisters ();
197 
198     virtual size_t
199     GetRegisterCount ();
200 
201     virtual const lldb_private::RegisterInfo *
202     GetRegisterInfoAtIndex (uint32_t reg);
203 
204     virtual size_t
205     GetRegisterSetCount ();
206 
207     virtual const lldb_private::RegisterSet *
208     GetRegisterSet (uint32_t reg_set);
209 
210     virtual bool
211     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
212 
213     virtual bool
214     WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
215 
216     virtual bool
217     ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
218 
219     virtual bool
220     WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
221 
222     virtual uint32_t
223     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
224 
225 protected:
226     friend class ThreadGDBRemote;
227 
228     bool
229     ReadRegisterBytes (const lldb_private::RegisterInfo *reg_info,
230                        lldb_private::DataExtractor &data);
231 
232     bool
233     WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info,
234                         lldb_private::DataExtractor &data,
235                         uint32_t data_offset);
236 
237     bool
238     PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
239 
240     void
241     SetAllRegisterValid (bool b);
242 
243     ProcessGDBRemote &
244     GetGDBProcess();
245 
246     ThreadGDBRemote &
247     GetGDBThread();
248 
249     GDBRemoteDynamicRegisterInfo &m_reg_info;
250     std::vector<bool> m_reg_valid;
251     lldb_private::DataExtractor m_reg_data;
252     bool m_read_all_at_once;
253 
254 private:
255     //------------------------------------------------------------------
256     // For GDBRemoteRegisterContext only
257     //------------------------------------------------------------------
258     DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
259 };
260 
261 #endif  // lldb_GDBRemoteRegisterContext_h_
262