aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2020-04-22 16:48:31 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2020-04-23 06:57:36 +0000
commitb7851eeb55fd284bd647b7042e7f94a1ea1d3490 (patch)
tree7f94acbcf752ca4dc24fa2cfa01c3d3a0ff8ce0a /src
parentf781a728256b9b25c0df8cc46d386f2ebca27ba7 (diff)
Debugger: Fix breakpoint insertion stalling for UVSC engine
The UVSC support the debugger commands execution feature using the UVSC_DBG_EXEC_CMD function. This function non-blocks if an command execution fails. So we can use this function to execute a breakpoint insertion command: * http://www.keil.com/support/man/docs/uv4/uv4_cm_breakset.htm But, to get the properties of the inserted breakpoint we need to enumerate all available breakpoints and to find the desired breakpoint by its expression. Besides, we need to fix and the 'expressionBuffer' field of the BKRSP structure according to the original UVSC API. Change-Id: I3c52e8955de28180aaafa1af9f6001ff6ee3b7fb Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/debugger/uvsc/uvscclient.cpp124
-rw-r--r--src/plugins/debugger/uvsc/uvscclient.h3
-rw-r--r--src/plugins/debugger/uvsc/uvscdatatypes.h4
-rw-r--r--src/plugins/debugger/uvsc/uvscutils.cpp8
-rw-r--r--src/plugins/debugger/uvsc/uvscutils.h1
5 files changed, 99 insertions, 41 deletions
diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp
index 588ca9c18b..5c31411248 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::Type>(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 *>(bkparm.data()),
- bkparm.size(),
- reinterpret_cast<BKRSP *>(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;
+
+ std::vector<BKRSP> bpenums;
+ if (!enumerateBreakpoints(bpenums))
return false;
- }
- const auto bkrspPtr = reinterpret_cast<const BKRSP *>(bkrsp.constData());
- tickMark = bkrspPtr->tickMark;
- address = bkrspPtr->address;
+ 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<const char *>(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 *>(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 *>(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 *>(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 *>(bkparm.data()),
bkparm.size(),
- reinterpret_cast<BKRSP *>(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<const BKRSP *>(bkrsp.constData())->tickMark;
- bkrspLength = bkrsp.size();
- st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg),
- reinterpret_cast<BKRSP *>(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<BKRSP> &bpenums)
+{
+ if (!checkConnection())
+ return false;
+
+ bpenums.resize(kMaximumBreakpointEnumsCount);
+ qint32 bpenumsCount = kMaximumBreakpointEnumsCount;
+ std::vector<qint32> 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<qint8 *>(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 c39a5f4a07..98b001ac4e 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<BKRSP> &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 c2ef9d7712..4392d81644 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 d7fb4d22ef..a8e7d97e62 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 b51ac017a5..61778f11e5 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);