APIs to GetValueAsSigned/Unsigned() in SBValue now also accept an SBError parameter to give more info about any problem

The synthetic children providers now use the new (safer) APIs to get the values of objects
As a side effect, fixed an issue in ValueObject where ResolveValue() was not always updating the value before reading it

llvm-svn: 136861
This commit is contained in:
Enrico Granata 2011-08-04 01:41:02 +00:00
parent b224db72b0
commit 6fd87d5d33
12 changed files with 156 additions and 60 deletions

View File

@ -45,7 +45,7 @@ class CFStringSynthProvider:
# for 32bit targets, use safe ObjC code # for 32bit targets, use safe ObjC code
return self.handle_unicode_string_safe() return self.handle_unicode_string_safe()
offset = 12 offset = 12
pointer = int(self.valobj.GetValue(), 0) + offset pointer = self.valobj.GetValueAsUnsigned(0) + offset
pystr = self.read_unicode(pointer) pystr = self.read_unicode(pointer)
return self.valobj.CreateValueFromExpression("content", return self.valobj.CreateValueFromExpression("content",
"(char*)\"" + pystr.encode('utf-8') + "\"") "(char*)\"" + pystr.encode('utf-8') + "\"")
@ -60,7 +60,7 @@ class CFStringSynthProvider:
def handle_unicode_string(self): def handle_unicode_string(self):
# step 1: find offset # step 1: find offset
if self.inline: 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: if self.explicit == False:
# untested, use the safe code path # untested, use the safe code path
return self.handle_unicode_string_safe(); return self.handle_unicode_string_safe();
@ -76,11 +76,11 @@ class CFStringSynthProvider:
# for an inline string) # for an inline string)
pointer = pointer + 8; pointer = pointer + 8;
else: 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 # read 8 bytes here and make an address out of them
vopointer = self.valobj.CreateChildAtOffset("dummy", vopointer = self.valobj.CreateChildAtOffset("dummy",
pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()); pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
pointer = int(vopointer.GetValue(), 0) pointer = vopointer.GetValueAsUnsigned(0)
# step 2: read Unicode data at pointer # step 2: read Unicode data at pointer
pystr = self.read_unicode(pointer) pystr = self.read_unicode(pointer)
# step 3: return it # step 3: return it

View File

@ -1,61 +1,68 @@
import re import re
class StdListSynthProvider: class StdListSynthProvider:
def __init__(self, valobj, dict): def __init__(self, valobj, dict):
self.valobj = valobj; self.valobj = valobj
self.update() self.update()
def num_children(self): def num_children(self):
next_val = int(self.Mnext.GetValue(),0) next_val = self.next.GetValueAsUnsigned(0)
prev_val = int(self.Mprev.GetValue(),0) prev_val = self.prev.GetValueAsUnsigned(0)
if next_val == 0: # After a std::list has been initialized, both next and prev will be non-NULL
return 0; if next_val == 0 or prev_val == 0:
if next_val == self.Mnode_address: return 0
return 0; if next_val == self.node_address:
return 0
if next_val == prev_val: if next_val == prev_val:
return 1; return 1
size = 2 size = 2
current = self.Mnext current = self.next
while int(current.GetChildMemberWithName('_M_next').GetValue(),0) != self.Mnode_address: while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
size = size + 1; size = size + 1
current = current.GetChildMemberWithName('_M_next') current = current.GetChildMemberWithName('_M_next')
return (size - 1) return (size - 1)
def get_child_index(self,name): def get_child_index(self,name):
if name == "len": if name == "len":
return self.num_children(); return self.num_children()
else: else:
return int(name.lstrip('[').rstrip(']')) return int(name.lstrip('[').rstrip(']'))
def get_child_at_index(self,index): def get_child_at_index(self,index):
if index == self.num_children(): if index == self.num_children():
return self.valobj.CreateValueFromExpression("len",str(self.num_children())) return self.valobj.CreateValueFromExpression("len",str(self.num_children()))
else: else:
offset = index offset = index
current = self.Mnext; current = self.next
while offset > 0: while offset > 0:
current = current.GetChildMemberWithName('_M_next'); current = current.GetChildMemberWithName('_M_next')
offset = offset - 1; offset = offset - 1
return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type) return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type)
def extract_type_name(self,name): def extract_type_name(self,name):
self.type_name = name[16:] self.type_name = name[16:]
index = 2 index = 2
count_of_template = 1 count_of_template = 1
while index < len(self.type_name): while index < len(self.type_name):
if self.type_name[index] == '<': if self.type_name[index] == '<':
count_of_template = count_of_template + 1; count_of_template = count_of_template + 1
elif self.type_name[index] == '>': 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: elif self.type_name[index] == ',' and count_of_template == 1:
self.type_name = self.type_name[:index] self.type_name = self.type_name[:index]
break break
index = index + 1; index = index + 1
self.type_name_nospaces = self.type_name.replace(", ", ",") self.type_name_nospaces = self.type_name.replace(", ", ",")
def update(self): def update(self):
self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') impl = self.valobj.GetChildMemberWithName('_M_impl')
self.Mnode = self.Mimpl.GetChildMemberWithName('_M_node') node = impl.GetChildMemberWithName('_M_node')
self.extract_type_name(self.Mimpl.GetType().GetName()) self.extract_type_name(impl.GetType().GetName())
self.Mnode_address = int(self.valobj.AddressOf().GetValue(), 0) self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
self.Mnext = self.Mnode.GetChildMemberWithName('_M_next') self.next = node.GetChildMemberWithName('_M_next')
self.Mprev = self.Mnode.GetChildMemberWithName('_M_prev') self.prev = node.GetChildMemberWithName('_M_prev')
self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name) self.data_type = node.GetTarget().FindFirstType(self.type_name)
# tries to fight against a difference in formatting type names between gcc and clang # tries to fight against a difference in formatting type names between gcc and clang
if self.data_type.IsValid() == False: 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() self.data_size = self.data_type.GetByteSize()

