GetVariableInfo () collected the values of the variable in a list. But it also
tried to generate the name/value pairs for children. This caused generation of
a wrong value string for may items. This function has been fixed to put value in
the list only.

The handling of --print-value related option has been moved to caller.

GetVariableInfo2 and MIResponseFormVariableInfo3 have been removed. They were
almost the duplicate of functions of similar names. I dont see any difference in
the output of -stack-list-locals and -stack-list-arguments. So these functions
just seemed unnecessary.

Char variable was being printed as a string which caused garbage output. This has
been fixed.

Some misc. cleanup.

Test cases have been added that check -stack-list-locals for struct, array and
pointers. Modified other tests which depended on hard coded line numbers.

Reviewed in http://reviews.llvm.org/D7589

llvm-svn: 229102
This commit is contained in:
Hafiz Abid Qadeer 2015-02-13 11:53:50 +00:00
parent 5eb75aced4
commit 095b128671
10 changed files with 236 additions and 368 deletions

View File

@ -1,5 +1,5 @@
LEVEL = ../../make
C_SOURCES := main.c a.c b.c loop.c
C_SOURCES := main.c a.c b.c loop.c locals.c
include $(LEVEL)/Makefile.rules

View File

@ -153,22 +153,22 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
# Test -exec-next
self.runCmd("-exec-next --thread 1 --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
# Test that --thread is optional
self.runCmd("-exec-next --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"23\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"")
# Test that --frame is optional
self.runCmd("-exec-next --thread 1")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"")
# Test that both --thread and --frame are optional
self.runCmd("-exec-next --thread 1")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"29\"")
# Test that an invalid --thread is handled
self.runCmd("-exec-next --thread 0")
@ -205,23 +205,23 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
# Test -exec-next-instruction
self.runCmd("-exec-next-instruction --thread 1 --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
# Test that --thread is optional
self.runCmd("-exec-next-instruction --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
# Test that --frame is optional
self.runCmd("-exec-next-instruction --thread 1")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
# Test that both --thread and --frame are optional
self.runCmd("-exec-next-instruction --thread 1")
self.expect("\^running")
# Depending on compiler, it can stop at different line.
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[0-2]\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
# Test that an invalid --thread is handled
self.runCmd("-exec-next-instruction --thread 0")
@ -260,7 +260,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
#FIXME: is this supposed to step into printf?
self.runCmd("-exec-step --thread 1 --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
# Test that -exec-step steps into a_MyFunction and back out
# (and that --thread is optional)
@ -275,10 +275,10 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
# -exec-step can keep us in the a_MyFunction for gcc
self.runCmd("-exec-finish --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
self.runCmd("-exec-step --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"23\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"")
# Test that -exec-step steps into b_MyFunction
# (and that --frame is optional)
@ -330,13 +330,13 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
# instruction
self.runCmd("-exec-step-instruction --thread 1 --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
# Test that -exec-step-instruction steps over non branching
# instruction (and that --thread is optional)
self.runCmd("-exec-step-instruction --frame 0")
self.expect("\^running")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
# Test that -exec-step-instruction steps into a_MyFunction
# (and that --frame is optional)

View File

@ -80,6 +80,87 @@ class MiStackTestCase(lldbmi_testcase.MiTestCaseBase):
self.expect("\^done,locals=\[{name=\"a\",value=\"10\"},{name=\"b\",value=\"20\"}\]")
self.runCmd("-stack-list-locals --simple-values")
self.expect("\^done,locals=\[{name=\"a\",value=\"10\"},{name=\"b\",value=\"20\"}\]")
# Test struct local variable
line = line_number('locals.c', '// BP_LOCAL_STRUCT')
self.runCmd("-break-insert --file locals.c:%d" % line)
self.expect("\^done,bkpt={number=\"2\"")
self.runCmd("-exec-continue")
self.expect("\^running")
self.expect("\*stopped,reason=\"breakpoint-hit\"")
# Test -stack-list-locals: use 0 or --no-values
self.runCmd("-stack-list-locals 0")
self.expect("\^done,locals=\[name=\"var_c\"\]")
self.runCmd("-stack-list-locals --no-values")
self.expect("\^done,locals=\[name=\"var_c\"\]")
# Test -stack-list-locals: use 1 or --all-values
self.runCmd("-stack-list-locals 1")
self.expect("\^done,locals=\[{name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }}\"}\]")
self.runCmd("-stack-list-locals --all-values")
self.expect("\^done,locals=\[{name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }}\"}\]")
# Test -stack-list-locals: use 2 or --simple-values
self.runCmd("-stack-list-locals 2")
self.expect("\^done,locals=\[name=\"var_c\"\]")
self.runCmd("-stack-list-locals --simple-values")
self.expect("\^done,locals=\[name=\"var_c\"\]")
# Test array local variable
line = line_number('locals.c', '// BP_LOCAL_ARRAY')
self.runCmd("-break-insert --file locals.c:%d" % line)
self.expect("\^done,bkpt={number=\"3\"")
self.runCmd("-exec-continue")
self.expect("\^running")
self.expect("\*stopped,reason=\"breakpoint-hit\"")
# Test -stack-list-locals: use 0 or --no-values
self.runCmd("-stack-list-locals 0")
self.expect("\^done,locals=\[name=\"array\"\]")
self.runCmd("-stack-list-locals --no-values")
self.expect("\^done,locals=\[name=\"array\"\]")
# Test -stack-list-locals: use 1 or --all-values
self.runCmd("-stack-list-locals 1")
self.expect("\^done,locals=\[{name=\"array\",value=\"{\[0\] = 100,\[1\] = 200,\[2\] = 300}\"}\]")
self.runCmd("-stack-list-locals --all-values")
self.expect("\^done,locals=\[{name=\"array\",value=\"{\[0\] = 100,\[1\] = 200,\[2\] = 300}\"}\]")
# Test -stack-list-locals: use 2 or --simple-values
self.runCmd("-stack-list-locals 2")
self.expect("\^done,locals=\[name=\"array\"\]")
self.runCmd("-stack-list-locals --simple-values")
self.expect("\^done,locals=\[name=\"array\"\]")
# Test pointers as local variable
line = line_number('locals.c', '// BP_LOCAL_PTR')
self.runCmd("-break-insert --file locals.c:%d" % line)
self.expect("\^done,bkpt={number=\"4\"")
self.runCmd("-exec-continue")
self.expect("\^running")
self.expect("\*stopped,reason=\"breakpoint-hit\"")
# Test -stack-list-locals: use 0 or --no-values
self.runCmd("-stack-list-locals 0")
self.expect("\^done,locals=\[name=\"test_str\",name=\"var_e\",name=\"ptr\"\]")
self.runCmd("-stack-list-locals --no-values")
self.expect("\^done,locals=\[name=\"test_str\",name=\"var_e\",name=\"ptr\"\]")
# Test -stack-list-locals: use 1 or --all-values
self.runCmd("-stack-list-locals 1")
self.expect("\^done,locals=\[{name=\"test_str\",value=\".*Rakaposhi.*\"},{name=\"var_e\",value=\"24\"},{name=\"ptr\",value=\".*\"}\]")
self.runCmd("-stack-list-locals --all-values")
self.expect("\^done,locals=\[{name=\"test_str\",value=\".*Rakaposhi.*\"},{name=\"var_e\",value=\"24\"},{name=\"ptr\",value=\".*\"}\]")
# Test -stack-list-locals: use 2 or --simple-values
self.runCmd("-stack-list-locals 2")
self.expect("\^done,locals=\[{name=\"test_str\",value=\".*Rakaposhi.*\"},{name=\"var_e\",value=\"24\"},{name=\"ptr\",value=\".*\"}\]")
self.runCmd("-stack-list-locals --simple-values")
self.expect("\^done,locals=\[{name=\"test_str\",value=\".*Rakaposhi.*\"},{name=\"var_e\",value=\"24\"},{name=\"ptr\",value=\".*\"}\]")
@lldbmi_test
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")

View File

@ -0,0 +1,45 @@
struct inner
{
int var_d;
};
struct my_type
{
int var_a;
char var_b;
struct inner inner_;
};
int local_struct_test(void)
{
struct my_type var_c;
var_c.var_a = 10;
var_c.var_b = 'a';
var_c.inner_.var_d = 30;
return 0; // BP_LOCAL_STRUCT
}
int local_array_test(void)
{
int array[3];
array[0] = 100;
array[1] = 200;
array[2] = 300;
return 0; // BP_LOCAL_ARRAY
}
int local_pointer_test(void)
{
const char* test_str = "Rakaposhi";
int var_e = 24;
int *ptr = &var_e;
return 0; // BP_LOCAL_PTR
}
int local_test()
{
local_struct_test();
local_array_test();
local_pointer_test();
return 0;
}

View File

@ -11,9 +11,11 @@
extern int a_MyFunction();
extern int b_MyFunction();
extern int infloop();
extern int local_test();
int doloop, dosegfault;
int g_MyVar = 3;
static int s_MyVar = 4;
int main (int argc, char const *argv[])
{
int a, b;
@ -31,5 +33,6 @@ int main (int argc, char const *argv[])
printf("a=%d, argv[1]=%s\n", a, argv[1]); //BP_argtest
}
s_MyVar = a + b;
local_test();
return a + b - s_MyVar; //BP_source
}

View File

@ -465,7 +465,7 @@ CMICmdCmdStackListArguments::Execute(void)
lldb::SBFrame frame = thread.GetFrameAtIndex(i);
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
if (!rSessionInfo.MIResponseFormVariableInfo3(frame, maskVarTypes, eVarInfoFormat, miValueList))
if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i));
const CMICmnMIValueResult miValueResult("level", miValueConst);

View File

@ -705,58 +705,45 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr
const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
const MIuint nMaxRecusiveDepth = 10;
MIuint nCurrentRecursiveDepth = 0;
const MIuint nCurrentRecursiveDepth = 0;
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
const MIuint nArgs = listArg.GetSize();
for (MIuint i = 0; bOk && (i < nArgs); i++)
{
CMICmnMIValueTuple miValueTuple;
lldb::SBValue value = listArg.GetValueAtIndex(i);
bOk = GetVariableInfo(nMaxRecusiveDepth, value, false, veVarInfoFormat, vwrMiValueList, nCurrentRecursiveDepth);
const CMICmnMIValueConst miValueConst(value.GetName());
const CMICmnMIValueResult miValueResultName("name", miValueConst);
if (veVarInfoFormat != eVariableInfoFormat_NoValues)
{
const MIuint nChildren = value.GetNumChildren();
const bool bIsPointerType = value.GetType().IsPointerType();
if (nChildren == 0 || // no children
(bIsPointerType && nChildren == 1) || // pointers
veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values
{
CMICmnMIValueList miValueList(true);
if (GetVariableInfo(nMaxRecusiveDepth, value, false, nCurrentRecursiveDepth, miValueList))
{
CMIUtilString valueStr = miValueList.ExtractContentNoBrackets();
// Surround by {} if there is , inside indicating multiple values.
if (valueStr.find (',') != CMIUtilString::npos)
valueStr = CMIUtilString::Format("{%s}", valueStr.c_str());
const CMICmnMIValueConst miValueConst2(valueStr);
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResultName); // name
miValueTuple.Add(miValueResult2);
vwrMiValueList.Add(miValueTuple);
continue;
}
}
}
// If we are printing name only then no need to put it in the tuple.
vwrMiValueList.Add(miValueResultName);
}
return bOk;
}
// *** Do not refactor this function to be one function with same name as it can break more than
// *** than one stack type command
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.
// Type: Method.
// Args: vrFrame - (R) LLDB thread object.
// vMaskVarTypes - (R) Construed according to VariableType_e.
// veVarInfoFormat - (R) The type of variable info that should be shown.
// vwrMIValueList - (W) MI value list object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList)
{
bool bOk = MIstatus::success;
lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
const MIuint nMaxRecusiveDepth = 10;
MIuint nCurrentRecursiveDepth = 0;
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
const MIuint nArgs = listArg.GetSize();
for (MIuint i = 0; bOk && (i < nArgs); i++)
{
lldb::SBValue value = listArg.GetValueAtIndex(i);
bOk = GetVariableInfo2(nMaxRecusiveDepth, value, false, veVarInfoFormat, vwrMiValueList, nCurrentRecursiveDepth);
}
return bOk;
}
// *** Do not refactor this function to be one function with same name as it can break more than
// *** than one stack type command
//++ ------------------------------------------------------------------------------------
// Details: Extract the value's name and value or recurse into child value object.
// Type: Method.
@ -764,7 +751,6 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrF
// vrValue - (R) LLDB value object.
// vbIsChildValue - (R) True = Value object is a child of a higher Value object,
// - False = Value object not a child.
// veVarInfoFormat - (R) The type of variable info that should be shown.
// vwrMIValueList - (W) MI value list object.
// vnDepth - (RW) The current recursive depth of this function.
// Return: MIstatus::success - Functional succeeded.
@ -773,19 +759,15 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrF
//--
bool
CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList,
MIuint &vrwnDepth)
const MIuint vnDepth, CMICmnMIValueList &vwrMiValueList)
{
// *** Update GetVariableInfo2() with any code changes here ***
// Check recursive depth
if (vrwnDepth >= vnMaxDepth)
if (vnDepth >= vnMaxDepth)
return MIstatus::success;
bool bOk = MIstatus::success;
lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue);
const CMICmnLLDBUtilSBValue utilValue(vrValue, true);
CMICmnMIValueTuple miValueTuple;
const MIchar *pName = rValue.GetName();
MIunused(pName);
const bool bIsPointerType = rValue.GetType().IsPointerType();
@ -794,98 +776,43 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb:
{
if (vbIsChildValue)
{
if (utilValue.IsCharType())
{
// For char types and try to form text string
const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true);
miValueTuple.Add(miValueConst, true);
}
else
{
// For composite types
const CMICmnMIValueConst miValueConst(
// For composite types
const CMICmnMIValueConst miValueConst(
CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true);
miValueTuple.Add(miValueConst, true);
}
return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true));
return vwrMiValueList.Add(miValueConst);
}
else
{
// Basic types
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMICmnMIValueConst miValueConst2(utilValue.GetValue());
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
return vwrMiValueList.Add(miValueConst);
}
}
else if (bIsPointerType && utilValue.IsChildCharType())
{
switch (veVarInfoFormat)
const CMIUtilString &rText(utilValue.GetChildValueCString());
if (rText.empty())
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// Append string text to the parent value information
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMIUtilString &rText(utilValue.GetChildValueCString());
if (rText.empty())
{
const CMICmnMIValueConst miValueConst(utilValue.GetValue());
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
else
{
if (utilValue.IsValueUnknown())
{
const CMICmnMIValueConst miValueConst(rText);
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
else
{
// Note code that has const in will not show the text suffix to the string pointer
// i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
// but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str()));
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
}
break;
}
default:
break;
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
bOk = vwrMiValueList.Add(miValueConst);
}
return vwrMiValueList.Add(miValueTuple);
else
{
if (utilValue.IsValueUnknown())
{
const CMICmnMIValueConst miValueConst(rText, true);
bOk = vwrMiValueList.Add(miValueConst);
}
else
{
// Note code that has const in will not show the text suffix to the string pointer
// i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
// but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str()), true);
bOk = vwrMiValueList.Add(miValueConst);
}
}
return bOk;
}
else if (bIsPointerType)
{
@ -893,226 +820,44 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb:
{
// For composite types
const CMICmnMIValueConst miValueConst(
CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true);
miValueTuple.Add(miValueConst, true);
return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true));
CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true);
return vwrMiValueList.Add(miValueConst);
}
else
{
// Basic types
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMICmnMIValueConst miValueConst2(utilValue.GetValue());
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
return vwrMiValueList.Add(miValueConst);
}
}
else
{
switch (veVarInfoFormat)
CMICmnMIValueList miValueList2(true);
// Build parent child composite types
for (MIuint i = 0; bOk && (i < nChildren); i++)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// Build parent child composite types
CMICmnMIValueList miValueList(true);
for (MIuint i = 0; bOk && (i < nChildren); i++)
{
lldb::SBValue member = rValue.GetChildAtIndex(i);
bOk = GetVariableInfo(vnMaxDepth, member, true, veVarInfoFormat, miValueList, ++vrwnDepth);
}
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str()));
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
break;
}
default:
break;
lldb::SBValue member = rValue.GetChildAtIndex(i);
bOk = GetVariableInfo(vnMaxDepth, member, true, vnDepth + 1, miValueList2);
}
return vwrMiValueList.Add(miValueTuple);
}
}
// *** Do not refactor this function to be one function with same name as it can break more than
// *** than one stack type command
//++ ------------------------------------------------------------------------------------
// Details: Extract the value's name and value or recurse into child value object.
// Type: Method.
// Args: vnMaxDepth - (R) The max recursive depth for this function.
// vrValue - (R) LLDB value object.
// vbIsChildValue - (R) True = Value object is a child of a higher Value object,
// - False = Value object not a child.
// veVarInfoFormat - (R) The type of variable info that should be shown.
// vwrMIValueList - (W) MI value list object.
// vnDepth - (RW) The current recursive depth of this function.
// // Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList,
MIuint &vrwnDepth)
{
// *** Update GetVariableInfo() with any code changes here ***
// Check recursive depth
if (vrwnDepth >= vnMaxDepth)
return MIstatus::success;
bool bOk = MIstatus::success;
lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue);
const CMICmnLLDBUtilSBValue utilValue(vrValue, true);
CMICmnMIValueTuple miValueTuple;
const MIchar *pName = rValue.GetName();
MIunused(pName);
const MIuint nChildren = rValue.GetNumChildren();
if (nChildren == 0)
{
if (vbIsChildValue && utilValue.IsCharType())
if (bOk)
{
// For char types and try to form text string
const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true);
miValueTuple.Add(miValueConst, true);
return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true));
CMIUtilString valueStr = miValueList2.ExtractContentNoBrackets();
// This is to handle case when a child has further children. For example,
// a struct containing another struct member
// value="{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }}
if(vbIsChildValue)
{
const CMICmnMIValueConst miValueConst(
CMIUtilString::Format("%s = { %s }", utilValue.GetName().c_str (), valueStr.c_str()), true);
return vwrMiValueList.Add(miValueConst);
}
else
{
const CMICmnMIValueConst miValueConst(valueStr, true);
return vwrMiValueList.Add(miValueConst);
}
}
else
{
// Basic types
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMICmnMIValueConst miValueConst2(utilValue.GetValue());
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
}
else if (utilValue.IsChildCharType())
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// Append string text to the parent value information
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMIUtilString &rText(utilValue.GetChildValueCString());
if (rText.empty())
{
const CMICmnMIValueConst miValueConst(utilValue.GetValue());
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
else
{
if (utilValue.IsValueUnknown())
{
const CMICmnMIValueConst miValueConst(rText);
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
else
{
// Note code that has const in will not show the text suffix to the string pointer
// i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
// but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str()));
const CMICmnMIValueResult miValueResult("value", miValueConst);
miValueTuple.Add(miValueResult);
}
}
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
else
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// Build parent child composite types
CMICmnMIValueList miValueList(true);
for (MIuint i = 0; bOk && (i < nChildren); i++)
{
lldb::SBValue member = rValue.GetChildAtIndex(i);
bOk = GetVariableInfo(vnMaxDepth, member, true, veVarInfoFormat, miValueList, ++vrwnDepth);
}
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
miValueTuple.Add(miValueResult);
const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str()));
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
return bOk;
}
}

