File indexing completed on 2024-04-28 04:38:57

0001 /*
0002     SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "lldbcommand.h"
0008 
0009 using namespace KDevMI::LLDB;
0010 using namespace KDevMI::MI;
0011 
0012 LldbCommand::LldbCommand(CommandType type, const QString& arguments, CommandFlags flags)
0013     : MICommand(type, arguments, flags)
0014 {
0015 
0016 }
0017 
0018 LldbCommand::~LldbCommand()
0019 {
0020 }
0021 
0022 QString LldbCommand::miCommand() const
0023 {
0024     if (!overrideCmd.isEmpty()) {
0025         return overrideCmd;
0026     }
0027 
0028     QString command;
0029     bool isMI = false;
0030 
0031     // TODO: find alternatives to the following command which are not supported in lldb-mi
0032     switch(type()) {
0033         case BreakCommands:
0034             // empty command
0035             break;
0036         case BreakInfo:
0037             // empty command
0038             break;
0039         case BreakInsert: // in lldb-mi, '-f' must be the last option switch right before location
0040             command = QStringLiteral("break-insert");
0041             isMI = true;
0042             break;
0043         case BreakList:
0044             // empty command
0045             break;
0046         case BreakWatch:
0047             command = QStringLiteral("break set var");
0048             break;
0049 
0050         case DataListChangedRegisters:
0051             command = QStringLiteral("data-list-changed-registers");
0052             break;
0053         case DataReadMemory: // not implemented, deprecated
0054             command = QStringLiteral("data-read-memory");
0055             break;
0056         case DataWriteRegisterVariables:
0057             command = QStringLiteral("data-write-register-values");
0058             break;
0059 
0060         case EnableTimings:
0061             command = QStringLiteral("enable-timings");
0062             break;
0063 
0064         case EnvironmentDirectory:
0065             command = QStringLiteral("environment-directory");
0066             break;
0067         case EnvironmentPath:
0068             command = QStringLiteral("environment-path");
0069             break;
0070         case EnvironmentPwd:
0071             command = QStringLiteral("environment-pwd");
0072             break;
0073 
0074         case ExecUntil:
0075             // TODO: write test case for this
0076             command = QStringLiteral("thread until");
0077             break;
0078 
0079         case FileExecFile:
0080             command = QStringLiteral("file-exec-file");//"exec-file"
0081             break;
0082         case FileListExecSourceFile:
0083             command = QStringLiteral("file-list-exec-source-file");
0084             break;
0085         case FileListExecSourceFiles:
0086             command = QStringLiteral("file-list-exec-source-files");
0087             break;
0088         case FileSymbolFile:
0089             command = QStringLiteral("file-symbol-file");//"symbol-file"
0090             break;
0091 
0092         case GdbVersion:
0093             command = QStringLiteral("gdb-version");//"show version"
0094             break;
0095 
0096         case InferiorTtyShow:
0097             command = QStringLiteral("inferior-tty-show");
0098             break;
0099 
0100         case SignalHandle:
0101             command = QStringLiteral("process handle");
0102             break;
0103 
0104         case TargetDisconnect:
0105             command = QStringLiteral("target-disconnect");//"disconnect"
0106             break;
0107         case TargetDownload:
0108             command = QStringLiteral("target-download");
0109             break;
0110 
0111         case ThreadListIds:
0112             command = QStringLiteral("thread-list-ids");
0113             break;
0114         case ThreadSelect:
0115             command = QStringLiteral("thread-select");
0116             break;
0117 
0118         case TraceFind:
0119             command = QStringLiteral("trace-find");
0120             break;
0121         case TraceStart:
0122             command = QStringLiteral("trace-start");
0123             break;
0124         case TraceStop:
0125             command = QStringLiteral("trace-stop");
0126             break;
0127 
0128         case VarInfoNumChildren:
0129             command = QStringLiteral("var-info-num-children");
0130             break;
0131         case VarInfoType:
0132             command = QStringLiteral("var-info-type");
0133             break;
0134         case VarSetFrozen:
0135             command = QStringLiteral("var-set-frozen");
0136             break;
0137         case VarShowFormat:
0138             command = QStringLiteral("var-show-format");
0139             break;
0140         default:
0141             return MICommand::miCommand();
0142     }
0143 
0144     if (isMI) {
0145         command.prepend(QLatin1Char('-'));
0146     }
0147     return command;
0148 }
0149 
0150 QString LldbCommand::cmdToSend()
0151 {
0152     switch (type()) {
0153         // -gdb-set is only partially implemented
0154         case GdbSet: {
0155             QString env_name = QStringLiteral("environment ");
0156             QString disassembly_flavor = QStringLiteral("disassembly-flavor ");
0157             if (command_.startsWith(env_name)) {
0158                 command_.remove(0, env_name.length());
0159                 overrideCmd = QStringLiteral("settings set target.env-vars");
0160             } else if (command_.startsWith(disassembly_flavor)) {
0161                 command_.remove(0, disassembly_flavor.length());
0162                 overrideCmd = QStringLiteral("settings set target.x86-disassembly-flavor");
0163             }
0164             break;
0165         }
0166         // find the position to insert '-f'
0167         case BreakInsert: {
0168             if (!overrideCmd.isEmpty()) {
0169                 // already done
0170                 break;
0171             }
0172             int p = command_.length() - 1;
0173             bool quoted = false;
0174             if (command_[p] == QLatin1Char('"')) {
0175                 quoted = true; // should always be the case
0176             }
0177             --p;
0178             for (; p >= 0; --p) {
0179                 // find next '"' or ' '
0180                 if (quoted) {
0181                     if (command_[p] == QLatin1Char('"') && (p == 0 || command_[p-1] != QLatin1Char('\\')))
0182                         break;
0183                 } else {
0184                     if (command_[p] == QLatin1Char(' '))
0185                         break;
0186                 }
0187             }
0188             if (p < 0) p = 0; // this means the command is malformated, we proceed anyway.
0189 
0190             // move other switches like '-d' '-c' into miCommand part
0191             overrideCmd = miCommand() + QLatin1Char(' ') + command_.leftRef(p);
0192             command_ = QLatin1String("-f ") + command_.midRef(p, command_.length());
0193             break;
0194         }
0195         case BreakWatch:
0196             if (command_.startsWith(QLatin1String("-r "))) {
0197                 command_ = QLatin1String("-w read ") + command_.midRef(3);
0198             } else if (command_.startsWith(QLatin1String("-a "))) {
0199                 command_ = QLatin1String("-w read_write ") + command_.midRef(3);
0200             }
0201             break;
0202         case StackListArguments:
0203             // some times when adding the command, the current frame is invalid,
0204             // but is valid at sending time
0205             if (command_.endsWith(QLatin1String("-1 -1"))) {
0206                 command_.replace(QLatin1String("-1 -1"), QStringLiteral("%1 %1").arg(frame()));
0207             }
0208             break;
0209         default:
0210             break;
0211     }
0212     return MICommand::cmdToSend();
0213 }