View File

@ -58,7 +58,7 @@ class StdMapSynthProvider:
root_ptr_val = self.node_ptr_value(self.Mroot) root_ptr_val = self.node_ptr_value(self.Mroot)
if root_ptr_val == 0: if root_ptr_val == 0:
return 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): def get_child_index(self,name):
if name == "len": if name == "len":
return self.num_children(); return self.num_children();
@ -77,7 +77,7 @@ class StdMapSynthProvider:
return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
# utility functions # utility functions
def node_ptr_value(self,node): def node_ptr_value(self,node):
return int(node.GetValue(),0); return node.GetValueAsUnsigned(0)
def right(self,node): def right(self,node):
return node.GetChildMemberWithName("_M_right"); return node.GetChildMemberWithName("_M_right");
def left(self,node): def left(self,node):

View File

@ -1,25 +1,55 @@
class StdVectorSynthProvider: class StdVectorSynthProvider:
def __init__(self, valobj, dict): def __init__(self, valobj, dict):
self.valobj = valobj; self.valobj = valobj;
self.update() self.update()
def num_children(self): def num_children(self):
start_val = int(self.Mstart.GetValue(),0) start_val = self.start.GetValueAsUnsigned(0)
finish_val = int(self.Mfinish.GetValue(),0) finish_val = self.finish.GetValueAsUnsigned(0)
return (finish_val-start_val)/self.data_size 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): def get_child_index(self,name):
if name == "len": if name == "len":
return self.num_children(); return self.num_children();
else: else:
return int(name.lstrip('[').rstrip(']')) return int(name.lstrip('[').rstrip(']'))
def get_child_at_index(self,index): def get_child_at_index(self,index):
if index == self.num_children(): if index == self.num_children():
return self.valobj.CreateValueFromExpression("len",str(self.num_children())) return self.valobj.CreateValueFromExpression("len",str(self.num_children()))
else: else:
offset = index * self.data_size 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): def update(self):
self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') impl = self.valobj.GetChildMemberWithName('_M_impl')
self.Mstart = self.Mimpl.GetChildMemberWithName('_M_start') self.start = impl.GetChildMemberWithName('_M_start')
self.Mfinish = self.Mimpl.GetChildMemberWithName('_M_finish') self.finish = impl.GetChildMemberWithName('_M_finish')
self.data_type = self.Mstart.GetType().GetPointeeType() self.end = impl.GetChildMemberWithName('_M_end_of_storage')
self.data_type = self.start.GetType().GetPointeeType()
self.data_size = self.data_type.GetByteSize() self.data_size = self.data_type.GetByteSize()

View File

@ -71,6 +71,12 @@ public:
const char * const char *
GetValue (); GetValue ();
int64_t
GetValueAsSigned(SBError& error, int64_t fail_value=0);
uint64_t
GetValueAsUnsigned(SBError& error, uint64_t fail_value=0);
int64_t int64_t
GetValueAsSigned(int64_t fail_value=0); GetValueAsSigned(int64_t fail_value=0);

View File

@ -94,6 +94,12 @@ public:
const char * const char *
GetValue (); GetValue ();
int64_t
GetValueAsSigned(SBError& error, int64_t fail_value=0);
uint64_t
GetValueAsUnsigned(SBError& error, uint64_t fail_value=0);
int64_t int64_t
GetValueAsSigned(int64_t fail_value=0); GetValueAsSigned(int64_t fail_value=0);

View File

