diff --git a/lldb/examples/synthetic/CFString.py b/lldb/examples/synthetic/CFString.py index 7d3a43ae98e8..ed1bd3143468 100644 --- a/lldb/examples/synthetic/CFString.py +++ b/lldb/examples/synthetic/CFString.py @@ -45,7 +45,7 @@ class CFStringSynthProvider: # for 32bit targets, use safe ObjC code return self.handle_unicode_string_safe() offset = 12 - pointer = int(self.valobj.GetValue(), 0) + offset + pointer = self.valobj.GetValueAsUnsigned(0) + offset pystr = self.read_unicode(pointer) return self.valobj.CreateValueFromExpression("content", "(char*)\"" + pystr.encode('utf-8') + "\"") @@ -60,7 +60,7 @@ class CFStringSynthProvider: def handle_unicode_string(self): # step 1: find offset if self.inline: - pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base(); + pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base(); if self.explicit == False: # untested, use the safe code path return self.handle_unicode_string_safe(); @@ -76,11 +76,11 @@ class CFStringSynthProvider: # for an inline string) pointer = pointer + 8; else: - pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base(); + pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base(); # read 8 bytes here and make an address out of them vopointer = self.valobj.CreateChildAtOffset("dummy", pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()); - pointer = int(vopointer.GetValue(), 0) + pointer = vopointer.GetValueAsUnsigned(0) # step 2: read Unicode data at pointer pystr = self.read_unicode(pointer) # step 3: return it diff --git a/lldb/examples/synthetic/StdListSynthProvider.py b/lldb/examples/synthetic/StdListSynthProvider.py index 0f6ca4d5dd6d..1cfe8c24147a 100644 --- a/lldb/examples/synthetic/StdListSynthProvider.py +++ b/lldb/examples/synthetic/StdListSynthProvider.py @@ -1,61 +1,68 @@ import re class StdListSynthProvider: + def __init__(self, valobj, dict): - self.valobj = valobj; + self.valobj = valobj self.update() + def num_children(self): - next_val = int(self.Mnext.GetValue(),0) - prev_val = int(self.Mprev.GetValue(),0) - if next_val == 0: - return 0; - if next_val == self.Mnode_address: - return 0; + next_val = self.next.GetValueAsUnsigned(0) + prev_val = self.prev.GetValueAsUnsigned(0) + # After a std::list has been initialized, both next and prev will be non-NULL + if next_val == 0 or prev_val == 0: + return 0 + if next_val == self.node_address: + return 0 if next_val == prev_val: - return 1; + return 1 size = 2 - current = self.Mnext - while int(current.GetChildMemberWithName('_M_next').GetValue(),0) != self.Mnode_address: - size = size + 1; + current = self.next + while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address: + size = size + 1 current = current.GetChildMemberWithName('_M_next') return (size - 1) + def get_child_index(self,name): if name == "len": - return self.num_children(); + return self.num_children() else: return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): if index == self.num_children(): return self.valobj.CreateValueFromExpression("len",str(self.num_children())) else: offset = index - current = self.Mnext; + current = self.next while offset > 0: - current = current.GetChildMemberWithName('_M_next'); - offset = offset - 1; + current = current.GetChildMemberWithName('_M_next') + offset = offset - 1 return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type) + def extract_type_name(self,name): self.type_name = name[16:] index = 2 count_of_template = 1 while index < len(self.type_name): if self.type_name[index] == '<': - count_of_template = count_of_template + 1; + count_of_template = count_of_template + 1 elif self.type_name[index] == '>': - count_of_template = count_of_template - 1; + count_of_template = count_of_template - 1 elif self.type_name[index] == ',' and count_of_template == 1: self.type_name = self.type_name[:index] break - index = index + 1; + index = index + 1 self.type_name_nospaces = self.type_name.replace(", ", ",") + def update(self): - self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') - self.Mnode = self.Mimpl.GetChildMemberWithName('_M_node') - self.extract_type_name(self.Mimpl.GetType().GetName()) - self.Mnode_address = int(self.valobj.AddressOf().GetValue(), 0) - self.Mnext = self.Mnode.GetChildMemberWithName('_M_next') - self.Mprev = self.Mnode.GetChildMemberWithName('_M_prev') - self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name) + impl = self.valobj.GetChildMemberWithName('_M_impl') + node = impl.GetChildMemberWithName('_M_node') + self.extract_type_name(impl.GetType().GetName()) + self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0) + self.next = node.GetChildMemberWithName('_M_next') + self.prev = node.GetChildMemberWithName('_M_prev') + self.data_type = node.GetTarget().FindFirstType(self.type_name) # tries to fight against a difference in formatting type names between gcc and clang if self.data_type.IsValid() == False: - self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name_nospaces) + self.data_type = node.GetTarget().FindFirstType(self.type_name_nospaces) self.data_size = self.data_type.GetByteSize() diff --git a/lldb/examples/synthetic/StdMapSynthProvider.py b/lldb/examples/synthetic/StdMapSynthProvider.py index 0665889896ea..bb109331e228 100644 --- a/lldb/examples/synthetic/StdMapSynthProvider.py +++ b/lldb/examples/synthetic/StdMapSynthProvider.py @@ -58,7 +58,7 @@ class StdMapSynthProvider: root_ptr_val = self.node_ptr_value(self.Mroot) if root_ptr_val == 0: return 0; - return int(self.Mimpl.GetChildMemberWithName('_M_node_count').GetValue(), 0); + return self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0) def get_child_index(self,name): if name == "len": return self.num_children(); @@ -77,7 +77,7 @@ class StdMapSynthProvider: return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) # utility functions def node_ptr_value(self,node): - return int(node.GetValue(),0); + return node.GetValueAsUnsigned(0) def right(self,node): return node.GetChildMemberWithName("_M_right"); def left(self,node): diff --git a/lldb/examples/synthetic/StdVectorSynthProvider.py b/lldb/examples/synthetic/StdVectorSynthProvider.py index 91e634a718af..dc226902d1eb 100644 --- a/lldb/examples/synthetic/StdVectorSynthProvider.py +++ b/lldb/examples/synthetic/StdVectorSynthProvider.py @@ -1,25 +1,55 @@ class StdVectorSynthProvider: + def __init__(self, valobj, dict): self.valobj = valobj; self.update() + def num_children(self): - start_val = int(self.Mstart.GetValue(),0) - finish_val = int(self.Mfinish.GetValue(),0) - return (finish_val-start_val)/self.data_size + start_val = self.start.GetValueAsUnsigned(0) + finish_val = self.finish.GetValueAsUnsigned(0) + end_val = self.end.GetValueAsUnsigned(0) + # Before a vector has been constructed, it will contain bad values + # so we really need to be careful about the length we return since + # unitialized data can cause us to return a huge number. We need + # to also check for any of the start, finish or end of storage values + # being zero (NULL). If any are, then this vector has not been + # initialized yet and we should return zero + + # Make sure nothing is NULL + if start_val == 0 or finish_val == 0 or end_val == 0: + return 0 + # Make sure start is less than finish + if start_val >= finish_val: + return 0 + # Make sure finish is less than or equal to end of storage + if finish_val > end_val: + return 0 + + # We might still get things wrong, so cap things at 256 items for now + # TODO: read a target "settings set" variable for this to allow it to + # be customized + num_children = (finish_val-start_val)/self.data_size + if num_children > 256: + return 256 + return num_children + def get_child_index(self,name): if name == "len": return self.num_children(); else: return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): if index == self.num_children(): return self.valobj.CreateValueFromExpression("len",str(self.num_children())) else: offset = index * self.data_size - return self.Mstart.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) + return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) + def update(self): - self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') - self.Mstart = self.Mimpl.GetChildMemberWithName('_M_start') - self.Mfinish = self.Mimpl.GetChildMemberWithName('_M_finish') - self.data_type = self.Mstart.GetType().GetPointeeType() + impl = self.valobj.GetChildMemberWithName('_M_impl') + self.start = impl.GetChildMemberWithName('_M_start') + self.finish = impl.GetChildMemberWithName('_M_finish') + self.end = impl.GetChildMemberWithName('_M_end_of_storage') + self.data_type = self.start.GetType().GetPointeeType() self.data_size = self.data_type.GetByteSize() diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 5bae9a48087c..4851e43b418c 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -71,6 +71,12 @@ public: const char * GetValue (); + int64_t + GetValueAsSigned(SBError& error, int64_t fail_value=0); + + uint64_t + GetValueAsUnsigned(SBError& error, uint64_t fail_value=0); + int64_t GetValueAsSigned(int64_t fail_value=0); diff --git a/lldb/scripts/Python/interface/SBValue.i b/lldb/scripts/Python/interface/SBValue.i index 22186e1b8a3a..d73e6012c62c 100644 --- a/lldb/scripts/Python/interface/SBValue.i +++ b/lldb/scripts/Python/interface/SBValue.i @@ -95,8 +95,14 @@ public: GetValue (); int64_t - GetValueAsSigned(int64_t fail_value=0); + GetValueAsSigned(SBError& error, int64_t fail_value=0); + uint64_t + GetValueAsUnsigned(SBError& error, uint64_t fail_value=0); + + int64_t + GetValueAsSigned(int64_t fail_value=0); + uint64_t GetValueAsUnsigned(uint64_t fail_value=0); diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index d874cc2fabce..820121132ee7 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -618,6 +618,48 @@ SBValue::GetValueForExpressionPath(const char* expr_path) return sb_value; } +int64_t +SBValue::GetValueAsSigned(SBError& error, int64_t fail_value) +{ + if (m_opaque_sp) + { + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + { + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); + Scalar scalar; + if (m_opaque_sp->ResolveValue (scalar)) + return scalar.GetRawBits64(fail_value); + else + error.SetErrorString("could not get value"); + } + else + error.SetErrorString("could not get target"); + } + error.SetErrorString("invalid SBValue"); + return fail_value; +} + +uint64_t +SBValue::GetValueAsUnsigned(SBError& error, uint64_t fail_value) +{ + if (m_opaque_sp) + { + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + { + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); + Scalar scalar; + if (m_opaque_sp->ResolveValue (scalar)) + return scalar.GetRawBits64(fail_value); + else + error.SetErrorString("could not get value"); + } + else + error.SetErrorString("could not get target"); + } + error.SetErrorString("invalid SBValue"); + return fail_value; +} + int64_t SBValue::GetValueAsSigned(int64_t fail_value) { diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index c9310753d965..fce00f6d4f39 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -331,12 +331,17 @@ ValueObject::GetValue() const bool ValueObject::ResolveValue (Scalar &scalar) { - ExecutionContext exe_ctx; - ExecutionContextScope *exe_scope = GetExecutionContextScope(); - if (exe_scope) - exe_scope->CalculateExecutionContext(exe_ctx); - scalar = m_value.ResolveValue(&exe_ctx, GetClangAST ()); - return scalar.IsValid(); + if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything + { + ExecutionContext exe_ctx; + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) + exe_scope->CalculateExecutionContext(exe_ctx); + scalar = m_value.ResolveValue(&exe_ctx, GetClangAST ()); + return scalar.IsValid(); + } + else + return false; } bool diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/CFString.py b/lldb/test/functionalities/data-formatter/data-formatter-objc/CFString.py index 7d3a43ae98e8..ed1bd3143468 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-objc/CFString.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/CFString.py @@ -45,7 +45,7 @@ class CFStringSynthProvider: # for 32bit targets, use safe ObjC code return self.handle_unicode_string_safe() offset = 12 - pointer = int(self.valobj.GetValue(), 0) + offset + pointer = self.valobj.GetValueAsUnsigned(0) + offset pystr = self.read_unicode(pointer) return self.valobj.CreateValueFromExpression("content", "(char*)\"" + pystr.encode('utf-8') + "\"") @@ -60,7 +60,7 @@ class CFStringSynthProvider: def handle_unicode_string(self): # step 1: find offset if self.inline: - pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base(); + pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base(); if self.explicit == False: # untested, use the safe code path return self.handle_unicode_string_safe(); @@ -76,11 +76,11 @@ class CFStringSynthProvider: # for an inline string) pointer = pointer + 8; else: - pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base(); + pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base(); # read 8 bytes here and make an address out of them vopointer = self.valobj.CreateChildAtOffset("dummy", pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()); - pointer = int(vopointer.GetValue(), 0) + pointer = vopointer.GetValueAsUnsigned(0) # step 2: read Unicode data at pointer pystr = self.read_unicode(pointer) # step 3: return it diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py index c6ccc1814cf2..1cfe8c24147a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py @@ -6,8 +6,8 @@ class StdListSynthProvider: self.update() def num_children(self): - next_val = int(self.next.GetValue(),0) - prev_val = int(self.prev.GetValue(),0) + next_val = self.next.GetValueAsUnsigned(0) + prev_val = self.prev.GetValueAsUnsigned(0) # After a std::list has been initialized, both next and prev will be non-NULL if next_val == 0 or prev_val == 0: return 0 @@ -17,7 +17,7 @@ class StdListSynthProvider: return 1 size = 2 current = self.next - while int(current.GetChildMemberWithName('_M_next').GetValue(),0) != self.node_address: + while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address: size = size + 1 current = current.GetChildMemberWithName('_M_next') return (size - 1) @@ -58,7 +58,7 @@ class StdListSynthProvider: impl = self.valobj.GetChildMemberWithName('_M_impl') node = impl.GetChildMemberWithName('_M_node') self.extract_type_name(impl.GetType().GetName()) - self.node_address = int(self.valobj.AddressOf().GetValue(), 0) + self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0) self.next = node.GetChildMemberWithName('_M_next') self.prev = node.GetChildMemberWithName('_M_prev') self.data_type = node.GetTarget().FindFirstType(self.type_name) diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py index 0665889896ea..bb109331e228 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py @@ -58,7 +58,7 @@ class StdMapSynthProvider: root_ptr_val = self.node_ptr_value(self.Mroot) if root_ptr_val == 0: return 0; - return int(self.Mimpl.GetChildMemberWithName('_M_node_count').GetValue(), 0); + return self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0) def get_child_index(self,name): if name == "len": return self.num_children(); @@ -77,7 +77,7 @@ class StdMapSynthProvider: return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) # utility functions def node_ptr_value(self,node): - return int(node.GetValue(),0); + return node.GetValueAsUnsigned(0) def right(self,node): return node.GetChildMemberWithName("_M_right"); def left(self,node): diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py index ff0672b3928c..dc226902d1eb 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py @@ -5,9 +5,9 @@ class StdVectorSynthProvider: self.update() def num_children(self): - start_val = int(self.start.GetValue(),0) - finish_val = int(self.finish.GetValue(),0) - end_val = int(self.end.GetValue(),0) + start_val = self.start.GetValueAsUnsigned(0) + finish_val = self.finish.GetValueAsUnsigned(0) + end_val = self.end.GetValueAsUnsigned(0) # Before a vector has been constructed, it will contain bad values # so we really need to be careful about the length we return since # unitialized data can cause us to return a huge number. We need