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 <hjk@qt.io>
This commit is contained in:
Denis Shienkov
2020-04-22 14:56:55 +03:00
parent b7de4eb263
commit 4c3bdd1f67
2 changed files with 54 additions and 0 deletions

View File

@@ -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 *>(bkparm.data()),
bkparm.size(),
reinterpret_cast<BKRSP *>(bkrsp.data()),
&bkrspLength);
if (st != UVSC_STATUS_SUCCESS) {
setError(RuntimeError);
return false;
}
BKCHG bkchg = {};
bkchg.type = CHG_KILLBP;
bkchg.tickMark = reinterpret_cast<const BKRSP *>(bkrsp.constData())->tickMark;
bkrspLength = bkrsp.size();
st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg),
reinterpret_cast<BKRSP *>(bkrsp.data()),
&bkrspLength);
if (st != UVSC_STATUS_SUCCESS) {
setError(RuntimeError);
return false;
}
return true;
}
bool UvscClient::calculateExpression(const QString &exp, QByteArray &)
{
if (!checkConnection())

View File

@@ -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;