File indexing completed on 2024-05-12 04:39:44

0001 /*
0002     SPDX-FileCopyrightText: 2013 Vlas Puhov <vlas.puhov@mail.ru>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "registercontroller.h"
0008 
0009 #include "converters.h"
0010 #include "debuglog.h"
0011 #include "midebugsession.h"
0012 #include "mi/mi.h"
0013 #include "mi/micommand.h"
0014 
0015 #include <QRegExp>
0016 #include <QtMath>
0017 
0018 using namespace KDevMI::MI;
0019 using namespace KDevMI;
0020 
0021 void IRegisterController::setSession(MIDebugSession* debugSession)
0022 {
0023     m_debugSession = debugSession;
0024 }
0025 
0026 void IRegisterController::updateRegisters(const GroupsName& group)
0027 {
0028     if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) {
0029         return;
0030     }
0031 
0032     if (m_pendingGroups.contains(group)) {
0033         qCDebug(DEBUGGERCOMMON) << "Already updating " << group.name();
0034         return;
0035     }
0036 
0037     if (group.name().isEmpty()) {
0038         const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0039         for (const GroupsName& g : namesOfRegisterGroups) {
0040             IRegisterController::updateRegisters(g);
0041         }
0042         return;
0043     } else {
0044         qCDebug(DEBUGGERCOMMON) << "Updating: " << group.name();
0045         m_pendingGroups << group;
0046     }
0047 
0048     QString registers;
0049     Format currentFormat = formats(group).first();
0050     switch (currentFormat) {
0051     case Binary:
0052         registers = QStringLiteral("t ");
0053         break;
0054     case Octal:
0055         registers = QStringLiteral("o ");
0056         break;
0057     case Decimal :
0058         registers = QStringLiteral("d ");
0059         break;
0060     case Hexadecimal:
0061         registers = QStringLiteral("x ");
0062         break;
0063     case Raw:
0064         registers = QStringLiteral("r ");
0065         break;
0066     case Unsigned:
0067         registers = QStringLiteral("u ");
0068         break;
0069     default:
0070         break;
0071     }
0072 
0073     //float point registers have only two reasonable format.
0074     Mode currentMode = modes(group).first();
0075     if (((currentMode >= v4_float && currentMode <= v2_double) ||
0076         (currentMode >= f32 && currentMode <= f64) || group.type() == floatPoint) && currentFormat != Raw) {
0077         registers = QStringLiteral("N ");
0078     }
0079 
0080     if (group.type() == flag) {
0081         registers += numberForName(group.flagName());
0082     } else {
0083         const auto names = registerNamesForGroup(group);
0084         for (const QString& name : names) {
0085             registers += numberForName(name) + QLatin1Char(' ');
0086         }
0087     }
0088 
0089     //Not initialized yet. They'll be updated afterwards.
0090     if (registers.contains(QLatin1String("-1"))) {
0091         qCDebug(DEBUGGERCOMMON) << "Will update later";
0092         m_pendingGroups.clear();
0093         return;
0094     }
0095 
0096     void (IRegisterController::* handler)(const ResultRecord&);
0097     if (group.type() == structured && currentFormat != Raw) {
0098         handler = &IRegisterController::structuredRegistersHandler;
0099     } else {
0100         handler = &IRegisterController::generalRegistersHandler;
0101     }
0102 
0103     m_debugSession->addCommand(DataListRegisterValues, registers, this, handler);
0104 }
0105 
0106 void IRegisterController::registerNamesHandler(const ResultRecord& r)
0107 {
0108     const Value& names = r[QStringLiteral("register-names")];
0109 
0110     m_rawRegisterNames.clear();
0111     for (int i = 0; i < names.size(); ++i) {
0112         const Value& entry = names[i];
0113         m_rawRegisterNames.push_back(entry.literal());
0114     }
0115 
0116     //When here probably request for updating registers was sent, but m_rawRegisterNames were not initialized yet, so it wasn't successful. Update everything once again.
0117     updateRegisters();
0118 }
0119 
0120 void IRegisterController::generalRegistersHandler(const ResultRecord& r)
0121 {
0122     Q_ASSERT(!m_rawRegisterNames.isEmpty());
0123 
0124     QString registerName;
0125 
0126     const Value& values = r[QStringLiteral("register-values")];
0127     for (int i = 0; i < values.size(); ++i) {
0128         const Value& entry = values[i];
0129         int number = entry[QStringLiteral("number")].literal().toInt();
0130         Q_ASSERT(m_rawRegisterNames.size() >  number);
0131 
0132         if (!m_rawRegisterNames[number].isEmpty()) {
0133             if (registerName.isEmpty()) {
0134                 registerName = m_rawRegisterNames[number];
0135             }
0136             const QString value = entry[QStringLiteral("value")].literal();
0137             m_registers.insert(m_rawRegisterNames[number], value);
0138         }
0139     }
0140 
0141     GroupsName group = groupForRegisterName(registerName);
0142 
0143     const int groupIndex = m_pendingGroups.indexOf(group);
0144     if (groupIndex != -1) {
0145         emit registersChanged(registersFromGroup(group));
0146         m_pendingGroups.remove(groupIndex);
0147     }
0148 }
0149 
0150 void IRegisterController::setRegisterValue(const Register& reg)
0151 {
0152     Q_ASSERT(!m_registers.isEmpty());
0153 
0154     const GroupsName group = groupForRegisterName(reg.name);
0155     if (!group.name().isEmpty()) {
0156         setRegisterValueForGroup(group, reg);
0157     }
0158 }
0159 
0160 QString IRegisterController::registerValue(const QString& name) const
0161 {
0162     QString value;
0163     if (!name.isEmpty()) {
0164         const auto registerIt = m_registers.find(name);
0165         if (registerIt != m_registers.end()) {
0166             value = *registerIt;
0167         }
0168     }
0169     return value;
0170 }
0171 
0172 bool IRegisterController::initializeRegisters()
0173 {
0174     if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) {
0175         return false;
0176     }
0177 
0178     m_debugSession->addCommand(DataListRegisterNames, QString(), this, &IRegisterController::registerNamesHandler);
0179     return true;
0180 }
0181 
0182 GroupsName IRegisterController::groupForRegisterName(const QString& name) const
0183 {
0184     const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0185     for (const GroupsName& group : namesOfRegisterGroups) {
0186         const QStringList registersInGroup = registerNamesForGroup(group);
0187         if (group.flagName() == name) {
0188             return group;
0189         }
0190         for (const QString& n : registersInGroup) {
0191             if (n == name) {
0192                 return group;
0193             }
0194         }
0195     }
0196     return GroupsName();
0197 }
0198 
0199 void IRegisterController::updateValuesForRegisters(RegistersGroup* registers) const
0200 {
0201     Q_ASSERT(!m_registers.isEmpty());
0202 
0203     for (auto& reg : registers->registers) {
0204         const auto registerIt = m_registers.find(reg.name);
0205         if (registerIt != m_registers.end()) {
0206             reg.value = *registerIt;
0207         }
0208     }
0209 }
0210 
0211 void IRegisterController::setFlagRegister(const Register& reg, const FlagRegister& flag)
0212 {
0213     quint32 flagsValue = registerValue(flag.registerName).toUInt(nullptr, 16);
0214 
0215     const int idx = flag.flags.indexOf(reg.name);
0216 
0217     if (idx != -1) {
0218         flagsValue ^= static_cast<int>(qPow(2, flag.bits[idx].toUInt()));
0219         setGeneralRegister(Register(flag.registerName, QStringLiteral("0x%1").arg(flagsValue, 0, 16)), flag.groupName);
0220     } else {
0221         updateRegisters(flag.groupName);
0222         qCDebug(DEBUGGERCOMMON) << reg.name << ' ' << reg.value << "is incorrect flag name/value";
0223     }
0224 }
0225 
0226 void IRegisterController::setGeneralRegister(const Register& reg, const GroupsName& group)
0227 {
0228     if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) {
0229         return;
0230     }
0231 
0232     const QString command = QStringLiteral("set var $%1=%2").arg(reg.name, reg.value);
0233     qCDebug(DEBUGGERCOMMON) << "Setting register: " << command;
0234 
0235     m_debugSession->addCommand(NonMI, command);
0236     updateRegisters(group);
0237 }
0238 
0239 IRegisterController::IRegisterController(MIDebugSession* debugSession, QObject* parent)
0240 : QObject(parent), m_debugSession(debugSession) {}
0241 
0242 IRegisterController::~IRegisterController() {}
0243 
0244 void IRegisterController::updateFlagValues(RegistersGroup* flagsGroup, const FlagRegister& flagRegister) const
0245 {
0246     const quint32 flagsValue = registerValue(flagRegister.registerName).toUInt(nullptr, 16);
0247 
0248     for (int idx = 0; idx < flagRegister.flags.count(); idx++) {
0249         flagsGroup->registers[idx].value = ((flagsValue >> flagRegister.bits[idx].toInt()) & 1) ? QStringLiteral("1") : QStringLiteral("0");
0250     }
0251 }
0252 
0253 QVector<Format> IRegisterController::formats(const GroupsName& group)
0254 {
0255     int idx = -1;
0256     const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0257     for (const GroupsName& g : namesOfRegisterGroups) {
0258         if (g == group) {
0259             idx = g.index();
0260         }
0261     }
0262     Q_ASSERT(idx != -1);
0263     return m_formatsModes[idx].formats;
0264 }
0265 
0266 GroupsName IRegisterController::createGroupName(const QString& name, int idx, RegisterType t, const QString& flag) const
0267 {
0268     return GroupsName(name, idx, t, flag);
0269 }
0270 
0271 void IRegisterController::setFormat(Format f, const GroupsName& group)
0272 {
0273     const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0274     for (const GroupsName& g : namesOfRegisterGroups) {
0275         if (g == group) {
0276             int i = m_formatsModes[g.index()].formats.indexOf(f);
0277             if (i != -1) {
0278                 m_formatsModes[g.index()].formats.remove(i);
0279                 m_formatsModes[g.index()].formats.prepend(f);
0280             }
0281         }
0282     }
0283 }
0284 
0285 QString IRegisterController::numberForName(const QString& name) const
0286 {
0287     //Requests for number come in order(if the previous was, let's say 10, then most likely the next one will be 11)
0288     static int previousNumber = -1;
0289     if (m_rawRegisterNames.isEmpty()) {
0290         previousNumber = -1;
0291         return QString::number(previousNumber);
0292     }
0293 
0294     if (previousNumber != -1 && m_rawRegisterNames.size() > ++previousNumber) {
0295         if (m_rawRegisterNames[previousNumber] == name) {
0296             return QString::number(previousNumber);
0297         }
0298     }
0299 
0300     for (int number = 0; number < m_rawRegisterNames.size(); number++) {
0301         if (name == m_rawRegisterNames[number]) {
0302             previousNumber = number;
0303             return QString::number(number);
0304         }
0305     }
0306 
0307     previousNumber = -1;
0308     return QString::number(previousNumber);
0309 }
0310 
0311 void IRegisterController::setStructuredRegister(const Register& reg, const GroupsName& group)
0312 {
0313     Register r = reg;
0314     r.value = r.value.trimmed();
0315     r.value.replace(QLatin1Char(' '), QLatin1Char(','));
0316     if (r.value.contains(QLatin1Char(','))) {
0317         r.value = QLatin1Char('{') + r.value + QLatin1Char('}');
0318     }
0319 
0320     r.name += QLatin1Char('.') + Converters::modeToString(m_formatsModes[group.index()].modes.first());
0321 
0322     setGeneralRegister(r, group);
0323 }
0324 
0325 void IRegisterController::structuredRegistersHandler(const ResultRecord& r)
0326 {
0327     //Parsing records in format like:
0328     //{u8 = {0, 0, 128, 146, 0, 48, 197, 65}, u16 = {0, 37504, 12288, 16837}, u32 = {2457862144, 1103441920}, u64 = 4739246961893310464, f32 = {-8.07793567e-28, 24.6484375}, f64 = 710934821}
0329     //{u8 = {0 <repeats 16 times>}, u16 = {0, 0, 0, 0, 0, 0, 0, 0}, u32 = {0, 0, 0, 0}, u64 = {0, 0}, f32 = {0, 0, 0, 0}, f64 = {0, 0}}
0330 
0331     QRegExp rx(QStringLiteral("^\\s*=\\s*\\{(.*)\\}"));
0332     rx.setMinimal(true);
0333 
0334     QString registerName;
0335     Mode currentMode = LAST_MODE;
0336     GroupsName group;
0337     const Value& values = r[QStringLiteral("register-values")];
0338 
0339     Q_ASSERT(!m_rawRegisterNames.isEmpty());
0340 
0341     for (int i = 0; i < values.size(); ++i) {
0342         const Value& entry = values[i];
0343         int number = entry[QStringLiteral("number")].literal().toInt();
0344         registerName = m_rawRegisterNames[number];
0345         if (currentMode == LAST_MODE) {
0346             group = groupForRegisterName(registerName);
0347             currentMode = modes(group).first();
0348         }
0349 
0350         QString record = entry[QStringLiteral("value")].literal();
0351         int start = record.indexOf(Converters::modeToString(currentMode));
0352         Q_ASSERT(start != -1);
0353         start += Converters::modeToString(currentMode).size();
0354 
0355         QString value = record.mid(start);
0356         int idx = rx.indexIn(value);
0357         value = rx.cap(1);
0358 
0359         if (idx == -1) {
0360             //if here then value without braces: u64 = 4739246961893310464, f32 = {-8.07793567e-28, 24.6484375}, f64 = 710934821}
0361             QRegExp rx2(QStringLiteral("=\\s+(.*)(\\}|,)"));
0362             rx2.setMinimal(true);
0363             rx2.indexIn(record, start);
0364             value = rx2.cap(1);
0365         }
0366         value = value.trimmed().remove(QLatin1Char(','));
0367         m_registers.insert(registerName, value);
0368     }
0369 
0370     const int groupIndex = m_pendingGroups.indexOf(group);
0371     if (groupIndex != -1) {
0372         emit registersChanged(registersFromGroup(group));
0373         m_pendingGroups.remove(groupIndex);
0374     }
0375 }
0376 
0377 QVector< Mode > IRegisterController::modes(const GroupsName& group)
0378 {
0379     int idx = -1;
0380     const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0381     for (const GroupsName& g : namesOfRegisterGroups) {
0382         if (g == group) {
0383             idx = g.index();
0384         }
0385     }
0386     Q_ASSERT(idx != -1);
0387     return m_formatsModes[idx].modes;
0388 }
0389 
0390 void IRegisterController::setMode(Mode m, const GroupsName& group)
0391 {
0392     const auto namesOfRegisterGroups = this->namesOfRegisterGroups();
0393     for (const GroupsName& g : namesOfRegisterGroups) {
0394         if (g == group) {
0395             int i = m_formatsModes[g.index()].modes.indexOf(m);
0396             if (i != -1) {
0397                 m_formatsModes[g.index()].modes.remove(i);
0398                 m_formatsModes[g.index()].modes.prepend(m);
0399             }
0400         }
0401     }
0402 }
0403 
0404 #include "moc_registercontroller.cpp"