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