1 //===-- SBValue.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 #include "lldb/API/SBValue.h"
11 #include "lldb/API/SBStream.h"
12 
13 #include "lldb/Core/DataExtractor.h"
14 #include "lldb/Core/Log.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Core/StreamFile.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Symbol/Block.h"
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Symbol/Variable.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/StackFrame.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28 
29 #include "lldb/API/SBProcess.h"
30 #include "lldb/API/SBTarget.h"
31 #include "lldb/API/SBThread.h"
32 #include "lldb/API/SBFrame.h"
33 #include "lldb/API/SBDebugger.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 SBValue::SBValue () :
39     m_opaque_sp ()
40 {
41 }
42 
43 SBValue::SBValue (const lldb::ValueObjectSP &value_sp) :
44     m_opaque_sp (value_sp)
45 {
46 }
47 
48 SBValue::SBValue(const SBValue &rhs) :
49     m_opaque_sp (rhs.m_opaque_sp)
50 {
51 }
52 
53 const SBValue &
54 SBValue::operator = (const SBValue &rhs)
55 {
56     if (this != &rhs)
57         m_opaque_sp = rhs.m_opaque_sp;
58     return *this;
59 }
60 
61 SBValue::~SBValue()
62 {
63 }
64 
65 bool
66 SBValue::IsValid () const
67 {
68     // If this function ever changes to anything that does more than just
69     // check if the opaque shared pointer is non NULL, then we need to update
70     // all "if (m_opaque_sp)" code in this file.
71     return m_opaque_sp.get() != NULL;
72 }
73 
74 SBError
75 SBValue::GetError()
76 {
77     SBError sb_error;
78 
79     if (m_opaque_sp.get())
80         sb_error.SetError(m_opaque_sp->GetError());
81 
82     return sb_error;
83 }
84 
85 const char *
86 SBValue::GetName()
87 {
88 
89     const char *name = NULL;
90     if (m_opaque_sp)
91         name = m_opaque_sp->GetName().GetCString();
92 
93     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
94     if (log)
95     {
96         if (name)
97             log->Printf ("SBValue(%p)::GetName () => \"%s\"", m_opaque_sp.get(), name);
98         else
99             log->Printf ("SBValue(%p)::GetName () => NULL", m_opaque_sp.get(), name);
100     }
101 
102     return name;
103 }
104 
105 const char *
106 SBValue::GetTypeName ()
107 {
108     const char *name = NULL;
109     if (m_opaque_sp)
110         name = m_opaque_sp->GetTypeName().GetCString();
111     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
112     if (log)
113     {
114         if (name)
115             log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"", m_opaque_sp.get(), name);
116         else
117             log->Printf ("SBValue(%p)::GetTypeName () => NULL", m_opaque_sp.get());
118     }
119 
120     return name;
121 }
122 
123 size_t
124 SBValue::GetByteSize ()
125 {
126     size_t result = 0;
127 
128     if (m_opaque_sp)
129         result = m_opaque_sp->GetByteSize();
130 
131     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
132     if (log)
133         log->Printf ("SBValue(%p)::GetByteSize () => %zu", m_opaque_sp.get(), result);
134 
135     return result;
136 }
137 
138 bool
139 SBValue::IsInScope (const SBFrame &sb_frame)
140 {
141     bool result = false;
142 
143     if (m_opaque_sp)
144     {
145         StackFrame *frame = sb_frame.get();
146         if (frame)
147         {
148             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
149             result = m_opaque_sp->IsInScope (frame);
150         }
151     }
152 
153     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
154     if (log)
155         log->Printf ("SBValue(%p)::IsInScope () => %i", m_opaque_sp.get(), result);
156 
157     return result;
158 }
159 
160 const char *
161 SBValue::GetValue (const SBFrame &sb_frame)
162 {
163     const char *cstr = NULL;
164     if (m_opaque_sp)
165     {
166         StackFrame *frame = sb_frame.get();
167         if (frame)
168         {
169             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
170             cstr = m_opaque_sp->GetValueAsCString (frame);
171         }
172     }
173     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
174     if (log)
175     {
176         if (cstr)
177             log->Printf ("SBValue(%p)::GetValue (SBFrame(%p)) => \"%s\"", m_opaque_sp.get(), sb_frame.get(), cstr);
178         else
179             log->Printf ("SBValue(%p)::GetValue (SBFrame(%p)) => NULL", m_opaque_sp.get(), sb_frame.get());
180     }
181 
182     return cstr;
183 }
184 
185 ValueType
186 SBValue::GetValueType ()
187 {
188     ValueType result = eValueTypeInvalid;
189     if (m_opaque_sp)
190         result = m_opaque_sp->GetValueType();
191     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
192     if (log)
193     {
194         switch (result)
195         {
196         case eValueTypeInvalid:         log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", m_opaque_sp.get()); break;
197         case eValueTypeVariableGlobal:  log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", m_opaque_sp.get()); break;
198         case eValueTypeVariableStatic:  log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", m_opaque_sp.get()); break;
199         case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", m_opaque_sp.get()); break;
200         case eValueTypeVariableLocal:   log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", m_opaque_sp.get()); break;
201         case eValueTypeRegister:        log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", m_opaque_sp.get()); break;
202         case eValueTypeRegisterSet:     log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", m_opaque_sp.get()); break;
203         case eValueTypeConstResult:     log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", m_opaque_sp.get()); break;
204         default:     log->Printf ("SBValue(%p)::GetValueType () => %i ???", m_opaque_sp.get(), result); break;
205         }
206     }
207     return result;
208 }
209 
210 const char *
211 SBValue::GetObjectDescription (const SBFrame &sb_frame)
212 {
213     const char *cstr = NULL;
214     if ( m_opaque_sp)
215     {
216         StackFrame *frame = sb_frame.get();
217         if (frame)
218         {
219             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
220             cstr = m_opaque_sp->GetObjectDescription (frame);
221         }
222     }
223     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
224     if (log)
225     {
226         if (cstr)
227             log->Printf ("SBValue(%p)::GetObjectDescription (SBFrame(%p)) => \"%s\"", m_opaque_sp.get(), sb_frame.get(), cstr);
228         else
229             log->Printf ("SBValue(%p)::GetObjectDescription (SBFrame(%p)) => NULL", m_opaque_sp.get(), sb_frame.get());
230     }
231     return cstr;
232 }
233 
234 bool
235 SBValue::GetValueDidChange (const SBFrame &sb_frame)
236 {
237     bool result = false;
238     if (m_opaque_sp)
239     {
240         StackFrame *frame = sb_frame.get();
241         if (frame)
242         {
243             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
244             result = m_opaque_sp->GetValueDidChange (frame);
245         }
246     }
247     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
248     if (log)
249         log->Printf ("SBValue(%p)::GetValueDidChange (SBFrame(%p)) => %i", m_opaque_sp.get(), sb_frame.get(), result);
250 
251     return result;
252 }
253 
254 const char *
255 SBValue::GetSummary (const SBFrame &sb_frame)
256 {
257     const char *cstr = NULL;
258     if (m_opaque_sp)
259     {
260         StackFrame *frame = sb_frame.get();
261         if (frame)
262         {
263             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
264             cstr = m_opaque_sp->GetSummaryAsCString(frame);
265         }
266     }
267     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
268     if (log)
269     {
270         if (cstr)
271             log->Printf ("SBValue(%p)::GetSummary (SBFrame(%p)) => \"%s\"", m_opaque_sp.get(), sb_frame.get(), cstr);
272         else
273             log->Printf ("SBValue(%p)::GetSummary (SBFrame(%p)) => NULL", m_opaque_sp.get(), sb_frame.get());
274     }
275     return cstr;
276 }
277 
278 const char *
279 SBValue::GetLocation (const SBFrame &sb_frame)
280 {
281     const char *cstr = NULL;
282     if (m_opaque_sp)
283     {
284         StackFrame *frame = sb_frame.get();
285         if (frame)
286         {
287             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
288             cstr = m_opaque_sp->GetLocationAsCString(frame);
289         }
290     }
291     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
292     if (log)
293     {
294         if (cstr)
295             log->Printf ("SBValue(%p)::GetSummary (SBFrame(%p)) => \"%s\"", m_opaque_sp.get(), sb_frame.get(), cstr);
296         else
297             log->Printf ("SBValue(%p)::GetSummary (SBFrame(%p)) => NULL", m_opaque_sp.get(), sb_frame.get());
298     }
299     return cstr;
300 }
301 
302 bool
303 SBValue::SetValueFromCString (const SBFrame &sb_frame, const char *value_str)
304 {
305     bool success = false;
306     if (m_opaque_sp)
307     {
308         StackFrame *frame = sb_frame.get();
309         if (frame)
310         {
311             Mutex::Locker api_locker (frame->GetThread().GetProcess().GetTarget().GetAPIMutex());
312             success = m_opaque_sp->SetValueFromCString (frame, value_str);
313         }
314     }
315     return success;
316 }
317 
318 SBValue
319 SBValue::GetChildAtIndex (uint32_t idx)
320 {
321     lldb::ValueObjectSP child_sp;
322 
323     if (m_opaque_sp)
324     {
325         child_sp = m_opaque_sp->GetChildAtIndex (idx, true);
326     }
327 
328     SBValue sb_value (child_sp);
329     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
330     if (log)
331         log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", m_opaque_sp.get(), idx, sb_value.get());
332 
333     return sb_value;
334 }
335 
336 uint32_t
337 SBValue::GetIndexOfChildWithName (const char *name)
338 {
339     uint32_t idx = UINT32_MAX;
340     if (m_opaque_sp)
341         idx = m_opaque_sp->GetIndexOfChildWithName (ConstString(name));
342     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
343     if (log)
344     {
345         if (idx == UINT32_MAX)
346             log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => NOT FOUND", m_opaque_sp.get(), name, idx);
347         else
348             log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => %u", m_opaque_sp.get(), name, idx);
349     }
350     return idx;
351 }
352 
353 SBValue
354 SBValue::GetChildMemberWithName (const char *name)
355 {
356     lldb::ValueObjectSP child_sp;
357     const ConstString str_name (name);
358 
359     if (m_opaque_sp)
360     {
361         child_sp = m_opaque_sp->GetChildMemberWithName (str_name, true);
362     }
363 
364     SBValue sb_value (child_sp);
365 
366     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
367     if (log)
368         log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", m_opaque_sp.get(), name, sb_value.get());
369 
370     return sb_value;
371 }
372 
373 
374 uint32_t
375 SBValue::GetNumChildren ()
376 {
377     uint32_t num_children = 0;
378 
379     if (m_opaque_sp)
380         num_children = m_opaque_sp->GetNumChildren();
381 
382     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
383     if (log)
384         log->Printf ("SBValue(%p)::GetNumChildren () => %u", m_opaque_sp.get(), num_children);
385 
386     return num_children;
387 }
388 
389 
390 SBValue
391 SBValue::Dereference ()
392 {
393     SBValue sb_value;
394     if (m_opaque_sp)
395     {
396         Error error;
397         sb_value = m_opaque_sp->Dereference (error);
398     }
399     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
400     if (log)
401         log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", m_opaque_sp.get(), sb_value.get());
402 
403     return sb_value;
404 }
405 
406 bool
407 SBValue::TypeIsPointerType ()
408 {
409     bool is_ptr_type = false;
410 
411     if (m_opaque_sp)
412         is_ptr_type = m_opaque_sp->IsPointerType();
413 
414     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
415     if (log)
416         log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", m_opaque_sp.get(), is_ptr_type);
417 
418 
419     return is_ptr_type;
420 }
421 
422 void *
423 SBValue::GetOpaqueType()
424 {
425     if (m_opaque_sp)
426         return m_opaque_sp->GetClangType();
427     return NULL;
428 }
429 
430 // Mimic shared pointer...
431 lldb_private::ValueObject *
432 SBValue::get() const
433 {
434     return m_opaque_sp.get();
435 }
436 
437 lldb_private::ValueObject *
438 SBValue::operator->() const
439 {
440     return m_opaque_sp.get();
441 }
442 
443 lldb::ValueObjectSP &
444 SBValue::operator*()
445 {
446     return m_opaque_sp;
447 }
448 
449 const lldb::ValueObjectSP &
450 SBValue::operator*() const
451 {
452     return m_opaque_sp;
453 }
454 
455 bool
456 SBValue::GetExpressionPath (SBStream &description)
457 {
458     if (m_opaque_sp)
459     {
460         m_opaque_sp->GetExpressionPath (description.ref(), false);
461         return true;
462     }
463     return false;
464 }
465 
466 bool
467 SBValue::GetExpressionPath (SBStream &description, bool qualify_cxx_base_classes)
468 {
469     if (m_opaque_sp)
470     {
471         m_opaque_sp->GetExpressionPath (description.ref(), qualify_cxx_base_classes);
472         return true;
473     }
474     return false;
475 }
476 
477 bool
478 SBValue::GetDescription (SBStream &description)
479 {
480     if (m_opaque_sp)
481     {
482         // Don't call all these APIs and cause more logging!
483 //        const char *name = GetName();
484 //        const char *type_name = GetTypeName ();
485 //        size_t byte_size = GetByteSize ();
486 //        uint32_t num_children = GetNumChildren ();
487 //        bool is_stale = ValueIsStale ();
488 //        description.Printf ("name: '%s', type: %s, size: %d", (name != NULL ? name : "<unknown name>"),
489 //                            (type_name != NULL ? type_name : "<unknown type name>"), (int) byte_size);
490 //        if (num_children > 0)
491 //            description.Printf (", num_children: %d", num_children);
492 //
493 //        if (is_stale)
494 //            description.Printf (" [value is stale]");
495 
496         description.Printf ("name: '%s'", m_opaque_sp->GetName().GetCString());
497     }
498     else
499         description.Printf ("No value");
500 
501     return true;
502 }
503 
504 lldb::Format
505 SBValue::GetFormat () const
506 {
507     if (m_opaque_sp)
508         return m_opaque_sp->GetFormat();
509     return eFormatDefault;
510 }
511 
512 void
513 SBValue::SetFormat (lldb::Format format)
514 {
515     if (m_opaque_sp)
516         m_opaque_sp->SetFormat(format);
517 }
518 
519