Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI)

Summary:
This patch includes the following changes:

# Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI)
Also it expands the variable value format for strings (aka char*):
was:
```
^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0"
```
now:
```
^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0"
```

# Expand the variable value format for arrays (according to GDB)
For example:
was:
```
^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0"
```
now:
```
^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0"
```

# Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI)

# Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI)

# Refactor CMICmnLLDBUtilSBValue
## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType
## Refactor CMICmnLLDBUtilSBValue::GetValue
## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs
## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType
## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[]

# Minor changes in CMICmnLLDBUtilSBValue::GetValue

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI)

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI)
## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2
## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI)
## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo
## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace

# Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI)
## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2
## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth

# Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI)

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI)
## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one

# Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI)

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI)
## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3
## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI)
## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2
## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format
## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat
## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added)

# Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI)

# Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI)
## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format
## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat
## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added)

# Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI)

# Refactor CMICmnLLDBUtilSBValue::GetValue (MI)
## Add CMICmnLLDBUtilSBValue::GetSimpleValue
## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue

# Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI)
## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0.
## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat
## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead)

# Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI)
## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types
## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code
## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false)
## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue
## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo
## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets:
was:
```
{name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }}
```
now:
```
{name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}}
```
## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue)

# Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI)
## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo
## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue
## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead)
## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values
was:
```
{name="p",value="0x0000000000000000 """}
```
now:
```
{name="p",value="0x0000000000000000 \"\""}
```

# Refactor CMICmnLLDBUtilSBValue
## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates
## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]")

# Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI)
For example:
was:
```
^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0"
```
now:
```
^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0"
```

# Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI)

Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/

Reviewers: abidh

Subscribers: lldb-commits, abidh

Differential Revision: http://reviews.llvm.org/D8913

llvm-svn: 234476
This commit is contained in:
Ilia K 2015-04-09 11:17:54 +00:00
parent be218927f8
commit 58627321f6
11 changed files with 312 additions and 615 deletions

View File

@ -137,9 +137,9 @@ class MiStackTestCase(lldbmi_testcase.MiTestCaseBase):
# 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.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 }}\"}\]")
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")
@ -164,9 +164,9 @@ class MiStackTestCase(lldbmi_testcase.MiTestCaseBase):
# 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.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}\"}\]")
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")

View File

@ -112,13 +112,13 @@ class MiVarTestCase(lldbmi_testcase.MiTestCaseBase):
self.runCmd("-data-evaluate-expression \"argv[0]\"")
self.expect("\^done,value=\"0x[0-9a-f]+\"")
self.runCmd("-var-create var6 * \"argv[0]\"")
self.expect("\^done,name=\"var6\",numchild=\"1\",value=\"0x[0-9a-f]+\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var6\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\".*%s\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"" % self.myexe)
self.runCmd("-var-evaluate-expression var6")
self.expect("\^done,value=\"0x[0-9a-f]+\"")
self.expect("\^done,value=\"0x[0-9a-f]+ \\\\\\\".*%s\\\\\\\"\"" % self.myexe)
self.runCmd("-var-show-attributes var6")
self.expect("\^done,status=\"editable\"")
self.runCmd("-var-list-children var6")
#self.expect("\^done,numchild=\"1\",children=\[child=\{name=\"var6\.\*\$15\",exp=\"\*\$15\",numchild=\"0\",type=\"const char\",thread-id=\"1\",has_more=\"0\"\}\]") #FIXME -var-list-children shows invalid thread-id
self.runCmd("-var-list-children --all-values var6")
self.expect("\^done,numchild=\"1\",children=\[child=\{name=\"var6\.\*\$11\",exp=\"\*\$11\",numchild=\"0\",type=\"const char\",thread-id=\"4294967295\",value=\"47 '/'\",has_more=\"0\"\}\]") #FIXME -var-list-children shows invalid thread-id
@lldbmi_test
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
@ -147,7 +147,7 @@ class MiVarTestCase(lldbmi_testcase.MiTestCaseBase):
self.runCmd("-var-create var_complx * complx")
self.expect("\^done,name=\"var_complx\",numchild=\"3\",value=\"\{\.\.\.\}\",type=\"complex_type\",thread-id=\"1\",has_more=\"0\"")
self.runCmd("-var-create var_complx_array * complx_array")
self.expect("\^done,name=\"var_complx_array\",numchild=\"2\",value=\"\{\.\.\.\}\",type=\"complex_type \[2\]\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var_complx_array\",numchild=\"2\",value=\"\[2\]\",type=\"complex_type \[2\]\",thread-id=\"1\",has_more=\"0\"")
# Go to BP_var_update_test_l
line = line_number('main.cpp', '// BP_var_update_test_l')
@ -183,7 +183,7 @@ class MiVarTestCase(lldbmi_testcase.MiTestCaseBase):
# Test that var_complex_array was updated
self.runCmd("-var-update --all-values var_complx_array")
self.expect("\^done,changelist=\[\{name=\"var_complx_array\",value=\"\{\.\.\.\}\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\]")
self.expect("\^done,changelist=\[\{name=\"var_complx_array\",value=\"\[2\]\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\]")
if __name__ == '__main__':
unittest2.main()

View File

@ -239,7 +239,7 @@ CMICmdCmdListThreadGroups::Execute(void)
if (thread.IsValid())
{
CMICmnMIValueTuple miTuple;
if (!rSessionInfo.MIResponseFormThreadInfo2(m_cmdData, thread, miTuple))
if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_NoFrames, miTuple))
return MIstatus::failure;
m_vecMIValueTuple.push_back(miTuple);

