Index: test/tools/lldb-mi/Makefile =================================================================== --- test/tools/lldb-mi/Makefile +++ test/tools/lldb-mi/Makefile @@ -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 Index: test/tools/lldb-mi/TestMiExec.py =================================================================== --- test/tools/lldb-mi/TestMiExec.py +++ test/tools/lldb-mi/TestMiExec.py @@ -153,22 +153,22 @@ # 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 @@ # 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 @@ #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 @@ # -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 @@ # 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) Index: test/tools/lldb-mi/TestMiStack.py =================================================================== --- test/tools/lldb-mi/TestMiStack.py +++ test/tools/lldb-mi/TestMiStack.py @@ -80,6 +80,87 @@ 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") Index: test/tools/lldb-mi/locals.c =================================================================== --- /dev/null +++ test/tools/lldb-mi/locals.c @@ -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; +} \ No newline at end of file Index: test/tools/lldb-mi/main.c =================================================================== --- test/tools/lldb-mi/main.c +++ test/tools/lldb-mi/main.c @@ -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 @@ 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 } Index: tools/lldb-mi/MICmdCmdStack.cpp =================================================================== --- tools/lldb-mi/MICmdCmdStack.cpp +++ tools/lldb-mi/MICmdCmdStack.cpp @@ -465,7 +465,7 @@ 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); Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.h =================================================================== --- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h +++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.h @@ -163,8 +163,6 @@ 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 @@ 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: Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp +++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp @@ -705,58 +705,45 @@ 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 = GetVariableInfo(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: 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(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; + 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 = GetVariableInfo2(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: Extract the value's name and value or recurse into child value object. // Type: Method. @@ -764,7 +751,6 @@ // 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 @@ //-- 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(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 @@ { 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.GetValue(), true); + bOk = vwrMiValueList.Add(miValueConst); + } + else + { + if (utilValue.IsValueUnknown()) { - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - return vwrMiValueList.Add(miValueResult); + const CMICmnMIValueConst miValueConst(rText, true); + bOk = vwrMiValueList.Add(miValueConst); } - case eVariableInfoFormat_AllValues: - case eVariableInfoFormat_SimpleValues: + else { - // 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; + // 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); } - default: - break; } - return vwrMiValueList.Add(miValueTuple); + return bOk; } else if (bIsPointerType) { @@ -893,226 +820,44 @@ { // 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(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()) - { - // 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)); - } - else + if (bOk) { - // Basic types - switch (veVarInfoFormat) + 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) { - 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); + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%s = { %s }", utilValue.GetName().c_str (), valueStr.c_str()), true); + return vwrMiValueList.Add(miValueConst); } - case eVariableInfoFormat_AllValues: - case eVariableInfoFormat_SimpleValues: + else { - // 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; + const CMICmnMIValueConst miValueConst(valueStr, true); + return vwrMiValueList.Add(miValueConst); } - default: - break; } - return vwrMiValueList.Add(miValueTuple); + return bOk; } } Index: tools/lldb-mi/MICmnLLDBUtilSBValue.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -85,11 +85,8 @@ 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 @@ 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)); } Index: tools/lldb-mi/MICmnMIValueList.cpp =================================================================== --- tools/lldb-mi/MICmnMIValueList.cpp +++ tools/lldb-mi/MICmnMIValueList.cpp @@ -175,9 +175,12 @@ 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;