1 /* 2 SPDX-FileCopyrightText: 2004 Roberto Raggi <roberto@kdevelop.org> 3 SPDX-FileCopyrightText: 2005-2006 Vladimir Prus <ghost@cs.msu.su> 4 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 5 6 SPDX-License-Identifier: LGPL-2.0-or-later 7 */ 8 9 #ifndef GDBMI_H 10 #define GDBMI_H 11 12 #include <QString> 13 #include <QMap> 14 15 #include <stdexcept> 16 17 /** 18 @author Roberto Raggi 19 @author Vladimir Prus 20 */ 21 namespace KDevMI { namespace MI { 22 enum CommandType { 23 NonMI, 24 25 BreakAfter, 26 BreakCommands, 27 BreakCondition, 28 BreakDelete, 29 BreakDisable, 30 BreakEnable, 31 BreakInfo, 32 BreakInsert, 33 BreakList, 34 BreakWatch, 35 36 DataDisassemble, 37 DataEvaluateExpression, 38 DataListChangedRegisters, 39 DataListRegisterNames, 40 DataListRegisterValues, 41 DataReadMemory, 42 DataWriteMemory, 43 DataWriteRegisterVariables, 44 45 EnablePrettyPrinting, 46 EnableTimings, 47 48 EnvironmentCd, 49 EnvironmentDirectory, 50 EnvironmentPath, 51 EnvironmentPwd, 52 53 ExecAbort, 54 ExecArguments, 55 ExecContinue, 56 ExecFinish, 57 ExecInterrupt, 58 ExecNext, 59 ExecNextInstruction, 60 ExecRun, 61 ExecStep, 62 ExecStepInstruction, 63 ExecUntil, 64 65 FileExecAndSymbols, 66 FileExecFile, 67 FileListExecSourceFile, 68 FileListExecSourceFiles, 69 FileSymbolFile, 70 71 GdbExit, 72 GdbSet, 73 GdbShow, 74 GdbVersion, 75 76 InferiorTtySet, 77 InferiorTtyShow, 78 79 InterpreterExec, 80 81 ListFeatures, 82 83 SignalHandle, 84 85 StackInfoDepth, 86 StackInfoFrame, 87 StackListArguments, 88 StackListFrames, 89 StackListLocals, 90 StackSelectFrame, 91 92 SymbolListLines, 93 94 TargetAttach, 95 TargetDetach, 96 TargetDisconnect, 97 TargetDownload, 98 TargetSelect, 99 100 ThreadInfo, 101 ThreadListIds, 102 ThreadSelect, 103 104 TraceFind, 105 TraceStart, 106 TraceStop, 107 108 VarAssign, 109 VarCreate, 110 VarDelete, 111 VarEvaluateExpression, 112 VarInfoPathExpression, 113 VarInfoNumChildren, 114 VarInfoType, 115 VarListChildren, 116 VarSetFormat, 117 VarSetFrozen, 118 VarShowAttributes, 119 VarShowFormat, 120 VarUpdate 121 }; 122 123 /** Exception that is thrown when we're trying to invoke an 124 operation that is not supported by specific MI value. For 125 example, trying to index a string literal. 126 127 Such errors are conceptually the same as assert, but in GUI 128 we can't use regular assert, and Q_ASSERT, which only prints 129 a message, is not suitable either. We need to break processing, 130 and the higher-level code can report "Internal parsing error", 131 or something. 132 133 Being glorified assert, this exception does not cary any 134 useful information. 135 */ 136 class type_error : public std::logic_error 137 { 138 public: 139 type_error(); 140 }; 141 142 /** Base class for all MI values. 143 MI values are of three kinds: 144 - String literals 145 - Lists (indexed by integer) 146 - Tuple (set of named values, indexed by name) 147 148 The structure of response to a specific gdb command is fixed. 149 While any tuples in response may omit certain named fields, the 150 kind of each item never changes. That is, response to specific 151 command can't contains sometimes string and sometimes tuple in 152 specific position. 153 154 Because of that static structure, it's almost never needed to query 155 dynamic type of a MI value. Most often we know it's say, tuple, and 156 can subscripts it. 157 158 So, the Value class has methods for accessing all kinds of values. 159 Attempting to call a method that is not applicable to specific value 160 will result in exception. The client code will almost never need to 161 cast from 'Value' to its derived classes. 162 163 Note also that all methods in this class are const and return 164 const Value&. That's by design -- there's no need to modify gdb 165 responses in GUI. 166 */ 167 struct Value 168 { 169 enum Kind { 170 StringLiteral, 171 Tuple, 172 List 173 }; 174 175 protected: ValueValue176 constexpr explicit Value(Kind k) : kind(k) {} 177 178 public: 179 virtual ~Value() = default; 180 181 Value() = delete; 182 // Copy disabled to prevent slicing. 183 Value(const Value&) = delete; 184 Value& operator=(const Value&) = delete; 185 186 const Kind kind = StringLiteral; 187 188 /** If this value is a string literals, returns the string value. 189 Otherwise, throws type_error. 190 */ 191 virtual QString literal() const; 192 193 //NOTE: Wouldn't it be better to use literal().toInt and get rid of that? 194 /** If the value is a string literal, converts it to int and 195 returns. If conversion fails, or the value cannot be 196 converted to int, throws type_error. 197 */ 198 virtual int toInt(int base = 10) const; 199 200 /** If this value is a tuple, returns true if the tuple 201 has a field named 'variable'. Otherwise, 202 throws type_error. 203 */ 204 virtual bool hasField(const QString& variable) const; 205 206 /** If this value is a tuple, and contains named field 'variable', 207 returns it. Otherwise, throws 'type_error'. 208 This method is virtual, and derived in base class, so that 209 we can save on casting, when we know for sure that instance 210 is TupleValue, or ListValue. 211 */ 212 virtual const Value& operator[](const QString& variable) const; 213 214 /** If this value is a list, returns true if the list is empty. 215 If this value is not a list, throws 'type_error'. 216 */ 217 virtual bool empty() const; 218 219 /** If this value is a list, returns it's size. 220 Otherwise, throws 'type_error'. 221 */ 222 virtual int size() const; 223 224 /** If this value is a list, returns the element at 225 'index'. Otherwise, throws 'type_error'. 226 */ 227 virtual const Value& operator[](int index) const; 228 }; 229 230 /** @internal 231 Internal class to represent name-value pair in tuples. 232 */ 233 struct Result 234 { 235 Result() = default; ~ResultResult236 ~Result() { delete value; value = nullptr; } 237 238 QString variable; 239 Value *value = nullptr; 240 241 private: 242 Q_DISABLE_COPY(Result) 243 }; 244 245 struct StringLiteralValue : public Value 246 { StringLiteralValueStringLiteralValue247 explicit StringLiteralValue(const QString &lit) 248 : Value(StringLiteral) 249 , literal_(lit) 250 {} 251 252 public: // Value overrides 253 254 QString literal() const override; 255 int toInt(int base) const override; 256 257 private: 258 QString literal_; 259 }; 260 261 struct TupleValue : public Value 262 { TupleValueTupleValue263 TupleValue() : Value(Tuple) {} 264 ~TupleValue() override; 265 266 bool hasField(const QString&) const override; 267 268 using Value::operator[]; 269 const Value& operator[](const QString& variable) const override; 270 271 QList<Result*> results; 272 QMap<QString, Result*> results_by_name; 273 }; 274 275 struct ListValue : public Value 276 { ListValueListValue277 ListValue() : Value(List) {} 278 ~ListValue() override; 279 280 bool empty() const override; 281 282 int size() const override; 283 284 using Value::operator[]; 285 const Value& operator[](int index) const override; 286 287 QList<Result*> results; 288 }; 289 290 struct Record 291 { 292 enum Kind { 293 Prompt, 294 Stream, 295 Result, 296 Async 297 }; 298 299 protected: RecordRecord300 constexpr explicit Record(Kind k) : kind(k) {} 301 302 public: 303 Record() = delete; 304 Record(const Record&) = delete; 305 Record& operator=(const Record&) = delete; 306 307 virtual ~Record() = default; toStringRecord308 virtual QString toString() const { Q_ASSERT( 0 ); return QString(); } 309 310 const Kind kind; 311 }; 312 313 struct TupleRecord : public Record, public TupleValue 314 { 315 protected: TupleRecordTupleRecord316 explicit TupleRecord(Record::Kind k) : Record(k) {} 317 }; 318 319 struct ResultRecord : public TupleRecord 320 { ResultRecordResultRecord321 explicit ResultRecord(const QString& reason) 322 : TupleRecord(Result) 323 , reason(reason) 324 { 325 } 326 327 uint32_t token = 0; 328 QString reason; 329 }; 330 331 struct AsyncRecord : public TupleRecord 332 { 333 enum Subkind { 334 Exec, 335 Status, 336 Notify 337 }; 338 AsyncRecordAsyncRecord339 AsyncRecord(Subkind subkind, const QString& reason) 340 : TupleRecord(Async) 341 , subkind(subkind) 342 , reason(reason) 343 { 344 } 345 346 Subkind subkind; 347 QString reason; 348 }; 349 350 struct PromptRecord : public Record 351 { PromptRecordPromptRecord352 PromptRecord() : Record(Prompt) {} 353 toStringPromptRecord354 QString toString() const override 355 { return QStringLiteral("(prompt)\n"); } 356 }; 357 358 struct StreamRecord : public Record 359 { 360 enum Subkind { 361 /// Console stream: usual CLI output of GDB in response to non-MI commands 362 Console, 363 364 /// Target output stream (stdout/stderr of the inferior process, only in some 365 /// scenarios - usually we get stdout/stderr via other means) 366 Target, 367 368 /// Log stream: GDB internal messages that should be displayed as part of an error log 369 Log 370 }; 371 StreamRecordStreamRecord372 explicit StreamRecord(Subkind subkind) 373 : Record(Stream) 374 , subkind(subkind) 375 { 376 } 377 378 Subkind subkind; 379 QString message; 380 }; 381 } // end of namespace MI 382 } // end of namespace KDevMI 383 384 #endif 385