View File

@ -213,7 +213,7 @@ CMICmdCmdStackInfoFrame::Execute(void)
lldb::SBThread sbThread = sbProcess.GetSelectedThread();
MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID();
if (!rSessionInfo.MIResponseFormFrameInfo(sbThread, nFrameId, m_miValueTuple))
if (!rSessionInfo.MIResponseFormFrameInfo(sbThread, nFrameId, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, m_miValueTuple))
return MIstatus::failure;
return MIstatus::success;
@ -356,7 +356,7 @@ CMICmdCmdStackListFrames::Execute(void)
for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++)
{
CMICmnMIValueTuple miValueTuple;
if (!rSessionInfo.MIResponseFormFrameInfo(thread, nLevel, miValueTuple))
if (!rSessionInfo.MIResponseFormFrameInfo(thread, nLevel, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple))
return MIstatus::failure;
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);

View File

@ -100,7 +100,7 @@ CMICmdCmdThreadInfo::Execute(void)
return MIstatus::success;
CMICmnMIValueTuple miTuple;
if (!rSessionInfo.MIResponseFormThreadInfo3(m_cmdData, thread, miTuple))
if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
return MIstatus::failure;
m_miValueTupleThread = miTuple;
@ -117,7 +117,7 @@ CMICmdCmdThreadInfo::Execute(void)
if (thread.IsValid())
{
CMICmnMIValueTuple miTuple;
if (!rSessionInfo.MIResponseFormThreadInfo3(m_cmdData, thread, miTuple))
if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
return MIstatus::failure;
m_vecMIValueTuple.push_back(miTuple);

View File

@ -211,7 +211,8 @@ CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId)
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames)
CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, const FrameInfoFormat_e veFrameInfoFormat,
CMIUtilString &vwrThreadFrames)
{
lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx);
const uint32_t nFrames = thread.GetNumFrames();
@ -230,108 +231,8 @@ CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MI
CMIUtilString strListCommaSeperated;
for (MIuint nLevel = 0; nLevel < nFrames; nLevel++)
{
lldb::SBFrame frame = thread.GetFrameAtIndex(nLevel);
lldb::addr_t pc = 0;
CMIUtilString fnName;
CMIUtilString fileName;
CMIUtilString path;
MIuint nLine = 0;
if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
return MIstatus::failure;
// Function args
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = eVariableType_Arguments;
if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList))
return MIstatus::failure;
const MIchar *pUnknown = "??";
if (fnName != pUnknown)
{
std::replace(fnName.begin(), fnName.end(), ')', ' ');
std::replace(fnName.begin(), fnName.end(), '(', ' ');
std::replace(fnName.begin(), fnName.end(), '\'', ' ');
}
CMICmnMIValueTuple miValueTuple;
const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel));
const CMICmnMIValueConst miValueConst(strLevel);
const CMICmnMIValueResult miValueResult("level", miValueConst);
miValueTuple.Add(miValueResult);
if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
return MIstatus::failure;
const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
if (nLevel != 0)
strListCommaSeperated += ",";
strListCommaSeperated += miValueResult2.GetString();
}
vwrThreadFrames = strListCommaSeperated;
return MIstatus::success;
}
// Todo: Refactor maybe to so only one function with this name, but not just yet
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the specified thread's frame information.
// Type: Method.
// Args: vCmdData - (R) A command's information.
// vThreadIdx - (R) Thread index.
// vwrThreadFrames - (W) Frame data.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames)
{
lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx);
const uint32_t nFrames = thread.GetNumFrames();
if (nFrames == 0)
{
// MI print "frame={}"
CMICmnMIValueTuple miValueTuple;
CMICmnMIValueResult miValueResult("frame", miValueTuple);
vwrThreadFrames = miValueResult.GetString();
return MIstatus::success;
}
// MI print
// "frame={level=\"%d\",addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},
// ..."
CMIUtilString strListCommaSeperated;
for (MIuint nLevel = 0; nLevel < nFrames; nLevel++)
{
lldb::SBFrame frame = thread.GetFrameAtIndex(nLevel);
lldb::addr_t pc = 0;
CMIUtilString fnName;
CMIUtilString fileName;
CMIUtilString path;
MIuint nLine = 0;
if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
return MIstatus::failure;
// Function args
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = eVariableType_Arguments;
if (!MIResponseFormVariableInfo2(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList))
return MIstatus::failure;
const MIchar *pUnknown = "??";
if (fnName != pUnknown)
{
std::replace(fnName.begin(), fnName.end(), ')', ' ');
std::replace(fnName.begin(), fnName.end(), '(', ' ');
std::replace(fnName.begin(), fnName.end(), '\'', ' ');
}
CMICmnMIValueTuple miValueTuple;
const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel));
const CMICmnMIValueConst miValueConst(strLevel);
const CMICmnMIValueResult miValueResult("level", miValueConst);
miValueTuple.Add(miValueResult);
if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat, miValueTuple))
return MIstatus::failure;
const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
@ -459,14 +360,10 @@ CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, bool &vwbYesA
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
CMICmnMIValueTuple &vwrMIValueTuple)
const ThreadInfoFormat_e veThreadInfoFormat, CMICmnMIValueTuple &vwrMIValueTuple)
{
lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
CMIUtilString strFrames;
if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), strFrames))
return MIstatus::failure;
const bool bSuspended = rThread.IsSuspended();
const lldb::StopReason eReason = rThread.GetStopReason();
const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
@ -496,178 +393,24 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData,
return MIstatus::failure;
// Add "frame"
const CMICmnMIValueConst miValueConst3(strFrames, true);
if (!vwrMIValueTuple.Add(miValueConst3, false))
return MIstatus::failure;
// Add "state"
const CMICmnMIValueConst miValueConst4(strState);
const CMICmnMIValueResult miValueResult4("state", miValueConst4);
if (!vwrMIValueTuple.Add(miValueResult4))
return MIstatus::failure;
return MIstatus::success;
}
// Todo: Refactor maybe to so only one function with this name, but not just yet
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.
// Type: Method.
// Args: vCmdData - (R) A command's information.
// vrThread - (R) LLDB thread object.
// vwrMIValueTuple - (W) MI value tuple object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3(const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
CMICmnMIValueTuple &vwrMIValueTuple)
{
lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
CMIUtilString strFrames;
if (!GetThreadFrames2(vCmdData, rThread.GetIndexID(), strFrames))
return MIstatus::failure;
const bool bSuspended = rThread.IsSuspended();
const lldb::StopReason eReason = rThread.GetStopReason();
const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running");
// Add "id"
const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID()));
const CMICmnMIValueConst miValueConst1(strId);
const CMICmnMIValueResult miValueResult1("id", miValueConst1);
if (!vwrMIValueTuple.Add(miValueResult1))
return MIstatus::failure;
// Add "target-id"
const MIchar *pThreadName = rThread.GetName();
const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0;
const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) &&
CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number
const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d";
CMIUtilString strThread;
if (bHaveName)
strThread = CMIUtilString::Format(pThrdFmt, pThreadName);
else
strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID());
const CMICmnMIValueConst miValueConst2(strThread);
const CMICmnMIValueResult miValueResult2("target-id", miValueConst2);
if (!vwrMIValueTuple.Add(miValueResult2))
return MIstatus::failure;
// Add "frame"
const CMICmnMIValueConst miValueConst3(strFrames, true);
if (!vwrMIValueTuple.Add(miValueConst3, false))
return MIstatus::failure;
// Add "state"
const CMICmnMIValueConst miValueConst4(strState);
const CMICmnMIValueResult miValueResult4("state", miValueConst4);
if (!vwrMIValueTuple.Add(miValueResult4))
return MIstatus::failure;
return MIstatus::success;
}
// Todo: Refactor maybe to so only one function with this name, but not just yet
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.
// Type: Method.
// Args: vCmdData - (R) A command's information.
// vrThread - (R) LLDB thread object.
// vwrMIValueTuple - (W) MI value tuple object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2(const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
CMICmnMIValueTuple &vwrMIValueTuple)
{
lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
const bool bSuspended = rThread.IsSuspended();
const lldb::StopReason eReason = rThread.GetStopReason();
const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running");
// Add "id"
const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID()));
const CMICmnMIValueConst miValueConst1(strId);
const CMICmnMIValueResult miValueResult1("id", miValueConst1);
if (!vwrMIValueTuple.Add(miValueResult1))
return MIstatus::failure;
// Add "target-id"
const MIchar *pThreadName = rThread.GetName();
const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0;
const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) &&
CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number
const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d";
CMIUtilString strThread;
if (bHaveName)
strThread = CMIUtilString::Format(pThrdFmt, pThreadName);
else
strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID());
const CMICmnMIValueConst miValueConst2(strThread);
const CMICmnMIValueResult miValueResult2("target-id", miValueConst2);
if (!vwrMIValueTuple.Add(miValueResult2))
return MIstatus::failure;
// Add "state"
const CMICmnMIValueConst miValueConst4(strState);
const CMICmnMIValueResult miValueResult4("state", miValueConst4);
if (!vwrMIValueTuple.Add(miValueResult4))
return MIstatus::failure;
return MIstatus::success;
}
// Todo: Refactor maybe to so only one function with this name, but not just yet
//++ ------------------------------------------------------------------------------------
// 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::MIResponseFormVariableInfo2(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);
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
const MIuint nArgs = listArg.GetSize();
for (MIuint i = 0; bOk && (i < nArgs); i++)
if (veThreadInfoFormat != eThreadInfoFormat_NoFrames)
{
lldb::SBValue value = listArg.GetValueAtIndex(i);
const CMICmnLLDBUtilSBValue utilValue(value);
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
const CMICmnMIValueConst miValueConst2(utilValue.GetValue());
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResult2);
bOk = vwrMiValueList.Add(miValueTuple);
CMIUtilString strFrames;
if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst3(strFrames, true);
if (!vwrMIValueTuple.Add(miValueConst3, false))
return MIstatus::failure;
}
return bOk;
// Add "state"
const CMICmnMIValueConst miValueConst4(strState);
const CMICmnMIValueResult miValueResult4("state", miValueConst4);
if (!vwrMIValueTuple.Add(miValueResult4))
return MIstatus::failure;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@ -684,7 +427,8 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrF
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList)
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList,
const MIuint vnMaxDepth /* = 10 */)
{
bool bOk = MIstatus::success;
lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
@ -693,8 +437,6 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr
const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
const MIuint nMaxRecusiveDepth = 10;
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++)
@ -711,14 +453,10 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr
(bIsPointerType && nChildren == 1) || // pointers
veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values
{
CMICmnMIValueList miValueList(true);
if (GetVariableInfo(nMaxRecusiveDepth, value, false, nCurrentRecursiveDepth, miValueList))
CMIUtilString strValue;
if (GetVariableInfo(value, vnMaxDepth == 0, strValue))
{
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 CMICmnMIValueConst miValueConst2(strValue.Escape().AddSlashes());
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
miValueTuple.Add(miValueResultName); // name
miValueTuple.Add(miValueResult2);
@ -736,118 +474,21 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr
//++ ------------------------------------------------------------------------------------
// 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.
// vwrMIValueList - (W) MI value list object.
// vnDepth - (RW) The current recursive depth of this function.
// Args: vrValue - (R) LLDB value object.
// vbInSimpleForm - (R) True = Get variable info in simple form (i.e. don't expand aggregates).
// - False = Get variable info (and expand aggregates if any).
// vwrStrValue t - (W) The string representatin of this value.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const MIuint vnDepth, CMICmnMIValueList &vwrMiValueList)
CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, CMIUtilString &vwrStrValue)
{
// Check recursive depth
if (vnDepth >= vnMaxDepth)
return MIstatus::success;
bool bOk = MIstatus::success;
lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue);
const CMICmnLLDBUtilSBValue utilValue(vrValue, true);
const MIchar *pName = rValue.GetName();
MIunused(pName);
const bool bIsPointerType = rValue.GetType().IsPointerType();
const MIuint nChildren = rValue.GetNumChildren();
if (nChildren == 0)
{
if (vbIsChildValue)
{
// For composite types
const CMICmnMIValueConst miValueConst(
CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true);
return vwrMiValueList.Add(miValueConst);
}
else
{
// Basic types
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
return vwrMiValueList.Add(miValueConst);
}
}
else if (bIsPointerType && utilValue.IsChildCharType())
{
const CMIUtilString &rText(utilValue.GetChildValueCString());
if (rText.empty())
{
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
bOk = vwrMiValueList.Add(miValueConst);
}
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)
{
if (vbIsChildValue)
{
// For composite types
const CMICmnMIValueConst miValueConst(
CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true);
return vwrMiValueList.Add(miValueConst);
}
else
{
// Basic types
const CMICmnMIValueConst miValueConst(utilValue.GetValue(), true);
return vwrMiValueList.Add(miValueConst);
}
}
else
{
CMICmnMIValueList miValueList2(true);
// Build parent child composite types
for (MIuint i = 0; bOk && (i < nChildren); i++)
{
lldb::SBValue member = rValue.GetChildAtIndex(i);
bOk = GetVariableInfo(vnMaxDepth, member, true, vnDepth + 1, miValueList2);
}
if (bOk)
{
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);
}
}
return bOk;
}
const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false);
const bool bExpandAggregates = vbInSimpleForm ? false : true;
vwrStrValue = utilValue.GetValue(bExpandAggregates);
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@ -856,13 +497,14 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb:
// Type: Method.
// Args: vrThread - (R) LLDB thread object.
// vwrMIValueTuple - (W) MI value tuple object.
// vArgInfo - (R) Args information in MI response form.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel,
CMICmnMIValueTuple &vwrMiValueTuple)
const FrameInfoFormat_e veFrameInfoFormat, CMICmnMIValueTuple &vwrMiValueTuple)
{
lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
@ -879,11 +521,47 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThre
const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel));
const CMICmnMIValueConst miValueConst(strLevel);
const CMICmnMIValueResult miValueResult("level", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
if (!MIResponseFormFrameInfo(pc, fnName, fileName, path, nLine, miValueTuple))
if (!vwrMiValueTuple.Add(miValueResult))
return MIstatus::failure;
const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc));
const CMICmnMIValueConst miValueConst2(strAddr);
const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
if (!vwrMiValueTuple.Add(miValueResult2))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst3(fnName);
const CMICmnMIValueResult miValueResult3("func", miValueConst3);
if (!vwrMiValueTuple.Add(miValueResult3))
return MIstatus::failure;
if (veFrameInfoFormat != eFrameInfoFormat_NoArguments)
{
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = eVariableType_Arguments;
if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm)
{
if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList, 0))
return MIstatus::failure;
}
else
if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList))
return MIstatus::failure;
vwrMiValueTuple = miValueTuple;
const CMICmnMIValueResult miValueResult4("args", miValueList);
if (!vwrMiValueTuple.Add(miValueResult4))
return MIstatus::failure;
}
const CMICmnMIValueConst miValueConst5(fileName);
const CMICmnMIValueResult miValueResult5("file", miValueConst5);
if (!vwrMiValueTuple.Add(miValueResult5))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst6(path);
const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
if (!vwrMiValueTuple.Add(miValueResult6))
return MIstatus::failure;
const CMIUtilString strLine(CMIUtilString::Format("%d", nLine));
const CMICmnMIValueConst miValueConst7(strLine);
const CMICmnMIValueResult miValueResult7("line", miValueConst7);
if (!vwrMiValueTuple.Add(miValueResult7))
return MIstatus::failure;
return MIstatus::success;
}
@ -929,101 +607,6 @@ CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::add
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.
// Type: Method.
// Args: vPc - (R) Address number.
// vFnName - (R) Function name.
// vFileName - (R) File name text.
// vPath - (R) Full file name and path text.
// vnLine - (R) File line number.
// vwrMIValueTuple - (W) MI value tuple object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::addr_t vPc, const CMIUtilString &vFnName, const CMIUtilString &vFileName,
const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple)
{
const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, vPc));
const CMICmnMIValueConst miValueConst2(strAddr);
const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
if (!vwrMiValueTuple.Add(miValueResult2))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst3(vFnName);
const CMICmnMIValueResult miValueResult3("func", miValueConst3);
if (!vwrMiValueTuple.Add(miValueResult3))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst5(vFileName);
const CMICmnMIValueResult miValueResult5("file", miValueConst5);
if (!vwrMiValueTuple.Add(miValueResult5))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst6(vPath);
const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
if (!vwrMiValueTuple.Add(miValueResult6))
return MIstatus::failure;
const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine));
const CMICmnMIValueConst miValueConst7(strLine);
const CMICmnMIValueResult miValueResult7("line", miValueConst7);
if (!vwrMiValueTuple.Add(miValueResult7))
return MIstatus::failure;
return MIstatus::success;
}
// Todo: Refactor maybe to so only one function with this name, but not just yet
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.
// Type: Method.
// Args: vPc - (R) Address number.
// vArgInfo - (R) Args information in MI response form.
// vFnName - (R) Function name.
// vFileName - (R) File name text.
// vPath - (R) Full file name and path text.
// vnLine - (R) File line number.
// vwrMIValueTuple - (W) MI value tuple object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2(const lldb::addr_t vPc, const CMIUtilString &vArgInfo, const CMIUtilString &vFnName,
const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine,
CMICmnMIValueTuple &vwrMiValueTuple)
{
const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, vPc));
const CMICmnMIValueConst miValueConst2(strAddr);
const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
if (!vwrMiValueTuple.Add(miValueResult2))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst3(vFnName);
const CMICmnMIValueResult miValueResult3("func", miValueConst3);
if (!vwrMiValueTuple.Add(miValueResult3))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst4(vArgInfo, true);
const CMICmnMIValueResult miValueResult4("args", miValueConst4);
if (!vwrMiValueTuple.Add(miValueResult4))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst5(vFileName);
const CMICmnMIValueResult miValueResult5("file", miValueConst5);
if (!vwrMiValueTuple.Add(miValueResult5))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst6(vPath);
const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
if (!vwrMiValueTuple.Add(miValueResult6))
return MIstatus::failure;
const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine));
const CMICmnMIValueConst miValueConst7(strLine);
const CMICmnMIValueResult miValueResult7("line", miValueConst7);
if (!vwrMiValueTuple.Add(miValueResult7))
return MIstatus::failure;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Form MI partial response by appending more MI value type objects to the
// tuple type object past in.

