diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2015-06-23 14:40:38 -0700 |
---|---|---|
committer | Mike McLaughlin <mikem@microsoft.com> | 2015-06-23 14:40:38 -0700 |
commit | 8c70800b5e8dc5535c379dec4a6fb32f7ab5e878 (patch) | |
tree | adcb086444386e99b8ea44c7d8429433168b5702 /src/ToolBox | |
parent | 2403caba11fa5a9dd3ba7b67acd1b7dd0505cc9c (diff) | |
parent | ed78e1f8d1de2c3cf94c1e54e3e4ec17258eac2f (diff) | |
download | coreclr-8c70800b5e8dc5535c379dec4a6fb32f7ab5e878.tar.gz coreclr-8c70800b5e8dc5535c379dec4a6fb32f7ab5e878.tar.bz2 coreclr-8c70800b5e8dc5535c379dec4a6fb32f7ab5e878.zip |
Merge pull request #1159 from mikem8361/bpmd
Enable bpmd command (even unjitted functions work)
Diffstat (limited to 'src/ToolBox')
-rw-r--r-- | src/ToolBox/SOS/Strike/datatarget.cpp | 6 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/strike.cpp | 129 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/util.cpp | 71 | ||||
-rw-r--r-- | src/ToolBox/SOS/Strike/util.h | 11 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/debugclient.cpp | 120 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/debugclient.h | 18 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/inc/dbgeng.h | 100 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/soscommand.cpp | 7 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/sosplugin.h | 1 |
9 files changed, 395 insertions, 68 deletions
diff --git a/src/ToolBox/SOS/Strike/datatarget.cpp b/src/ToolBox/SOS/Strike/datatarget.cpp index 227f7c3422..15d61d449b 100644 --- a/src/ToolBox/SOS/Strike/datatarget.cpp +++ b/src/ToolBox/SOS/Strike/datatarget.cpp @@ -119,7 +119,11 @@ DataTarget::WriteVirtual( /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done) { - return E_NOTIMPL; + if (g_ExtData == NULL) + { + return E_UNEXPECTED; + } + return g_ExtData->WriteVirtual(address, (PVOID)buffer, request, done); } HRESULT STDMETHODCALLTYPE diff --git a/src/ToolBox/SOS/Strike/strike.cpp b/src/ToolBox/SOS/Strike/strike.cpp index 1d27c71515..d9b96bfe7f 100644 --- a/src/ToolBox/SOS/Strike/strike.cpp +++ b/src/ToolBox/SOS/Strike/strike.cpp @@ -271,7 +271,9 @@ DECLARE_API(IP2MD) TADDR IP = 0; CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -655,7 +657,9 @@ DECLARE_API(DumpStackObjects) CMDOption option[] = { // name, vptr, type, hasValue {"-verify", &bVerify, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE} +#endif }; CMDValue arg[] = { // vptr, type @@ -691,7 +695,9 @@ DECLARE_API(DumpMD) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -1129,7 +1135,9 @@ DECLARE_API(DumpClass) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -1257,7 +1265,9 @@ DECLARE_API(DumpMT) CMDOption option[] = { // name, vptr, type, hasValue {"-MD", &bDumpMDTable, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE} +#endif }; CMDValue arg[] = { // vptr, type @@ -1757,7 +1767,9 @@ DECLARE_API(DumpArray) {"-length", &flags.Length, COSIZE_T, TRUE}, {"-details", &flags.bDetail, COBOOL, FALSE}, {"-nofields", &flags.bNoFieldsForElement, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -1973,7 +1985,9 @@ DECLARE_API(DumpObj) { // name, vptr, type, hasValue {"-nofields", &bNoFields, COBOOL, FALSE}, {"-refs", &bRefs, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -2589,7 +2603,9 @@ DECLARE_API(PrintException) {"-lines", &bLineNumbers, COBOOL, FALSE}, {"-l", &bLineNumbers, COBOOL, FALSE}, {"-ccw", &bCCW, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE} +#endif }; CMDValue arg[] = { // vptr, type @@ -2733,8 +2749,6 @@ DECLARE_API(PrintException) return Status; } -#ifndef FEATURE_PAL - /**********************************************************************\ * Routine Description: * * * @@ -2753,7 +2767,9 @@ DECLARE_API(DumpVC) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE} +#endif }; CMDValue arg[] = { // vptr, type @@ -2782,6 +2798,8 @@ DECLARE_API(DumpVC) return PrintVC(p_MT, p_Object); } +#ifndef FEATURE_PAL + #ifdef FEATURE_COMINTEROP DECLARE_API(DumpRCW) @@ -3610,7 +3628,9 @@ public: {"-max", &mMaxSize, COHEX, TRUE}, // max size of objects to display {"-live", &mLive, COHEX, FALSE}, // only print live objects {"-dead", &mDead, COHEX, FALSE}, // only print dead objects +#ifndef FEATURE_PAL {"/d", &mDML, COBOOL, FALSE}, // Debugger Markup Language +#endif }; CMDValue arg[] = @@ -5208,7 +5228,9 @@ DECLARE_API(DumpModule) CMDOption option[] = { // name, vptr, type, hasValue {"-mt", &bMethodTables, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE} +#endif }; CMDValue arg[] = { // vptr, type @@ -5296,7 +5318,9 @@ DECLARE_API(DumpDomain) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -5414,7 +5438,9 @@ DECLARE_API(DumpAssembly) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -5952,7 +5978,9 @@ DECLARE_API(Threads) { // name, vptr, type, hasValue {"-special", &bPrintSpecialThreads, COBOOL, FALSE}, {"-live", &bPrintLiveThreadsOnly, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; if (!GetCMDOption(args, option, _countof(option), NULL, 0, NULL)) { @@ -6041,6 +6069,7 @@ DECLARE_API(WatsonBuckets) return Status; } // WatsonBuckets() +#endif // FEATURE_PAL struct PendingBreakpoint { @@ -6062,7 +6091,7 @@ struct PendingBreakpoint } PendingBreakpoint *pNext; - PendingBreakpoint() : pNext(NULL), ilOffset(0), lineNumber(0), methodToken(0) + PendingBreakpoint() : lineNumber(0), ilOffset(0), methodToken(0), pNext(NULL) { szModuleName[0] = L'\0'; szFunctionName[0] = L'\0'; @@ -6106,9 +6135,13 @@ void IssueDebuggerBPCommand ( CLRDATA_ADDRESS addr ) wcscpy_s(wszNameBuffer, _countof(wszNameBuffer), W("UNKNOWN")); } +#ifndef FEATURE_PAL sprintf_s(buffer, _countof(buffer), "bp %p", (void*) (size_t) addr); +#else + sprintf_s(buffer, _countof(buffer), "breakpoint set --address 0x%p", (void*) (size_t) addr); +#endif ExtOut("Setting breakpoint: %s [%S]\n", buffer, wszNameBuffer); - g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if ( curLimit < MaxBPsCached ) alreadyPlacedBPs[curLimit++] = addr; @@ -6264,6 +6297,7 @@ public: } } +#ifndef FEATURE_PAL void SaveBreakpoints(FILE* pFile) { PendingBreakpoint *pCur = m_breakpoints; @@ -6276,6 +6310,7 @@ public: pCur = pCur->pNext; } } +#endif void ClearBreakpoint(size_t breakPointToClear) { @@ -6332,11 +6367,11 @@ public: //get a pointer to just the filename (the portion after the last backslash) WCHAR* pModuleFilename = wszNameBuffer; - WCHAR* pSlash = wcschr(pModuleFilename, L'\\'); + WCHAR* pSlash = wcschr(pModuleFilename, DIRECTORY_SEPARATOR_CHAR_W); while(pSlash != NULL) { pModuleFilename = pSlash+1; - pSlash = wcschr(pModuleFilename, L'\\'); + pSlash = wcschr(pModuleFilename, DIRECTORY_SEPARATOR_CHAR_W); } ImageInfo ii; @@ -6687,9 +6722,7 @@ public: DacpGetModuleAddress dgma; if (SUCCEEDED(dgma.Request(pMod))) { -#ifndef FEATURE_PAL g_bpoints.Update(TO_TADDR(dgma.ModulePtr), FALSE); -#endif } else { @@ -6723,9 +6756,7 @@ public: DacpGetModuleAddress dgma; if (SUCCEEDED(dgma.Request(mod))) { -#ifndef FEATURE_PAL g_bpoints.Update(TO_TADDR(dgma.ModulePtr), TRUE); -#endif } if(!g_fAllowJitOptimization) @@ -6754,9 +6785,7 @@ public: DacpGetModuleAddress dgma; if (SUCCEEDED(dgma.Request(mod))) { -#ifndef FEATURE_PAL g_bpoints.RemovePendingForModule(TO_TADDR(dgma.ModulePtr)); -#endif } m_dbgStatus = DEBUG_STATUS_GO_HANDLED; @@ -6838,15 +6867,16 @@ BOOL CheckCLRNotificationEvent(DEBUG_LAST_EVENT_INFO_EXCEPTION* pdle) { ULONG Type, ProcessId, ThreadId; ULONG ExtraInformationUsed; - HRESULT Status = g_ExtControl->GetLastEventInformation( &Type, - &ProcessId, - &ThreadId, - pdle, - sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION), - &ExtraInformationUsed, - NULL, - 0, - NULL); + HRESULT Status = g_ExtControl->GetLastEventInformation( + &Type, + &ProcessId, + &ThreadId, + pdle, + sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION), + &ExtraInformationUsed, + NULL, + 0, + NULL); if (Status != S_OK || Type != DEBUG_EVENT_EXCEPTION) { @@ -6859,11 +6889,10 @@ BOOL CheckCLRNotificationEvent(DEBUG_LAST_EVENT_INFO_EXCEPTION* pdle) } return TRUE; - } +} HRESULT HandleCLRNotificationEvent() { - HRESULT Status = E_FAIL; /* * Did we get module load notification? If so, check if any in our pending list * need to be registered for jit notification. @@ -6877,12 +6906,13 @@ HRESULT HandleCLRNotificationEvent() if (!CheckCLRNotificationEvent(&dle)) { ExtOut("Expecting first chance CLRN exception\n"); - return Status; + return E_FAIL; } // Notification only needs to live for the lifetime of the call below, so it's a non-static // local. - if (g_clrData->TranslateExceptionRecordToNotification(&dle.ExceptionRecord, &Notification) != S_OK) + HRESULT Status = g_clrData->TranslateExceptionRecordToNotification(&dle.ExceptionRecord, &Notification); + if (Status != S_OK) { ExtOut("Error processing exception notification\n"); return Status; @@ -6894,17 +6924,20 @@ HRESULT HandleCLRNotificationEvent() case DEBUG_STATUS_GO: case DEBUG_STATUS_GO_HANDLED: case DEBUG_STATUS_GO_NOT_HANDLED: +#ifndef FEATURE_PAL g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, "g", 0); +#else + g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, "process continue", 0); +#endif break; default: break; } } - return Status; + return S_OK; } - DECLARE_API(HandleCLRN) { INIT_API(); @@ -6913,7 +6946,6 @@ DECLARE_API(HandleCLRN) return HandleCLRNotificationEvent(); } -#ifndef FEATURE_PAL DECLARE_API(bpmd) { INIT_API_NOEE(); @@ -7222,6 +7254,7 @@ DECLARE_API(bpmd) } else if (MethodDescData.bIsDynamic) { +#ifndef FEATURE_PAL // Dynamic methods don't have JIT notifications. This is something we must // fix in the next release. Until then, you have a cumbersome user experience. ExtOut("This DynamicMethodDesc is not yet JITTED. Placing memory breakpoint at %p\n", @@ -7238,12 +7271,15 @@ DECLARE_API(bpmd) (void*) (size_t) MethodDescData.AddressOfNativeCodeSlot, (void*) (size_t) MethodDescData.AddressOfNativeCodeSlot); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if (FAILED(Status)) { ExtOut("Unable to set breakpoint with IDebugControl::Execute: %x\n",Status); ExtOut("Attempted to run: %s\n", buffer); } +#else + ExtErr("This DynamicMethodDesc is not yet JITTED %p\n", MethodDescData.AddressOfNativeCodeSlot); +#endif // FEATURE_PAL } else { @@ -7267,13 +7303,24 @@ DECLARE_API(bpmd) if (bNeedNotificationExceptions) { ExtOut("Adding pending breakpoints...\n"); +#ifndef FEATURE_PAL sprintf_s(buffer, _countof(buffer), "sxe -c \"!HandleCLRN\" clrn"); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); +#else + sprintf_s(buffer, _countof(buffer), "breakpoint set -E c++ -h false -w true"); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); + if (Status == S_OK) + { + sprintf_s(buffer, _countof(buffer), "breakpoint command add -o \"sos HandleCLRN\""); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); + } +#endif // FEATURE_PAL } return Status; } -#endif + +#ifndef FEATURE_PAL /**********************************************************************\ * Routine Description: * @@ -7430,7 +7477,9 @@ DECLARE_API(FindAppDomain) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type @@ -8877,7 +8926,9 @@ DECLARE_API(Token2EE) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = @@ -8932,7 +8983,7 @@ DECLARE_API(Token2EE) FileNameForModule(dwAddr, FileName); // We'd like a short form for this output - LPWSTR pszFilename = wcsrchr (FileName, L'\\'); + LPWSTR pszFilename = wcsrchr (FileName, DIRECTORY_SEPARATOR_CHAR_W); if (pszFilename == NULL) { pszFilename = FileName; @@ -8969,7 +9020,9 @@ DECLARE_API(Name2EE) CMDOption option[] = { // name, vptr, type, hasValue +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = @@ -9060,7 +9113,7 @@ DECLARE_API(Name2EE) FileNameForModule (dwAddr, FileName); // We'd like a short form for this output - LPWSTR pszFilename = wcsrchr (FileName, L'\\'); + LPWSTR pszFilename = wcsrchr (FileName, DIRECTORY_SEPARATOR_CHAR_W); if (pszFilename == NULL) { pszFilename = FileName; @@ -10012,7 +10065,7 @@ DECLARE_API(GetCodeTypeFlags) sprintf_s(buffer,_countof (buffer), "r$t%d=%x", preg, codeType); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if (FAILED(Status)) { ExtOut("Error setting register $t%d\n", preg); @@ -10081,7 +10134,7 @@ DECLARE_API(StopOnException) sprintf_s(buffer,_countof (buffer), "r$t%d=0", preg); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if (FAILED(Status)) { ExtOut("Error initialized register $t%d to zero\n", preg); @@ -10101,7 +10154,7 @@ DECLARE_API(StopOnException) EXCEPTION_COMPLUS ); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if (FAILED(Status)) { ExtOut("Error setting breakpoint: %s\n", buffer); @@ -10147,7 +10200,7 @@ DECLARE_API(StopOnException) sprintf_s(buffer,_countof (buffer), "r$t%d=1", preg); - Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer ,0); + Status = g_ExtControl->Execute(DEBUG_EXECUTE_NOT_LOGGED, buffer, 0); if (FAILED(Status)) { ExtOut("Failed to execute the following command: %s\n", buffer); @@ -12120,7 +12173,9 @@ DECLARE_API(ClrStack) {"-n", &bSuppressLines, COBOOL, FALSE}, {"-i", &bICorDebug, COBOOL, FALSE}, {"-gc", &bGC, COBOOL, FALSE}, +#ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, +#endif }; CMDValue arg[] = { // vptr, type diff --git a/src/ToolBox/SOS/Strike/util.cpp b/src/ToolBox/SOS/Strike/util.cpp index 361ab45577..275113a9dc 100644 --- a/src/ToolBox/SOS/Strike/util.cpp +++ b/src/ToolBox/SOS/Strike/util.cpp @@ -596,7 +596,7 @@ BOOL GetPathFromModule( if (len == 0 || len == cFqPath) return FALSE; - WCHAR *pLastSep = wcsrchr(fqPath, L'\\'); + WCHAR *pLastSep = wcsrchr(fqPath, DIRECTORY_SEPARATOR_CHAR_W); if (pLastSep == NULL || pLastSep+1 >= fqPath+cFqPath) return FALSE; @@ -2353,13 +2353,21 @@ BOOL IsSameModuleName (const char *str1, const char *str2) const char *ptr2 = str2 + strlen(str2)-1; while (ptr2 >= str2) { +#ifndef FEATURE_PAL if (tolower(*ptr1) != tolower(*ptr2)) +#else + if (*ptr1 != *ptr2) +#endif + { return FALSE; - ptr2 --; - ptr1 --; + } + ptr2--; + ptr1--; } - if (ptr1 >= str1 && *ptr1 != '\\' && *ptr1 != ':') + if (ptr1 >= str1 && *ptr1 != DIRECTORY_SEPARATOR_CHAR_A && *ptr1 != ':') + { return FALSE; + } return TRUE; } @@ -2602,7 +2610,11 @@ BOOL IsFusionLoadedModule (LPCSTR fusionName, LPCSTR mName) return FALSE; } +#ifndef FEATURE_PAL if (tolower(*fusionName) != tolower(*mName)) +#else + if (*fusionName != *mName) +#endif { return FALSE; } @@ -2635,12 +2647,14 @@ BOOL DebuggerModuleNamesMatch (CLRDATA_ADDRESS PEFileAddr, __in __in_z LPSTR mNa { CHAR ModuleName[MAX_PATH+1]; - if (g_ExtSymbols->GetModuleNames (Index, base, - NULL, 0, NULL, - ModuleName, MAX_PATH, NULL, - NULL, 0, NULL) == S_OK) + if (g_ExtSymbols->GetModuleNames(Index, base, NULL, 0, NULL, ModuleName, + MAX_PATH, NULL, NULL, 0, NULL) == S_OK) { +#ifndef FEATURE_PAL if (_stricmp (ModuleName, mName) == 0) +#else + if (strcmp (ModuleName, mName) == 0) +#endif { return TRUE; } @@ -2792,9 +2806,9 @@ DWORD_PTR *ModuleFromName(__in __in_z __in_opt LPSTR mName, int *numModule) fileName[m] = '\0'; if ((mName == NULL) || - IsSameModuleName (fileName, mName) || + IsSameModuleName(fileName, mName) || DebuggerModuleNamesMatch(ModuleData.File, mName) || - IsFusionLoadedModule (fileName, mName)) + IsFusionLoadedModule(fileName, mName)) { AddToModuleList(moduleList, *numModule, maxList, (DWORD_PTR)ModuleAddr); @@ -3155,11 +3169,15 @@ void GetInfoFromModule (DWORD_PTR ModuleAddr, ULONG token, DWORD_PTR *ret) } else { +#ifndef FEATURE_PAL if (IsDMLEnabled()) DMLOut("Not JITTED yet. Use <exec cmd=\"!bpmd -md %p\">!bpmd -md %p</exec> to break on run.\n", - SOS_PTR(md), SOS_PTR(md)); + SOS_PTR(md), SOS_PTR(md)); else ExtOut("Not JITTED yet. Use !bpmd -md %p to break on run.\n", SOS_PTR(md)); +#else + ExtOut("Not JITTED yet. Use 'sos bpmd -md %p' to break on run.\n", SOS_PTR(md)); +#endif } } else @@ -3992,7 +4010,11 @@ BOOL GetCMDOption(const char *string, CMDOption *option, size_t nOption, } } +#ifndef FEATURE_PAL if (ptr[0] != '-' && ptr[0] != '/') { +#else + if (ptr[0] != '-') { +#endif if (maxArg == 0) { ExtOut ("Incorrect argument: %s\n", ptr); return FALSE; @@ -5531,9 +5553,6 @@ NoOutputHolder::~NoOutputHolder() Output::g_bSuppressOutput--; } -// Do not support source line numbers on PAL platforms -#ifndef FEATURE_PAL - // // Code to support mapping RVAs to managed code line numbers. // @@ -5806,9 +5825,6 @@ ConvertNativeToIlOffset( } -#endif - - // Based on a native offset, passed in the first argument this function // identifies the corresponding source file name and line number. HRESULT @@ -6138,10 +6154,11 @@ HRESULT __stdcall PERvaMemoryReader::ReadExecutableAtRVA(DWORD relativeVirtualAd return SafeReadMemory(m_moduleBaseAddress + relativeVirtualAddress, data, cbData, pcbData) ? S_OK : E_FAIL; } - +#endif // FEATURE_PAL HRESULT SymbolReader::LoadSymbols(IMetaDataImport * pMD, ICorDebugModule * pModule) { +#ifndef FEATURE_PAL HRESULT Status = S_OK; if(m_pSymReader != NULL) return S_OK; @@ -6167,10 +6184,14 @@ HRESULT SymbolReader::LoadSymbols(IMetaDataImport * pMD, ICorDebugModule * pModu IfFailRet(pModule->GetName(_countof(moduleName), &len, moduleName)); return LoadSymbols(pMD, baseAddress, moduleName, isInMemory); +#else + return E_FAIL; +#endif // FEATURE_PAL } HRESULT SymbolReader::LoadSymbols(IMetaDataImport * pMD, ULONG64 baseAddress, __in_z WCHAR* pModuleName, BOOL isInMemory) { +#ifndef FEATURE_PAL HRESULT Status = S_OK; if(m_pSymReader != NULL) return S_OK; @@ -6236,6 +6257,9 @@ HRESULT SymbolReader::LoadSymbols(IMetaDataImport * pMD, ULONG64 baseAddress, __ m_pSymReader = NULL; } return Status; +#else + return E_FAIL; +#endif // FEATURE_PAL } HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDebugILFrame * pILFrame, mdMethodDef methodToken, ULONG localIndex, __inout_ecount(paramNameLen) WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue) @@ -6244,6 +6268,7 @@ HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDeb if(pScope == NULL) { +#ifndef FEATURE_PAL ToRelease<ISymUnmanagedMethod> pSymMethod; IfFailRet(m_pSymReader->GetMethod(methodToken, &pSymMethod)); @@ -6251,6 +6276,9 @@ HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDeb IfFailRet(pSymMethod->GetRootScope(&pScope)); return GetNamedLocalVariable(pScope, pILFrame, methodToken, localIndex, paramName, paramNameLen, ppValue); +#else + return E_FAIL; +#endif // FEATURE_PAL } else { @@ -6306,6 +6334,7 @@ HRESULT SymbolReader::GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDeb } return E_FAIL; } + HRESULT SymbolReader::GetNamedLocalVariable(ICorDebugFrame * pFrame, ULONG localIndex, __inout_ecount(paramNameLen) WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue) { HRESULT Status = S_OK; @@ -6328,8 +6357,10 @@ HRESULT SymbolReader::GetNamedLocalVariable(ICorDebugFrame * pFrame, ULONG local return GetNamedLocalVariable(NULL, pILFrame, methodDef, localIndex, paramName, paramNameLen, ppValue); } + HRESULT SymbolReader::ResolveSequencePoint(__in_z WCHAR* pFilename, ULONG32 lineNumber, mdMethodDef* pToken, ULONG32* pIlOffset) { +#ifndef FEATURE_PAL HRESULT Status = S_OK; ULONG32 cDocs = 0; ULONG32 cDocsNeeded = 0; @@ -6387,12 +6418,10 @@ HRESULT SymbolReader::ResolveSequencePoint(__in_z WCHAR* pFilename, ULONG32 line } return S_OK; } +#endif // FEATURE_PAL return E_FAIL; } - -#endif - WString GetFrameFromAddress(TADDR frameAddr, IXCLRDataStackWalk *pStackWalk) { TADDR vtAddr; diff --git a/src/ToolBox/SOS/Strike/util.h b/src/ToolBox/SOS/Strike/util.h index 9e32e9d06b..5b0c40f93c 100644 --- a/src/ToolBox/SOS/Strike/util.h +++ b/src/ToolBox/SOS/Strike/util.h @@ -2368,15 +2368,20 @@ private: volatile ULONG m_refCount; }; +#endif // !FEATURE_PAL + class SymbolReader { private: +#ifndef FEATURE_PAL ISymUnmanagedReader* m_pSymReader; +#endif private: HRESULT GetNamedLocalVariable(ISymUnmanagedScope * pScope, ICorDebugILFrame * pILFrame, mdMethodDef methodToken, ULONG localIndex, __inout_ecount(paramNameLen) WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue); public: +#ifndef FEATURE_PAL SymbolReader() : m_pSymReader (NULL) {} ~SymbolReader() { @@ -2386,6 +2391,10 @@ public: m_pSymReader = NULL; } } +#else + SymbolReader() {} + ~SymbolReader() {} +#endif HRESULT LoadSymbols(IMetaDataImport * pMD, ICorDebugModule * pModule); HRESULT LoadSymbols(IMetaDataImport * pMD, ULONG64 baseAddress, __in_z WCHAR* pModuleName, BOOL isInMemory); @@ -2393,8 +2402,6 @@ public: HRESULT SymbolReader::ResolveSequencePoint(__in_z WCHAR* pFilename, ULONG32 lineNumber, mdMethodDef* pToken, ULONG32* pIlOffset); }; -#endif // !FEATURE_PAL - HRESULT GetLineByOffset( __in ULONG64 IP, diff --git a/src/ToolBox/SOS/lldbplugin/debugclient.cpp b/src/ToolBox/SOS/lldbplugin/debugclient.cpp index 8b2f9c7bbd..75d5cee594 100644 --- a/src/ToolBox/SOS/lldbplugin/debugclient.cpp +++ b/src/ToolBox/SOS/lldbplugin/debugclient.cpp @@ -15,6 +15,7 @@ DebugClient::DebugClient(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject m_returnObject(returnObject), m_coreclrDirectory(coreclrDirectory) { + returnObject.SetStatus(lldb::eReturnStatusSuccessFinishResult); } DebugClient::~DebugClient() @@ -153,12 +154,115 @@ DebugClient::GetExecutingProcessorType( return S_OK; } +HRESULT +DebugClient::Execute( + ULONG outputControl, + PCSTR command, + ULONG flags) +{ + lldb::SBCommandInterpreter interpreter = m_debugger.GetCommandInterpreter(); + + lldb::SBCommandReturnObject result; + lldb::ReturnStatus status = interpreter.HandleCommand(command, result); + + return status <= lldb::eReturnStatusSuccessContinuingResult ? S_OK : E_FAIL; +} + +// PAL raise exception function and exception record pointer variable name +// See coreclr\src\pal\src\exception\seh-unwind.cpp for the details. +#define FUNCTION_NAME "RtlpRaiseException" +#define VARIABLE_NAME "ExceptionRecord" + +HRESULT +DebugClient::GetLastEventInformation( + PULONG type, + PULONG processId, + PULONG threadId, + PVOID extraInformation, + ULONG extraInformationSize, + PULONG extraInformationUsed, + PSTR description, + ULONG descriptionSize, + PULONG descriptionUsed) +{ + if (extraInformationSize < sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION) || + type == NULL || processId == NULL || threadId == NULL || extraInformationUsed == NULL) + { + return E_FAIL; + } + + *type = DEBUG_EVENT_EXCEPTION; + *processId = 0; + *threadId = 0; + *extraInformationUsed = sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION); + + DEBUG_LAST_EVENT_INFO_EXCEPTION *pdle = (DEBUG_LAST_EVENT_INFO_EXCEPTION *)extraInformation; + pdle->FirstChance = 1; + + lldb::SBProcess process = GetCurrentProcess(); + if (!process.IsValid()) + { + return E_FAIL; + } + lldb::SBThread thread = process.GetSelectedThread(); + if (!thread.IsValid()) + { + return E_FAIL; + } + + // Enumerate each stack frame at the special "throw" + // breakpoint and find the raise exception function + // with the exception record parameter. + int numFrames = thread.GetNumFrames(); + for (int i = 0; i < numFrames; i++) + { + lldb::SBFrame frame = thread.GetFrameAtIndex(i); + if (!frame.IsValid()) + { + break; + } + + const char *functionName = frame.GetFunctionName(); + if (functionName == NULL || strncmp(functionName, FUNCTION_NAME, sizeof(FUNCTION_NAME) - 1) != 0) + { + continue; + } + + lldb::SBValue exValue = frame.FindVariable(VARIABLE_NAME); + if (!exValue.IsValid()) + { + break; + } + + lldb::SBError error; + ULONG64 pExceptionRecord = exValue.GetValueAsUnsigned(error); + if (error.Fail()) + { + break; + } + + process.ReadMemory(pExceptionRecord, &pdle->ExceptionRecord, sizeof(pdle->ExceptionRecord), error); + if (error.Fail()) + { + break; + } + + return S_OK; + } + + return E_FAIL; +} + // Internal output string function void DebugClient::OutputString( ULONG mask, PCSTR str) { + if (mask == DEBUG_OUTPUT_ERROR) + { + m_returnObject.SetStatus(lldb::eReturnStatusFailed); + } // Can not use AppendMessage or AppendWarning because they add a newline. SetError // can not be used for DEBUG_OUTPUT_ERROR mask because it caches the error strings // seperately from the normal output so error/normal texts are not intermixed @@ -203,11 +307,23 @@ DebugClient::WriteVirtual( ULONG bufferSize, PULONG bytesWritten) { + lldb::SBError error; + size_t written = 0; + + lldb::SBProcess process = GetCurrentProcess(); + if (!process.IsValid()) + { + goto exit; + } + + written = process.WriteMemory(offset, buffer, bufferSize, error); + +exit: if (bytesWritten) { - *bytesWritten = 0; + *bytesWritten = written; } - return E_NOTIMPL; + return error.Success() ? S_OK : E_FAIL; } //---------------------------------------------------------------------------- diff --git a/src/ToolBox/SOS/lldbplugin/debugclient.h b/src/ToolBox/SOS/lldbplugin/debugclient.h index d2a2201bd5..3081189fa1 100644 --- a/src/ToolBox/SOS/lldbplugin/debugclient.h +++ b/src/ToolBox/SOS/lldbplugin/debugclient.h @@ -58,7 +58,23 @@ public: PULONG size); HRESULT GetExecutingProcessorType( - PULONG Type); + PULONG type); + + HRESULT Execute( + ULONG outputControl, + PCSTR command, + ULONG flags); + + HRESULT GetLastEventInformation( + PULONG type, + PULONG processId, + PULONG threadId, + PVOID extraInformation, + ULONG extraInformationSize, + PULONG extraInformationUsed, + PSTR description, + ULONG descriptionSize, + PULONG descriptionUsed); //---------------------------------------------------------------------------- // IDebugDataSpaces diff --git a/src/ToolBox/SOS/lldbplugin/inc/dbgeng.h b/src/ToolBox/SOS/lldbplugin/inc/dbgeng.h index 9871a3ea30..9890e1396e 100644 --- a/src/ToolBox/SOS/lldbplugin/inc/dbgeng.h +++ b/src/ToolBox/SOS/lldbplugin/inc/dbgeng.h @@ -78,9 +78,38 @@ public: // current processor context. virtual HRESULT GetExecutingProcessorType( PULONG type) = 0; + + // Executes the given command string. + // If the string has multiple commands + // Execute will not return until all + // of them have been executed. If this + // requires waiting for the debuggee to + // execute an internal wait will be done + // so Execute can take an arbitrary amount + // of time. + virtual HRESULT Execute( + ULONG outputControl, + PCSTR command, + ULONG flags) = 0; + + // Retrieves information about the last event that occurred. + // EventType is one of the event callback mask bits. + // ExtraInformation contains additional event-specific + // information. Not all events have additional information. + virtual HRESULT GetLastEventInformation( + PULONG type, + PULONG processId, + PULONG threadId, + PVOID extraInformation, + ULONG extraInformationSize, + PULONG extraInformationUsed, + PSTR description, + ULONG descriptionSize, + PULONG descriptionUsed) = 0; }; typedef class IDebugControl2* PDEBUG_CONTROL2; + // Output mask bits. // Normal output. #define DEBUG_OUTPUT_NORMAL 0x00000001 @@ -103,6 +132,26 @@ typedef class IDebugControl2* PDEBUG_CONTROL2; // Symbol messages, such as for !sym noisy. #define DEBUG_OUTPUT_SYMBOLS 0x00000200 +// Execute and ExecuteCommandFile flags. +// These flags only apply to the command +// text itself; output from the executed +// command is controlled by the output +// control parameter. +// Default execution. Command is logged +// but not output. +#define DEBUG_EXECUTE_DEFAULT 0x00000000 +// Echo commands during execution. In +// ExecuteCommandFile also echoes the prompt +// for each line of the file. +#define DEBUG_EXECUTE_ECHO 0x00000001 +// Do not log or output commands during execution. +// Overridden by DEBUG_EXECUTE_ECHO. +#define DEBUG_EXECUTE_NOT_LOGGED 0x00000002 +// If this flag is not set an empty string +// to Execute will repeat the last Execute +// string. +#define DEBUG_EXECUTE_NO_REPEAT 0x00000004 + // Classes of debuggee. Each class // has different qualifiers for specific // kinds of debuggees. @@ -114,6 +163,57 @@ typedef class IDebugControl2* PDEBUG_CONTROL2; #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +// Execution status codes used for waiting, +// for returning current status and for +// event method return values. +#define DEBUG_STATUS_NO_CHANGE 0 +#define DEBUG_STATUS_GO 1 +#define DEBUG_STATUS_GO_HANDLED 2 +#define DEBUG_STATUS_GO_NOT_HANDLED 3 +#define DEBUG_STATUS_STEP_OVER 4 +#define DEBUG_STATUS_STEP_INTO 5 +#define DEBUG_STATUS_BREAK 6 +#define DEBUG_STATUS_NO_DEBUGGEE 7 +#define DEBUG_STATUS_STEP_BRANCH 8 +#define DEBUG_STATUS_IGNORE_EVENT 9 +#define DEBUG_STATUS_RESTART_REQUESTED 10 +#define DEBUG_STATUS_REVERSE_GO 11 +#define DEBUG_STATUS_REVERSE_STEP_BRANCH 12 +#define DEBUG_STATUS_REVERSE_STEP_OVER 13 +#define DEBUG_STATUS_REVERSE_STEP_INTO 14 +#define DEBUG_STATUS_OUT_OF_SYNC 15 +#define DEBUG_STATUS_WAIT_INPUT 16 +#define DEBUG_STATUS_TIMEOUT 17 + +#define DEBUG_STATUS_MASK 0x1f + +#define DEBUG_EVENT_EXCEPTION 0x00000002 + +#ifdef DEFINE_EXCEPTION_RECORD + +#define EXCEPTION_MAXIMUM_PARAMETERS 15 + +// This copy of the "64" bit record has been modified +// by removing the alignment field to make it the same +// as the _EXCEPTION_RECORD used in the pal defined in +// pal.h. +typedef struct _EXCEPTION_RECORD64 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD64 ExceptionRecord; + DWORD64 ExceptionAddress; + DWORD NumberParameters; + DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; + +#endif // DEFINE_EXCEPTION_RECORD + +typedef struct _DEBUG_LAST_EVENT_INFO_EXCEPTION +{ + EXCEPTION_RECORD64 ExceptionRecord; + ULONG FirstChance; +} DEBUG_LAST_EVENT_INFO_EXCEPTION, *PDEBUG_LAST_EVENT_INFO_EXCEPTION; + //---------------------------------------------------------------------------- // IDebugDataSpaces //---------------------------------------------------------------------------- diff --git a/src/ToolBox/SOS/lldbplugin/soscommand.cpp b/src/ToolBox/SOS/lldbplugin/soscommand.cpp index b321321acd..be0ef9b4b4 100644 --- a/src/ToolBox/SOS/lldbplugin/soscommand.cpp +++ b/src/ToolBox/SOS/lldbplugin/soscommand.cpp @@ -5,6 +5,7 @@ #include "sosplugin.h" #include <dlfcn.h> +#include <string.h> #include <string> class sosCommand : public lldb::SBCommandPluginInterface @@ -72,10 +73,8 @@ public: } else { - std::string directoryString; - directoryString.append(directory); - directoryString.append("/"); - directoryString.copy(m_coreclrDirectory, MAX_PATH, 0); + strcpy(m_coreclrDirectory, directory); + strcat(m_coreclrDirectory, "/"); // Load the DAC module first explicitly because SOS and DBI // have implicit references to the DAC's PAL. diff --git a/src/ToolBox/SOS/lldbplugin/sosplugin.h b/src/ToolBox/SOS/lldbplugin/sosplugin.h index e031660f7f..412955c9bb 100644 --- a/src/ToolBox/SOS/lldbplugin/sosplugin.h +++ b/src/ToolBox/SOS/lldbplugin/sosplugin.h @@ -5,6 +5,7 @@ #include <lldb/API/LLDB.h> #include "mstypes.h" +#define DEFINE_EXCEPTION_RECORD #include <dbgeng.h> #include "debugclient.h" |