blob: bd613ba7b2cf934f313c3d0c40d2af832dd7e4fb [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ValueObject.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/Core/ValueObject.h"
11
12// C Includes
Greg Claytonf5e56de2010-09-14 23:36:40 +000013#include <stdlib.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "llvm/Support/raw_ostream.h"
Jim Ingham5a369122010-09-28 01:25:32 +000018#include "clang/AST/Type.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019
20// Project includes
21#include "lldb/Core/DataBufferHeap.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Core/ValueObjectChild.h"
24#include "lldb/Core/ValueObjectList.h"
25
Greg Claytone1a916a2010-07-21 22:12:05 +000026#include "lldb/Symbol/ClangASTType.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Symbol/ClangASTContext.h"
28#include "lldb/Symbol/Type.h"
29
Jim Ingham53c47f12010-09-10 23:12:17 +000030#include "lldb/Target/ExecutionContext.h"
Jim Ingham5a369122010-09-28 01:25:32 +000031#include "lldb/Target/LanguageRuntime.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032#include "lldb/Target/Process.h"
33#include "lldb/Target/RegisterContext.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000034#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
37using namespace lldb;
38using namespace lldb_private;
39
40static lldb::user_id_t g_value_obj_uid = 0;
41
42//----------------------------------------------------------------------
43// ValueObject constructor
44//----------------------------------------------------------------------
45ValueObject::ValueObject () :
46 UserID (++g_value_obj_uid), // Unique identifier for every value object
47 m_update_id (0), // Value object lists always start at 1, value objects start at zero
48 m_name (),
49 m_data (),
50 m_value (),
51 m_error (),
Greg Clayton288bdf92010-09-02 02:59:18 +000052 m_value_str (),
53 m_old_value_str (),
54 m_location_str (),
55 m_summary_str (),
Jim Ingham53c47f12010-09-10 23:12:17 +000056 m_object_desc_str (),
Greg Clayton288bdf92010-09-02 02:59:18 +000057 m_children (),
58 m_synthetic_children (),
Greg Clayton32c40852010-10-06 03:09:11 +000059 m_dynamic_value_sp (),
60 m_format (eFormatDefault),
Greg Clayton288bdf92010-09-02 02:59:18 +000061 m_value_is_valid (false),
62 m_value_did_change (false),
63 m_children_count_valid (false),
64 m_old_value_valid (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065{
66}
67
68//----------------------------------------------------------------------
69// Destructor
70//----------------------------------------------------------------------
71ValueObject::~ValueObject ()
72{
73}
74
75user_id_t
76ValueObject::GetUpdateID() const
77{
78 return m_update_id;
79}
80
81bool
82ValueObject::UpdateValueIfNeeded (ExecutionContextScope *exe_scope)
83{
Greg Claytonb71f3842010-10-05 03:13:51 +000084 // If this is a constant value, then our success is predicated on whether
85 // we have an error or not
86 if (GetIsConstant())
87 return m_error.Success();
88
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089 if (exe_scope)
90 {
91 Process *process = exe_scope->CalculateProcess();
92 if (process)
93 {
94 const user_id_t stop_id = process->GetStopID();
95 if (m_update_id != stop_id)
96 {
Greg Clayton288bdf92010-09-02 02:59:18 +000097 bool first_update = m_update_id == 0;
Greg Clayton73b953b2010-08-28 00:08:07 +000098 // Save the old value using swap to avoid a string copy which
99 // also will clear our m_value_str
Greg Clayton288bdf92010-09-02 02:59:18 +0000100 if (m_value_str.empty())
101 {
102 m_old_value_valid = false;
103 }
104 else
105 {
106 m_old_value_valid = true;
107 m_old_value_str.swap (m_value_str);
108 m_value_str.clear();
109 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110 m_location_str.clear();
111 m_summary_str.clear();
Jim Ingham53c47f12010-09-10 23:12:17 +0000112 m_object_desc_str.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113
Greg Clayton73b953b2010-08-28 00:08:07 +0000114 const bool value_was_valid = GetValueIsValid();
115 SetValueDidChange (false);
116
117 m_error.Clear();
118
119 // Call the pure virtual function to update the value
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120 UpdateValue (exe_scope);
Greg Clayton73b953b2010-08-28 00:08:07 +0000121
122 // Update the fact that we tried to update the value for this
Greg Claytoned8a7052010-09-18 03:37:20 +0000123 // value object whether or not we succeed
Greg Clayton73b953b2010-08-28 00:08:07 +0000124 m_update_id = stop_id;
125 bool success = m_error.Success();
126 SetValueIsValid (success);
Greg Clayton288bdf92010-09-02 02:59:18 +0000127
128 if (first_update)
129 SetValueDidChange (false);
130 else if (!m_value_did_change && success == false)
Greg Clayton73b953b2010-08-28 00:08:07 +0000131 {
Greg Clayton288bdf92010-09-02 02:59:18 +0000132 // The value wasn't gotten successfully, so we mark this
133 // as changed if the value used to be valid and now isn't
134 SetValueDidChange (value_was_valid);
Greg Clayton73b953b2010-08-28 00:08:07 +0000135 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136 }
137 }
138 }
139 return m_error.Success();
140}
141
142const DataExtractor &
143ValueObject::GetDataExtractor () const
144{
145 return m_data;
146}
147
148DataExtractor &
149ValueObject::GetDataExtractor ()
150{
151 return m_data;
152}
153
154const Error &
155ValueObject::GetError() const
156{
157 return m_error;
158}
159
160const ConstString &
161ValueObject::GetName() const
162{
163 return m_name;
164}
165
166const char *
167ValueObject::GetLocationAsCString (ExecutionContextScope *exe_scope)
168{
169 if (UpdateValueIfNeeded(exe_scope))
170 {
171 if (m_location_str.empty())
172 {
173 StreamString sstr;
174
175 switch (m_value.GetValueType())
176 {
177 default:
178 break;
179
180 case Value::eValueTypeScalar:
181 if (m_value.GetContextType() == Value::eContextTypeDCRegisterInfo)
182 {
183 RegisterInfo *reg_info = m_value.GetRegisterInfo();
184 if (reg_info)
185 {
186 if (reg_info->name)
187 m_location_str = reg_info->name;
188 else if (reg_info->alt_name)
189 m_location_str = reg_info->alt_name;
190 break;
191 }
192 }
193 m_location_str = "scalar";
194 break;
195
196 case Value::eValueTypeLoadAddress:
197 case Value::eValueTypeFileAddress:
198 case Value::eValueTypeHostAddress:
199 {
200 uint32_t addr_nibble_size = m_data.GetAddressByteSize() * 2;
201 sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
202 m_location_str.swap(sstr.GetString());
203 }
204 break;
205 }
206 }
207 }
208 return m_location_str.c_str();
209}
210
211Value &
212ValueObject::GetValue()
213{
214 return m_value;
215}
216
217const Value &
218ValueObject::GetValue() const
219{
220 return m_value;
221}
222
223bool
Greg Clayton288bdf92010-09-02 02:59:18 +0000224ValueObject::GetValueIsValid () const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225{
Greg Clayton288bdf92010-09-02 02:59:18 +0000226 return m_value_is_valid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227}
228
229
230void
231ValueObject::SetValueIsValid (bool b)
232{
Greg Clayton288bdf92010-09-02 02:59:18 +0000233 m_value_is_valid = b;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000234}
235
236bool
Greg Clayton288bdf92010-09-02 02:59:18 +0000237ValueObject::GetValueDidChange (ExecutionContextScope *exe_scope)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238{
Greg Clayton288bdf92010-09-02 02:59:18 +0000239 GetValueAsCString (exe_scope);
240 return m_value_did_change;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241}
242
243void
244ValueObject::SetValueDidChange (bool value_changed)
245{
Greg Clayton288bdf92010-09-02 02:59:18 +0000246 m_value_did_change = value_changed;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247}
248
249ValueObjectSP
250ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
251{
252 ValueObjectSP child_sp;
253 if (idx < GetNumChildren())
254 {
255 // Check if we have already made the child value object?
256 if (can_create && m_children[idx].get() == NULL)
257 {
258 // No we haven't created the child at this index, so lets have our
259 // subclass do it and cache the result for quick future access.
260 m_children[idx] = CreateChildAtIndex (idx, false, 0);
261 }
262
263 child_sp = m_children[idx];
264 }
265 return child_sp;
266}
267
268uint32_t
269ValueObject::GetIndexOfChildWithName (const ConstString &name)
270{
271 bool omit_empty_base_classes = true;
272 return ClangASTContext::GetIndexOfChildWithName (GetClangAST(),
Greg Clayton1be10fc2010-09-29 01:12:09 +0000273 GetClangType(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000274 name.AsCString(),
275 omit_empty_base_classes);
276}
277
278ValueObjectSP
279ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
280{
281 // when getting a child by name, it could be burried inside some base
282 // classes (which really aren't part of the expression path), so we
283 // need a vector of indexes that can get us down to the correct child
284 std::vector<uint32_t> child_indexes;
285 clang::ASTContext *clang_ast = GetClangAST();
Greg Clayton1be10fc2010-09-29 01:12:09 +0000286 void *clang_type = GetClangType();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000287 bool omit_empty_base_classes = true;
288 const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
289 clang_type,
290 name.AsCString(),
291 omit_empty_base_classes,
292 child_indexes);
293 ValueObjectSP child_sp;
294 if (num_child_indexes > 0)
295 {
296 std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
297 std::vector<uint32_t>::const_iterator end = child_indexes.end ();
298
299 child_sp = GetChildAtIndex(*pos, can_create);
300 for (++pos; pos != end; ++pos)
301 {
302 if (child_sp)
303 {
304 ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
305 child_sp = new_child_sp;
306 }
307 else
308 {
309 child_sp.reset();
310 }
311
312 }
313 }
314 return child_sp;
315}
316
317
318uint32_t
319ValueObject::GetNumChildren ()
320{
Greg Clayton288bdf92010-09-02 02:59:18 +0000321 if (!m_children_count_valid)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 {
323 SetNumChildren (CalculateNumChildren());
324 }
325 return m_children.size();
326}
327void
328ValueObject::SetNumChildren (uint32_t num_children)
329{
Greg Clayton288bdf92010-09-02 02:59:18 +0000330 m_children_count_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331 m_children.resize(num_children);
332}
333
334void
335ValueObject::SetName (const char *name)
336{
337 m_name.SetCString(name);
338}
339
340void
341ValueObject::SetName (const ConstString &name)
342{
343 m_name = name;
344}
345
346ValueObjectSP
347ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
348{
349 ValueObjectSP valobj_sp;
350 bool omit_empty_base_classes = true;
351
352 std::string child_name_str;
353 uint32_t child_byte_size = 0;
354 int32_t child_byte_offset = 0;
355 uint32_t child_bitfield_bit_size = 0;
356 uint32_t child_bitfield_bit_offset = 0;
357 const bool transparent_pointers = synthetic_array_member == false;
358 clang::ASTContext *clang_ast = GetClangAST();
Greg Clayton1be10fc2010-09-29 01:12:09 +0000359 void *clang_type = GetClangType();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 void *child_clang_type;
361 child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast,
362 GetName().AsCString(),
363 clang_type,
364 idx,
365 transparent_pointers,
366 omit_empty_base_classes,
367 child_name_str,
368 child_byte_size,
369 child_byte_offset,
370 child_bitfield_bit_size,
371 child_bitfield_bit_offset);
372 if (child_clang_type)
373 {
374 if (synthetic_index)
375 child_byte_offset += child_byte_size * synthetic_index;
376
377 ConstString child_name;
378 if (!child_name_str.empty())
379 child_name.SetCString (child_name_str.c_str());
380
381 valobj_sp.reset (new ValueObjectChild (this,
382 clang_ast,
383 child_clang_type,
384 child_name,
385 child_byte_size,
386 child_byte_offset,
387 child_bitfield_bit_size,
388 child_bitfield_bit_offset));
389 }
390 return valobj_sp;
391}
392
393const char *
394ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope)
395{
396 if (UpdateValueIfNeeded (exe_scope))
397 {
398 if (m_summary_str.empty())
399 {
Greg Clayton1be10fc2010-09-29 01:12:09 +0000400 void *clang_type = GetClangType();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401
402 // See if this is a pointer to a C string?
403 uint32_t fixed_length = 0;
Greg Clayton737b9322010-09-13 03:32:57 +0000404 if (clang_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405 {
Greg Clayton737b9322010-09-13 03:32:57 +0000406 StreamString sstr;
407
408 if (ClangASTContext::IsCStringType (clang_type, fixed_length))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 {
Greg Clayton737b9322010-09-13 03:32:57 +0000410 Process *process = exe_scope->CalculateProcess();
411 if (process != NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412 {
Greg Clayton737b9322010-09-13 03:32:57 +0000413 lldb::AddressType cstr_address_type = eAddressTypeInvalid;
414 lldb::addr_t cstr_address = GetPointerValue (cstr_address_type, true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415
Greg Clayton737b9322010-09-13 03:32:57 +0000416 if (cstr_address != LLDB_INVALID_ADDRESS)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000417 {
Greg Clayton737b9322010-09-13 03:32:57 +0000418 DataExtractor data;
419 size_t bytes_read = 0;
420 std::vector<char> data_buffer;
421 std::vector<char> cstr_buffer;
422 size_t cstr_length;
423 Error error;
424 if (fixed_length > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000425 {
Greg Clayton737b9322010-09-13 03:32:57 +0000426 data_buffer.resize(fixed_length);
427 // Resize the formatted buffer in case every character
428 // uses the "\xXX" format and one extra byte for a NULL
429 cstr_buffer.resize(data_buffer.size() * 4 + 1);
430 data.SetData (&data_buffer.front(), data_buffer.size(), eByteOrderHost);
431 bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), fixed_length, error);
432 if (bytes_read > 0)
433 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000434 sstr << '"';
Greg Clayton737b9322010-09-13 03:32:57 +0000435 cstr_length = data.Dump (&sstr,
436 0, // Start offset in "data"
437 eFormatChar, // Print as characters
438 1, // Size of item (1 byte for a char!)
439 bytes_read, // How many bytes to print?
440 UINT32_MAX, // num per line
441 LLDB_INVALID_ADDRESS,// base address
442 0, // bitfield bit size
443 0); // bitfield bit offset
444 sstr << '"';
445 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000446 }
Greg Clayton737b9322010-09-13 03:32:57 +0000447 else
448 {
449 const size_t k_max_buf_size = 256;
450 data_buffer.resize (k_max_buf_size + 1);
451 // NULL terminate in case we don't get the entire C string
452 data_buffer.back() = '\0';
453 // Make a formatted buffer that can contain take 4
454 // bytes per character in case each byte uses the
455 // "\xXX" format and one extra byte for a NULL
456 cstr_buffer.resize (k_max_buf_size * 4 + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000457
Greg Clayton737b9322010-09-13 03:32:57 +0000458 data.SetData (&data_buffer.front(), data_buffer.size(), eByteOrderHost);
459 size_t total_cstr_len = 0;
460 while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0)
461 {
462 size_t len = strlen(&data_buffer.front());
463 if (len == 0)
464 break;
465 if (len > bytes_read)
466 len = bytes_read;
467 if (sstr.GetSize() == 0)
468 sstr << '"';
469
470 cstr_length = data.Dump (&sstr,
471 0, // Start offset in "data"
472 eFormatChar, // Print as characters
473 1, // Size of item (1 byte for a char!)
474 len, // How many bytes to print?
475 UINT32_MAX, // num per line
476 LLDB_INVALID_ADDRESS,// base address
477 0, // bitfield bit size
478 0); // bitfield bit offset
479
480 if (len < k_max_buf_size)
481 break;
482 cstr_address += total_cstr_len;
483 }
484 if (sstr.GetSize() > 0)
485 sstr << '"';
486 }
487 }
488 }
489
490 if (sstr.GetSize() > 0)
491 m_summary_str.assign (sstr.GetData(), sstr.GetSize());
492 }
493 else if (ClangASTContext::IsFunctionPointerType (clang_type))
494 {
495 lldb::AddressType func_ptr_address_type = eAddressTypeInvalid;
496 lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true);
497
498 if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
499 {
500 switch (func_ptr_address_type)
501 {
502 case eAddressTypeInvalid:
503 case eAddressTypeFile:
504 break;
505
506 case eAddressTypeLoad:
507 {
508 Address so_addr;
Greg Claytonf5e56de2010-09-14 23:36:40 +0000509 Target *target = exe_scope->CalculateTarget();
510 if (target && target->GetSectionLoadList().IsEmpty() == false)
Greg Clayton737b9322010-09-13 03:32:57 +0000511 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000512 if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
Greg Clayton737b9322010-09-13 03:32:57 +0000513 {
514 so_addr.Dump (&sstr,
515 exe_scope,
516 Address::DumpStyleResolvedDescription,
517 Address::DumpStyleSectionNameOffset);
518 }
519 }
520 }
521 break;
522
523 case eAddressTypeHost:
524 break;
525 }
526 }
527 if (sstr.GetSize() > 0)
528 {
529 m_summary_str.assign (1, '(');
530 m_summary_str.append (sstr.GetData(), sstr.GetSize());
531 m_summary_str.append (1, ')');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000532 }
533 }
534 }
535 }
536 }
537 if (m_summary_str.empty())
538 return NULL;
539 return m_summary_str.c_str();
540}
541
Jim Ingham53c47f12010-09-10 23:12:17 +0000542const char *
543ValueObject::GetObjectDescription (ExecutionContextScope *exe_scope)
544{
545 if (!m_object_desc_str.empty())
546 return m_object_desc_str.c_str();
547
Jim Ingham53c47f12010-09-10 23:12:17 +0000548 if (!GetValueIsValid())
549 return NULL;
550
551 Process *process = exe_scope->CalculateProcess();
Jim Ingham5a369122010-09-28 01:25:32 +0000552 if (process == NULL)
Jim Ingham53c47f12010-09-10 23:12:17 +0000553 return NULL;
Jim Ingham5a369122010-09-28 01:25:32 +0000554
Jim Ingham53c47f12010-09-10 23:12:17 +0000555 StreamString s;
Jim Ingham5a369122010-09-28 01:25:32 +0000556
557 lldb::LanguageType language = GetObjectRuntimeLanguage();
558 LanguageRuntime *runtime = process->GetLanguageRuntime(language);
559
560 if (runtime && runtime->GetObjectDescription(s, *this, exe_scope))
Jim Ingham53c47f12010-09-10 23:12:17 +0000561 {
562 m_object_desc_str.append (s.GetData());
563 }
564 return m_object_desc_str.c_str();
565}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000566
567const char *
568ValueObject::GetValueAsCString (ExecutionContextScope *exe_scope)
569{
570 // If our byte size is zero this is an aggregate type that has children
Greg Clayton1be10fc2010-09-29 01:12:09 +0000571 if (ClangASTContext::IsAggregateType (GetClangType()) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000572 {
573 if (UpdateValueIfNeeded(exe_scope))
574 {
575 if (m_value_str.empty())
576 {
577 const Value::ContextType context_type = m_value.GetContextType();
578
579 switch (context_type)
580 {
581 case Value::eContextTypeOpaqueClangQualType:
582 case Value::eContextTypeDCType:
583 case Value::eContextTypeDCVariable:
584 {
Greg Clayton1be10fc2010-09-29 01:12:09 +0000585 void *clang_type = GetClangType ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586 if (clang_type)
587 {
588 StreamString sstr;
Greg Clayton32c40852010-10-06 03:09:11 +0000589 if (m_format == eFormatDefault)
590 m_format = ClangASTType::GetFormat(clang_type);
591
592 if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST
593 clang_type, // The clang type to display
594 &sstr,
595 m_format, // Format to display this type with
596 m_data, // Data to extract from
597 0, // Byte offset into "m_data"
598 GetByteSize(), // Byte size of item in "m_data"
599 GetBitfieldBitSize(), // Bitfield bit size
600 GetBitfieldBitOffset())) // Bitfield bit offset
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601 m_value_str.swap(sstr.GetString());
602 else
603 m_value_str.clear();
604 }
605 }
606 break;
607
608 case Value::eContextTypeDCRegisterInfo:
609 {
610 const RegisterInfo *reg_info = m_value.GetRegisterInfo();
611 if (reg_info)
612 {
613 StreamString reg_sstr;
614 m_data.Dump(&reg_sstr, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
615 m_value_str.swap(reg_sstr.GetString());
616 }
617 }
618 break;
Greg Claytonc982c762010-07-09 20:39:50 +0000619
620 default:
621 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000622 }
623 }
Greg Clayton288bdf92010-09-02 02:59:18 +0000624
625 if (!m_value_did_change && m_old_value_valid)
626 {
627 // The value was gotten successfully, so we consider the
628 // value as changed if the value string differs
629 SetValueDidChange (m_old_value_str != m_value_str);
630 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631 }
632 }
633 if (m_value_str.empty())
634 return NULL;
635 return m_value_str.c_str();
636}
637
Greg Clayton737b9322010-09-13 03:32:57 +0000638addr_t
639ValueObject::GetPointerValue (lldb::AddressType &address_type, bool scalar_is_load_address)
640{
641 lldb::addr_t address = LLDB_INVALID_ADDRESS;
642 address_type = eAddressTypeInvalid;
643 switch (GetValue().GetValueType())
644 {
645 case Value::eValueTypeScalar:
646 if (scalar_is_load_address)
647 {
648 address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
649 address_type = eAddressTypeLoad;
650 }
651 break;
652
653 case Value::eValueTypeLoadAddress:
654 case Value::eValueTypeFileAddress:
655 case Value::eValueTypeHostAddress:
656 {
657 uint32_t data_offset = 0;
658 address = m_data.GetPointer(&data_offset);
659 address_type = m_value.GetValueAddressType();
660 if (address_type == eAddressTypeInvalid)
661 address_type = eAddressTypeLoad;
662 }
663 break;
664 }
665 return address;
666}
667
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000668bool
669ValueObject::SetValueFromCString (ExecutionContextScope *exe_scope, const char *value_str)
670{
671 // Make sure our value is up to date first so that our location and location
672 // type is valid.
673 if (!UpdateValueIfNeeded(exe_scope))
674 return false;
675
676 uint32_t count = 0;
Greg Clayton1be10fc2010-09-29 01:12:09 +0000677 lldb::Encoding encoding = ClangASTType::GetEncoding (GetClangType(), count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000678
679 char *end = NULL;
Greg Claytonb1320972010-07-14 00:18:15 +0000680 const size_t byte_size = GetByteSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000681 switch (encoding)
682 {
683 case eEncodingInvalid:
684 return false;
685
686 case eEncodingUint:
687 if (byte_size > sizeof(unsigned long long))
688 {
689 return false;
690 }
691 else
692 {
693 unsigned long long ull_val = strtoull(value_str, &end, 0);
694 if (end && *end != '\0')
695 return false;
696 m_value = ull_val;
697 // Limit the bytes in our m_data appropriately.
698 m_value.GetScalar().GetData (m_data, byte_size);
699 }
700 break;
701
702 case eEncodingSint:
703 if (byte_size > sizeof(long long))
704 {
705 return false;
706 }
707 else
708 {
709 long long sll_val = strtoll(value_str, &end, 0);
710 if (end && *end != '\0')
711 return false;
712 m_value = sll_val;
713 // Limit the bytes in our m_data appropriately.
714 m_value.GetScalar().GetData (m_data, byte_size);
715 }
716 break;
717
718 case eEncodingIEEE754:
719 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720 const off_t byte_offset = GetByteOffset();
Greg Claytonc982c762010-07-09 20:39:50 +0000721 uint8_t *dst = const_cast<uint8_t *>(m_data.PeekData(byte_offset, byte_size));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000722 if (dst != NULL)
723 {
724 // We are decoding a float into host byte order below, so make
725 // sure m_data knows what it contains.
726 m_data.SetByteOrder(eByteOrderHost);
727 const size_t converted_byte_size = ClangASTContext::ConvertStringToFloatValue (
728 GetClangAST(),
Greg Clayton1be10fc2010-09-29 01:12:09 +0000729 GetClangType(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000730 value_str,
731 dst,
732 byte_size);
733
734 if (converted_byte_size == byte_size)
735 {
736 }
737 }
738 }
739 break;
740
741 case eEncodingVector:
742 return false;
743
744 default:
745 return false;
746 }
747
748 // If we have made it here the value is in m_data and we should write it
749 // out to the target
750 return Write ();
751}
752
753bool
754ValueObject::Write ()
755{
756 // Clear the update ID so the next time we try and read the value
757 // we try and read it again.
758 m_update_id = 0;
759
760 // TODO: when Value has a method to write a value back, call it from here.
761 return false;
762
763}
764
Jim Ingham5a369122010-09-28 01:25:32 +0000765lldb::LanguageType
766ValueObject::GetObjectRuntimeLanguage ()
767{
Greg Clayton1be10fc2010-09-29 01:12:09 +0000768 void *opaque_qual_type = GetClangType();
Jim Ingham5a369122010-09-28 01:25:32 +0000769 if (opaque_qual_type == NULL)
770 return lldb::eLanguageTypeC;
771
772 // If the type is a reference, then resolve it to what it refers to first:
773 clang::QualType qual_type (clang::QualType::getFromOpaquePtr(opaque_qual_type).getNonReferenceType());
774 if (qual_type->isAnyPointerType())
775 {
776 if (qual_type->isObjCObjectPointerType())
777 return lldb::eLanguageTypeObjC;
778
779 clang::QualType pointee_type (qual_type->getPointeeType());
780 if (pointee_type->getCXXRecordDeclForPointerType() != NULL)
781 return lldb::eLanguageTypeC_plus_plus;
782 if (pointee_type->isObjCObjectOrInterfaceType())
783 return lldb::eLanguageTypeObjC;
784 if (pointee_type->isObjCClassType())
785 return lldb::eLanguageTypeObjC;
786 }
787 else
788 {
789 if (ClangASTContext::IsObjCClassType (opaque_qual_type))
790 return lldb::eLanguageTypeObjC;
Johnny Chend440bcc2010-09-28 16:10:54 +0000791 if (ClangASTContext::IsCXXClassType (opaque_qual_type))
Jim Ingham5a369122010-09-28 01:25:32 +0000792 return lldb::eLanguageTypeC_plus_plus;
793 }
794
795 return lldb::eLanguageTypeC;
796}
797
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000798void
799ValueObject::AddSyntheticChild (const ConstString &key, ValueObjectSP& valobj_sp)
800{
801 m_synthetic_children[key] = valobj_sp;
802}
803
804ValueObjectSP
805ValueObject::GetSyntheticChild (const ConstString &key) const
806{
807 ValueObjectSP synthetic_child_sp;
808 std::map<ConstString, ValueObjectSP>::const_iterator pos = m_synthetic_children.find (key);
809 if (pos != m_synthetic_children.end())
810 synthetic_child_sp = pos->second;
811 return synthetic_child_sp;
812}
813
814bool
815ValueObject::IsPointerType ()
816{
Greg Clayton1be10fc2010-09-29 01:12:09 +0000817 return ClangASTContext::IsPointerType (GetClangType());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000818}
819
820bool
821ValueObject::IsPointerOrReferenceType ()
822{
Greg Clayton1be10fc2010-09-29 01:12:09 +0000823 return ClangASTContext::IsPointerOrReferenceType(GetClangType());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000824}
825
826ValueObjectSP
827ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create)
828{
829 ValueObjectSP synthetic_child_sp;
830 if (IsPointerType ())
831 {
832 char index_str[64];
833 snprintf(index_str, sizeof(index_str), "[%i]", index);
834 ConstString index_const_str(index_str);
835 // Check if we have already created a synthetic array member in this
836 // valid object. If we have we will re-use it.
837 synthetic_child_sp = GetSyntheticChild (index_const_str);
838 if (!synthetic_child_sp)
839 {
840 // We haven't made a synthetic array member for INDEX yet, so
841 // lets make one and cache it for any future reference.
842 synthetic_child_sp = CreateChildAtIndex(0, true, index);
843
844 // Cache the value if we got one back...
845 if (synthetic_child_sp)
846 AddSyntheticChild(index_const_str, synthetic_child_sp);
847 }
848 }
849 return synthetic_child_sp;
850}
Jim Ingham22777012010-09-23 02:01:19 +0000851
852bool
853ValueObject::SetDynamicValue ()
854{
855 if (!IsPointerOrReferenceType())
856 return false;
857
858 // Check that the runtime class is correct for determining the most specific class.
859 // If it is a C++ class, see if it is dynamic:
Jim Ingham5a369122010-09-28 01:25:32 +0000860
Jim Ingham22777012010-09-23 02:01:19 +0000861 return true;
862}
Greg Clayton1d3afba2010-10-05 00:00:42 +0000863
864
865void
866ValueObject::DumpValueObject
867(
868 Stream &s,
869 ExecutionContextScope *exe_scope,
870 ValueObject *valobj,
871 const char *root_valobj_name,
872 uint32_t ptr_depth,
873 uint32_t curr_depth,
874 uint32_t max_depth,
875 bool show_types,
876 bool show_location,
877 bool use_objc,
878 bool scope_already_checked
879)
880{
881 if (valobj)
882 {
883 //const char *loc_cstr = valobj->GetLocationAsCString();
884 if (show_location)
885 {
886 s.Printf("%s: ", valobj->GetLocationAsCString(exe_scope));
887 }
888
889 s.Indent();
890
891 if (show_types)
892 s.Printf("(%s) ", valobj->GetTypeName().AsCString());
893
894 const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
895 s.Printf ("%s = ", name_cstr);
896
897 if (!scope_already_checked && !valobj->IsInScope(exe_scope->CalculateStackFrame()))
898 {
899 s.PutCString("error: out of scope");
900 return;
901 }
902
903 const char *val_cstr = valobj->GetValueAsCString(exe_scope);
904 const char *err_cstr = valobj->GetError().AsCString();
905
906 if (err_cstr)
907 {
908 s.Printf ("error: %s", err_cstr);
909 }
910 else
911 {
912 const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope);
913
914 const bool is_aggregate = ClangASTContext::IsAggregateType (valobj->GetClangType());
915
916 if (val_cstr)
917 s.PutCString(val_cstr);
918
919 if (sum_cstr)
920 s.Printf(" %s", sum_cstr);
921
922 if (use_objc)
923 {
924 const char *object_desc = valobj->GetObjectDescription(exe_scope);
925 if (object_desc)
926 s.Printf("\n%s\n", object_desc);
927 else
928 s.Printf ("No description available.\n");
929 return;
930 }
931
932
933 if (curr_depth < max_depth)
934 {
935 if (is_aggregate)
936 s.PutChar('{');
937
938 bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetClangType());
939
940 if (is_ptr_or_ref && ptr_depth == 0)
941 return;
942
943 const uint32_t num_children = valobj->GetNumChildren();
944 if (num_children)
945 {
946 s.IndentMore();
947 for (uint32_t idx=0; idx<num_children; ++idx)
948 {
949 ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
950 if (child_sp.get())
951 {
952 s.EOL();
953 DumpValueObject (s,
954 exe_scope,
955 child_sp.get(),
956 NULL,
957 is_ptr_or_ref ? ptr_depth - 1 : ptr_depth,
958 curr_depth + 1,
959 max_depth,
960 show_types,
961 show_location,
962 false,
963 true);
964 if (idx + 1 < num_children)
965 s.PutChar(',');
966 }
967 }
968 s.IndentLess();
969 }
970 if (is_aggregate)
971 {
972 s.EOL();
973 s.Indent("}");
974 }
975 }
976 else
977 {
978 if (is_aggregate)
979 {
980 s.PutCString("{...}");
981 }
982 }
983 }
984 }
985}
986