View File

@ -116,6 +116,25 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
kNumVariableInfoFormats
};
//++ ===================================================================
// Details: Determine the information that should be shown by using MIResponseFormThreadInfo family functions.
//--
enum ThreadInfoFormat_e
{
eThreadInfoFormat_NoFrames,
eThreadInfoFormat_AllFrames
};
//++ ===================================================================
// Details: Determine the information that should be shown by using MIResponseFormFrameInfo family functions.
//--
enum FrameInfoFormat_e
{
eFrameInfoFormat_NoArguments,
eFrameInfoFormat_AllArguments,
eFrameInfoFormat_AllArgumentsInSimpleForm
};
// Typedefs:
public:
typedef std::vector<uint32_t> VecActiveThreadId_t;
@ -132,25 +151,15 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
// Common command required functionality
bool AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible);
bool GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName,
CMIUtilString &vwPath, MIuint &vwnLine);
bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames);
bool GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames);
bool ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath);
bool ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath);
bool MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormFrameInfo(const lldb::addr_t vPc, const CMIUtilString &vFnName, const CMIUtilString &vFileName,
const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormFrameInfo2(const lldb::addr_t vPc, const CMIUtilString &vArgInfo, const CMIUtilString &vFnName,
const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine,
CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple);
bool MIResponseFormThreadInfo2(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple);
bool MIResponseFormThreadInfo3(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple);
bool MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel,
const FrameInfoFormat_e veFrameInfoFormat, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
const ThreadInfoFormat_e veThreadInfoFormat, CMICmnMIValueTuple &vwrMIValueTuple);
bool MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList);
bool MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList);
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList,
const MIuint vnMaxDepth = 10);
bool MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const;
@ -187,8 +196,11 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
/* ctor */ CMICmnLLDBDebugSessionInfo(const CMICmnLLDBDebugSessionInfo &);
void operator=(const CMICmnLLDBDebugSessionInfo &);
//
bool GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue,
const MIuint vnDepth, CMICmnMIValueList &vwrMiValueList);
bool GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, CMIUtilString &vwrStrValue);
bool GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName,
CMIUtilString &vwPath, MIuint &vwnLine);
bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, const FrameInfoFormat_e veFrameInfoFormat,
CMIUtilString &vwrThreadFrames);
// Overridden:
private:

