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 user_id_t
86 SBValue::GetID()
87 {
88     if (m_opaque_sp)
89         return m_opaque_sp->GetID();
90     return LLDB_INVALID_UID;
91 }
92 
93 const char *
94 SBValue::GetName()
95 {
96 
97     const char *name = NULL;
98     if (m_opaque_sp)
99         name = m_opaque_sp->GetName().GetCString();
100 
101     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
102     if (log)
103     {
104         if (name)
105             log->Printf ("SBValue(%p)::GetName () => \"%s\"", m_opaque_sp.get(), name);
106         else
107             log->Printf ("SBValue(%p)::GetName () => NULL", m_opaque_sp.get(), name);
108     }
109 
110     return name;
111 }
112 
113 const char *
114 SBValue::GetTypeName ()
115 {
116     const char *name = NULL;
117     if (m_opaque_sp)
118         name = m_opaque_sp->GetTypeName().GetCString();
119     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
120     if (log)
121     {
122         if (name)
123             log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"", m_opaque_sp.get(), name);
124         else
125             log->Printf ("SBValue(%p)::GetTypeName () => NULL", m_opaque_sp.get());
126     }
127 
128     return name;
129 }
130 
131 size_t
132 SBValue::GetByteSize ()
133 {
134     size_t result = 0;
135 
136     if (m_opaque_sp)
137         result = m_opaque_sp->GetByteSize();
138 
139     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
140     if (log)
141         log->Printf ("SBValue(%p)::GetByteSize () => %zu", m_opaque_sp.get(), result);
142 
143     return result;
144 }
145 
146 bool
147 SBValue::IsInScope (const SBFrame &sb_frame)
148 {
149     return IsInScope();
150 }
151 
152 bool
153 SBValue::IsInScope ()
154 {
155     bool result = false;
156 
157     if (m_opaque_sp)
158     {
159         if (m_opaque_sp->GetUpdatePoint().GetTarget())
160         {
161             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
162             result = m_opaque_sp->IsInScope ();
163         }
164     }
165 
166     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
167     if (log)
168         log->Printf ("SBValue(%p)::IsInScope () => %i", m_opaque_sp.get(), result);
169 
170     return result;
171 }
172 
173 const char *
174 SBValue::GetValue (const SBFrame &sb_frame)
175 {
176     return GetValue();
177 }
178 
179 const char *
180 SBValue::GetValue ()
181 {
182     const char *cstr = NULL;
183     if (m_opaque_sp)
184     {
185         if (m_opaque_sp->GetUpdatePoint().GetTarget())
186         {
187             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
188             cstr = m_opaque_sp->GetValueAsCString ();
189         }
190     }
191     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
192     if (log)
193     {
194         if (cstr)
195             log->Printf ("SBValue(%p)::GetValue => \"%s\"", m_opaque_sp.get(), cstr);
196         else
197             log->Printf ("SBValue(%p)::GetValue => NULL", m_opaque_sp.get());
198     }
199 
200     return cstr;
201 }
202 
203 ValueType
204 SBValue::GetValueType ()
205 {
206     ValueType result = eValueTypeInvalid;
207     if (m_opaque_sp)
208         result = m_opaque_sp->GetValueType();
209     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
210     if (log)
211     {
212         switch (result)
213         {
214         case eValueTypeInvalid:         log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", m_opaque_sp.get()); break;
215         case eValueTypeVariableGlobal:  log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", m_opaque_sp.get()); break;
216         case eValueTypeVariableStatic:  log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", m_opaque_sp.get()); break;
217         case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", m_opaque_sp.get()); break;
218         case eValueTypeVariableLocal:   log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", m_opaque_sp.get()); break;
219         case eValueTypeRegister:        log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", m_opaque_sp.get()); break;
220         case eValueTypeRegisterSet:     log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", m_opaque_sp.get()); break;
221         case eValueTypeConstResult:     log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", m_opaque_sp.get()); break;
222         default:     log->Printf ("SBValue(%p)::GetValueType () => %i ???", m_opaque_sp.get(), result); break;
223         }
224     }
225     return result;
226 }
227 
228 const char *
229 SBValue::GetObjectDescription (const SBFrame &sb_frame)
230 {
231     return GetObjectDescription ();
232 }
233 
234 const char *
235 SBValue::GetObjectDescription ()
236 {
237     const char *cstr = NULL;
238     if (m_opaque_sp)
239     {
240         if (m_opaque_sp->GetUpdatePoint().GetTarget())
241         {
242             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
243             cstr = m_opaque_sp->GetObjectDescription ();
244         }
245     }
246     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
247     if (log)
248     {
249         if (cstr)
250             log->Printf ("SBValue(%p)::GetObjectDescription => \"%s\"", m_opaque_sp.get(), cstr);
251         else
252             log->Printf ("SBValue(%p)::GetObjectDescription => NULL", m_opaque_sp.get());
253     }
254     return cstr;
255 }
256 
257 bool
258 SBValue::GetValueDidChange (const SBFrame &sb_frame)
259 {
260     return GetValueDidChange ();
261 }
262 
263 bool
264 SBValue::GetValueDidChange ()
265 {
266     bool result = false;
267     if (m_opaque_sp)
268     {
269         if (m_opaque_sp->GetUpdatePoint().GetTarget())
270         {
271             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
272             result = m_opaque_sp->GetValueDidChange ();
273         }
274     }
275     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
276     if (log)
277         log->Printf ("SBValue(%p)::GetValueDidChange => %i", m_opaque_sp.get(), result);
278 
279     return result;
280 }
281 
282 const char *
283 SBValue::GetSummary (const SBFrame &sb_frame)
284 {
285     return GetSummary ();
286 }
287 
288 const char *
289 SBValue::GetSummary ()
290 {
291     const char *cstr = NULL;
292     if (m_opaque_sp)
293     {
294         if (m_opaque_sp->GetUpdatePoint().GetTarget())
295         {
296             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
297             cstr = m_opaque_sp->GetSummaryAsCString();
298         }
299     }
300     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
301     if (log)
302     {
303         if (cstr)
304             log->Printf ("SBValue(%p)::GetSummary => \"%s\"", m_opaque_sp.get(), cstr);
305         else
306             log->Printf ("SBValue(%p)::GetSummary => NULL", m_opaque_sp.get());
307     }
308     return cstr;
309 }
310 
311 const char *
312 SBValue::GetLocation (const SBFrame &sb_frame)
313 {
314     return GetLocation ();
315 }
316 
317 const char *
318 SBValue::GetLocation ()
319 {
320     const char *cstr = NULL;
321     if (m_opaque_sp)
322     {
323         if (m_opaque_sp->GetUpdatePoint().GetTarget())
324         {
325             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
326             cstr = m_opaque_sp->GetLocationAsCString();
327         }
328     }
329     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
330     if (log)
331     {
332         if (cstr)
333             log->Printf ("SBValue(%p)::GetSummary => \"%s\"", m_opaque_sp.get(), cstr);
334         else
335             log->Printf ("SBValue(%p)::GetSummary => NULL", m_opaque_sp.get());
336     }
337     return cstr;
338 }
339 
340 bool
341 SBValue::SetValueFromCString (const SBFrame &sb_frame, const char *value_str)
342 {
343     return SetValueFromCString (value_str);
344 }
345 
346 bool
347 SBValue::SetValueFromCString (const char *value_str)
348 {
349     bool success = false;
350     if (m_opaque_sp)
351     {
352         if (m_opaque_sp->GetUpdatePoint().GetTarget())
353         {
354             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
355             success = m_opaque_sp->SetValueFromCString (value_str);
356         }
357     }
358     return success;
359 }
360 
361 SBValue
362 SBValue::GetChildAtIndex (uint32_t idx)
363 {
364     if (m_opaque_sp)
365     {
366         lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue();
367         return GetChildAtIndex (idx, use_dynamic_value);
368     }
369     else
370         return GetChildAtIndex (idx, eNoDynamicValues);
371 }
372 
373 SBValue
374 SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic)
375 {
376     lldb::ValueObjectSP child_sp;
377 
378     if (m_opaque_sp)
379     {
380         if (m_opaque_sp->GetUpdatePoint().GetTarget())
381         {
382             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
383 
384             child_sp = m_opaque_sp->GetChildAtIndex (idx, true);
385             if (use_dynamic != lldb::eNoDynamicValues)
386             {
387                 if (child_sp)
388                 {
389                     lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue (use_dynamic);
390                     if (dynamic_sp)
391                         child_sp = dynamic_sp;
392                 }
393             }
394         }
395     }
396 
397     SBValue sb_value (child_sp);
398     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
399     if (log)
400         log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", m_opaque_sp.get(), idx, sb_value.get());
401 
402     return sb_value;
403 }
404 
405 uint32_t
406 SBValue::GetIndexOfChildWithName (const char *name)
407 {
408     uint32_t idx = UINT32_MAX;
409     if (m_opaque_sp)
410     {
411         if (m_opaque_sp->GetUpdatePoint().GetTarget())
412         {
413             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
414 
415             idx = m_opaque_sp->GetIndexOfChildWithName (ConstString(name));
416         }
417     }
418     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
419     if (log)
420     {
421         if (idx == UINT32_MAX)
422             log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => NOT FOUND", m_opaque_sp.get(), name, idx);
423         else
424             log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => %u", m_opaque_sp.get(), name, idx);
425     }
426     return idx;
427 }
428 
429 SBValue
430 SBValue::GetChildMemberWithName (const char *name)
431 {
432     if (m_opaque_sp)
433     {
434         lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue();
435         return GetChildMemberWithName (name, use_dynamic_value);
436     }
437     else
438         return GetChildMemberWithName (name, eNoDynamicValues);
439 }
440 
441 SBValue
442 SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic_value)
443 {
444     lldb::ValueObjectSP child_sp;
445     const ConstString str_name (name);
446 
447 
448     if (m_opaque_sp)
449     {
450         if (m_opaque_sp->GetUpdatePoint().GetTarget())
451         {
452             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
453             child_sp = m_opaque_sp->GetChildMemberWithName (str_name, true);
454             if (use_dynamic_value != lldb::eNoDynamicValues)
455             {
456                 if (child_sp)
457                 {
458                     lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue (use_dynamic_value);
459                     if (dynamic_sp)
460                         child_sp = dynamic_sp;
461                 }
462             }
463         }
464     }
465 
466     SBValue sb_value (child_sp);
467 
468     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
469     if (log)
470         log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", m_opaque_sp.get(), name, sb_value.get());
471 
472     return sb_value;
473 }
474 
475 
476 uint32_t
477 SBValue::GetNumChildren ()
478 {
479     uint32_t num_children = 0;
480 
481     if (m_opaque_sp)
482     {
483         if (m_opaque_sp->GetUpdatePoint().GetTarget())
484         {
485             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
486 
487             num_children = m_opaque_sp->GetNumChildren();
488         }
489     }
490 
491     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
492     if (log)
493         log->Printf ("SBValue(%p)::GetNumChildren () => %u", m_opaque_sp.get(), num_children);
494 
495     return num_children;
496 }
497 
498 
499 SBValue
500 SBValue::Dereference ()
501 {
502     SBValue sb_value;
503     if (m_opaque_sp)
504     {
505         if (m_opaque_sp->GetUpdatePoint().GetTarget())
506         {
507             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
508 
509             Error error;
510             sb_value = m_opaque_sp->Dereference (error);
511         }
512     }
513     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
514     if (log)
515         log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", m_opaque_sp.get(), sb_value.get());
516 
517     return sb_value;
518 }
519 
520 bool
521 SBValue::TypeIsPointerType ()
522 {
523     bool is_ptr_type = false;
524 
525     if (m_opaque_sp)
526     {
527         if (m_opaque_sp->GetUpdatePoint().GetTarget())
528         {
529             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
530 
531             is_ptr_type = m_opaque_sp->IsPointerType();
532         }
533     }
534 
535     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
536     if (log)
537         log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", m_opaque_sp.get(), is_ptr_type);
538 
539 
540     return is_ptr_type;
541 }
542 
543 void *
544 SBValue::GetOpaqueType()
545 {
546     if (m_opaque_sp)
547     {
548         if (m_opaque_sp->GetUpdatePoint().GetTarget())
549         {
550             Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
551 
552             return m_opaque_sp->GetClangType();
553         }
554     }
555     return NULL;
556 }
557 
558 // Mimic shared pointer...
559 lldb_private::ValueObject *
560 SBValue::get() const
561 {
562     return m_opaque_sp.get();
563 }
564 
565 lldb_private::ValueObject *
566 SBValue::operator->() const
567 {
568     return m_opaque_sp.get();
569 }
570 
571 lldb::ValueObjectSP &
572 SBValue::operator*()
573 {
574     return m_opaque_sp;
575 }
576 
577 const lldb::ValueObjectSP &
578 SBValue::operator*() const
579 {
580     return m_opaque_sp;
581 }
582 
583 bool
584 SBValue::GetExpressionPath (SBStream &description)
585 {
586     if (m_opaque_sp)
587     {
588         m_opaque_sp->GetExpressionPath (description.ref(), false);
589         return true;
590     }
591     return false;
592 }
593 
594 bool
595 SBValue::GetExpressionPath (SBStream &description, bool qualify_cxx_base_classes)
596 {
597     if (m_opaque_sp)
598     {
599         m_opaque_sp->GetExpressionPath (description.ref(), qualify_cxx_base_classes);
600         return true;
601     }
602     return false;
603 }
604 
605 bool
606 SBValue::GetDescription (SBStream &description)
607 {
608     if (m_opaque_sp)
609     {
610         uint32_t ptr_depth = 0;
611         uint32_t curr_depth = 0;
612         uint32_t max_depth = UINT32_MAX;
613         bool show_types = false;
614         bool show_location = false;
615         bool use_objc = false;
616         lldb::DynamicValueType use_dynamic = eNoDynamicValues;
617         bool scope_already_checked = false;
618         bool flat_output = false;
619         ValueObject::DumpValueObject (description.ref(),
620                                       m_opaque_sp.get(),
621                                       m_opaque_sp->GetName().GetCString(),
622                                       ptr_depth,
623                                       curr_depth,
624                                       max_depth,
625                                       show_types, show_location,
626                                       use_objc,
627                                       use_dynamic,
628                                       scope_already_checked,
629                                       flat_output);
630     }
631     else
632         description.Printf ("No value");
633 
634     return true;
635 }
636 
637 lldb::Format
638 SBValue::GetFormat () const
639 {
640     if (m_opaque_sp)
641         return m_opaque_sp->GetFormat();
642     return eFormatDefault;
643 }
644 
645 void
646 SBValue::SetFormat (lldb::Format format)
647 {
648     if (m_opaque_sp)
649         m_opaque_sp->SetFormat(format);
650 }
651 
652