From: Igor Kulaychuk Date: Thu, 6 Jul 2017 21:21:44 +0000 (+0300) Subject: Enable printing simple values and strings X-Git-Tag: submit/tizen/20180620.071641~251 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d4b8f2b526d409669189766f7cef7f8c4307abd;p=sdk%2Ftools%2Fnetcoredbg.git Enable printing simple values and strings --- diff --git a/src/debug/debugger/varobj.cpp b/src/debug/debugger/varobj.cpp index 3c49975..ce3956c 100644 --- a/src/debug/debugger/varobj.cpp +++ b/src/debug/debugger/varobj.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include "torelease.h" +#include "arrayholder.h" // Modules HRESULT GetFrameNamedLocalVariable( @@ -23,8 +25,253 @@ HRESULT GetFrameNamedLocalVariable( ICorDebugValue** ppValue); +// From strike.cpp +static HRESULT DereferenceAndUnboxValue(ICorDebugValue * pValue, ICorDebugValue** ppOutputValue, BOOL * pIsNull = NULL) +{ + HRESULT Status = S_OK; + *ppOutputValue = NULL; + if (pIsNull != NULL) *pIsNull = FALSE; + + ToRelease pReferenceValue; + Status = pValue->QueryInterface(IID_ICorDebugReferenceValue, (LPVOID*) &pReferenceValue); + if (SUCCEEDED(Status)) + { + BOOL isNull = FALSE; + IfFailRet(pReferenceValue->IsNull(&isNull)); + if(!isNull) + { + ToRelease pDereferencedValue; + IfFailRet(pReferenceValue->Dereference(&pDereferencedValue)); + return DereferenceAndUnboxValue(pDereferencedValue, ppOutputValue); + } + else + { + if(pIsNull != NULL) *pIsNull = TRUE; + *ppOutputValue = pValue; + (*ppOutputValue)->AddRef(); + return S_OK; + } + } + + ToRelease pBoxedValue; + Status = pValue->QueryInterface(IID_ICorDebugBoxValue, (LPVOID*) &pBoxedValue); + if (SUCCEEDED(Status)) + { + ToRelease pUnboxedValue; + IfFailRet(pBoxedValue->GetObject(&pUnboxedValue)); + return DereferenceAndUnboxValue(pUnboxedValue, ppOutputValue); + } + *ppOutputValue = pValue; + (*ppOutputValue)->AddRef(); + return S_OK; +} + +static BOOL IsEnum(ICorDebugValue * pInputValue) +{ + return FALSE; +} + +static HRESULT PrintStringValue(ICorDebugValue * pValue, std::string &output) +{ + HRESULT Status; + + ToRelease pStringValue; + IfFailRet(pValue->QueryInterface(IID_ICorDebugStringValue, (LPVOID*) &pStringValue)); + + ULONG32 cchValue; + IfFailRet(pStringValue->GetLength(&cchValue)); + cchValue++; // Allocate one more for null terminator + + ArrayHolder str = new WCHAR[cchValue]; + + ULONG32 cchValueReturned; + IfFailRet(pStringValue->GetString( + cchValue, + &cchValueReturned, + str)); + + ULONG32 cstrLen = cchValue * 2; + ArrayHolder cstr = new char[cstrLen]; + + WideCharToMultiByte(CP_UTF8, 0, str, cchValue, cstr, cstrLen, NULL, NULL); + + output = cstr; + + return S_OK; +} + +HRESULT PrintValue(ICorDebugValue *pInputValue, ICorDebugILFrame * pILFrame, IMetaDataImport * pMD, std::string &output) +{ + HRESULT Status; + + BOOL isNull = TRUE; + ToRelease pValue; + IfFailRet(DereferenceAndUnboxValue(pInputValue, &pValue, &isNull)); + + if(isNull) + { + output = "null"; + return S_OK; + } + + ULONG32 cbSize; + IfFailRet(pValue->GetSize(&cbSize)); + ArrayHolder rgbValue = new (std::nothrow) BYTE[cbSize]; + if (rgbValue == NULL) + { + return E_OUTOFMEMORY; + } + + memset(rgbValue.GetPtr(), 0, cbSize * sizeof(BYTE)); + + CorElementType corElemType; + IfFailRet(pValue->GetType(&corElemType)); + if (corElemType == ELEMENT_TYPE_STRING) + { + std::string raw_str; + IfFailRet(PrintStringValue(pValue, raw_str)); + + std::stringstream ss; + ss << "\\\"" << raw_str << "\\\""; + output = ss.str(); + return S_OK; + } + + if (corElemType == ELEMENT_TYPE_SZARRAY) + { + output = ""; + //return PrintSzArrayValue(pValue, pILFrame, pMD); + return S_OK; + } + + ToRelease pGenericValue; + IfFailRet(pValue->QueryInterface(IID_ICorDebugGenericValue, (LPVOID*) &pGenericValue)); + IfFailRet(pGenericValue->GetValue((LPVOID) &(rgbValue[0]))); + + if(IsEnum(pValue)) + { + output = ""; + //Status = PrintEnumValue(pValue, rgbValue); + return Status; + } + + std::stringstream ss; + + switch (corElemType) + { + default: + ss << "(Unhandled CorElementType: 0x" << std::hex << corElemType << ")"; + break; + + case ELEMENT_TYPE_PTR: + ss << ""; + break; + + case ELEMENT_TYPE_FNPTR: + { + CORDB_ADDRESS addr = 0; + ToRelease pReferenceValue = NULL; + if(SUCCEEDED(pValue->QueryInterface(IID_ICorDebugReferenceValue, (LPVOID*) &pReferenceValue))) + pReferenceValue->GetValue(&addr); + ss << ""; + } + break; + + case ELEMENT_TYPE_VALUETYPE: + case ELEMENT_TYPE_CLASS: + CORDB_ADDRESS addr; + if(SUCCEEDED(pValue->GetAddress(&addr))) + { + ss << " @ 0x" << std::hex << addr; + } + else + { + ss << ""; + } + //ProcessFields(pValue, NULL, pILFrame, indent + 1, varToExpand, currentExpansion, currentExpansionSize, currentFrame); + break; + + case ELEMENT_TYPE_BOOLEAN: + ss << (rgbValue[0] == 0 ? "false" : "true"); + break; + + case ELEMENT_TYPE_CHAR: + { + WCHAR ws[2] = W("\0"); + ws[0] = *(WCHAR *) &(rgbValue[0]); + char printableVal[10] = {0}; + WideCharToMultiByte(CP_UTF8, 0, ws, 2, printableVal, _countof(printableVal), NULL, NULL); + + ss << (unsigned int)ws[0] << " '" << printableVal << "'"; + } + break; + + case ELEMENT_TYPE_I1: + ss << *(char*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_U1: + ss << *(unsigned char*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_I2: + ss << *(short*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_U2: + ss << *(unsigned short*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_I: + ss << *(int*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_U: + ss << *(unsigned int*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_I4: + ss << *(int*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_U4: + ss << *(unsigned int*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_I8: + ss << *(__int64*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_U8: + ss << *(unsigned __int64*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_R4: + ss << *(float*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_R8: + ss << *(double*) &(rgbValue[0]); + break; + + case ELEMENT_TYPE_OBJECT: + ss << "object"; + break; + + // TODO: The following corElementTypes are not yet implemented here. Array + // might be interesting to add, though the others may be of rather limited use: + // ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... + // + // ELEMENT_TYPE_GENERICINST = 0x15, // GENERICINST ... + } + + output = ss.str(); + return S_OK; +} + HRESULT ListVariables(ICorDebugFrame *pFrame, std::string &output) { + bool printValues = true; HRESULT Status; ToRelease pILFrame; @@ -91,7 +338,14 @@ HRESULT ListVariables(ICorDebugFrame *pFrame, std::string &output) char cParamName[mdNameLen] = {0}; WideCharToMultiByte(CP_UTF8, 0, paramName, (int)(_wcslen(paramName) + 1), cParamName, _countof(cParamName), NULL, NULL); - ss << sep << "{name=\"" << cParamName << "\"}"; + ss << sep << "{name=\"" << cParamName << "\""; + if (printValues) + { + std::string strVal; + if (SUCCEEDED(PrintValue(pValue, pILFrame, pMD, strVal))) + ss << ",value=\"" << strVal << "\""; + } + ss << "}"; sep = ","; } } @@ -116,7 +370,14 @@ HRESULT ListVariables(ICorDebugFrame *pFrame, std::string &output) if (Status == S_FALSE) break; - ss << sep << "{name=\"" << paramName << "\"}"; + ss << sep << "{name=\"" << paramName << "\""; + if (printValues) + { + std::string strVal; + if (SUCCEEDED(PrintValue(pValue, pILFrame, pMD, strVal))) + ss << ",value=\"" << strVal << "\""; + } + ss << "}"; sep = ","; } }