forked from OSchip/llvm-project
Fixed ValueObject::UpdateValueIfNeeded to keep
track of the checksum of the object so we can track if it is modified. This fixes a testcase (test/expression_command/issue_11588) on OS X. Patch by Enrico Granata. llvm-svn: 223830
This commit is contained in:
parent
21909e35cb
commit
7375f3e30e
|
@ -13,9 +13,13 @@
|
|||
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -1309,6 +1313,11 @@ public:
|
|||
return size - offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Checksum (llvm::SmallVectorImpl<uint8_t> &dest,
|
||||
uint64_t max_data = 0);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
// C++ Includes
|
||||
#include <map>
|
||||
#include <vector>
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
// Project includes
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
|
@ -270,12 +272,6 @@ public:
|
|||
m_mod_id = new_id;
|
||||
}
|
||||
|
||||
bool
|
||||
IsFirstEvaluation () const
|
||||
{
|
||||
return m_first_update;
|
||||
}
|
||||
|
||||
void
|
||||
SetNeedsUpdate ()
|
||||
{
|
||||
|
@ -324,7 +320,6 @@ public:
|
|||
ProcessModID m_mod_id; // This is the stop id when this ValueObject was last evaluated.
|
||||
ExecutionContextRef m_exe_ctx_ref;
|
||||
bool m_needs_update;
|
||||
bool m_first_update;
|
||||
};
|
||||
|
||||
const EvaluationPoint &
|
||||
|
@ -1103,6 +1098,8 @@ protected:
|
|||
ProcessModID m_user_id_of_forced_summary;
|
||||
AddressType m_address_type_of_ptr_or_ref_children;
|
||||
|
||||
llvm::SmallVector<uint8_t, 16> m_value_checksum;
|
||||
|
||||
bool m_value_is_valid:1,
|
||||
m_value_did_change:1,
|
||||
m_children_count_valid:1,
|
||||
|
@ -1208,6 +1205,9 @@ protected:
|
|||
GetLocationAsCStringImpl (const Value& value,
|
||||
const DataExtractor& data);
|
||||
|
||||
bool
|
||||
IsChecksumEmpty ();
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
// For ValueObject only
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
#include "llvm/Support/MD5.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
|
@ -2238,3 +2238,27 @@ DataExtractor::Append(void* buf, offset_t length)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DataExtractor::Checksum (llvm::SmallVectorImpl<uint8_t> &dest,
|
||||
uint64_t max_data)
|
||||
{
|
||||
if (max_data == 0)
|
||||
max_data = GetByteSize();
|
||||
else
|
||||
max_data = std::min(max_data, GetByteSize());
|
||||
|
||||
llvm::MD5 md5;
|
||||
|
||||
const llvm::ArrayRef<uint8_t> data(GetDataStart(),max_data);
|
||||
md5.update(data);
|
||||
|
||||
llvm::MD5::MD5Result result;
|
||||
md5.final(result);
|
||||
|
||||
dest.resize(16);
|
||||
std::copy(result,
|
||||
result+16,
|
||||
dest.begin());
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ ValueObject::ValueObject (ValueObject &parent) :
|
|||
m_type_validator_sp(),
|
||||
m_user_id_of_forced_summary(),
|
||||
m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid),
|
||||
m_value_checksum(),
|
||||
m_value_is_valid (false),
|
||||
m_value_did_change (false),
|
||||
m_children_count_valid (false),
|
||||
|
@ -147,6 +148,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope,
|
|||
m_type_validator_sp(),
|
||||
m_user_id_of_forced_summary(),
|
||||
m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
|
||||
m_value_checksum(),
|
||||
m_value_is_valid (false),
|
||||
m_value_did_change (false),
|
||||
m_children_count_valid (false),
|
||||
|
@ -192,7 +194,7 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
|
|||
return m_error.Success();
|
||||
}
|
||||
|
||||
bool first_update = m_update_point.IsFirstEvaluation();
|
||||
bool first_update = IsChecksumEmpty();
|
||||
|
||||
if (m_update_point.NeedsUpdating())
|
||||
{
|
||||
|
@ -221,10 +223,35 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
|
|||
m_error.Clear();
|
||||
|
||||
// Call the pure virtual function to update the value
|
||||
|
||||
bool need_compare_checksums = false;
|
||||
llvm::SmallVector<uint8_t, 16> old_checksum;
|
||||
|
||||
if (!first_update && CanProvideValue())
|
||||
{
|
||||
need_compare_checksums = true;
|
||||
old_checksum.resize(m_value_checksum.size());
|
||||
std::copy(m_value_checksum.begin(), m_value_checksum.end(), old_checksum.begin());
|
||||
}
|
||||
|
||||
bool success = UpdateValue ();
|
||||
|
||||
SetValueIsValid (success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
const uint64_t max_checksum_size = 128;
|
||||
m_data.Checksum(m_value_checksum,
|
||||
max_checksum_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
need_compare_checksums = false;
|
||||
m_value_checksum.clear();
|
||||
}
|
||||
|
||||
assert (old_checksum.empty() == !need_compare_checksums);
|
||||
|
||||
if (first_update)
|
||||
SetValueDidChange (false);
|
||||
else if (!m_value_did_change && success == false)
|
||||
|
@ -233,6 +260,11 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
|
|||
// as changed if the value used to be valid and now isn't
|
||||
SetValueDidChange (value_was_valid);
|
||||
}
|
||||
else if (need_compare_checksums)
|
||||
{
|
||||
SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], m_value_checksum.size()));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -498,7 +530,6 @@ ValueObject::SetValueIsValid (bool b)
|
|||
bool
|
||||
ValueObject::GetValueDidChange ()
|
||||
{
|
||||
GetValueAsCString ();
|
||||
return m_value_did_change;
|
||||
}
|
||||
|
||||
|
@ -3834,16 +3865,14 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
|
|||
ValueObject::EvaluationPoint::EvaluationPoint () :
|
||||
m_mod_id(),
|
||||
m_exe_ctx_ref(),
|
||||
m_needs_update (true),
|
||||
m_first_update (true)
|
||||
m_needs_update (true)
|
||||
{
|
||||
}
|
||||
|
||||
ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
|
||||
m_mod_id(),
|
||||
m_exe_ctx_ref(),
|
||||
m_needs_update (true),
|
||||
m_first_update (true)
|
||||
m_needs_update (true)
|
||||
{
|
||||
ExecutionContext exe_ctx(exe_scope);
|
||||
TargetSP target_sp (exe_ctx.GetTargetSP());
|
||||
|
@ -3887,8 +3916,7 @@ ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope,
|
|||
ValueObject::EvaluationPoint::EvaluationPoint (const ValueObject::EvaluationPoint &rhs) :
|
||||
m_mod_id(),
|
||||
m_exe_ctx_ref(rhs.m_exe_ctx_ref),
|
||||
m_needs_update (true),
|
||||
m_first_update (true)
|
||||
m_needs_update (true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -3982,7 +4010,6 @@ ValueObject::EvaluationPoint::SetUpdated ()
|
|||
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
|
||||
if (process_sp)
|
||||
m_mod_id = process_sp->GetModID();
|
||||
m_first_update = false;
|
||||
m_needs_update = false;
|
||||
}
|
||||
|
||||
|
@ -4183,7 +4210,17 @@ ValueObject::GetPreferredDisplayLanguage ()
|
|||
bool
|
||||
ValueObject::CanProvideValue ()
|
||||
{
|
||||
return (false == GetClangType().IsAggregateType());
|
||||
// we need to support invalid types as providers of values because some bare-board
|
||||
// debugging scenarios have no notion of types, but still manage to have raw numeric
|
||||
// values for things like registers. sigh.
|
||||
const ClangASTType &type(GetClangType());
|
||||
return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
|
||||
}
|
||||
|
||||
bool
|
||||
ValueObject::IsChecksumEmpty ()
|
||||
{
|
||||
return m_value_checksum.empty();
|
||||
}
|
||||
|
||||
ValueObjectSP
|
||||
|
|
Loading…
Reference in New Issue