CDB extension: Also look for QV4::ExecutionEngine for the QML stack

The struct has been renamed from QV4::ExecutionContext to
QV4::ExecutionEngine in Qt 5.7.

Task-number: QTCREATORBUG-17097
Change-Id: If9685d039d3d1f9caf369ec847ac6705747ae9f7
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Friedemann Kleint
2016-10-21 15:23:27 +02:00
parent 2428135319
commit bb380a00f0
3 changed files with 27 additions and 19 deletions

View File

@@ -202,14 +202,22 @@ static std::string findModule(CIDebugSymbols *syms,
} }
// Try to find a JS execution context passed as parameter in a complete stack dump (kp) // Try to find a JS execution context passed as parameter in a complete stack dump (kp)
static ULONG64 jsExecutionContextFromStackTrace(const std::wstring &stack) static ULONG64 jsExecutionEngineFromStackTrace(const std::wstring &stack)
{ {
// Search for "QV4::ExecutionContext * - varying variable names - 0x...[,)]" // Search for "QV4::ExecutionEngine * - varying variable names - 0x...[,)]"
const wchar_t needle[] = L"struct QV4::ExecutionContext * "; // .. varying variable names .. 0x... const wchar_t needle[] = L"struct QV4::ExecutionEngine * "; // Qt 5.7 onwards
const std::string::size_type varPos = stack.find(needle); std::string::size_type varEnd = std::string::npos;
if (varPos == std::string::npos) std::string::size_type varPos = stack.find(needle);
if (varPos != std::string::npos) {
varEnd = varPos + sizeof(needle) / sizeof(wchar_t) - 1;
} else {
const wchar_t needle56[] = L"struct QV4::ExecutionContext * "; // up to Qt 5.6
varPos = stack.find(needle56);
if (varPos != std::string::npos)
varEnd = varPos + sizeof(needle56) / sizeof(wchar_t) - 1;
}
if (varEnd == std::string::npos)
return 0; return 0;
const std::string::size_type varEnd = varPos + sizeof(needle) / sizeof(wchar_t) - 1;
std::string::size_type numPos = stack.find(L"0x", varEnd); std::string::size_type numPos = stack.find(L"0x", varEnd);
if (numPos == std::string::npos || numPos > (varEnd + 20)) if (numPos == std::string::npos || numPos > (varEnd + 20))
return 0; return 0;
@@ -227,10 +235,10 @@ static ULONG64 jsExecutionContextFromStackTrace(const std::wstring &stack)
return str.fail() ? 0 : result; return str.fail() ? 0 : result;
} }
// Try to find address of jsExecutionContext by looking at the // Try to find address of jsExecutionEngine by looking at the
// stack trace in case QML is loaded. // stack trace in case QML is loaded.
ULONG64 ExtensionContext::jsExecutionContext(ExtensionCommandContext &exc, ULONG64 ExtensionContext::jsExecutionEngine(ExtensionCommandContext &exc,
std::string *errorMessage) std::string *errorMessage)
{ {
const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols())); const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()));
@@ -241,7 +249,7 @@ ULONG64 ExtensionContext::jsExecutionContext(ExtensionCommandContext &exc,
*errorMessage = "QML not loaded"; *errorMessage = "QML not loaded";
return 0; return 0;
} }
// Retrieve full stack (costly) and try to find a JS execution context passed as parameter // Retrieve full stack (costly) and try to find a JS execution engine passed as parameter
startRecordingOutput(); startRecordingOutput();
StateNotificationBlocker blocker(this); StateNotificationBlocker blocker(this);
const HRESULT hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "kp", DEBUG_EXECUTE_ECHO); const HRESULT hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "kp", DEBUG_EXECUTE_ECHO);
@@ -255,9 +263,9 @@ ULONG64 ExtensionContext::jsExecutionContext(ExtensionCommandContext &exc,
*errorMessage = "Unable to obtain stack (output redirection in place?)"; *errorMessage = "Unable to obtain stack (output redirection in place?)";
return 0; return 0;
} }
const ULONG64 result = jsExecutionContextFromStackTrace(fullStackTrace); const ULONG64 result = jsExecutionEngineFromStackTrace(fullStackTrace);
if (!result) if (!result)
*errorMessage = "JS ExecutionContext address not found in stack"; *errorMessage = "JS ExecutionEngine address not found in stack";
return result; return result;
} }

View File

@@ -115,7 +115,7 @@ public:
const Parameters &parameters() const { return m_parameters; } const Parameters &parameters() const { return m_parameters; }
Parameters &parameters() { return m_parameters; } Parameters &parameters() { return m_parameters; }
ULONG64 jsExecutionContext(ExtensionCommandContext &exc, std::string *errorMessage); ULONG64 jsExecutionEngine(ExtensionCommandContext &exc, std::string *errorMessage);
bool stateNotification() const { return m_stateNotification; } bool stateNotification() const { return m_stateNotification; }
void setStateNotification(bool s) { m_stateNotification = s; } void setStateNotification(bool s) { m_stateNotification = s; }

View File

@@ -1091,7 +1091,7 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
int token = 0; int token = 0;
bool humanReadable = false; bool humanReadable = false;
ULONG64 jsExecutionContext = 0; ULONG64 jsExecutionEngine = 0;
std::string stackDump; std::string stackDump;
do { do {
@@ -1101,16 +1101,16 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
tokens.pop_front(); tokens.pop_front();
} }
if (!tokens.empty()) { if (!tokens.empty()) {
if (!integerFromString(tokens.front(), &jsExecutionContext)) { if (!integerFromString(tokens.front(), &jsExecutionEngine)) {
errorMessage = "Invalid address " + tokens.front(); errorMessage = "Invalid address " + tokens.front();
break; break;
} }
tokens.pop_front(); tokens.pop_front();
} }
ExtensionCommandContext exc(client); ExtensionCommandContext exc(client);
if (!jsExecutionContext) { // Try to find execution context unless it was given. if (!jsExecutionEngine) { // Try to find execution engine unless it was given.
jsExecutionContext = ExtensionContext::instance().jsExecutionContext(exc, &errorMessage); jsExecutionEngine = ExtensionContext::instance().jsExecutionEngine(exc, &errorMessage);
if (!jsExecutionContext) if (!jsExecutionEngine)
break; break;
} }
// call function to get stack trace. Call with exceptions handled right from // call function to get stack trace. Call with exceptions handled right from
@@ -1118,7 +1118,7 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
std::ostringstream callStr; std::ostringstream callStr;
const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols())); const QtInfo &qtInfo = QtInfo::get(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()));
callStr << qtInfo.prependQtModule("qt_v4StackTrace(", QtInfo::Qml) << std::showbase << std::hex callStr << qtInfo.prependQtModule("qt_v4StackTrace(", QtInfo::Qml) << std::showbase << std::hex
<< jsExecutionContext << std::dec << std::noshowbase << ')'; << jsExecutionEngine << std::dec << std::noshowbase << ')';
std::wstring wOutput; std::wstring wOutput;
if (!ExtensionContext::instance().call(callStr.str(), ExtensionContext::CallWithExceptionsHandled, &wOutput, &errorMessage)) if (!ExtensionContext::instance().call(callStr.str(), ExtensionContext::CallWithExceptionsHandled, &wOutput, &errorMessage))
break; break;