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"