forked from OSchip/llvm-project
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:
parent
5eb75aced4
commit
095b128671
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue