From 4c3bdd1f6776b7f02f6a3abca0e2e225fd951b34 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Wed, 22 Apr 2020 14:56:55 +0300 Subject: [PATCH] Debugger: Minimize stalling at break-points insertion in UVSC engine Sometime the UVSC_DBG_CREATE_BP function stalls within 10 seconds and then returns with the timeout error. But this problem can be avoided by creating and then removing the fake breakpoint before creating the original breakpoint. In this case, we need to remove the line number from the expression of this fake breakpoint. Of course, it does not help when the breakpoint cannot be created with the specified expression. In this case the UVSC_DBG_CREATE_BP function will stall anyway within 10 seconds. Change-Id: Ie8d39c545683d6bb3e29e5bb7c4ac0fd1e34222a Reviewed-by: hjk --- src/plugins/debugger/uvsc/uvscclient.cpp | 52 ++++++++++++++++++++++++ src/plugins/debugger/uvsc/uvscclient.h | 2 + 2 files changed, 54 insertions(+) diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp index b0feca3c776..588ca9c18b0 100644 --- a/src/plugins/debugger/uvsc/uvscclient.cpp +++ b/src/plugins/debugger/uvsc/uvscclient.cpp @@ -799,6 +799,10 @@ bool UvscClient::createBreakpoint(const QString &exp, quint32 &tickMark, quint64 if (!checkConnection()) return false; + // Magic workaround to prevent the stalling. + if (!controlHiddenBreakpoint(exp)) + return false; + QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, exp); QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); qint32 bkrspLength = bkrsp.size(); @@ -881,6 +885,54 @@ bool UvscClient::disableBreakpoint(quint32 tickMark) return true; } +bool UvscClient::controlHiddenBreakpoint(const QString &exp) +{ + if (!checkConnection()) + return false; + + // It is a magic workaround to prevent the UVSC bug when the break-point + // creation may stall. A problem is that sometime the UVSC_DBG_CREATE_BP + // function blocks and returns then with the timeout error when the original + // break-point contains the full expression including the line number. + // + // It can be avoided with helps of creation and then deletion of the + // 'fake hidden' break-point with the same expression excluding the line + // number, before creation of an original break-point. + + const int slashIndex = exp.lastIndexOf('\\'); + if (slashIndex == -1 || (slashIndex + 1) == exp.size()) + return true; + + QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); + + const QString hiddenExp = exp.mid(0, slashIndex); + QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, hiddenExp); + qint32 bkrspLength = bkrsp.size(); + UVSC_STATUS st = ::UVSC_DBG_CREATE_BP(m_descriptor, + reinterpret_cast(bkparm.data()), + bkparm.size(), + reinterpret_cast(bkrsp.data()), + &bkrspLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + BKCHG bkchg = {}; + bkchg.type = CHG_KILLBP; + bkchg.tickMark = reinterpret_cast(bkrsp.constData())->tickMark; + bkrspLength = bkrsp.size(); + st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), + reinterpret_cast(bkrsp.data()), + &bkrspLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + return true; +} + bool UvscClient::calculateExpression(const QString &exp, QByteArray &) { if (!checkConnection()) diff --git a/src/plugins/debugger/uvsc/uvscclient.h b/src/plugins/debugger/uvsc/uvscclient.h index a1fed713092..c39a5f4a076 100644 --- a/src/plugins/debugger/uvsc/uvscclient.h +++ b/src/plugins/debugger/uvsc/uvscclient.h @@ -141,6 +141,8 @@ private: void updateLocation(const QByteArray &bpreason); bool addressToFileLine(quint64 address, QString &fileName, QString &function, quint32 &line); + bool controlHiddenBreakpoint(const QString &exp); + qint32 m_descriptor = -1; quint64 m_exitAddress = 0; UvscError m_error = NoError;