1//===-- ValueObjectRegister.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
11#include "lldb/Core/ValueObjectRegister.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16// Project includes
17#include "lldb/Core/Module.h"
18#include "lldb/Symbol/ClangASTType.h"
19#include "lldb/Symbol/ClangASTContext.h"
20#include "lldb/Symbol/TypeList.h"
21#include "lldb/Target/ExecutionContext.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30#pragma mark ValueObjectRegisterContext
31
32ValueObjectRegisterContext::ValueObjectRegisterContext (ValueObject &parent, RegisterContextSP &reg_ctx) :
33    ValueObject (parent),
34    m_reg_ctx_sp (reg_ctx)
35{
36    assert (reg_ctx);
37    m_name.SetCString("Registers");
38    SetValueIsValid (true);
39}
40
41ValueObjectRegisterContext::~ValueObjectRegisterContext()
42{
43}
44
45ClangASTType
46ValueObjectRegisterContext::GetClangTypeImpl ()
47{
48    return ClangASTType();
49}
50
51ConstString
52ValueObjectRegisterContext::GetTypeName()
53{
54    return ConstString();
55}
56
57ConstString
58ValueObjectRegisterContext::GetQualifiedTypeName()
59{
60    return ConstString();
61}
62
63size_t
64ValueObjectRegisterContext::CalculateNumChildren()
65{
66    return m_reg_ctx_sp->GetRegisterSetCount();
67}
68
69uint64_t
70ValueObjectRegisterContext::GetByteSize()
71{
72    return 0;
73}
74
75bool
76ValueObjectRegisterContext::UpdateValue ()
77{
78    m_error.Clear();
79    ExecutionContext exe_ctx(GetExecutionContextRef());
80    StackFrame *frame = exe_ctx.GetFramePtr();
81    if (frame)
82        m_reg_ctx_sp = frame->GetRegisterContext();
83    else
84        m_reg_ctx_sp.reset();
85
86    if (m_reg_ctx_sp.get() == NULL)
87    {
88        SetValueIsValid (false);
89        m_error.SetErrorToGenericError();
90    }
91    else
92        SetValueIsValid (true);
93
94    return m_error.Success();
95}
96
97ValueObject *
98ValueObjectRegisterContext::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index)
99{
100    ValueObject *new_valobj = NULL;
101
102    const size_t num_children = GetNumChildren();
103    if (idx < num_children)
104    {
105        ExecutionContext exe_ctx(GetExecutionContextRef());
106        new_valobj = new ValueObjectRegisterSet(exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx);
107    }
108
109    return new_valobj;
110}
111
112
113#pragma mark -
114#pragma mark ValueObjectRegisterSet
115
116ValueObjectSP
117ValueObjectRegisterSet::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t set_idx)
118{
119    return (new ValueObjectRegisterSet (exe_scope, reg_ctx_sp, set_idx))->GetSP();
120}
121
122
123ValueObjectRegisterSet::ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx, uint32_t reg_set_idx) :
124    ValueObject (exe_scope),
125    m_reg_ctx_sp (reg_ctx),
126    m_reg_set (NULL),
127    m_reg_set_idx (reg_set_idx)
128{
129    assert (reg_ctx);
130    m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
131    if (m_reg_set)
132    {
133        m_name.SetCString (m_reg_set->name);
134    }
135}
136
137ValueObjectRegisterSet::~ValueObjectRegisterSet()
138{
139}
140
141ClangASTType
142ValueObjectRegisterSet::GetClangTypeImpl ()
143{
144    return ClangASTType();
145}
146
147ConstString
148ValueObjectRegisterSet::GetTypeName()
149{
150    return ConstString();
151}
152
153ConstString
154ValueObjectRegisterSet::GetQualifiedTypeName()
155{
156    return ConstString();
157}
158
159size_t
160ValueObjectRegisterSet::CalculateNumChildren()
161{
162    const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
163    if (reg_set)
164        return reg_set->num_registers;
165    return 0;
166}
167
168uint64_t
169ValueObjectRegisterSet::GetByteSize()
170{
171    return 0;
172}
173
174bool
175ValueObjectRegisterSet::UpdateValue ()
176{
177    m_error.Clear();
178    SetValueDidChange (false);
179    ExecutionContext exe_ctx(GetExecutionContextRef());
180    StackFrame *frame = exe_ctx.GetFramePtr();
181    if (frame == NULL)
182        m_reg_ctx_sp.reset();
183    else
184    {
185        m_reg_ctx_sp = frame->GetRegisterContext ();
186        if (m_reg_ctx_sp)
187        {
188            const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet (m_reg_set_idx);
189            if (reg_set == NULL)
190                m_reg_ctx_sp.reset();
191            else if (m_reg_set != reg_set)
192            {
193                SetValueDidChange (true);
194                m_name.SetCString(reg_set->name);
195            }
196        }
197    }
198    if (m_reg_ctx_sp)
199    {
200        SetValueIsValid (true);
201    }
202    else
203    {
204        SetValueIsValid (false);
205        m_error.SetErrorToGenericError ();
206        m_children.Clear();
207    }
208    return m_error.Success();
209}
210
211
212ValueObject *
213ValueObjectRegisterSet::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index)
214{
215    ValueObject *valobj = NULL;
216    if (m_reg_ctx_sp && m_reg_set)
217    {
218        const size_t num_children = GetNumChildren();
219        if (idx < num_children)
220            valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, m_reg_set->registers[idx]);
221    }
222    return valobj;
223}
224
225lldb::ValueObjectSP
226ValueObjectRegisterSet::GetChildMemberWithName (const ConstString &name, bool can_create)
227{
228    ValueObject *valobj = NULL;
229    if (m_reg_ctx_sp && m_reg_set)
230    {
231        const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString());
232        if (reg_info != NULL)
233            valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info->kinds[eRegisterKindLLDB]);
234    }
235    if (valobj)
236        return valobj->GetSP();
237    else
238        return ValueObjectSP();
239}
240
241size_t
242ValueObjectRegisterSet::GetIndexOfChildWithName (const ConstString &name)
243{
244    if (m_reg_ctx_sp && m_reg_set)
245    {
246        const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString());
247        if (reg_info != NULL)
248            return reg_info->kinds[eRegisterKindLLDB];
249    }
250    return UINT32_MAX;
251}
252
253#pragma mark -
254#pragma mark ValueObjectRegister
255
256void
257ValueObjectRegister::ConstructObject (uint32_t reg_num)
258{
259    const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex (reg_num);
260    if (reg_info)
261    {
262        m_reg_info = *reg_info;
263        if (reg_info->name)
264            m_name.SetCString(reg_info->name);
265        else if (reg_info->alt_name)
266            m_name.SetCString(reg_info->alt_name);
267    }
268}
269
270ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num) :
271    ValueObject (parent),
272    m_reg_ctx_sp (reg_ctx_sp),
273    m_reg_info (),
274    m_reg_value (),
275    m_type_name (),
276    m_clang_type ()
277{
278    assert (reg_ctx_sp.get());
279    ConstructObject(reg_num);
280}
281
282ValueObjectSP
283ValueObjectRegister::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num)
284{
285    return (new ValueObjectRegister (exe_scope, reg_ctx_sp, reg_num))->GetSP();
286}
287
288ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx, uint32_t reg_num) :
289    ValueObject (exe_scope),
290    m_reg_ctx_sp (reg_ctx),
291    m_reg_info (),
292    m_reg_value (),
293    m_type_name (),
294    m_clang_type ()
295{
296    assert (reg_ctx);
297    ConstructObject(reg_num);
298}
299
300ValueObjectRegister::~ValueObjectRegister()
301{
302}
303
304ClangASTType
305ValueObjectRegister::GetClangTypeImpl ()
306{
307    if (!m_clang_type.IsValid())
308    {
309        ExecutionContext exe_ctx (GetExecutionContextRef());
310        Target *target = exe_ctx.GetTargetPtr();
311        if (target)
312        {
313            Module *exe_module = target->GetExecutableModulePointer();
314            if (exe_module)
315            {
316                m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
317                                                                                                     m_reg_info.byte_size * 8);
318            }
319        }
320    }
321    return m_clang_type;
322}
323
324ConstString
325ValueObjectRegister::GetTypeName()
326{
327    if (m_type_name.IsEmpty())
328        m_type_name = GetClangType().GetConstTypeName ();
329    return m_type_name;
330}
331
332size_t
333ValueObjectRegister::CalculateNumChildren()
334{
335    return GetClangType().GetNumChildren(true);
336}
337
338uint64_t
339ValueObjectRegister::GetByteSize()
340{
341    return m_reg_info.byte_size;
342}
343
344bool
345ValueObjectRegister::UpdateValue ()
346{
347    m_error.Clear();
348    ExecutionContext exe_ctx(GetExecutionContextRef());
349    StackFrame *frame = exe_ctx.GetFramePtr();
350    if (frame == NULL)
351    {
352        m_reg_ctx_sp.reset();
353        m_reg_value.Clear();
354    }
355
356
357    if (m_reg_ctx_sp)
358    {
359        if (m_reg_ctx_sp->ReadRegister (&m_reg_info, m_reg_value))
360        {
361            if (m_reg_value.GetData (m_data))
362            {
363                Process *process = exe_ctx.GetProcessPtr();
364                if (process)
365                    m_data.SetAddressByteSize(process->GetAddressByteSize());
366                m_value.SetContext(Value::eContextTypeRegisterInfo, (void *)&m_reg_info);
367                m_value.SetValueType(Value::eValueTypeHostAddress);
368                m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
369                SetValueIsValid (true);
370                return true;
371            }
372        }
373    }
374
375    SetValueIsValid (false);
376    m_error.SetErrorToGenericError ();
377    return false;
378}
379
380bool
381ValueObjectRegister::SetValueFromCString (const char *value_str, Error& error)
382{
383    // The new value will be in the m_data.  Copy that into our register value.
384    error = m_reg_value.SetValueFromCString (&m_reg_info, value_str);
385    if (error.Success())
386    {
387        if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value))
388        {
389            SetNeedsUpdate();
390            return true;
391        }
392        else
393            return false;
394    }
395    else
396        return false;
397}
398
399bool
400ValueObjectRegister::SetData (DataExtractor &data, Error &error)
401{
402    error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
403    if (error.Success())
404    {
405        if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value))
406        {
407            SetNeedsUpdate();
408            return true;
409        }
410        else
411            return false;
412    }
413    else
414        return false;
415}
416
417bool
418ValueObjectRegister::ResolveValue (Scalar &scalar)
419{
420    if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything
421        return m_reg_value.GetScalarValue(scalar);
422    return false;
423}
424
425void
426ValueObjectRegister::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
427{
428    s.Printf("$%s", m_reg_info.name);
429}
430
431
432