View File

@ -163,8 +163,6 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList);
bool MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList);
bool MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList);
bool MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const;
@ -202,9 +200,7 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
void operator=(const CMICmnLLDBDebugSessionInfo &);
//
bool GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth);
bool GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth);
const MIuint vnDepth, CMICmnMIValueList &vwrMiValueList);
// Overridden:
private:

View File

@ -85,11 +85,8 @@ CMICmnLLDBUtilSBValue::GetValue(void) const
if (m_bHandleCharType && IsCharType())
{
const lldb::addr_t addr = m_rValue.GetLoadAddress();
text = CMIUtilString::Format("0x%08x", addr);
const CMIUtilString cString(GetValueCString());
if (!cString.empty())
text += CMIUtilString::Format(" %s", cString.c_str());
uint8_t val = (uint8_t)m_rValue.GetValueAsUnsigned ();
text += CMIUtilString::Format("%d '%c'", val, (char)val);
}
else
{
@ -133,8 +130,6 @@ CMICmnLLDBUtilSBValue::GetValueCString(void) const
bool
CMICmnLLDBUtilSBValue::IsCharType(void) const
{
const MIchar *pName = m_rValue.GetName();
MIunused(pName);
const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
return ((eType == lldb::eBasicTypeChar) || (eType == lldb::eBasicTypeSignedChar) || (eType == lldb::eBasicTypeUnsignedChar));
}

View File

@ -175,9 +175,12 @@ CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue)
return BuildList();
}
// Remove already present '[' and ']' from the start and end
m_strValue = m_strValue.Trim();
size_t len = m_strValue.size();
if ( (len > 1) && (m_strValue[0] == '[') && (m_strValue[len - 1] == ']') )
m_strValue = m_strValue.substr(1, len - 2);
const MIchar *pFormat = "[%s,%s]";
m_strValue = m_strValue.FindAndReplace("[", "");
m_strValue = m_strValue.FindAndReplace("]", "");
m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vValue.GetString().c_str());
return MIstatus::success;