diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp index 588ca9c18b0..5c31411248c 100644 --- a/src/plugins/debugger/uvsc/uvscclient.cpp +++ b/src/plugins/debugger/uvsc/uvscclient.cpp @@ -43,7 +43,7 @@ constexpr int kMaximumRegisterGroupsCount = 128; constexpr int kMaximumRegisterEnumsCount = 512; constexpr int kMaximumVarinfosCount = 256; constexpr int kMaximumValueBitsSize = 32; -constexpr int kMaximumBreakpointResponseSize = 1024; +constexpr int kMaximumBreakpointEnumsCount = 128; constexpr int kMaximumDisassembledBytesCount = 1024; const QEvent::Type kUvscMsgEventType = static_cast(QEvent::User + 1); @@ -803,22 +803,28 @@ bool UvscClient::createBreakpoint(const QString &exp, quint32 &tickMark, quint64 if (!controlHiddenBreakpoint(exp)) return false; - QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, exp); - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const 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); + // Execute command to create the BP. + const QString setCmd = QStringLiteral("BS %1").arg(exp); + QString setCmdOutput; + if (!executeCommand(setCmd, setCmdOutput)) return false; - } - const auto bkrspPtr = reinterpret_cast(bkrsp.constData()); - tickMark = bkrspPtr->tickMark; - address = bkrspPtr->address; + std::vector bpenums; + if (!enumerateBreakpoints(bpenums)) + return false; + + const auto bpenumBegin = bpenums.cbegin(); + const auto bpenumEnd = bpenums.cend(); + const auto bpenumIt = std::find_if(bpenumBegin, bpenumEnd, [exp](const BKRSP &bpenum) { + const QString bpexp = QString::fromLatin1(reinterpret_cast(bpenum.expressionBuffer), + bpenum.expressionLength).trimmed(); + return bpexp.contains(exp); + }); + if (bpenumIt == bpenumEnd) + return false; + + tickMark = bpenumIt->tickMark; + address = bpenumIt->address; if (!addressToFileLine(address, fileName, function, line)) return false; @@ -833,11 +839,9 @@ bool UvscClient::deleteBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_KILLBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -853,11 +857,9 @@ bool UvscClient::enableBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_ENABLEBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -873,11 +875,9 @@ bool UvscClient::disableBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_DISABLEBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -903,16 +903,15 @@ bool UvscClient::controlHiddenBreakpoint(const QString &exp) if (slashIndex == -1 || (slashIndex + 1) == exp.size()) return true; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); + BKRSP bkrsp = {}; const QString hiddenExp = exp.mid(0, slashIndex); QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, hiddenExp); - qint32 bkrspLength = bkrsp.size(); + qint32 bkrspLength = sizeof(bkrsp); UVSC_STATUS st = ::UVSC_DBG_CREATE_BP(m_descriptor, reinterpret_cast(bkparm.data()), bkparm.size(), - reinterpret_cast(bkrsp.data()), - &bkrspLength); + &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -920,11 +919,9 @@ bool UvscClient::controlHiddenBreakpoint(const QString &exp) 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); + bkchg.tickMark = bkrsp.tickMark; + bkrspLength = sizeof(bkrsp); + st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -933,6 +930,24 @@ bool UvscClient::controlHiddenBreakpoint(const QString &exp) return true; } +bool UvscClient::enumerateBreakpoints(std::vector &bpenums) +{ + if (!checkConnection()) + return false; + + bpenums.resize(kMaximumBreakpointEnumsCount); + qint32 bpenumsCount = kMaximumBreakpointEnumsCount; + std::vector indexes(bpenumsCount, 0); + const UVSC_STATUS st = ::UVSC_DBG_ENUMERATE_BP(m_descriptor, bpenums.data(), + indexes.data(), &bpenumsCount); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + bpenums.resize(bpenumsCount); + return true; +} + bool UvscClient::calculateExpression(const QString &exp, QByteArray &) { if (!checkConnection()) @@ -1184,5 +1199,36 @@ bool UvscClient::addressToFileLine(quint64 address, QString &fileName, return true; } +bool UvscClient::executeCommand(const QString &cmd, QString &output) +{ + if (!checkConnection()) + return false; + + EXECCMD exeCmd = UvscUtils::encodeCommand(cmd); + UVSC_STATUS st = ::UVSC_DBG_EXEC_CMD(m_descriptor, &exeCmd, sizeof(exeCmd.command)); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + qint32 outputLength = 0; + st = ::UVSC_GetCmdOutputSize(m_descriptor, &outputLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + QByteArray data(outputLength, 0); + st = UVSC_GetCmdOutput(m_descriptor, reinterpret_cast(data.data()), data.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + // Note: UVSC API support only ASCII! + output = QString::fromLatin1(data); + return true; +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/uvsc/uvscclient.h b/src/plugins/debugger/uvsc/uvscclient.h index c39a5f4a076..98b001ac4e3 100644 --- a/src/plugins/debugger/uvsc/uvscclient.h +++ b/src/plugins/debugger/uvsc/uvscclient.h @@ -36,6 +36,7 @@ QT_END_NAMESPACE // From UVSC api. struct STACKENUM; +struct BKRSP; namespace Utils { class FilePath; } @@ -142,6 +143,8 @@ private: bool addressToFileLine(quint64 address, QString &fileName, QString &function, quint32 &line); bool controlHiddenBreakpoint(const QString &exp); + bool enumerateBreakpoints(std::vector &bpenums); + bool executeCommand(const QString &cmd, QString &output); qint32 m_descriptor = -1; quint64 m_exitAddress = 0; diff --git a/src/plugins/debugger/uvsc/uvscdatatypes.h b/src/plugins/debugger/uvsc/uvscdatatypes.h index c2ef9d77129..4392d81644c 100644 --- a/src/plugins/debugger/uvsc/uvscdatatypes.h +++ b/src/plugins/debugger/uvsc/uvscdatatypes.h @@ -610,9 +610,9 @@ struct BKRSP { quint32 tickMark; quint64 address; quint32 expressionLength; - qint8 expressionBuffer[1]; + qint8 expressionBuffer[512]; }; -static_assert(sizeof(BKRSP) == 29, "BKRSP size is not 29 bytes"); +static_assert(sizeof(BKRSP) == 540, "BKRSP size is not 540 bytes"); // Breakpoint change data. struct BKCHG { diff --git a/src/plugins/debugger/uvsc/uvscutils.cpp b/src/plugins/debugger/uvsc/uvscutils.cpp index d7fb4d22eff..a8e7d97e623 100644 --- a/src/plugins/debugger/uvsc/uvscutils.cpp +++ b/src/plugins/debugger/uvsc/uvscutils.cpp @@ -120,6 +120,14 @@ QByteArray encodeAmem(quint64 address, const QByteArray &data) return buffer; } +EXECCMD encodeCommand(const QString &cmd) +{ + EXECCMD exeCmd = {}; + exeCmd.useEcho = false; + exeCmd.command = encodeSstr(cmd); + return exeCmd; +} + TVAL encodeVoidTval() { TVAL tval = {}; diff --git a/src/plugins/debugger/uvsc/uvscutils.h b/src/plugins/debugger/uvsc/uvscutils.h index b51ac017a5a..61778f11e5d 100644 --- a/src/plugins/debugger/uvsc/uvscutils.h +++ b/src/plugins/debugger/uvsc/uvscutils.h @@ -57,6 +57,7 @@ QByteArray encodeProjectData(const QStringList &someNames); QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd = QString()); QByteArray encodeAmem(quint64 address, quint32 bytesCount); QByteArray encodeAmem(quint64 address, const QByteArray &data); +EXECCMD encodeCommand(const QString &cmd); TVAL encodeVoidTval(); TVAL encodeIntTval(int value); TVAL encodeU64Tval(quint64 value);