@ -618,6 +618,48 @@ SBValue::GetValueForExpressionPath(const char* expr_path)
return sb_value; 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 int64_t
SBValue::GetValueAsSigned(int64_t fail_value) SBValue::GetValueAsSigned(int64_t fail_value)
{ {

View File

@ -330,6 +330,8 @@ ValueObject::GetValue() const
bool bool
ValueObject::ResolveValue (Scalar &scalar) ValueObject::ResolveValue (Scalar &scalar)
{
if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything
{ {
ExecutionContext exe_ctx; ExecutionContext exe_ctx;
ExecutionContextScope *exe_scope = GetExecutionContextScope(); ExecutionContextScope *exe_scope = GetExecutionContextScope();
@ -338,6 +340,9 @@ ValueObject::ResolveValue (Scalar &scalar)
scalar = m_value.ResolveValue(&exe_ctx, GetClangAST ()); scalar = m_value.ResolveValue(&exe_ctx, GetClangAST ());
return scalar.IsValid(); return scalar.IsValid();
} }
else
return false;
}
bool bool
ValueObject::GetValueIsValid () const ValueObject::GetValueIsValid () const

View File

@ -45,7 +45,7 @@ class CFStringSynthProvider:
# for 32bit targets, use safe ObjC code # for 32bit targets, use safe ObjC code
return self.handle_unicode_string_safe() return self.handle_unicode_string_safe()
offset = 12 offset = 12
pointer = int(self.valobj.GetValue(), 0) + offset pointer = self.valobj.GetValueAsUnsigned(0) + offset
pystr = self.read_unicode(pointer) pystr = self.read_unicode(pointer)
return self.valobj.CreateValueFromExpression("content", return self.valobj.CreateValueFromExpression("content",
"(char*)\"" + pystr.encode('utf-8') + "\"") "(char*)\"" + pystr.encode('utf-8') + "\"")
@ -60,7 +60,7 @@ class CFStringSynthProvider:
def handle_unicode_string(self): def handle_unicode_string(self):
# step 1: find offset # step 1: find offset
if self.inline: 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: if self.explicit == False:
# untested, use the safe code path # untested, use the safe code path
return self.handle_unicode_string_safe(); return self.handle_unicode_string_safe();
@ -76,11 +76,11 @@ class CFStringSynthProvider:
# for an inline string) # for an inline string)
pointer = pointer + 8; pointer = pointer + 8;
else: 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 # read 8 bytes here and make an address out of them
vopointer = self.valobj.CreateChildAtOffset("dummy", vopointer = self.valobj.CreateChildAtOffset("dummy",
pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()); pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
pointer = int(vopointer.GetValue(), 0) pointer = vopointer.GetValueAsUnsigned(0)
# step 2: read Unicode data at pointer # step 2: read Unicode data at pointer
pystr = self.read_unicode(pointer) pystr = self.read_unicode(pointer)
# step 3: return it # step 3: return it

View File

@ -6,8 +6,8 @@ class StdListSynthProvider:
self.update() self.update()
def num_children(self): def num_children(self):
next_val = int(self.next.GetValue(),0) next_val = self.next.GetValueAsUnsigned(0)
prev_val = int(self.prev.GetValue(),0) prev_val = self.prev.GetValueAsUnsigned(0)
# After a std::list has been initialized, both next and prev will be non-NULL # After a std::list has been initialized, both next and prev will be non-NULL
if next_val == 0 or prev_val == 0: if next_val == 0 or prev_val == 0:
return 0 return 0
@ -17,7 +17,7 @@ class StdListSynthProvider:
return 1 return 1
size = 2 size = 2
current = self.next 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 size = size + 1
current = current.GetChildMemberWithName('_M_next') current = current.GetChildMemberWithName('_M_next')
return (size - 1) return (size - 1)
@ -58,7 +58,7 @@ class StdListSynthProvider:
impl = self.valobj.GetChildMemberWithName('_M_impl') impl = self.valobj.GetChildMemberWithName('_M_impl')
node = impl.GetChildMemberWithName('_M_node') node = impl.GetChildMemberWithName('_M_node')
self.extract_type_name(impl.GetType().GetName()) 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.next = node.GetChildMemberWithName('_M_next')
self.prev = node.GetChildMemberWithName('_M_prev') self.prev = node.GetChildMemberWithName('_M_prev')
self.data_type = node.GetTarget().FindFirstType(self.type_name) self.data_type = node.GetTarget().FindFirstType(self.type_name)

View File

@ -58,7 +58,7 @@ class StdMapSynthProvider:
root_ptr_val = self.node_ptr_value(self.Mroot) root_ptr_val = self.node_ptr_value(self.Mroot)
if root_ptr_val == 0: if root_ptr_val == 0:
return 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): def get_child_index(self,name):
if name == "len": if name == "len":
return self.num_children(); return self.num_children();
@ -77,7 +77,7 @@ class StdMapSynthProvider:
return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
# utility functions # utility functions
def node_ptr_value(self,node): def node_ptr_value(self,node):
return int(node.GetValue(),0); return node.GetValueAsUnsigned(0)
def right(self,node): def right(self,node):
return node.GetChildMemberWithName("_M_right"); return node.GetChildMemberWithName("_M_right");
def left(self,node): def left(self,node):

View File

@ -5,9 +5,9 @@ class StdVectorSynthProvider:
self.update() self.update()
def num_children(self): def num_children(self):
start_val = int(self.start.GetValue(),0) start_val = self.start.GetValueAsUnsigned(0)
finish_val = int(self.finish.GetValue(),0) finish_val = self.finish.GetValueAsUnsigned(0)
end_val = int(self.end.GetValue(),0) end_val = self.end.GetValueAsUnsigned(0)
# Before a vector has been constructed, it will contain bad values # Before a vector has been constructed, it will contain bad values
# so we really need to be careful about the length we return since # 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 # unitialized data can cause us to return a huge number. We need