-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[SOS][Linux] Support of reading local variables from portable PDB #5897
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,7 @@ PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL) symBuffer; | |
void *SymbolReader::coreclrLib; | ||
ResolveSequencePointDelegate SymbolReader::resolveSequencePointDelegate; | ||
LoadSymbolsForModuleDelegate SymbolReader::loadSymbolsForModuleDelegate; | ||
GetLocalVariableName SymbolReader::getLocalVariableNameDelegate; | ||
#endif // !FEATURE_PAL | ||
|
||
const char * const CorElementTypeName[ELEMENT_TYPE_MAX]= | ||
|
@@ -6284,6 +6285,11 @@ HRESULT SymbolReader::LoadCoreCLR() { | |
SymbolReaderClassName, "LoadSymbolsForModule", | ||
(void **)&loadSymbolsForModuleDelegate); | ||
IfFailRet(Status); | ||
Status = CreateDelegate(hostHandle, domainId, SymbolReaderDllName, | ||
SymbolReaderClassName, "GetLocalVariableName", | ||
(void **)&getLocalVariableNameDelegate); | ||
IfFailRet(Status); | ||
|
||
return Status; | ||
} | ||
#endif //FEATURE_PAL | ||
|
@@ -6363,30 +6369,50 @@ HRESULT SymbolReader::LoadSymbols(IMetaDataImport * pMD, ULONG64 baseAddress, __ | |
if (Status != S_OK) | ||
return Status; | ||
|
||
char szName[mdNameLen]; | ||
WideCharToMultiByte(CP_ACP, 0, pModuleName, (int) (_wcslen(pModuleName) + 1), | ||
szName, mdNameLen, NULL, NULL); | ||
return !loadSymbolsForModuleDelegate(szName); | ||
m_szModuleName, mdNameLen, NULL, NULL); | ||
return !loadSymbolsForModuleDelegate(m_szModuleName); | ||
#endif // FEATURE_PAL | ||
} | ||
|
||
HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDebugILFrame * pILFrame, mdMethodDef methodToken, ULONG localIndex, __inout_ecount(paramNameLen) WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue) | ||
{ | ||
HRESULT Status = S_OK; | ||
#ifdef FEATURE_PAL | ||
if (getLocalVariableNameDelegate == nullptr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style comment: I noticed that there are a few different styles all in use in this area. Sometimes there are braces around single-statement 'if' blocks, and sometimes there aren't. Brace position should also be consistent with the surrounding code (I think before your changes, most/all of the file used Allman style). |
||
Status = LoadCoreCLR(); | ||
if (Status != S_OK) | ||
return Status; | ||
// FIXME: we need to find a way to release memory after getting string from managed code. | ||
WCHAR *wszParamName = new (std::nothrow) WCHAR[mdNameLen]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The managed code shouldn't free this memory; it should be freed when the function returns. The managed code shouldn't save this pointer in any global state. If it is, then maybe the managed code needs to change. If you absolutely have to save the string in the managed code, then you could allocate is a bstr with SysAllocString and use Marshal.FreeBSTR to free it managed code. But I don't remember if this is supported in the xplat platforms. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like @Dmitri-Botcharnikov is changing GetLocalVariableName to return a BSTR for the name so my comment is moot other than using SysFreeString to free it in this native code. I don't remember if we properly support BSTRs on the xplat platforms. It still may be simpler to allocate a buffer like the current code and free it in native code. The managed code just copies the name string to the incoming buffer. |
||
if (wszParamName == NULL) { | ||
return E_OUTOFMEMORY; | ||
} | ||
int ret = getLocalVariableNameDelegate(m_szModuleName, methodToken, | ||
localIndex, &wszParamName); | ||
if (ret) { | ||
wcscpy_s(paramName, _wcslen(wszParamName) + 1, wszParamName); | ||
paramNameLen = _wcslen(paramName); | ||
|
||
if (SUCCEEDED(pILFrame->GetLocalVariable(localIndex, ppValue)) && (*ppValue != NULL)) { | ||
return S_OK; | ||
} else { | ||
*ppValue = NULL; | ||
return E_FAIL; | ||
} | ||
} | ||
return E_FAIL; | ||
|
||
#else | ||
if(pScope == NULL) | ||
{ | ||
#ifndef FEATURE_PAL | ||
ToRelease<ISymUnmanagedMethod> pSymMethod; | ||
IfFailRet(m_pSymReader->GetMethod(methodToken, &pSymMethod)); | ||
|
||
ToRelease<ISymUnmanagedScope> pScope; | ||
IfFailRet(pSymMethod->GetRootScope(&pScope)); | ||
|
||
return GetNamedLocalVariable(pScope, pILFrame, methodToken, localIndex, paramName, paramNameLen, ppValue); | ||
#else | ||
return E_FAIL; | ||
#endif // FEATURE_PAL | ||
} | ||
else | ||
{ | ||
|
@@ -6404,7 +6430,7 @@ HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDeb | |
if(varIndexInMethod != localIndex) | ||
continue; | ||
|
||
ULONG32 nameLen = 0; | ||
ULONG32 nameLen = 0; | ||
if(FAILED(pLocals[i]->GetName(paramNameLen, &nameLen, paramName))) | ||
swprintf_s(paramName, paramNameLen, W("local_%d\0"), localIndex); | ||
|
||
|
@@ -6440,7 +6466,9 @@ HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDeb | |
for(ULONG j = 0; j < numChildren; j++) pChildren[j]->Release(); | ||
|
||
} | ||
|
||
return E_FAIL; | ||
#endif // FEATURE_PAL | ||
} | ||
|
||
HRESULT SymbolReader::GetNamedLocalVariable(ICorDebugFrame * pFrame, ULONG localIndex, __inout_ecount(paramNameLen) WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't needed, since you're returning Status next anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, it looks like in this change and in some previous changes, the following pattern has been added:
Status = Something(); IfFailRet(Status);
whereas the convention is normally:
IfFailRet(Something());