blob: a8696be3f7f5a6ebe7f4e5abe5da50ef66f12f16 [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"
Enrico Granata4becb372011-06-29 22:27:15 +000022#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Core/StreamString.h"
24#include "lldb/Core/ValueObjectChild.h"
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000025#include "lldb/Core/ValueObjectConstResult.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000026#include "lldb/Core/ValueObjectDynamicValue.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Core/ValueObjectList.h"
Greg Claytonb2dcc362011-05-05 23:32:56 +000028#include "lldb/Core/ValueObjectMemory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029
Greg Clayton7fb56d02011-02-01 01:31:41 +000030#include "lldb/Host/Endian.h"
31
Greg Claytone1a916a2010-07-21 22:12:05 +000032#include "lldb/Symbol/ClangASTType.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033#include "lldb/Symbol/ClangASTContext.h"
34#include "lldb/Symbol/Type.h"
35
Jim Ingham53c47f12010-09-10 23:12:17 +000036#include "lldb/Target/ExecutionContext.h"
Jim Ingham5a369122010-09-28 01:25:32 +000037#include "lldb/Target/LanguageRuntime.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038#include "lldb/Target/Process.h"
39#include "lldb/Target/RegisterContext.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000040#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042
43using namespace lldb;
44using namespace lldb_private;
45
46static lldb::user_id_t g_value_obj_uid = 0;
47
48//----------------------------------------------------------------------
49// ValueObject constructor
50//----------------------------------------------------------------------
Jim Ingham6035b672011-03-31 00:19:25 +000051ValueObject::ValueObject (ValueObject &parent) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052 UserID (++g_value_obj_uid), // Unique identifier for every value object
Jim Ingham6035b672011-03-31 00:19:25 +000053 m_parent (&parent),
Stephen Wilson71c21d12011-04-11 19:41:40 +000054 m_update_point (parent.GetUpdatePoint ()),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055 m_name (),
56 m_data (),
57 m_value (),
58 m_error (),
Greg Clayton288bdf92010-09-02 02:59:18 +000059 m_value_str (),
60 m_old_value_str (),
61 m_location_str (),
62 m_summary_str (),
Jim Ingham53c47f12010-09-10 23:12:17 +000063 m_object_desc_str (),
Jim Ingham58b59f92011-04-22 23:53:53 +000064 m_manager(parent.GetManager()),
Greg Clayton288bdf92010-09-02 02:59:18 +000065 m_children (),
66 m_synthetic_children (),
Jim Ingham58b59f92011-04-22 23:53:53 +000067 m_dynamic_value (NULL),
68 m_deref_valobj(NULL),
Greg Clayton32c40852010-10-06 03:09:11 +000069 m_format (eFormatDefault),
Greg Clayton288bdf92010-09-02 02:59:18 +000070 m_value_is_valid (false),
71 m_value_did_change (false),
72 m_children_count_valid (false),
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000073 m_old_value_valid (false),
Greg Claytone221f822011-01-21 01:59:00 +000074 m_pointers_point_to_load_addrs (false),
Enrico Granata4becb372011-06-29 22:27:15 +000075 m_is_deref_of_parent (false),
Enrico Granata0a3958e2011-07-02 00:25:22 +000076 m_is_array_item_for_pointer(false),
Enrico Granata4becb372011-06-29 22:27:15 +000077 m_last_format_mgr_revision(0),
78 m_last_summary_format(),
79 m_last_value_format()
Jim Ingham6035b672011-03-31 00:19:25 +000080{
Jim Ingham58b59f92011-04-22 23:53:53 +000081 m_manager->ManageObject(this);
Jim Ingham6035b672011-03-31 00:19:25 +000082}
83
84//----------------------------------------------------------------------
85// ValueObject constructor
86//----------------------------------------------------------------------
87ValueObject::ValueObject (ExecutionContextScope *exe_scope) :
88 UserID (++g_value_obj_uid), // Unique identifier for every value object
89 m_parent (NULL),
Stephen Wilson71c21d12011-04-11 19:41:40 +000090 m_update_point (exe_scope),
Jim Ingham6035b672011-03-31 00:19:25 +000091 m_name (),
92 m_data (),
93 m_value (),
94 m_error (),
95 m_value_str (),
96 m_old_value_str (),
97 m_location_str (),
98 m_summary_str (),
99 m_object_desc_str (),
Jim Ingham58b59f92011-04-22 23:53:53 +0000100 m_manager(),
Jim Ingham6035b672011-03-31 00:19:25 +0000101 m_children (),
102 m_synthetic_children (),
Jim Ingham58b59f92011-04-22 23:53:53 +0000103 m_dynamic_value (NULL),
104 m_deref_valobj(NULL),
Jim Ingham6035b672011-03-31 00:19:25 +0000105 m_format (eFormatDefault),
106 m_value_is_valid (false),
107 m_value_did_change (false),
108 m_children_count_valid (false),
109 m_old_value_valid (false),
110 m_pointers_point_to_load_addrs (false),
Enrico Granata4becb372011-06-29 22:27:15 +0000111 m_is_deref_of_parent (false),
Enrico Granata0a3958e2011-07-02 00:25:22 +0000112 m_is_array_item_for_pointer(false),
Enrico Granata4becb372011-06-29 22:27:15 +0000113 m_last_format_mgr_revision(0),
114 m_last_summary_format(),
115 m_last_value_format()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116{
Jim Ingham58b59f92011-04-22 23:53:53 +0000117 m_manager = new ValueObjectManager();
118 m_manager->ManageObject (this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119}
120
121//----------------------------------------------------------------------
122// Destructor
123//----------------------------------------------------------------------
124ValueObject::~ValueObject ()
125{
126}
127
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128bool
Enrico Granata0a3958e2011-07-02 00:25:22 +0000129ValueObject::UpdateValueIfNeeded (bool update_format)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130{
Enrico Granata4becb372011-06-29 22:27:15 +0000131
Enrico Granata0a3958e2011-07-02 00:25:22 +0000132 if (update_format)
133 UpdateFormatsIfNeeded();
Enrico Granata4becb372011-06-29 22:27:15 +0000134
Greg Claytonb71f3842010-10-05 03:13:51 +0000135 // If this is a constant value, then our success is predicated on whether
136 // we have an error or not
137 if (GetIsConstant())
138 return m_error.Success();
139
Jim Ingham6035b672011-03-31 00:19:25 +0000140 bool first_update = m_update_point.IsFirstEvaluation();
141
142 if (m_update_point.NeedsUpdating())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 {
Jim Ingham6035b672011-03-31 00:19:25 +0000144 m_update_point.SetUpdated();
145
146 // Save the old value using swap to avoid a string copy which
147 // also will clear our m_value_str
148 if (m_value_str.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149 {
Jim Ingham6035b672011-03-31 00:19:25 +0000150 m_old_value_valid = false;
151 }
152 else
153 {
154 m_old_value_valid = true;
155 m_old_value_str.swap (m_value_str);
156 m_value_str.clear();
157 }
158 m_location_str.clear();
159 m_summary_str.clear();
160 m_object_desc_str.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161
Jim Ingham6035b672011-03-31 00:19:25 +0000162 const bool value_was_valid = GetValueIsValid();
163 SetValueDidChange (false);
Greg Clayton73b953b2010-08-28 00:08:07 +0000164
Jim Ingham6035b672011-03-31 00:19:25 +0000165 m_error.Clear();
Greg Clayton73b953b2010-08-28 00:08:07 +0000166
Jim Ingham6035b672011-03-31 00:19:25 +0000167 // Call the pure virtual function to update the value
168 bool success = UpdateValue ();
169
170 SetValueIsValid (success);
171
172 if (first_update)
173 SetValueDidChange (false);
174 else if (!m_value_did_change && success == false)
175 {
176 // The value wasn't gotten successfully, so we mark this
177 // as changed if the value used to be valid and now isn't
178 SetValueDidChange (value_was_valid);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179 }
180 }
181 return m_error.Success();
182}
183
Enrico Granata4becb372011-06-29 22:27:15 +0000184void
185ValueObject::UpdateFormatsIfNeeded()
186{
187 /*printf("CHECKING FOR UPDATES. I am at revision %d, while the format manager is at revision %d\n",
188 m_last_format_mgr_revision,
189 Debugger::ValueFormats::GetCurrentRevision());*/
190 if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision())
191 {
192 if (m_last_summary_format.get())
193 m_last_summary_format.reset((SummaryFormat*)NULL);
194 if (m_last_value_format.get())
195 m_last_value_format.reset((ValueFormat*)NULL);
196 Debugger::ValueFormats::Get(*this, m_last_value_format);
Enrico Granata0a3958e2011-07-02 00:25:22 +0000197 if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format))
198 Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format);
Enrico Granata4becb372011-06-29 22:27:15 +0000199 m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision();
200 m_value_str.clear();
201 m_summary_str.clear();
202 }
203}
204
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205DataExtractor &
206ValueObject::GetDataExtractor ()
207{
Jim Ingham78a685a2011-04-16 00:01:13 +0000208 UpdateValueIfNeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209 return m_data;
210}
211
212const Error &
213ValueObject::GetError() const
214{
215 return m_error;
216}
217
218const ConstString &
219ValueObject::GetName() const
220{
221 return m_name;
222}
223
224const char *
Jim Ingham6035b672011-03-31 00:19:25 +0000225ValueObject::GetLocationAsCString ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226{
Jim Ingham6035b672011-03-31 00:19:25 +0000227 if (UpdateValueIfNeeded())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 {
229 if (m_location_str.empty())
230 {
231 StreamString sstr;
232
233 switch (m_value.GetValueType())
234 {
235 default:
236 break;
237
238 case Value::eValueTypeScalar:
Greg Clayton526e5af2010-11-13 03:52:47 +0000239 if (m_value.GetContextType() == Value::eContextTypeRegisterInfo)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 {
241 RegisterInfo *reg_info = m_value.GetRegisterInfo();
242 if (reg_info)
243 {
244 if (reg_info->name)
245 m_location_str = reg_info->name;
246 else if (reg_info->alt_name)
247 m_location_str = reg_info->alt_name;
248 break;
249 }
250 }
251 m_location_str = "scalar";
252 break;
253
254 case Value::eValueTypeLoadAddress:
255 case Value::eValueTypeFileAddress:
256 case Value::eValueTypeHostAddress:
257 {
258 uint32_t addr_nibble_size = m_data.GetAddressByteSize() * 2;
259 sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
260 m_location_str.swap(sstr.GetString());
261 }
262 break;
263 }
264 }
265 }
266 return m_location_str.c_str();
267}
268
269Value &
270ValueObject::GetValue()
271{
272 return m_value;
273}
274
275const Value &
276ValueObject::GetValue() const
277{
278 return m_value;
279}
280
281bool
Jim Ingham6035b672011-03-31 00:19:25 +0000282ValueObject::ResolveValue (Scalar &scalar)
Greg Clayton8f343b02010-11-04 01:54:29 +0000283{
284 ExecutionContext exe_ctx;
Jim Ingham6035b672011-03-31 00:19:25 +0000285 ExecutionContextScope *exe_scope = GetExecutionContextScope();
286 if (exe_scope)
287 exe_scope->CalculateExecutionContext(exe_ctx);
Greg Clayton8f343b02010-11-04 01:54:29 +0000288 scalar = m_value.ResolveValue(&exe_ctx, GetClangAST ());
289 return scalar.IsValid();
290}
291
292bool
Greg Clayton288bdf92010-09-02 02:59:18 +0000293ValueObject::GetValueIsValid () const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294{
Greg Clayton288bdf92010-09-02 02:59:18 +0000295 return m_value_is_valid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000296}
297
298
299void
300ValueObject::SetValueIsValid (bool b)
301{
Greg Clayton288bdf92010-09-02 02:59:18 +0000302 m_value_is_valid = b;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303}
304
305bool
Jim Ingham6035b672011-03-31 00:19:25 +0000306ValueObject::GetValueDidChange ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307{
Jim Ingham6035b672011-03-31 00:19:25 +0000308 GetValueAsCString ();
Greg Clayton288bdf92010-09-02 02:59:18 +0000309 return m_value_did_change;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310}
311
312void
313ValueObject::SetValueDidChange (bool value_changed)
314{
Greg Clayton288bdf92010-09-02 02:59:18 +0000315 m_value_did_change = value_changed;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000316}
317
318ValueObjectSP
319ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
320{
321 ValueObjectSP child_sp;
Greg Claytondea8cb42011-06-29 22:09:02 +0000322 // We may need to update our value if we are dynamic
323 if (IsPossibleDynamicType ())
324 UpdateValueIfNeeded();
325 if (idx < GetNumChildren())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000327 // Check if we have already made the child value object?
328 if (can_create && m_children[idx] == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000330 // No we haven't created the child at this index, so lets have our
331 // subclass do it and cache the result for quick future access.
332 m_children[idx] = CreateChildAtIndex (idx, false, 0);
Jim Ingham78a685a2011-04-16 00:01:13 +0000333 }
Greg Claytondea8cb42011-06-29 22:09:02 +0000334
335 if (m_children[idx] != NULL)
336 return m_children[idx]->GetSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337 }
338 return child_sp;
339}
340
341uint32_t
342ValueObject::GetIndexOfChildWithName (const ConstString &name)
343{
344 bool omit_empty_base_classes = true;
345 return ClangASTContext::GetIndexOfChildWithName (GetClangAST(),
Greg Clayton1be10fc2010-09-29 01:12:09 +0000346 GetClangType(),
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000347 name.GetCString(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000348 omit_empty_base_classes);
349}
350
351ValueObjectSP
352ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
353{
Greg Clayton710dd5a2011-01-08 20:28:42 +0000354 // when getting a child by name, it could be buried inside some base
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000355 // classes (which really aren't part of the expression path), so we
356 // need a vector of indexes that can get us down to the correct child
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 ValueObjectSP child_sp;
Jim Ingham78a685a2011-04-16 00:01:13 +0000358
Greg Claytondea8cb42011-06-29 22:09:02 +0000359 // We may need to update our value if we are dynamic
360 if (IsPossibleDynamicType ())
361 UpdateValueIfNeeded();
362
363 std::vector<uint32_t> child_indexes;
364 clang::ASTContext *clang_ast = GetClangAST();
365 void *clang_type = GetClangType();
366 bool omit_empty_base_classes = true;
367 const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
368 clang_type,
369 name.GetCString(),
370 omit_empty_base_classes,
371 child_indexes);
372 if (num_child_indexes > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000374 std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
375 std::vector<uint32_t>::const_iterator end = child_indexes.end ();
376
377 child_sp = GetChildAtIndex(*pos, can_create);
378 for (++pos; pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000380 if (child_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +0000381 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000382 ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
383 child_sp = new_child_sp;
Jim Ingham78a685a2011-04-16 00:01:13 +0000384 }
Greg Claytondea8cb42011-06-29 22:09:02 +0000385 else
386 {
387 child_sp.reset();
388 }
389
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 }
391 }
392 return child_sp;
393}
394
395
396uint32_t
397ValueObject::GetNumChildren ()
398{
Greg Clayton288bdf92010-09-02 02:59:18 +0000399 if (!m_children_count_valid)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400 {
401 SetNumChildren (CalculateNumChildren());
402 }
403 return m_children.size();
404}
405void
406ValueObject::SetNumChildren (uint32_t num_children)
407{
Greg Clayton288bdf92010-09-02 02:59:18 +0000408 m_children_count_valid = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 m_children.resize(num_children);
410}
411
412void
413ValueObject::SetName (const char *name)
414{
415 m_name.SetCString(name);
416}
417
418void
419ValueObject::SetName (const ConstString &name)
420{
421 m_name = name;
422}
423
Jim Ingham58b59f92011-04-22 23:53:53 +0000424ValueObject *
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000425ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
426{
Jim Ingham2eec4872011-05-07 00:10:58 +0000427 ValueObject *valobj = NULL;
Jim Ingham78a685a2011-04-16 00:01:13 +0000428
Greg Claytondea8cb42011-06-29 22:09:02 +0000429 bool omit_empty_base_classes = true;
430
431 std::string child_name_str;
432 uint32_t child_byte_size = 0;
433 int32_t child_byte_offset = 0;
434 uint32_t child_bitfield_bit_size = 0;
435 uint32_t child_bitfield_bit_offset = 0;
436 bool child_is_base_class = false;
437 bool child_is_deref_of_parent = false;
438
439 const bool transparent_pointers = synthetic_array_member == false;
440 clang::ASTContext *clang_ast = GetClangAST();
441 clang_type_t clang_type = GetClangType();
442 clang_type_t child_clang_type;
443
444 ExecutionContext exe_ctx;
445 GetExecutionContextScope()->CalculateExecutionContext (exe_ctx);
446
447 child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
448 clang_ast,
449 GetName().GetCString(),
450 clang_type,
451 idx,
452 transparent_pointers,
453 omit_empty_base_classes,
454 child_name_str,
455 child_byte_size,
456 child_byte_offset,
457 child_bitfield_bit_size,
458 child_bitfield_bit_offset,
459 child_is_base_class,
460 child_is_deref_of_parent);
461 if (child_clang_type && child_byte_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000462 {
Greg Claytondea8cb42011-06-29 22:09:02 +0000463 if (synthetic_index)
464 child_byte_offset += child_byte_size * synthetic_index;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000465
Greg Claytondea8cb42011-06-29 22:09:02 +0000466 ConstString child_name;
467 if (!child_name_str.empty())
468 child_name.SetCString (child_name_str.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000469
Greg Claytondea8cb42011-06-29 22:09:02 +0000470 valobj = new ValueObjectChild (*this,
471 clang_ast,
472 child_clang_type,
473 child_name,
474 child_byte_size,
475 child_byte_offset,
476 child_bitfield_bit_size,
477 child_bitfield_bit_offset,
478 child_is_base_class,
479 child_is_deref_of_parent);
480 if (m_pointers_point_to_load_addrs)
481 valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000482 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000483
Jim Ingham58b59f92011-04-22 23:53:53 +0000484 return valobj;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000485}
486
487const char *
Jim Ingham6035b672011-03-31 00:19:25 +0000488ValueObject::GetSummaryAsCString ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489{
Jim Ingham6035b672011-03-31 00:19:25 +0000490 if (UpdateValueIfNeeded ())
Enrico Granata4becb372011-06-29 22:27:15 +0000491 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492 if (m_summary_str.empty())
493 {
Enrico Granata4becb372011-06-29 22:27:15 +0000494 if (m_last_summary_format.get())
495 {
496 StreamString s;
497 ExecutionContext exe_ctx;
498 this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx);
499 SymbolContext sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
Enrico Granata0a3958e2011-07-02 00:25:22 +0000500
501 if (m_last_summary_format->m_show_members_oneliner)
Enrico Granata4becb372011-06-29 22:27:15 +0000502 {
Enrico Granata0a3958e2011-07-02 00:25:22 +0000503 const uint32_t num_children = GetNumChildren();
504 if (num_children)
505 {
506
507 s.PutChar('(');
508
509 for (uint32_t idx=0; idx<num_children; ++idx)
510 {
511 ValueObjectSP child_sp(GetChildAtIndex(idx, true));
512 if (child_sp.get())
513 {
514 if (idx)
515 s.PutCString(", ");
516 s.PutCString(child_sp.get()->GetName().AsCString());
517 s.PutChar('=');
518 s.PutCString(child_sp.get()->GetValueAsCString());
519 }
520 }
521
522 s.PutChar(')');
523
524 m_summary_str.swap(s.GetString());
525 return m_summary_str.c_str();
526 }
527 else
528 return "()";
529
Enrico Granata4becb372011-06-29 22:27:15 +0000530 }
Enrico Granata0a3958e2011-07-02 00:25:22 +0000531 else
532 {
533 if (Debugger::FormatPrompt(m_last_summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this))
534 {
535 m_summary_str.swap(s.GetString());
536 return m_summary_str.c_str();
537 }
538 else
539 return NULL;
540 }
Enrico Granata4becb372011-06-29 22:27:15 +0000541 }
542
Greg Clayton73b472d2010-10-27 03:32:59 +0000543 clang_type_t clang_type = GetClangType();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544
545 // See if this is a pointer to a C string?
Greg Clayton737b9322010-09-13 03:32:57 +0000546 if (clang_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000547 {
Greg Clayton737b9322010-09-13 03:32:57 +0000548 StreamString sstr;
Greg Clayton73b472d2010-10-27 03:32:59 +0000549 clang_type_t elem_or_pointee_clang_type;
550 const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000551 GetClangAST(),
552 &elem_or_pointee_clang_type));
Greg Clayton737b9322010-09-13 03:32:57 +0000553
Jim Ingham6035b672011-03-31 00:19:25 +0000554 ExecutionContextScope *exe_scope = GetExecutionContextScope();
555 if (exe_scope)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556 {
Jim Ingham6035b672011-03-31 00:19:25 +0000557 if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) &&
558 ClangASTContext::IsCharType (elem_or_pointee_clang_type))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000559 {
Jim Ingham6035b672011-03-31 00:19:25 +0000560 Process *process = exe_scope->CalculateProcess();
561 if (process != NULL)
562 {
563 lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
564 AddressType cstr_address_type = eAddressTypeInvalid;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565
Jim Ingham6035b672011-03-31 00:19:25 +0000566 size_t cstr_len = 0;
567 if (type_flags.Test (ClangASTContext::eTypeIsArray))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000568 {
Jim Ingham6035b672011-03-31 00:19:25 +0000569 // We have an array
570 cstr_len = ClangASTContext::GetArraySize (clang_type);
571 cstr_address = GetAddressOf (cstr_address_type, true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000572 }
Greg Clayton737b9322010-09-13 03:32:57 +0000573 else
574 {
Jim Ingham6035b672011-03-31 00:19:25 +0000575 // We have a pointer
576 cstr_address = GetPointerValue (cstr_address_type, true);
Greg Clayton737b9322010-09-13 03:32:57 +0000577 }
Jim Ingham6035b672011-03-31 00:19:25 +0000578 if (cstr_address != LLDB_INVALID_ADDRESS)
Greg Clayton737b9322010-09-13 03:32:57 +0000579 {
Jim Ingham6035b672011-03-31 00:19:25 +0000580 DataExtractor data;
581 size_t bytes_read = 0;
582 std::vector<char> data_buffer;
583 Error error;
584 if (cstr_len > 0)
Greg Clayton737b9322010-09-13 03:32:57 +0000585 {
Jim Ingham6035b672011-03-31 00:19:25 +0000586 data_buffer.resize(cstr_len);
587 data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder());
588 bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), cstr_len, error);
589 if (bytes_read > 0)
Greg Clayton737b9322010-09-13 03:32:57 +0000590 {
Jim Ingham6035b672011-03-31 00:19:25 +0000591 sstr << '"';
592 data.Dump (&sstr,
593 0, // Start offset in "data"
Greg Clayton4e4294b2011-06-17 23:50:44 +0000594 eFormatCharArray, // Print as characters
Jim Ingham6035b672011-03-31 00:19:25 +0000595 1, // Size of item (1 byte for a char!)
596 bytes_read, // How many bytes to print?
597 UINT32_MAX, // num per line
598 LLDB_INVALID_ADDRESS,// base address
599 0, // bitfield bit size
600 0); // bitfield bit offset
601 sstr << '"';
Greg Clayton737b9322010-09-13 03:32:57 +0000602 }
603 }
Jim Ingham6035b672011-03-31 00:19:25 +0000604 else
605 {
606 const size_t k_max_buf_size = 256;
607 data_buffer.resize (k_max_buf_size + 1);
608 // NULL terminate in case we don't get the entire C string
609 data_buffer.back() = '\0';
Greg Clayton737b9322010-09-13 03:32:57 +0000610
Jim Ingham6035b672011-03-31 00:19:25 +0000611 sstr << '"';
612
613 data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder());
614 while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0)
615 {
616 size_t len = strlen(&data_buffer.front());
617 if (len == 0)
618 break;
619 if (len > bytes_read)
620 len = bytes_read;
621
622 data.Dump (&sstr,
623 0, // Start offset in "data"
Greg Clayton4e4294b2011-06-17 23:50:44 +0000624 eFormatCharArray, // Print as characters
Jim Ingham6035b672011-03-31 00:19:25 +0000625 1, // Size of item (1 byte for a char!)
626 len, // How many bytes to print?
627 UINT32_MAX, // num per line
628 LLDB_INVALID_ADDRESS,// base address
629 0, // bitfield bit size
630 0); // bitfield bit offset
631
632 if (len < k_max_buf_size)
633 break;
634 cstr_address += k_max_buf_size;
635 }
636 sstr << '"';
637 }
638 }
Greg Clayton737b9322010-09-13 03:32:57 +0000639 }
Jim Ingham6035b672011-03-31 00:19:25 +0000640
641 if (sstr.GetSize() > 0)
642 m_summary_str.assign (sstr.GetData(), sstr.GetSize());
Greg Clayton737b9322010-09-13 03:32:57 +0000643 }
Jim Ingham6035b672011-03-31 00:19:25 +0000644 else if (ClangASTContext::IsFunctionPointerType (clang_type))
Greg Clayton737b9322010-09-13 03:32:57 +0000645 {
Jim Ingham6035b672011-03-31 00:19:25 +0000646 AddressType func_ptr_address_type = eAddressTypeInvalid;
647 lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true);
648
649 if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
650 {
651 switch (func_ptr_address_type)
652 {
653 case eAddressTypeInvalid:
654 case eAddressTypeFile:
655 break;
656
657 case eAddressTypeLoad:
658 {
659 Address so_addr;
660 Target *target = exe_scope->CalculateTarget();
661 if (target && target->GetSectionLoadList().IsEmpty() == false)
662 {
663 if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
664 {
665 so_addr.Dump (&sstr,
666 exe_scope,
667 Address::DumpStyleResolvedDescription,
668 Address::DumpStyleSectionNameOffset);
669 }
670 }
671 }
672 break;
673
674 case eAddressTypeHost:
675 break;
676 }
677 }
678 if (sstr.GetSize() > 0)
679 {
680 m_summary_str.assign (1, '(');
681 m_summary_str.append (sstr.GetData(), sstr.GetSize());
682 m_summary_str.append (1, ')');
683 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684 }
685 }
686 }
687 }
688 }
689 if (m_summary_str.empty())
690 return NULL;
691 return m_summary_str.c_str();
692}
693
Jim Ingham53c47f12010-09-10 23:12:17 +0000694const char *
Jim Ingham6035b672011-03-31 00:19:25 +0000695ValueObject::GetObjectDescription ()
Jim Ingham53c47f12010-09-10 23:12:17 +0000696{
Enrico Granata0a3958e2011-07-02 00:25:22 +0000697
Jim Ingham6035b672011-03-31 00:19:25 +0000698 if (!UpdateValueIfNeeded ())
Jim Ingham53c47f12010-09-10 23:12:17 +0000699 return NULL;
Enrico Granata0a3958e2011-07-02 00:25:22 +0000700
701 if (!m_object_desc_str.empty())
702 return m_object_desc_str.c_str();
703
Jim Ingham6035b672011-03-31 00:19:25 +0000704 ExecutionContextScope *exe_scope = GetExecutionContextScope();
705 if (exe_scope == NULL)
706 return NULL;
707
Jim Ingham53c47f12010-09-10 23:12:17 +0000708 Process *process = exe_scope->CalculateProcess();
Jim Ingham5a369122010-09-28 01:25:32 +0000709 if (process == NULL)
Jim Ingham53c47f12010-09-10 23:12:17 +0000710 return NULL;
Jim Ingham5a369122010-09-28 01:25:32 +0000711
Jim Ingham53c47f12010-09-10 23:12:17 +0000712 StreamString s;
Jim Ingham5a369122010-09-28 01:25:32 +0000713
714 lldb::LanguageType language = GetObjectRuntimeLanguage();
715 LanguageRuntime *runtime = process->GetLanguageRuntime(language);
716
Jim Inghama2cf2632010-12-23 02:29:54 +0000717 if (runtime == NULL)
718 {
Jim Inghamb7603bb2011-03-18 00:05:18 +0000719 // Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway...
Jim Inghama2cf2632010-12-23 02:29:54 +0000720 clang_type_t opaque_qual_type = GetClangType();
721 if (opaque_qual_type != NULL)
722 {
Jim Inghamb7603bb2011-03-18 00:05:18 +0000723 bool is_signed;
724 if (ClangASTContext::IsIntegerType (opaque_qual_type, is_signed)
725 || ClangASTContext::IsPointerType (opaque_qual_type))
726 {
Jim Inghama2cf2632010-12-23 02:29:54 +0000727 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
Jim Inghamb7603bb2011-03-18 00:05:18 +0000728 }
Jim Inghama2cf2632010-12-23 02:29:54 +0000729 }
730 }
731
Jim Ingham8d543de2011-03-31 23:01:21 +0000732 if (runtime && runtime->GetObjectDescription(s, *this))
Jim Ingham53c47f12010-09-10 23:12:17 +0000733 {
734 m_object_desc_str.append (s.GetData());
735 }
Sean Callanan672ad942010-10-23 00:18:49 +0000736
737 if (m_object_desc_str.empty())
738 return NULL;
739 else
740 return m_object_desc_str.c_str();
Jim Ingham53c47f12010-09-10 23:12:17 +0000741}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000742
743const char *
Jim Ingham6035b672011-03-31 00:19:25 +0000744ValueObject::GetValueAsCString ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000745{
746 // If our byte size is zero this is an aggregate type that has children
Greg Clayton1be10fc2010-09-29 01:12:09 +0000747 if (ClangASTContext::IsAggregateType (GetClangType()) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000748 {
Jim Ingham6035b672011-03-31 00:19:25 +0000749 if (UpdateValueIfNeeded())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750 {
751 if (m_value_str.empty())
752 {
753 const Value::ContextType context_type = m_value.GetContextType();
754
755 switch (context_type)
756 {
Greg Clayton526e5af2010-11-13 03:52:47 +0000757 case Value::eContextTypeClangType:
758 case Value::eContextTypeLLDBType:
759 case Value::eContextTypeVariable:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000760 {
Greg Clayton73b472d2010-10-27 03:32:59 +0000761 clang_type_t clang_type = GetClangType ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000762 if (clang_type)
763 {
764 StreamString sstr;
Greg Clayton68ebae62011-04-28 20:55:26 +0000765 Format format = GetFormat();
Enrico Granata4becb372011-06-29 22:27:15 +0000766 if (format == eFormatDefault)
767 {
768 if (m_last_value_format)
769 format = m_last_value_format->m_format;
770 else
771 format = ClangASTType::GetFormat(clang_type);
772 }
Greg Clayton32c40852010-10-06 03:09:11 +0000773
774 if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST
775 clang_type, // The clang type to display
776 &sstr,
Enrico Granata4becb372011-06-29 22:27:15 +0000777 format, // Format to display this type with
Greg Clayton32c40852010-10-06 03:09:11 +0000778 m_data, // Data to extract from
779 0, // Byte offset into "m_data"
780 GetByteSize(), // Byte size of item in "m_data"
781 GetBitfieldBitSize(), // Bitfield bit size
782 GetBitfieldBitOffset())) // Bitfield bit offset
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000783 m_value_str.swap(sstr.GetString());
784 else
Greg Clayton007d5be2011-05-30 00:49:24 +0000785 {
786 m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)",
787 m_data.GetByteSize(),
788 GetByteSize());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000789 m_value_str.clear();
Greg Clayton007d5be2011-05-30 00:49:24 +0000790 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000791 }
792 }
793 break;
794
Greg Clayton526e5af2010-11-13 03:52:47 +0000795 case Value::eContextTypeRegisterInfo:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000796 {
797 const RegisterInfo *reg_info = m_value.GetRegisterInfo();
798 if (reg_info)
799 {
800 StreamString reg_sstr;
801 m_data.Dump(&reg_sstr, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
802 m_value_str.swap(reg_sstr.GetString());
803 }
804 }
805 break;
Greg Claytonc982c762010-07-09 20:39:50 +0000806
807 default:
808 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000809 }
810 }
Greg Clayton288bdf92010-09-02 02:59:18 +0000811
812 if (!m_value_did_change && m_old_value_valid)
813 {
814 // The value was gotten successfully, so we consider the
815 // value as changed if the value string differs
816 SetValueDidChange (m_old_value_str != m_value_str);
817 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000818 }
819 }
820 if (m_value_str.empty())
821 return NULL;
822 return m_value_str.c_str();
823}
824
Enrico Granata0a3958e2011-07-02 00:25:22 +0000825const char *
826ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,
827 lldb::Format custom_format)
828{
829 if(custom_format != lldb::eFormatInvalid)
830 SetFormat(custom_format);
831
832 const char * return_value;
833
834 switch(val_obj_display)
835 {
836 case eDisplayValue:
837 return_value = GetValueAsCString();
838 break;
839 case eDisplaySummary:
840 return_value = GetSummaryAsCString();
841 break;
842 case eDisplayLanguageSpecific:
843 return_value = GetObjectDescription();
844 break;
845 }
846
847
848 // try to use the value if the user's choice failed
849 if(!return_value && val_obj_display != eDisplayValue)
850 return_value = GetValueAsCString();
851
852 return return_value;
853
854}
855
Greg Clayton737b9322010-09-13 03:32:57 +0000856addr_t
Greg Claytone0d378b2011-03-24 21:19:54 +0000857ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address)
Greg Clayton73b472d2010-10-27 03:32:59 +0000858{
Jim Ingham78a685a2011-04-16 00:01:13 +0000859 if (!UpdateValueIfNeeded())
860 return LLDB_INVALID_ADDRESS;
861
Greg Clayton73b472d2010-10-27 03:32:59 +0000862 switch (m_value.GetValueType())
863 {
864 case Value::eValueTypeScalar:
865 if (scalar_is_load_address)
866 {
867 address_type = eAddressTypeLoad;
868 return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
869 }
870 break;
871
872 case Value::eValueTypeLoadAddress:
873 case Value::eValueTypeFileAddress:
874 case Value::eValueTypeHostAddress:
875 {
876 address_type = m_value.GetValueAddressType ();
877 return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
878 }
879 break;
880 }
881 address_type = eAddressTypeInvalid;
882 return LLDB_INVALID_ADDRESS;
883}
884
885addr_t
Greg Claytone0d378b2011-03-24 21:19:54 +0000886ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_address)
Greg Clayton737b9322010-09-13 03:32:57 +0000887{
888 lldb::addr_t address = LLDB_INVALID_ADDRESS;
889 address_type = eAddressTypeInvalid;
Jim Ingham78a685a2011-04-16 00:01:13 +0000890
891 if (!UpdateValueIfNeeded())
892 return address;
893
Greg Clayton73b472d2010-10-27 03:32:59 +0000894 switch (m_value.GetValueType())
Greg Clayton737b9322010-09-13 03:32:57 +0000895 {
896 case Value::eValueTypeScalar:
897 if (scalar_is_load_address)
898 {
899 address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
900 address_type = eAddressTypeLoad;
901 }
902 break;
903
904 case Value::eValueTypeLoadAddress:
905 case Value::eValueTypeFileAddress:
906 case Value::eValueTypeHostAddress:
907 {
908 uint32_t data_offset = 0;
909 address = m_data.GetPointer(&data_offset);
910 address_type = m_value.GetValueAddressType();
911 if (address_type == eAddressTypeInvalid)
912 address_type = eAddressTypeLoad;
913 }
914 break;
915 }
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000916
917 if (m_pointers_point_to_load_addrs)
918 address_type = eAddressTypeLoad;
919
Greg Clayton737b9322010-09-13 03:32:57 +0000920 return address;
921}
922
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000923bool
Jim Ingham6035b672011-03-31 00:19:25 +0000924ValueObject::SetValueFromCString (const char *value_str)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000925{
926 // Make sure our value is up to date first so that our location and location
927 // type is valid.
Jim Ingham6035b672011-03-31 00:19:25 +0000928 if (!UpdateValueIfNeeded())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000929 return false;
930
931 uint32_t count = 0;
Greg Clayton1be10fc2010-09-29 01:12:09 +0000932 lldb::Encoding encoding = ClangASTType::GetEncoding (GetClangType(), count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000933
934 char *end = NULL;
Greg Claytonb1320972010-07-14 00:18:15 +0000935 const size_t byte_size = GetByteSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000936 switch (encoding)
937 {
938 case eEncodingInvalid:
939 return false;
940
941 case eEncodingUint:
942 if (byte_size > sizeof(unsigned long long))
943 {
944 return false;
945 }
946 else
947 {
948 unsigned long long ull_val = strtoull(value_str, &end, 0);
949 if (end && *end != '\0')
950 return false;
951 m_value = ull_val;
952 // Limit the bytes in our m_data appropriately.
953 m_value.GetScalar().GetData (m_data, byte_size);
954 }
955 break;
956
957 case eEncodingSint:
958 if (byte_size > sizeof(long long))
959 {
960 return false;
961 }
962 else
963 {
964 long long sll_val = strtoll(value_str, &end, 0);
965 if (end && *end != '\0')
966 return false;
967 m_value = sll_val;
968 // Limit the bytes in our m_data appropriately.
969 m_value.GetScalar().GetData (m_data, byte_size);
970 }
971 break;
972
973 case eEncodingIEEE754:
974 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000975 const off_t byte_offset = GetByteOffset();
Greg Claytonc982c762010-07-09 20:39:50 +0000976 uint8_t *dst = const_cast<uint8_t *>(m_data.PeekData(byte_offset, byte_size));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000977 if (dst != NULL)
978 {
979 // We are decoding a float into host byte order below, so make
980 // sure m_data knows what it contains.
Greg Clayton7fb56d02011-02-01 01:31:41 +0000981 m_data.SetByteOrder(lldb::endian::InlHostByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000982 const size_t converted_byte_size = ClangASTContext::ConvertStringToFloatValue (
983 GetClangAST(),
Greg Clayton1be10fc2010-09-29 01:12:09 +0000984 GetClangType(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000985 value_str,
986 dst,
987 byte_size);
988
989 if (converted_byte_size == byte_size)
990 {
991 }
992 }
993 }
994 break;
995
996 case eEncodingVector:
997 return false;
998
999 default:
1000 return false;
1001 }
1002
1003 // If we have made it here the value is in m_data and we should write it
1004 // out to the target
1005 return Write ();
1006}
1007
1008bool
1009ValueObject::Write ()
1010{
1011 // Clear the update ID so the next time we try and read the value
1012 // we try and read it again.
Jim Ingham6035b672011-03-31 00:19:25 +00001013 m_update_point.SetNeedsUpdate();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001014
1015 // TODO: when Value has a method to write a value back, call it from here.
1016 return false;
1017
1018}
1019
Jim Ingham5a369122010-09-28 01:25:32 +00001020lldb::LanguageType
1021ValueObject::GetObjectRuntimeLanguage ()
1022{
Greg Clayton73b472d2010-10-27 03:32:59 +00001023 clang_type_t opaque_qual_type = GetClangType();
Jim Ingham5a369122010-09-28 01:25:32 +00001024 if (opaque_qual_type == NULL)
1025 return lldb::eLanguageTypeC;
1026
1027 // If the type is a reference, then resolve it to what it refers to first:
1028 clang::QualType qual_type (clang::QualType::getFromOpaquePtr(opaque_qual_type).getNonReferenceType());
1029 if (qual_type->isAnyPointerType())
1030 {
1031 if (qual_type->isObjCObjectPointerType())
1032 return lldb::eLanguageTypeObjC;
1033
1034 clang::QualType pointee_type (qual_type->getPointeeType());
1035 if (pointee_type->getCXXRecordDeclForPointerType() != NULL)
1036 return lldb::eLanguageTypeC_plus_plus;
1037 if (pointee_type->isObjCObjectOrInterfaceType())
1038 return lldb::eLanguageTypeObjC;
1039 if (pointee_type->isObjCClassType())
1040 return lldb::eLanguageTypeObjC;
1041 }
1042 else
1043 {
1044 if (ClangASTContext::IsObjCClassType (opaque_qual_type))
1045 return lldb::eLanguageTypeObjC;
Johnny Chend440bcc2010-09-28 16:10:54 +00001046 if (ClangASTContext::IsCXXClassType (opaque_qual_type))
Jim Ingham5a369122010-09-28 01:25:32 +00001047 return lldb::eLanguageTypeC_plus_plus;
1048 }
1049
1050 return lldb::eLanguageTypeC;
1051}
1052
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001053void
Jim Ingham58b59f92011-04-22 23:53:53 +00001054ValueObject::AddSyntheticChild (const ConstString &key, ValueObject *valobj)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001055{
Jim Ingham58b59f92011-04-22 23:53:53 +00001056 m_synthetic_children[key] = valobj;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001057}
1058
1059ValueObjectSP
1060ValueObject::GetSyntheticChild (const ConstString &key) const
1061{
1062 ValueObjectSP synthetic_child_sp;
Jim Ingham58b59f92011-04-22 23:53:53 +00001063 std::map<ConstString, ValueObject *>::const_iterator pos = m_synthetic_children.find (key);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001064 if (pos != m_synthetic_children.end())
Jim Ingham58b59f92011-04-22 23:53:53 +00001065 synthetic_child_sp = pos->second->GetSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001066 return synthetic_child_sp;
1067}
1068
1069bool
1070ValueObject::IsPointerType ()
1071{
Greg Clayton1be10fc2010-09-29 01:12:09 +00001072 return ClangASTContext::IsPointerType (GetClangType());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001073}
1074
Jim Inghamb7603bb2011-03-18 00:05:18 +00001075bool
1076ValueObject::IsIntegerType (bool &is_signed)
1077{
1078 return ClangASTContext::IsIntegerType (GetClangType(), is_signed);
1079}
Greg Clayton73b472d2010-10-27 03:32:59 +00001080
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001081bool
1082ValueObject::IsPointerOrReferenceType ()
1083{
Greg Clayton007d5be2011-05-30 00:49:24 +00001084 return ClangASTContext::IsPointerOrReferenceType (GetClangType());
1085}
1086
1087bool
1088ValueObject::IsPossibleCPlusPlusDynamicType ()
1089{
1090 return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001091}
1092
Greg Claytondea8cb42011-06-29 22:09:02 +00001093bool
1094ValueObject::IsPossibleDynamicType ()
1095{
1096 return ClangASTContext::IsPossibleDynamicType (GetClangAST (), GetClangType());
1097}
1098
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099ValueObjectSP
1100ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create)
1101{
1102 ValueObjectSP synthetic_child_sp;
1103 if (IsPointerType ())
1104 {
1105 char index_str[64];
1106 snprintf(index_str, sizeof(index_str), "[%i]", index);
1107 ConstString index_const_str(index_str);
1108 // Check if we have already created a synthetic array member in this
1109 // valid object. If we have we will re-use it.
1110 synthetic_child_sp = GetSyntheticChild (index_const_str);
1111 if (!synthetic_child_sp)
1112 {
Jim Ingham58b59f92011-04-22 23:53:53 +00001113 ValueObject *synthetic_child;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001114 // We haven't made a synthetic array member for INDEX yet, so
1115 // lets make one and cache it for any future reference.
Jim Ingham58b59f92011-04-22 23:53:53 +00001116 synthetic_child = CreateChildAtIndex(0, true, index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001117
1118 // Cache the value if we got one back...
Jim Ingham58b59f92011-04-22 23:53:53 +00001119 if (synthetic_child)
1120 {
1121 AddSyntheticChild(index_const_str, synthetic_child);
1122 synthetic_child_sp = synthetic_child->GetSP();
Enrico Granata0a3958e2011-07-02 00:25:22 +00001123 synthetic_child_sp->SetName(index_str);
1124 synthetic_child_sp->m_is_array_item_for_pointer = true;
Jim Ingham58b59f92011-04-22 23:53:53 +00001125 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001126 }
1127 }
1128 return synthetic_child_sp;
1129}
Jim Ingham22777012010-09-23 02:01:19 +00001130
Jim Ingham78a685a2011-04-16 00:01:13 +00001131void
Jim Ingham2837b762011-05-04 03:43:18 +00001132ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic)
Jim Ingham22777012010-09-23 02:01:19 +00001133{
Jim Ingham2837b762011-05-04 03:43:18 +00001134 if (use_dynamic == lldb::eNoDynamicValues)
1135 return;
1136
Jim Ingham58b59f92011-04-22 23:53:53 +00001137 if (!m_dynamic_value && !IsDynamic())
Jim Ingham78a685a2011-04-16 00:01:13 +00001138 {
1139 Process *process = m_update_point.GetProcess();
1140 bool worth_having_dynamic_value = false;
Jim Ingham22777012010-09-23 02:01:19 +00001141
Jim Ingham78a685a2011-04-16 00:01:13 +00001142
1143 // FIXME: Process should have some kind of "map over Runtimes" so we don't have to
1144 // hard code this everywhere.
1145 lldb::LanguageType known_type = GetObjectRuntimeLanguage();
1146 if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
1147 {
1148 LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
1149 if (runtime)
1150 worth_having_dynamic_value = runtime->CouldHaveDynamicValue(*this);
1151 }
1152 else
1153 {
1154 LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
1155 if (cpp_runtime)
1156 worth_having_dynamic_value = cpp_runtime->CouldHaveDynamicValue(*this);
1157
1158 if (!worth_having_dynamic_value)
1159 {
1160 LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
1161 if (objc_runtime)
Jim Ingham2837b762011-05-04 03:43:18 +00001162 worth_having_dynamic_value = objc_runtime->CouldHaveDynamicValue(*this);
Jim Ingham78a685a2011-04-16 00:01:13 +00001163 }
1164 }
1165
1166 if (worth_having_dynamic_value)
Jim Ingham2837b762011-05-04 03:43:18 +00001167 m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic);
Jim Ingham58b59f92011-04-22 23:53:53 +00001168
1169// if (worth_having_dynamic_value)
1170// printf ("Adding dynamic value %s (%p) to (%p) - manager %p.\n", m_name.GetCString(), m_dynamic_value, this, m_manager);
1171
Jim Ingham78a685a2011-04-16 00:01:13 +00001172 }
1173}
1174
Jim Ingham58b59f92011-04-22 23:53:53 +00001175ValueObjectSP
Jim Ingham2837b762011-05-04 03:43:18 +00001176ValueObject::GetDynamicValue (DynamicValueType use_dynamic)
Jim Ingham78a685a2011-04-16 00:01:13 +00001177{
Jim Ingham2837b762011-05-04 03:43:18 +00001178 if (use_dynamic == lldb::eNoDynamicValues)
1179 return ValueObjectSP();
1180
1181 if (!IsDynamic() && m_dynamic_value == NULL)
Jim Ingham78a685a2011-04-16 00:01:13 +00001182 {
Jim Ingham2837b762011-05-04 03:43:18 +00001183 CalculateDynamicValue(use_dynamic);
Jim Ingham78a685a2011-04-16 00:01:13 +00001184 }
Jim Ingham58b59f92011-04-22 23:53:53 +00001185 if (m_dynamic_value)
1186 return m_dynamic_value->GetSP();
1187 else
1188 return ValueObjectSP();
Jim Ingham22777012010-09-23 02:01:19 +00001189}
Greg Clayton1d3afba2010-10-05 00:00:42 +00001190
Greg Claytone221f822011-01-21 01:59:00 +00001191bool
1192ValueObject::GetBaseClassPath (Stream &s)
1193{
1194 if (IsBaseClass())
1195 {
Jim Ingham78a685a2011-04-16 00:01:13 +00001196 bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s);
Greg Claytone221f822011-01-21 01:59:00 +00001197 clang_type_t clang_type = GetClangType();
1198 std::string cxx_class_name;
1199 bool this_had_base_class = ClangASTContext::GetCXXClassName (clang_type, cxx_class_name);
1200 if (this_had_base_class)
1201 {
1202 if (parent_had_base_class)
1203 s.PutCString("::");
1204 s.PutCString(cxx_class_name.c_str());
1205 }
1206 return parent_had_base_class || this_had_base_class;
1207 }
1208 return false;
1209}
1210
1211
1212ValueObject *
1213ValueObject::GetNonBaseClassParent()
1214{
Jim Ingham78a685a2011-04-16 00:01:13 +00001215 if (GetParent())
Greg Claytone221f822011-01-21 01:59:00 +00001216 {
Jim Ingham78a685a2011-04-16 00:01:13 +00001217 if (GetParent()->IsBaseClass())
1218 return GetParent()->GetNonBaseClassParent();
Greg Claytone221f822011-01-21 01:59:00 +00001219 else
Jim Ingham78a685a2011-04-16 00:01:13 +00001220 return GetParent();
Greg Claytone221f822011-01-21 01:59:00 +00001221 }
1222 return NULL;
1223}
Greg Clayton1d3afba2010-10-05 00:00:42 +00001224
1225void
Enrico Granata4becb372011-06-29 22:27:15 +00001226ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001227{
Greg Claytone221f822011-01-21 01:59:00 +00001228 const bool is_deref_of_parent = IsDereferenceOfParent ();
Greg Claytone221f822011-01-21 01:59:00 +00001229
Enrico Granata4becb372011-06-29 22:27:15 +00001230 if(is_deref_of_parent && epformat == eDereferencePointers) {
1231 // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely
1232 // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName.
1233 // the eHonorPointers mode is meant to produce strings in this latter format
1234 s.PutCString("*(");
1235 }
Greg Claytone221f822011-01-21 01:59:00 +00001236
Enrico Granata4becb372011-06-29 22:27:15 +00001237 ValueObject* parent = GetParent();
1238
1239 if (parent)
1240 parent->GetExpressionPath (s, qualify_cxx_base_classes, epformat);
Enrico Granata0a3958e2011-07-02 00:25:22 +00001241
1242 // if we are a deref_of_parent just because we are synthetic array
1243 // members made up to allow ptr[%d] syntax to work in variable
1244 // printing, then add our name ([%d]) to the expression path
1245 if(m_is_array_item_for_pointer && epformat == eHonorPointers)
1246 s.PutCString(m_name.AsCString());
Enrico Granata4becb372011-06-29 22:27:15 +00001247
Greg Claytone221f822011-01-21 01:59:00 +00001248 if (!IsBaseClass())
1249 {
1250 if (!is_deref_of_parent)
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001251 {
Greg Claytone221f822011-01-21 01:59:00 +00001252 ValueObject *non_base_class_parent = GetNonBaseClassParent();
1253 if (non_base_class_parent)
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001254 {
Greg Claytone221f822011-01-21 01:59:00 +00001255 clang_type_t non_base_class_parent_clang_type = non_base_class_parent->GetClangType();
1256 if (non_base_class_parent_clang_type)
1257 {
1258 const uint32_t non_base_class_parent_type_info = ClangASTContext::GetTypeInfo (non_base_class_parent_clang_type, NULL, NULL);
1259
Enrico Granata4becb372011-06-29 22:27:15 +00001260 if(parent && parent->IsDereferenceOfParent() && epformat == eHonorPointers)
Greg Claytone221f822011-01-21 01:59:00 +00001261 {
1262 s.PutCString("->");
1263 }
Enrico Granata4becb372011-06-29 22:27:15 +00001264 else
1265 {
1266 if (non_base_class_parent_type_info & ClangASTContext::eTypeIsPointer)
1267 {
1268 s.PutCString("->");
1269 }
1270 else if ((non_base_class_parent_type_info & ClangASTContext::eTypeHasChildren) &&
1271 !(non_base_class_parent_type_info & ClangASTContext::eTypeIsArray))
1272 {
1273 s.PutChar('.');
1274 }
Greg Claytone221f822011-01-21 01:59:00 +00001275 }
1276 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001277 }
Greg Claytone221f822011-01-21 01:59:00 +00001278
1279 const char *name = GetName().GetCString();
1280 if (name)
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001281 {
Greg Claytone221f822011-01-21 01:59:00 +00001282 if (qualify_cxx_base_classes)
1283 {
1284 if (GetBaseClassPath (s))
1285 s.PutCString("::");
1286 }
1287 s.PutCString(name);
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001288 }
1289 }
1290 }
1291
Enrico Granata4becb372011-06-29 22:27:15 +00001292 if (is_deref_of_parent && epformat == eDereferencePointers) {
Greg Claytone221f822011-01-21 01:59:00 +00001293 s.PutChar(')');
Enrico Granata4becb372011-06-29 22:27:15 +00001294 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001295}
1296
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001297void
Greg Clayton1d3afba2010-10-05 00:00:42 +00001298ValueObject::DumpValueObject
1299(
1300 Stream &s,
Greg Clayton1d3afba2010-10-05 00:00:42 +00001301 ValueObject *valobj,
1302 const char *root_valobj_name,
1303 uint32_t ptr_depth,
1304 uint32_t curr_depth,
1305 uint32_t max_depth,
1306 bool show_types,
1307 bool show_location,
1308 bool use_objc,
Jim Ingham2837b762011-05-04 03:43:18 +00001309 lldb::DynamicValueType use_dynamic,
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001310 bool scope_already_checked,
1311 bool flat_output
Greg Clayton1d3afba2010-10-05 00:00:42 +00001312)
1313{
Greg Clayton007d5be2011-05-30 00:49:24 +00001314 if (valobj)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001315 {
Greg Clayton007d5be2011-05-30 00:49:24 +00001316 bool update_success = valobj->UpdateValueIfNeeded ();
1317
1318 if (update_success && use_dynamic != lldb::eNoDynamicValues)
Jim Ingham78a685a2011-04-16 00:01:13 +00001319 {
Jim Ingham2837b762011-05-04 03:43:18 +00001320 ValueObject *dynamic_value = valobj->GetDynamicValue(use_dynamic).get();
Jim Ingham78a685a2011-04-16 00:01:13 +00001321 if (dynamic_value)
1322 valobj = dynamic_value;
1323 }
1324
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001325 clang_type_t clang_type = valobj->GetClangType();
1326
Greg Clayton73b472d2010-10-27 03:32:59 +00001327 const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, NULL, NULL));
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001328 const char *err_cstr = NULL;
Greg Clayton73b472d2010-10-27 03:32:59 +00001329 const bool has_children = type_flags.Test (ClangASTContext::eTypeHasChildren);
1330 const bool has_value = type_flags.Test (ClangASTContext::eTypeHasValue);
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001331
1332 const bool print_valobj = flat_output == false || has_value;
1333
1334 if (print_valobj)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001335 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001336 if (show_location)
1337 {
Jim Ingham6035b672011-03-31 00:19:25 +00001338 s.Printf("%s: ", valobj->GetLocationAsCString());
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001339 }
Greg Clayton1d3afba2010-10-05 00:00:42 +00001340
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001341 s.Indent();
Greg Clayton1d3afba2010-10-05 00:00:42 +00001342
Greg Clayton7c8a9662010-11-02 01:50:16 +00001343 // Always show the type for the top level items.
Greg Claytone221f822011-01-21 01:59:00 +00001344 if (show_types || (curr_depth == 0 && !flat_output))
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001345 s.Printf("(%s) ", valobj->GetTypeName().AsCString("<invalid type>"));
Greg Clayton1d3afba2010-10-05 00:00:42 +00001346
Greg Clayton1d3afba2010-10-05 00:00:42 +00001347
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001348 if (flat_output)
1349 {
Greg Clayton6beaaa62011-01-17 03:46:26 +00001350 // If we are showing types, also qualify the C++ base classes
1351 const bool qualify_cxx_base_classes = show_types;
1352 valobj->GetExpressionPath(s, qualify_cxx_base_classes);
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001353 s.PutCString(" =");
1354 }
1355 else
1356 {
1357 const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
1358 s.Printf ("%s =", name_cstr);
1359 }
1360
Jim Ingham6035b672011-03-31 00:19:25 +00001361 if (!scope_already_checked && !valobj->IsInScope())
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001362 {
Greg Clayton007d5be2011-05-30 00:49:24 +00001363 err_cstr = "out of scope";
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001364 }
Greg Clayton1d3afba2010-10-05 00:00:42 +00001365 }
1366
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001367 const char *val_cstr = NULL;
Enrico Granata4becb372011-06-29 22:27:15 +00001368 const char *sum_cstr = NULL;
1369 SummaryFormat* entry = valobj->m_last_summary_format.get();
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001370
1371 if (err_cstr == NULL)
1372 {
Jim Ingham6035b672011-03-31 00:19:25 +00001373 val_cstr = valobj->GetValueAsCString();
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001374 err_cstr = valobj->GetError().AsCString();
1375 }
Greg Clayton1d3afba2010-10-05 00:00:42 +00001376
1377 if (err_cstr)
1378 {
Greg Clayton007d5be2011-05-30 00:49:24 +00001379 s.Printf (" <%s>\n", err_cstr);
Greg Clayton1d3afba2010-10-05 00:00:42 +00001380 }
1381 else
1382 {
Greg Clayton73b472d2010-10-27 03:32:59 +00001383 const bool is_ref = type_flags.Test (ClangASTContext::eTypeIsReference);
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001384 if (print_valobj)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001385 {
Enrico Granata4becb372011-06-29 22:27:15 +00001386
1387 sum_cstr = valobj->GetSummaryAsCString();
Greg Clayton1d3afba2010-10-05 00:00:42 +00001388
Enrico Granata4becb372011-06-29 22:27:15 +00001389 // We must calculate this value in realtime because entry might alter this variable's value
1390 // (e.g. by saying ${var%fmt}) and render precached values useless
1391 if (val_cstr && (!entry || entry->DoesPrintValue() || !sum_cstr))
1392 s.Printf(" %s", valobj->GetValueAsCString());
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001393
Enrico Granata0a3958e2011-07-02 00:25:22 +00001394 if(sum_cstr)
1395 {
1396 // for some reason, using %@ (ObjC description) in a summary string, makes
1397 // us believe we need to reset ourselves, thus invalidating the content of
1398 // sum_cstr. Thus, IF we had a valid sum_cstr before, but it is now empty
1399 // let us recalculate it!
1400 if (sum_cstr[0] == '\0')
1401 s.Printf(" %s", valobj->GetSummaryAsCString());
1402 else
1403 s.Printf(" %s", sum_cstr);
1404 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001405
1406 if (use_objc)
1407 {
Jim Ingham6035b672011-03-31 00:19:25 +00001408 const char *object_desc = valobj->GetObjectDescription();
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001409 if (object_desc)
1410 s.Printf(" %s\n", object_desc);
1411 else
Sean Callanan672ad942010-10-23 00:18:49 +00001412 s.Printf (" [no Objective-C description available]\n");
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001413 return;
Enrico Granata0a3958e2011-07-02 00:25:22 +00001414 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001415 }
Greg Clayton1d3afba2010-10-05 00:00:42 +00001416
1417 if (curr_depth < max_depth)
1418 {
Greg Clayton73b472d2010-10-27 03:32:59 +00001419 // We will show children for all concrete types. We won't show
1420 // pointer contents unless a pointer depth has been specified.
1421 // We won't reference contents unless the reference is the
1422 // root object (depth of zero).
1423 bool print_children = true;
1424
1425 // Use a new temporary pointer depth in case we override the
1426 // current pointer depth below...
1427 uint32_t curr_ptr_depth = ptr_depth;
1428
1429 const bool is_ptr = type_flags.Test (ClangASTContext::eTypeIsPointer);
1430 if (is_ptr || is_ref)
1431 {
1432 // We have a pointer or reference whose value is an address.
1433 // Make sure that address is not NULL
Greg Claytone0d378b2011-03-24 21:19:54 +00001434 AddressType ptr_address_type;
Greg Clayton73b472d2010-10-27 03:32:59 +00001435 if (valobj->GetPointerValue (ptr_address_type, true) == 0)
1436 print_children = false;
1437
1438 else if (is_ref && curr_depth == 0)
1439 {
1440 // If this is the root object (depth is zero) that we are showing
1441 // and it is a reference, and no pointer depth has been supplied
1442 // print out what it references. Don't do this at deeper depths
1443 // otherwise we can end up with infinite recursion...
1444 curr_ptr_depth = 1;
1445 }
1446
1447 if (curr_ptr_depth == 0)
1448 print_children = false;
1449 }
Greg Clayton1d3afba2010-10-05 00:00:42 +00001450
Enrico Granata0a3958e2011-07-02 00:25:22 +00001451 if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr))
Greg Clayton1d3afba2010-10-05 00:00:42 +00001452 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001453 const uint32_t num_children = valobj->GetNumChildren();
1454 if (num_children)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001455 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001456 if (flat_output)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001457 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001458 if (print_valobj)
1459 s.EOL();
1460 }
1461 else
1462 {
1463 if (print_valobj)
Greg Clayton93aa84e2010-10-29 04:59:35 +00001464 s.PutCString(is_ref ? ": {\n" : " {\n");
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001465 s.IndentMore();
1466 }
1467
1468 for (uint32_t idx=0; idx<num_children; ++idx)
1469 {
1470 ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
1471 if (child_sp.get())
1472 {
1473 DumpValueObject (s,
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001474 child_sp.get(),
1475 NULL,
Greg Clayton73b472d2010-10-27 03:32:59 +00001476 (is_ptr || is_ref) ? curr_ptr_depth - 1 : curr_ptr_depth,
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001477 curr_depth + 1,
1478 max_depth,
1479 show_types,
1480 show_location,
1481 false,
Jim Ingham78a685a2011-04-16 00:01:13 +00001482 use_dynamic,
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001483 true,
1484 flat_output);
1485 }
1486 }
1487
1488 if (!flat_output)
1489 {
1490 s.IndentLess();
1491 s.Indent("}\n");
Greg Clayton1d3afba2010-10-05 00:00:42 +00001492 }
1493 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001494 else if (has_children)
1495 {
1496 // Aggregate, no children...
1497 if (print_valobj)
Greg Clayton73b472d2010-10-27 03:32:59 +00001498 s.PutCString(" {}\n");
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001499 }
1500 else
1501 {
1502 if (print_valobj)
1503 s.EOL();
1504 }
1505
Greg Clayton1d3afba2010-10-05 00:00:42 +00001506 }
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001507 else
1508 {
Greg Clayton1d3afba2010-10-05 00:00:42 +00001509 s.EOL();
Greg Clayton1d3afba2010-10-05 00:00:42 +00001510 }
1511 }
1512 else
1513 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001514 if (has_children && print_valobj)
Greg Clayton1d3afba2010-10-05 00:00:42 +00001515 {
Greg Clayton8f92f0a2010-10-14 22:52:14 +00001516 s.PutCString("{...}\n");
Greg Clayton1d3afba2010-10-05 00:00:42 +00001517 }
1518 }
1519 }
1520 }
1521}
1522
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001523
1524ValueObjectSP
Jim Ingham6035b672011-03-31 00:19:25 +00001525ValueObject::CreateConstantValue (const ConstString &name)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001526{
1527 ValueObjectSP valobj_sp;
1528
Jim Ingham6035b672011-03-31 00:19:25 +00001529 if (UpdateValueIfNeeded() && m_error.Success())
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001530 {
Jim Ingham6035b672011-03-31 00:19:25 +00001531 ExecutionContextScope *exe_scope = GetExecutionContextScope();
1532 if (exe_scope)
1533 {
1534 ExecutionContext exe_ctx;
1535 exe_scope->CalculateExecutionContext(exe_ctx);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001536
Jim Ingham6035b672011-03-31 00:19:25 +00001537 clang::ASTContext *ast = GetClangAST ();
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001538
Jim Ingham6035b672011-03-31 00:19:25 +00001539 DataExtractor data;
1540 data.SetByteOrder (m_data.GetByteOrder());
1541 data.SetAddressByteSize(m_data.GetAddressByteSize());
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001542
Jim Ingham6035b672011-03-31 00:19:25 +00001543 m_error = m_value.GetValueAsData (&exe_ctx, ast, data, 0);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001544
Jim Ingham58b59f92011-04-22 23:53:53 +00001545 valobj_sp = ValueObjectConstResult::Create (exe_scope,
1546 ast,
1547 GetClangType(),
1548 name,
1549 data);
Jim Ingham6035b672011-03-31 00:19:25 +00001550 }
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001551 }
Jim Ingham6035b672011-03-31 00:19:25 +00001552
1553 if (!valobj_sp)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001554 {
Jim Ingham58b59f92011-04-22 23:53:53 +00001555 valobj_sp = ValueObjectConstResult::Create (NULL, m_error);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001556 }
1557 return valobj_sp;
1558}
1559
1560lldb::ValueObjectSP
Greg Claytonaf67cec2010-12-20 20:49:23 +00001561ValueObject::Dereference (Error &error)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001562{
Jim Ingham58b59f92011-04-22 23:53:53 +00001563 if (m_deref_valobj)
1564 return m_deref_valobj->GetSP();
Jim Ingham78a685a2011-04-16 00:01:13 +00001565
Greg Clayton54979cd2010-12-15 05:08:08 +00001566 const bool is_pointer_type = IsPointerType();
1567 if (is_pointer_type)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001568 {
1569 bool omit_empty_base_classes = true;
1570
1571 std::string child_name_str;
1572 uint32_t child_byte_size = 0;
1573 int32_t child_byte_offset = 0;
1574 uint32_t child_bitfield_bit_size = 0;
1575 uint32_t child_bitfield_bit_offset = 0;
1576 bool child_is_base_class = false;
Greg Claytone221f822011-01-21 01:59:00 +00001577 bool child_is_deref_of_parent = false;
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001578 const bool transparent_pointers = false;
1579 clang::ASTContext *clang_ast = GetClangAST();
1580 clang_type_t clang_type = GetClangType();
1581 clang_type_t child_clang_type;
Jim Inghamd555bac2011-06-24 22:03:24 +00001582
1583 ExecutionContext exe_ctx;
1584 GetExecutionContextScope()->CalculateExecutionContext (exe_ctx);
1585
1586 child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
1587 clang_ast,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001588 GetName().GetCString(),
1589 clang_type,
1590 0,
1591 transparent_pointers,
1592 omit_empty_base_classes,
1593 child_name_str,
1594 child_byte_size,
1595 child_byte_offset,
1596 child_bitfield_bit_size,
1597 child_bitfield_bit_offset,
Greg Claytone221f822011-01-21 01:59:00 +00001598 child_is_base_class,
1599 child_is_deref_of_parent);
Greg Clayton3e06bd92011-01-09 21:07:35 +00001600 if (child_clang_type && child_byte_size)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001601 {
1602 ConstString child_name;
1603 if (!child_name_str.empty())
1604 child_name.SetCString (child_name_str.c_str());
1605
Jim Ingham58b59f92011-04-22 23:53:53 +00001606 m_deref_valobj = new ValueObjectChild (*this,
1607 clang_ast,
1608 child_clang_type,
1609 child_name,
1610 child_byte_size,
1611 child_byte_offset,
1612 child_bitfield_bit_size,
1613 child_bitfield_bit_offset,
1614 child_is_base_class,
1615 child_is_deref_of_parent);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001616 }
1617 }
Greg Clayton54979cd2010-12-15 05:08:08 +00001618
Jim Ingham58b59f92011-04-22 23:53:53 +00001619 if (m_deref_valobj)
Greg Clayton54979cd2010-12-15 05:08:08 +00001620 {
1621 error.Clear();
Jim Ingham58b59f92011-04-22 23:53:53 +00001622 return m_deref_valobj->GetSP();
Greg Clayton54979cd2010-12-15 05:08:08 +00001623 }
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001624 else
1625 {
Greg Clayton54979cd2010-12-15 05:08:08 +00001626 StreamString strm;
Greg Clayton6beaaa62011-01-17 03:46:26 +00001627 GetExpressionPath(strm, true);
Greg Clayton54979cd2010-12-15 05:08:08 +00001628
1629 if (is_pointer_type)
1630 error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
1631 else
1632 error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
Jim Ingham58b59f92011-04-22 23:53:53 +00001633 return ValueObjectSP();
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001634 }
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001635}
1636
Jim Ingham78a685a2011-04-16 00:01:13 +00001637lldb::ValueObjectSP
Greg Clayton54979cd2010-12-15 05:08:08 +00001638ValueObject::AddressOf (Error &error)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001639{
Jim Ingham78a685a2011-04-16 00:01:13 +00001640 if (m_addr_of_valobj_sp)
1641 return m_addr_of_valobj_sp;
1642
Greg Claytone0d378b2011-03-24 21:19:54 +00001643 AddressType address_type = eAddressTypeInvalid;
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001644 const bool scalar_is_load_address = false;
1645 lldb::addr_t addr = GetAddressOf (address_type, scalar_is_load_address);
Greg Clayton54979cd2010-12-15 05:08:08 +00001646 error.Clear();
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001647 if (addr != LLDB_INVALID_ADDRESS)
1648 {
1649 switch (address_type)
1650 {
Greg Clayton54979cd2010-12-15 05:08:08 +00001651 default:
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001652 case eAddressTypeInvalid:
Greg Clayton54979cd2010-12-15 05:08:08 +00001653 {
1654 StreamString expr_path_strm;
Greg Clayton6beaaa62011-01-17 03:46:26 +00001655 GetExpressionPath(expr_path_strm, true);
Greg Clayton54979cd2010-12-15 05:08:08 +00001656 error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_strm.GetString().c_str());
1657 }
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001658 break;
Greg Clayton54979cd2010-12-15 05:08:08 +00001659
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001660 case eAddressTypeFile:
1661 case eAddressTypeLoad:
1662 case eAddressTypeHost:
1663 {
1664 clang::ASTContext *ast = GetClangAST();
1665 clang_type_t clang_type = GetClangType();
1666 if (ast && clang_type)
1667 {
1668 std::string name (1, '&');
1669 name.append (m_name.AsCString(""));
Jim Ingham58b59f92011-04-22 23:53:53 +00001670 m_addr_of_valobj_sp = ValueObjectConstResult::Create (GetExecutionContextScope(),
1671 ast,
1672 ClangASTContext::CreatePointerType (ast, clang_type),
1673 ConstString (name.c_str()),
1674 addr,
1675 eAddressTypeInvalid,
1676 m_data.GetAddressByteSize());
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001677 }
1678 }
1679 break;
1680 }
1681 }
Jim Ingham78a685a2011-04-16 00:01:13 +00001682 return m_addr_of_valobj_sp;
Greg Clayton8b2fe6d2010-12-14 02:59:59 +00001683}
1684
Greg Claytonb2dcc362011-05-05 23:32:56 +00001685
1686lldb::ValueObjectSP
1687ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type)
1688{
1689 lldb::ValueObjectSP valobj_sp;
1690 AddressType address_type;
1691 const bool scalar_is_load_address = true;
1692 lldb::addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address);
1693
1694 if (ptr_value != LLDB_INVALID_ADDRESS)
1695 {
1696 Address ptr_addr (NULL, ptr_value);
1697
1698 valobj_sp = ValueObjectMemory::Create (GetExecutionContextScope(),
1699 name,
1700 ptr_addr,
1701 clang_ast_type);
1702 }
1703 return valobj_sp;
1704}
1705
1706lldb::ValueObjectSP
1707ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
1708{
1709 lldb::ValueObjectSP valobj_sp;
1710 AddressType address_type;
1711 const bool scalar_is_load_address = true;
1712 lldb::addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address);
1713
1714 if (ptr_value != LLDB_INVALID_ADDRESS)
1715 {
1716 Address ptr_addr (NULL, ptr_value);
1717
1718 valobj_sp = ValueObjectMemory::Create (GetExecutionContextScope(),
1719 name,
1720 ptr_addr,
1721 type_sp);
1722 }
1723 return valobj_sp;
1724}
1725
1726
Jim Ingham6035b672011-03-31 00:19:25 +00001727ValueObject::EvaluationPoint::EvaluationPoint () :
Stephen Wilson71c21d12011-04-11 19:41:40 +00001728 m_thread_id (LLDB_INVALID_UID),
1729 m_stop_id (0)
Jim Ingham6035b672011-03-31 00:19:25 +00001730{
1731}
1732
1733ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
Jim Ingham6035b672011-03-31 00:19:25 +00001734 m_needs_update (true),
Stephen Wilson71c21d12011-04-11 19:41:40 +00001735 m_first_update (true),
1736 m_thread_id (LLDB_INVALID_UID),
1737 m_stop_id (0)
1738
Jim Ingham6035b672011-03-31 00:19:25 +00001739{
1740 ExecutionContext exe_ctx;
1741 ExecutionContextScope *computed_exe_scope = exe_scope; // If use_selected is true, we may find a better scope,
1742 // and if so we want to cache that not the original.
1743 if (exe_scope)
1744 exe_scope->CalculateExecutionContext(exe_ctx);
1745 if (exe_ctx.target != NULL)
1746 {
1747 m_target_sp = exe_ctx.target->GetSP();
1748
1749 if (exe_ctx.process == NULL)
1750 m_process_sp = exe_ctx.target->GetProcessSP();
1751 else
1752 m_process_sp = exe_ctx.process->GetSP();
1753
1754 if (m_process_sp != NULL)
1755 {
1756 m_stop_id = m_process_sp->GetStopID();
1757 Thread *thread = NULL;
1758
1759 if (exe_ctx.thread == NULL)
1760 {
1761 if (use_selected)
1762 {
1763 thread = m_process_sp->GetThreadList().GetSelectedThread().get();
1764 if (thread)
1765 computed_exe_scope = thread;
1766 }
1767 }
1768 else
1769 thread = exe_ctx.thread;
1770
1771 if (thread != NULL)
1772 {
1773 m_thread_id = thread->GetIndexID();
1774 if (exe_ctx.frame == NULL)
1775 {
1776 if (use_selected)
1777 {
1778 StackFrame *frame = exe_ctx.thread->GetSelectedFrame().get();
1779 if (frame)
1780 {
1781 m_stack_id = frame->GetStackID();
1782 computed_exe_scope = frame;
1783 }
1784 }
1785 }
1786 else
1787 m_stack_id = exe_ctx.frame->GetStackID();
1788 }
1789 }
1790 }
1791 m_exe_scope = computed_exe_scope;
1792}
1793
1794ValueObject::EvaluationPoint::EvaluationPoint (const ValueObject::EvaluationPoint &rhs) :
1795 m_exe_scope (rhs.m_exe_scope),
Stephen Wilson71c21d12011-04-11 19:41:40 +00001796 m_needs_update(true),
1797 m_first_update(true),
Jim Ingham6035b672011-03-31 00:19:25 +00001798 m_target_sp (rhs.m_target_sp),
1799 m_process_sp (rhs.m_process_sp),
1800 m_thread_id (rhs.m_thread_id),
1801 m_stack_id (rhs.m_stack_id),
Jim Ingham6035b672011-03-31 00:19:25 +00001802 m_stop_id (0)
1803{
1804}
1805
1806ValueObject::EvaluationPoint::~EvaluationPoint ()
1807{
1808}
1809
1810ExecutionContextScope *
1811ValueObject::EvaluationPoint::GetExecutionContextScope ()
1812{
1813 // We have to update before giving out the scope, or we could be handing out stale pointers.
1814 SyncWithProcessState();
1815
1816 return m_exe_scope;
1817}
1818
1819// This function checks the EvaluationPoint against the current process state. If the current
1820// state matches the evaluation point, or the evaluation point is already invalid, then we return
1821// false, meaning "no change". If the current state is different, we update our state, and return
1822// true meaning "yes, change". If we did see a change, we also set m_needs_update to true, so
1823// future calls to NeedsUpdate will return true.
1824
1825bool
1826ValueObject::EvaluationPoint::SyncWithProcessState()
1827{
1828 // If we're already invalid, we don't need to do anything, and nothing has changed:
1829 if (m_stop_id == LLDB_INVALID_UID)
1830 {
1831 // Can't update with an invalid state.
1832 m_needs_update = false;
1833 return false;
1834 }
1835
1836 // If we don't have a process nothing can change.
1837 if (!m_process_sp)
1838 return false;
1839
1840 // If our stop id is the current stop ID, nothing has changed:
Jim Ingham78a685a2011-04-16 00:01:13 +00001841 uint32_t cur_stop_id = m_process_sp->GetStopID();
1842 if (m_stop_id == cur_stop_id)
Jim Ingham6035b672011-03-31 00:19:25 +00001843 return false;
1844
Jim Ingham78a685a2011-04-16 00:01:13 +00001845 // If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
1846 // In either case, we aren't going to be able to sync with the process state.
1847 if (cur_stop_id == 0)
1848 return false;
1849
1850 m_stop_id = cur_stop_id;
Jim Ingham6035b672011-03-31 00:19:25 +00001851 m_needs_update = true;
1852 m_exe_scope = m_process_sp.get();
1853
1854 // Something has changed, so we will return true. Now make sure the thread & frame still exist, and if either
1855 // doesn't, mark ourselves as invalid.
1856
1857 if (m_thread_id != LLDB_INVALID_THREAD_ID)
1858 {
1859 Thread *our_thread = m_process_sp->GetThreadList().FindThreadByIndexID (m_thread_id).get();
1860 if (our_thread == NULL)
1861 SetInvalid();
1862 else
1863 {
1864 m_exe_scope = our_thread;
1865
1866 if (m_stack_id.IsValid())
1867 {
1868 StackFrame *our_frame = our_thread->GetFrameWithStackID (m_stack_id).get();
1869 if (our_frame == NULL)
1870 SetInvalid();
1871 else
1872 m_exe_scope = our_frame;
1873 }
1874 }
1875 }
1876 return true;
1877}
1878
Jim Ingham61be0902011-05-02 18:13:59 +00001879void
1880ValueObject::EvaluationPoint::SetUpdated ()
1881{
1882 m_first_update = false;
1883 m_needs_update = false;
1884 if (m_process_sp)
1885 m_stop_id = m_process_sp->GetStopID();
1886}
1887
1888
Jim Ingham6035b672011-03-31 00:19:25 +00001889bool
1890ValueObject::EvaluationPoint::SetContext (ExecutionContextScope *exe_scope)
1891{
1892 if (!IsValid())
1893 return false;
1894
1895 bool needs_update = false;
1896 m_exe_scope = NULL;
1897
1898 // The target has to be non-null, and the
1899 Target *target = exe_scope->CalculateTarget();
1900 if (target != NULL)
1901 {
1902 Target *old_target = m_target_sp.get();
1903 assert (target == old_target);
1904 Process *process = exe_scope->CalculateProcess();
1905 if (process != NULL)
1906 {
1907 // FOR NOW - assume you can't update variable objects across process boundaries.
1908 Process *old_process = m_process_sp.get();
1909 assert (process == old_process);
1910
1911 lldb::user_id_t stop_id = process->GetStopID();
1912 if (stop_id != m_stop_id)
1913 {
1914 needs_update = true;
1915 m_stop_id = stop_id;
1916 }
1917 // See if we're switching the thread or stack context. If no thread is given, this is
1918 // being evaluated in a global context.
1919 Thread *thread = exe_scope->CalculateThread();
1920 if (thread != NULL)
1921 {
1922 lldb::user_id_t new_thread_index = thread->GetIndexID();
1923 if (new_thread_index != m_thread_id)
1924 {
1925 needs_update = true;
1926 m_thread_id = new_thread_index;
1927 m_stack_id.Clear();
1928 }
1929
1930 StackFrame *new_frame = exe_scope->CalculateStackFrame();
1931 if (new_frame != NULL)
1932 {
1933 if (new_frame->GetStackID() != m_stack_id)
1934 {
1935 needs_update = true;
1936 m_stack_id = new_frame->GetStackID();
1937 }
1938 }
1939 else
1940 {
1941 m_stack_id.Clear();
1942 needs_update = true;
1943 }
1944 }
1945 else
1946 {
1947 // If this had been given a thread, and now there is none, we should update.
1948 // Otherwise we don't have to do anything.
1949 if (m_thread_id != LLDB_INVALID_UID)
1950 {
1951 m_thread_id = LLDB_INVALID_UID;
1952 m_stack_id.Clear();
1953 needs_update = true;
1954 }
1955 }
1956 }
1957 else
1958 {
1959 // If there is no process, then we don't need to update anything.
1960 // But if we're switching from having a process to not, we should try to update.
1961 if (m_process_sp.get() != NULL)
1962 {
1963 needs_update = true;
1964 m_process_sp.reset();
1965 m_thread_id = LLDB_INVALID_UID;
1966 m_stack_id.Clear();
1967 }
1968 }
1969 }
1970 else
1971 {
1972 // If there's no target, nothing can change so we don't need to update anything.
1973 // But if we're switching from having a target to not, we should try to update.
1974 if (m_target_sp.get() != NULL)
1975 {
1976 needs_update = true;
1977 m_target_sp.reset();
1978 m_process_sp.reset();
1979 m_thread_id = LLDB_INVALID_UID;
1980 m_stack_id.Clear();
1981 }
1982 }
1983 if (!m_needs_update)
1984 m_needs_update = needs_update;
1985
1986 return needs_update;
1987}