View File

@ -257,7 +257,9 @@ CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(const MIchar &vrcFormat)
}
//++ ------------------------------------------------------------------------------------
// Details: Return the equivalent var value formatted string for the given value type.
// Details: Return the equivalent var value formatted string for the given value type,
// which was prepared for printing (i.e. value was escaped and now it's ready
// for wrapping into quotes).
// The SBValue vrValue parameter is checked by LLDB private code for valid
// scalar type via MI Driver proxy function as the valued returned can also be
// an error condition. The proxy function determines if the check was valid
@ -272,21 +274,8 @@ CMIUtilString
CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(const lldb::SBValue &vrValue,
const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat)
{
CMIUtilString strFormattedValue;
MIuint64 nValue = 0;
if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(vrValue, nValue) == MIstatus::success)
{
lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue);
strFormattedValue = GetStringFormatted(nValue, rValue.GetValue(), veVarFormat);
}
else
{
// Composite variable type i.e. struct
strFormattedValue = "{...}";
}
return strFormattedValue;
const CMICmnLLDBUtilSBValue utilValue(vrValue, true);
return utilValue.GetValue().Escape().AddSlashes();
}
//++ ------------------------------------------------------------------------------------
@ -564,7 +553,7 @@ CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat(const varFormat_e veVarFormat)
void
CMICmnLLDBDebugSessionInfoVarObj::UpdateValue(void)
{
m_strFormattedValue = CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(m_SBValue, m_eVarFormat);
m_strFormattedValue = GetValueStringFormatted(m_SBValue, m_eVarFormat);
MIuint64 nValue = 0;
if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(m_SBValue, nValue) == MIstatus::failure)

