1 //===-- RegisterContext.cpp -------------------------------------*- 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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/RegisterContext.h"
15 #include "lldb/Core/Scalar.h"
16 #include "lldb/Target/ExecutionContext.h"
17 #include "lldb/Target/StackFrame.h"
18 #include "lldb/Target/Thread.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 //----------------------------------------------------------------------
24 // RegisterContext constructor
25 //----------------------------------------------------------------------
26 RegisterContext::RegisterContext (Thread &thread, StackFrame *frame) :
27     m_thread (thread),
28     m_frame (frame)
29 {
30 }
31 
32 //----------------------------------------------------------------------
33 // Destructor
34 //----------------------------------------------------------------------
35 RegisterContext::~RegisterContext()
36 {
37 }
38 
39 const RegisterInfo *
40 RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx)
41 {
42     if (reg_name && reg_name[0])
43     {
44         const uint32_t num_registers = GetRegisterCount();
45         for (uint32_t reg = start_idx; reg < num_registers; ++reg)
46         {
47             const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
48 
49             if ((reg_info->name != NULL && ::strcasecmp (reg_info->name, reg_name) == 0) ||
50                 (reg_info->alt_name != NULL && ::strcasecmp (reg_info->alt_name, reg_name) == 0))
51             {
52                 return reg_info;
53             }
54         }
55     }
56     return NULL;
57 }
58 
59 const char *
60 RegisterContext::GetRegisterName (uint32_t reg)
61 {
62     const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
63     if (reg_info)
64         return reg_info->name;
65     return NULL;
66 }
67 
68 uint64_t
69 RegisterContext::GetPC(uint64_t fail_value)
70 {
71     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
72     return ReadRegisterAsUnsigned (reg, fail_value);
73 }
74 
75 bool
76 RegisterContext::SetPC(uint64_t pc)
77 {
78     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
79     bool success = WriteRegisterFromUnsigned (reg, pc);
80     if (success)
81     {
82         if (m_frame)
83             m_frame->ChangePC(pc);
84         else
85             m_thread.ClearStackFrames ();
86     }
87     return success;
88 }
89 
90 uint64_t
91 RegisterContext::GetSP(uint64_t fail_value)
92 {
93     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
94     return ReadRegisterAsUnsigned (reg, fail_value);
95 }
96 
97 bool
98 RegisterContext::SetSP(uint64_t sp)
99 {
100     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
101     return WriteRegisterFromUnsigned (reg, sp);
102 }
103 
104 uint64_t
105 RegisterContext::GetFP(uint64_t fail_value)
106 {
107     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
108     return ReadRegisterAsUnsigned (reg, fail_value);
109 }
110 
111 bool
112 RegisterContext::SetFP(uint64_t fp)
113 {
114     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
115     return WriteRegisterFromUnsigned (reg, fp);
116 }
117 
118 uint64_t
119 RegisterContext::GetReturnAddress (uint64_t fail_value)
120 {
121     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
122     return ReadRegisterAsUnsigned (reg, fail_value);
123 }
124 
125 uint64_t
126 RegisterContext::GetFlags (uint64_t fail_value)
127 {
128     uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
129     return ReadRegisterAsUnsigned (reg, fail_value);
130 }
131 
132 
133 uint64_t
134 RegisterContext::ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value)
135 {
136     if (reg != LLDB_INVALID_REGNUM)
137     {
138         Scalar value;
139         if (ReadRegisterValue (reg, value))
140             return value.GetRawBits64(fail_value);
141     }
142     return fail_value;
143 }
144 
145 bool
146 RegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval)
147 {
148     if (reg == LLDB_INVALID_REGNUM)
149         return false;
150     Scalar value(uval);
151     return WriteRegisterValue (reg, value);
152 }
153 
154 lldb::tid_t
155 RegisterContext::GetThreadID() const
156 {
157     return m_thread.GetID();
158 }
159 
160 uint32_t
161 RegisterContext::NumSupportedHardwareBreakpoints ()
162 {
163     return 0;
164 }
165 
166 uint32_t
167 RegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
168 {
169     return LLDB_INVALID_INDEX32;
170 }
171 
172 bool
173 RegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx)
174 {
175     return false;
176 }
177 
178 
179 uint32_t
180 RegisterContext::NumSupportedHardwareWatchpoints ()
181 {
182     return 0;
183 }
184 
185 uint32_t
186 RegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
187 {
188     return LLDB_INVALID_INDEX32;
189 }
190 
191 bool
192 RegisterContext::ClearHardwareWatchpoint (uint32_t hw_index)
193 {
194     return false;
195 }
196 
197 bool
198 RegisterContext::HardwareSingleStep (bool enable)
199 {
200     return false;
201 }
202 
203 Target *
204 RegisterContext::CalculateTarget ()
205 {
206     return m_thread.CalculateTarget();
207 }
208 
209 
210 Process *
211 RegisterContext::CalculateProcess ()
212 {
213     return m_thread.CalculateProcess ();
214 }
215 
216 Thread *
217 RegisterContext::CalculateThread ()
218 {
219     return &m_thread;
220 }
221 
222 StackFrame *
223 RegisterContext::CalculateStackFrame ()
224 {
225     return m_frame;
226 }
227 
228 void
229 RegisterContext::Calculate (ExecutionContext &exe_ctx)
230 {
231     if (m_frame)
232         m_frame->Calculate (exe_ctx);
233     else
234         m_thread.Calculate (exe_ctx);
235 }
236 
237 
238 
239