View File

@ -1177,7 +1177,7 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &
}
CMICmnMIValueTuple miValueTuple;
if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, miValueTuple))
if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
return MIstatus::failure;
@ -1260,19 +1260,7 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
return bOk;
}
CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
lldb::addr_t pc = 0;
CMIUtilString fnName;
CMIUtilString fileName;
CMIUtilString path;
MIuint nLine = 0;
if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "MiStoppedAtBreakPoint()"));
return MIstatus::failure;
}
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
@ -1290,12 +1278,8 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
// frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
if (bOk)
{
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues, miValueList);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple);
bOk = bOk && rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple);
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
}
@ -1349,29 +1333,14 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
return bOk;
}
CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
lldb::addr_t pc = 0;
CMIUtilString fnName;
CMIUtilString fileName;
CMIUtilString path;
MIuint nLine = 0;
if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "HandleProcessEventStopReasonTrace()"));
return MIstatus::failure;
}
// Function args
CMICmnMIValueList miValueList(true);
const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues, miValueList))
return MIstatus::failure;
CMICmnMIValueTuple miValueTuple;
if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
if (!rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst("end-stepping-range");

View File

@ -9,8 +9,10 @@
// In-house headers:
#include "MICmnLLDBUtilSBValue.h"
#include "MIUtilString.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilString.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBUtilSBValue constructor.
@ -21,10 +23,13 @@
// Return: None.
// Throws: None.
//--
CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */)
CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */,
const bool vbHandleArrayType /* = true */)
: m_rValue(const_cast<lldb::SBValue &>(vrValue))
, m_pUnkwn("??")
, m_pComposite("{...}")
, m_bHandleCharType(vbHandleCharType)
, m_bHandleArrayType(vbHandleArrayType)
{
m_bValidSBValue = m_rValue.IsValid();
}
@ -67,28 +72,138 @@ CMICmnLLDBUtilSBValue::GetName(void) const
// Throws: None.
//--
CMIUtilString
CMICmnLLDBUtilSBValue::GetValue(void) const
CMICmnLLDBUtilSBValue::GetValue(const bool vbExpandAggregates /* = false */) const
{
CMIUtilString text;
if (!m_bValidSBValue)
return m_pUnkwn;
if (m_bHandleCharType && IsCharType())
{
uint8_t val = (uint8_t)m_rValue.GetValueAsUnsigned ();
text += CMIUtilString::Format("%d '%c'", val, (char)val);
}
else
{
const MIchar *pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr;
text = (pValue != nullptr) ? pValue : m_pUnkwn;
}
const bool bHandleArrayTypeAsSimple = m_bHandleArrayType && !vbExpandAggregates;
CMIUtilString value;
const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value);
if (bIsSimpleValue)
return value;
return text;
if (!vbExpandAggregates)
return m_pComposite;
CMICmnMIValueTuple miValueTuple;
const bool bOk = GetCompositeValue(miValueTuple);
if (!bOk)
return m_pUnkwn;
value = miValueTuple.GetString();
return value;
}
//++ ------------------------------------------------------------------------------------
// Details: If the LLDB SB Value object is a char type then form the text data string
// otherwise return nothing. m_bHandleCharType must be true to return text data
// if any.
// Details: Retrieve from the LLDB SB Value object the value of the variable described in
// text if it has a simple format (not composite).
// Type: Method.
// Args: vwrValue - (W) The SBValue in a string format.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vwrValue) const
{
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0)
{
if (m_bHandleCharType && IsCharType())
{
const uint8_t value = m_rValue.GetValueAsUnsigned();
const CMIUtilString prefix(CMIUtilString::Format("%c", value).Escape().AddSlashes());
vwrValue = CMIUtilString::Format("%hhu '%s'", value, prefix.c_str());
return MIstatus::success;
}
else
{
const MIchar *pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr;
vwrValue = pValue != nullptr ? pValue : m_pUnkwn;
return MIstatus::success;
}
}
else if (IsPointerType())
{
if (m_bHandleCharType && IsFirstChildCharType())
{
const MIchar *pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr;
const CMIUtilString value = pValue != nullptr ? pValue : m_pUnkwn;
const CMIUtilString prefix(GetChildValueCString().Escape().AddSlashes());
// 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
vwrValue = CMIUtilString::Format("%s \"%s\"", value.c_str(), prefix.c_str());
return MIstatus::success;
}
else
{
const MIchar *pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr;
vwrValue = pValue != nullptr ? pValue : m_pUnkwn;
return MIstatus::success;
}
}
else if (IsArrayType() && vbHandleArrayType)
{
vwrValue = CMIUtilString::Format("[%u]", nChildren);
return MIstatus::success;
}
// Composite variable type i.e. struct
return MIstatus::failure;
}
bool
CMICmnLLDBUtilSBValue::GetCompositeValue(CMICmnMIValueTuple &vwrMiValueTuple,
const MIuint vnDepth /* = 1 */) const
{
const MIuint nMaxDepth = 10;
const MIuint nChildren = m_rValue.GetNumChildren();
for (MIuint i = 0; i < nChildren; ++i)
{
const lldb::SBValue member = m_rValue.GetChildAtIndex(i);
const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType, m_bHandleArrayType);
const bool bHandleArrayTypeAsSimple = false;
CMIUtilString value;
const bool bIsSimpleValue = utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value);
if (bIsSimpleValue)
{
// OK. Value is simple (not composite) and was successfully got
}
else if (vnDepth < nMaxDepth)
{
// Need to get value from composite type
CMICmnMIValueTuple miValueTuple;
const bool bOk = utilMember.GetCompositeValue(miValueTuple, vnDepth + 1);
if (!bOk)
// Can't obtain composite type
value = m_pUnkwn;
else
// OK. Value is composite and was successfully got
value = miValueTuple.GetString();
}
else
{
// Need to get value from composite type, but vnMaxDepth is reached
value = m_pComposite;
}
const bool bNoQuotes = true;
const CMICmnMIValueConst miValueConst(value, bNoQuotes);
const bool bUseSpacing = true;
const CMICmnMIValueResult miValueResult(utilMember.GetName(), miValueConst, bUseSpacing);
const bool bOk = vwrMiValueTuple.Add(miValueResult, bUseSpacing);
if (!bOk)
return MIstatus::failure;
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: If the LLDB SB Value object is a char or char[] type then form the text data
// string otherwise return nothing. m_bHandleCharType must be true to return
// text data if any.
// Type: Method.
// Args: None.
// Return: CMIUtilString - Text description of the variable's value.
@ -99,7 +214,7 @@ CMICmnLLDBUtilSBValue::GetValueCString(void) const
{
CMIUtilString text;
if (m_bHandleCharType && IsCharType())
if (m_bHandleCharType && (IsCharType() || (IsArrayType() && IsFirstChildCharType())))
{
text = ReadCStringFromHostMemory(m_rValue);
}
@ -123,8 +238,8 @@ CMICmnLLDBUtilSBValue::IsCharType(void) const
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether any child value object of *this object is a
// char type or some other type. Returns false if there are not children. Char
// Details: Retrieve the flag stating whether first child value object of *this object is
// a char type or some other type. Returns false if there are not children. Char
// type can be signed or unsigned.
// Type: Method.
// Args: None.
@ -132,7 +247,7 @@ CMICmnLLDBUtilSBValue::IsCharType(void) const
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsChildCharType(void) const
CMICmnLLDBUtilSBValue::IsFirstChildCharType(void) const
{
const MIuint nChildren = m_rValue.GetNumChildren();
@ -140,15 +255,39 @@ CMICmnLLDBUtilSBValue::IsChildCharType(void) const
if (nChildren == 0)
return false;
// Is it a composite type
if (nChildren > 1)
return false;
lldb::SBValue member = m_rValue.GetChildAtIndex(0);
const lldb::SBValue member = m_rValue.GetChildAtIndex(0);
const CMICmnLLDBUtilSBValue utilValue(member);
return utilValue.IsCharType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is a pointer type or some
// other type.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a pointer type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsPointerType(void) const
{
return m_rValue.GetType().IsPointerType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is an array type or some
// other type.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is an array type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsArrayType(void) const
{
return m_rValue.GetType().IsArrayType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the C string data for a child of char type (one and only child) for
// the parent value object. If the child is not a char type or the parent has
@ -200,14 +339,11 @@ CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(const lldb::SBValue &vrValueObj
const lldb::addr_t addr = rValue.GetLoadAddress();
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const MIuint nBytes(128);
const MIchar *pBufferMemory = new MIchar[nBytes];
std::unique_ptr<char[]> apBufferMemory(new char[nBytes]);
lldb::SBError error;
const MIuint64 nReadBytes = rSessionInfo.GetProcess().ReadMemory(addr, (void *)pBufferMemory, nBytes, error);
const MIuint64 nReadBytes = rSessionInfo.GetProcess().ReadMemory(addr, apBufferMemory.get(), nBytes, error);
MIunused(nReadBytes);
text = CMIUtilString::Format("\\\"%s\\\"", pBufferMemory);
delete[] pBufferMemory;
return text;
return CMIUtilString(apBufferMemory.get());
}
//++ ------------------------------------------------------------------------------------

View File

@ -14,6 +14,7 @@
// In-house headers:
#include "MIDataTypes.h"
#include "MICmnMIValueTuple.h"
// Declerations:
class CMIUtilString;
@ -29,17 +30,20 @@ class CMICmnLLDBUtilSBValue
{
// Methods:
public:
/* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType = false);
/* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType = false,
const bool vbHandleArrayType = true);
/* dtor */ ~CMICmnLLDBUtilSBValue(void);
//
CMIUtilString GetName(void) const;
CMIUtilString GetValue(void) const;
CMIUtilString GetValue(const bool vbExpandAggregates = false) const;
CMIUtilString GetValueCString(void) const;
CMIUtilString GetChildValueCString(void) const;
CMIUtilString GetTypeName(void) const;
CMIUtilString GetTypeNameDisplay(void) const;
bool IsCharType(void) const;
bool IsChildCharType(void) const;
bool IsFirstChildCharType(void) const;
bool IsPointerType(void) const;
bool IsArrayType(void) const;
bool IsLLDBVariable(void) const;
bool IsNameUnknown(void) const;
bool IsValueUnknown(void) const;
@ -49,11 +53,15 @@ class CMICmnLLDBUtilSBValue
// Methods:
private:
CMIUtilString ReadCStringFromHostMemory(const lldb::SBValue &vrValueObj) const;
bool GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vrValue) const;
bool GetCompositeValue(CMICmnMIValueTuple &vwrMiValueTuple, const MIuint vnDepth = 1) const;
// Attributes:
private:
lldb::SBValue &m_rValue;
const MIchar *m_pUnkwn;
bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid.
bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data.
const MIchar *m_pComposite;
bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid.
bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data.
bool m_bHandleArrayType; // True = Yes return special stub for array type, false = just return data.
};