1 /* 2 * Copyright Johannes Sixt 3 * This file is licensed under the GNU General Public License Version 2. 4 * See the file COPYING in the toplevel directory of the source directory. 5 */ 6 7 #ifndef DBGDRIVER_H 8 #define DBGDRIVER_H 9 10 #include <QFile> 11 #include <QByteArray> 12 #include <QProcess> 13 #include <queue> 14 #include <list> 15 16 17 class VarTree; 18 class ExprValue; 19 class ExprWnd; 20 class KDebugger; 21 class QStringList; 22 23 24 /** 25 * A type representing an address. 26 */ 27 struct DbgAddr 28 { 29 QString a; 30 QString fnoffs; DbgAddrDbgAddr31 DbgAddr() { } 32 DbgAddr(const QString& aa); DbgAddrDbgAddr33 DbgAddr(const DbgAddr& src) : a(src.a), fnoffs(src.fnoffs) { } 34 void operator=(const QString& aa); 35 void operator=(const DbgAddr& src) { a = src.a; fnoffs = src.fnoffs; } 36 QString asString() const; isEmptyDbgAddr37 bool isEmpty() const { return a.isEmpty(); } 38 protected: 39 void cleanAddr(); 40 }; 41 bool operator==(const DbgAddr& a1, const DbgAddr& a2); 42 bool operator>(const DbgAddr& a1, const DbgAddr& a2); 43 44 45 enum DbgCommand { 46 DCinitialize, 47 DCtty, 48 DCexecutable, 49 DCtargetremote, 50 DCcorefile, 51 DCattach, 52 DCinfolinemain, 53 DCinfolocals, 54 DCinforegisters, 55 DCexamine, 56 DCinfoline, 57 DCdisassemble, 58 DCsetargs, 59 DCsetenv, 60 DCunsetenv, 61 DCsetoption, /* debugger options */ 62 DCcd, 63 DCbt, 64 DCrun, 65 DCcont, 66 DCstep, 67 DCstepi, 68 DCnext, 69 DCnexti, 70 DCfinish, 71 DCuntil, /* line number is zero-based! */ 72 DCkill, 73 DCdetach, 74 DCbreaktext, 75 DCbreakline, /* line number is zero-based! */ 76 DCtbreakline, /* line number is zero-based! */ 77 DCbreakaddr, 78 DCtbreakaddr, 79 DCwatchpoint, 80 DCdelete, 81 DCenable, 82 DCdisable, 83 DCprint, 84 DCprintDeref, 85 DCprintStruct, 86 DCprintQStringStruct, 87 DCprintPopup, 88 DCframe, 89 DCfindType, 90 DCinfosharedlib, 91 DCthread, 92 DCinfothreads, 93 DCinfobreak, 94 DCcondition, 95 DCsetpc, 96 DCignore, 97 DCprintWChar, 98 DCsetvariable 99 }; 100 101 enum RunDevNull { 102 RDNstdin = 0x1, /* redirect stdin to /dev/null */ 103 RDNstdout = 0x2, /* redirect stdout to /dev/null */ 104 RDNstderr = 0x4 /* redirect stderr to /dev/null */ 105 }; 106 107 /** 108 * How the memory dump is formated. The lowest 4 bits define the size of 109 * the entities. The higher bits define how these are formatted. Note that 110 * not all combinations make sense. 111 */ 112 enum MemoryDumpType { 113 // sizes 114 MDTbyte = 0x1, 115 MDThalfword = 0x2, 116 MDTword = 0x3, 117 MDTgiantword = 0x4, 118 MDTsizemask = 0xf, 119 // formats 120 MDThex = 0x10, 121 MDTsigned = 0x20, 122 MDTunsigned = 0x30, 123 MDToctal = 0x40, 124 MDTbinary = 0x50, 125 MDTaddress = 0x60, 126 MDTchar = 0x70, 127 MDTfloat = 0x80, 128 MDTstring = 0x90, 129 MDTinsn = 0xa0, 130 MDTformatmask = 0xf0 131 }; 132 133 struct Breakpoint; 134 135 /** 136 * Debugger commands are placed in a queue. Only one command at a time is 137 * sent down to the debugger. All other commands in the queue are retained 138 * until the sent command has been processed by gdb. The debugger tells us 139 * that it's done with the command by sending the prompt. The output of the 140 * debugger is parsed at that time. Then, if more commands are in the 141 * queue, the next one is sent to the debugger. 142 */ 143 struct CmdQueueItem 144 { 145 DbgCommand m_cmd; 146 QString m_cmdString; 147 bool m_committed; /* just a debugging aid */ 148 // remember which expression when printing an expression 149 VarTree* m_expr; 150 ExprWnd* m_exprWnd; 151 // remember file position 152 QString m_fileName; 153 int m_lineNo; 154 DbgAddr m_addr; 155 // the breakpoint info 156 Breakpoint* m_brkpt; 157 int m_existingBrkpt; 158 // whether command was emitted due to direct user request (only set when relevant) 159 bool m_byUser; 160 // used to store the expression to print in case of DCprintPopup is executed 161 QString m_popupExpr; 162 CmdQueueItemCmdQueueItem163 CmdQueueItem(DbgCommand cmd, const QString& str) : 164 m_cmd(cmd), 165 m_cmdString(str), 166 m_committed(false), 167 m_expr(0), 168 m_exprWnd(0), 169 m_lineNo(0), 170 m_brkpt(0), 171 m_existingBrkpt(0), 172 m_byUser(false) 173 { } 174 175 struct IsEqualCmd 176 { IsEqualCmdCmdQueueItem::IsEqualCmd177 IsEqualCmd(DbgCommand cmd, const QString& str) : m_cmd(cmd), m_str(str) { } 178 bool operator()(CmdQueueItem*) const; 179 DbgCommand m_cmd; 180 const QString& m_str; 181 }; 182 }; 183 184 /** 185 * The information about a breakpoint that is parsed from the list of 186 * breakpoints. 187 */ 188 struct Breakpoint 189 { 190 int id; /* gdb's number */ 191 enum Type { 192 breakpoint, watchpoint 193 } type; 194 bool temporary; 195 bool enabled; 196 QString location; 197 QString text; /* text if set using DCbreaktext */ 198 DbgAddr address; /* exact address of breakpoint */ 199 QString condition; /* condition as printed by gdb */ 200 int ignoreCount; /* ignore next that may hits */ 201 int hitCount; /* as reported by gdb */ 202 // the following items repeat the location, but in a better usable way 203 QString fileName; 204 int lineNo; /* zero-based line number */ 205 Breakpoint(); isOrphanedBreakpoint206 bool isOrphaned() const { return id < 0; } 207 }; 208 209 /** 210 * Information about a stack frame. 211 */ 212 struct FrameInfo 213 { 214 QString fileName; 215 int lineNo; /* zero-based line number */ 216 DbgAddr address; /* exact address of PC */ 217 }; 218 219 /** 220 * The information about a stack frame as parsed from the backtrace. 221 */ 222 struct StackFrame : FrameInfo 223 { 224 int frameNo; 225 ExprValue* var; /* more information if non-zero */ StackFrameStackFrame226 StackFrame() : var(0) { } 227 ~StackFrame(); 228 }; 229 230 /** 231 * The information about a thread as parsed from the threads list. 232 */ 233 struct ThreadInfo : FrameInfo 234 { 235 int id; /* gdb's number */ 236 QString threadName; /* the SYSTAG */ 237 QString function; /* where thread is halted */ 238 bool hasFocus; /* the thread whose stack we are watching */ 239 }; 240 241 /** 242 * Register information 243 */ 244 struct RegisterInfo 245 { 246 QString regName; 247 QString rawValue; 248 QString cookedValue; /* may be empty */ 249 QString type; /* of vector register if not empty */ 250 }; 251 252 /** 253 * Disassembled code 254 */ 255 struct DisassembledCode 256 { 257 DbgAddr address; 258 QString code; 259 }; 260 261 /** 262 * Memory contents 263 */ 264 struct MemoryDump 265 { 266 DbgAddr address; 267 QString dump; 268 bool littleendian = true; 269 bool endOfDump = false; 270 }; 271 272 /** 273 * This is an abstract base class for debugger process. 274 * 275 * This class represents the debugger program. It provides the low-level 276 * interface to the commandline debugger. As such it implements the 277 * commands and parses the output. 278 */ 279 class DebuggerDriver : public QProcess 280 { 281 Q_OBJECT 282 public: 283 DebuggerDriver(); 284 virtual ~DebuggerDriver() = 0; 285 286 virtual QString driverName() const = 0; 287 /** 288 * Returns the default command string to invoke the debugger driver. 289 */ 290 virtual QString defaultInvocation() const = 0; 291 292 /** 293 * Returns a list of options that can be turned on and off. 294 */ 295 virtual QStringList boolOptionList() const = 0; 296 297 virtual bool startup(QString cmdStr); setLogFileName(const QString & fname)298 void setLogFileName(const QString& fname) { m_logFileName = fname; } isRunning()299 bool isRunning() { return state() != NotRunning; } 300 301 protected: 302 QString m_runCmd; 303 304 enum DebuggerState { 305 DSidle, /* gdb waits for input */ 306 DSinterrupted, /* a command was interrupted */ 307 DSrunningLow, /* gdb is running a low-priority command */ 308 DSrunning, /* gdb waits for program */ 309 DScommandSent, /* command has been sent, we wait for wroteStdin signal */ 310 DScommandSentLow /* low-prioritycommand has been sent */ 311 }; 312 DebuggerState m_state; 313 314 public: isIdle()315 bool isIdle() const { return m_state == DSidle; } 316 /** 317 * Tells whether a high prority command would be executed immediately. 318 */ canExecuteImmediately()319 bool canExecuteImmediately() const { return m_hipriCmdQueue.empty(); } 320 321 protected: 322 QByteArray m_output; // normal gdb output 323 std::queue<QByteArray> m_delayedOutput; // output colleced before signal bytesWritten() arrived 324 325 public: 326 /** 327 * Enqueues a high-priority command. High-priority commands are 328 * executed before any low-priority commands. No user interaction is 329 * possible as long as there is a high-priority command in the queue. 330 */ 331 template<class... ARGS> executeCmd(DbgCommand cmd,ARGS &&...args)332 CmdQueueItem* executeCmd(DbgCommand cmd, ARGS&&... args) 333 { 334 return executeCmdString(cmd, 335 makeCmdString(cmd, std::forward<ARGS>(args)...), false); 336 } 337 template<class... ARGS> executeCmdOnce(DbgCommand cmd,ARGS &&...args)338 CmdQueueItem* executeCmdOnce(DbgCommand cmd, ARGS&&... args) 339 { 340 return executeCmdString(cmd, 341 makeCmdString(cmd, std::forward<ARGS>(args)...), true); 342 } 343 344 enum QueueMode { 345 QMnormal, /* queues the command last */ 346 QMoverride, /* removes an already queued command */ 347 QMoverrideMoreEqual /* ditto, also puts the command first in the queue */ 348 }; 349 350 /** 351 * Enqueues a low-priority command irrespective of whether it as already 352 * in the queue. 353 * Low-priority commands are executed after any high-priority commands. 354 */ 355 template<class... ARGS> queueCmdAgain(DbgCommand cmd,ARGS &&...args)356 CmdQueueItem* queueCmdAgain(DbgCommand cmd, ARGS&&... args) 357 { 358 return queueCmdString(cmd, 359 makeCmdString(cmd, std::forward<ARGS>(args)...), QMnormal); 360 } 361 362 /** 363 * Enqueues a low-priority command, unless it is already in the queue. 364 * Low-priority commands are executed after any high-priority commands. 365 */ 366 template<class... ARGS> queueCmd(DbgCommand cmd,ARGS &&...args)367 CmdQueueItem* queueCmd(DbgCommand cmd, ARGS&&... args) 368 { 369 return queueCmdString(cmd, 370 makeCmdString(cmd, std::forward<ARGS>(args)...), QMoverride); 371 } 372 373 /** 374 * Enqueues a low-priority command in front of all other low-prority 375 * commands. 376 * Low-priority commands are executed after any high-priority commands. 377 */ 378 template<class... ARGS> queueCmdPrio(DbgCommand cmd,ARGS &&...args)379 CmdQueueItem* queueCmdPrio(DbgCommand cmd, ARGS&&... args) 380 { 381 return queueCmdString(cmd, 382 makeCmdString(cmd, std::forward<ARGS>(args)...), QMoverrideMoreEqual); 383 } 384 385 /** 386 * Flushes the command queues. 387 * @param hipriOnly if true, only the high priority queue is flushed. 388 */ 389 virtual void flushCommands(bool hipriOnly = false); 390 391 /** 392 * Terminates the debugger process. 393 */ 394 virtual void terminate() = 0; 395 396 /** 397 * Terminates the debugger process, but also detaches any program that 398 * it has been attached to. 399 */ 400 virtual void detachAndTerminate() = 0; 401 402 /** 403 * Interrupts the debuggee. 404 */ 405 virtual void interruptInferior() = 0; 406 407 /** 408 * Specifies the command that prints the QString data. 409 */ 410 virtual void setPrintQStringDataCmd(const char* cmd) = 0; 411 412 /** 413 * Parses the output as an array of QChars. 414 */ 415 virtual ExprValue* parseQCharArray(const char* output, bool wantErrorValue, bool qt3like) = 0; 416 417 /** 418 * Parses a back-trace (the output of the DCbt command). 419 */ 420 virtual void parseBackTrace(const char* output, std::list<StackFrame>& stack) = 0; 421 422 /** 423 * Parses the output of the DCframe command; 424 * @param frameNo Returns the frame number. 425 * @param file Returns the source file name. 426 * @param lineNo The zero-based line number. 427 * @param address Returns the exact address. 428 * @return false if the frame could not be parsed successfully. The 429 * output values are undefined in this case. 430 */ 431 virtual bool parseFrameChange(const char* output, int& frameNo, 432 QString& file, int& lineNo, DbgAddr& address) = 0; 433 434 /** 435 * Parses a list of breakpoints. 436 * @param output The output of the debugger. 437 * @param brks The list of new #Breakpoint objects. The list 438 * must initially be empty. 439 * @return False if there was an error before the first breakpoint 440 * was found. Even if true is returned, #brks may be empty. 441 */ 442 virtual bool parseBreakList(const char* output, std::list<Breakpoint>& brks) = 0; 443 444 /** 445 * Parses a list of threads. 446 * @param output The output of the debugger. 447 * @return The new thread list. There is no indication if there was 448 * a parse error. 449 */ 450 virtual std::list<ThreadInfo> parseThreadList(const char* output) = 0; 451 452 /** 453 * Parses the output when the program stops to see whether this it 454 * stopped due to a breakpoint. 455 * @param output The output of the debugger. 456 * @param id Returns the breakpoint id. 457 * @param file Returns the file name in which the breakpoint is. 458 * @param lineNo Returns the zero-based line number of the breakpoint. 459 * @param address Returns the address of the breakpoint. 460 * @return False if there was no breakpoint. 461 */ 462 virtual bool parseBreakpoint(const char* output, int& id, 463 QString& file, int& lineNo, QString& address) = 0; 464 465 /** 466 * Parses the output of the DCinfolocals command. 467 * @param output The output of the debugger. 468 * @param newVars Receives the parsed variable values. The values are 469 * simply append()ed to the supplied list. 470 */ 471 virtual void parseLocals(const char* output, std::list<ExprValue*>& newVars) = 0; 472 473 /** 474 * Parses the output of a DCprint or DCprintStruct command. 475 * @param output The output of the debugger. 476 * @param wantErrorValue Specifies whether the error message should be 477 * provided as the value of a NKplain variable. If this is false, 478 * 0 is returned if the printed value is an error message. 479 * @return the parsed value. It is 0 if there was a parse error 480 * or if the output is an error message and #wantErrorValue 481 * is \c false. The returned object's text() is undefined. 482 */ 483 virtual ExprValue* parsePrintExpr(const char* output, bool wantErrorValue) = 0; 484 485 /** 486 * Parses the output of the DCcd command. 487 * @return false if the message is an error message. 488 */ 489 virtual bool parseChangeWD(const char* output, QString& message) = 0; 490 491 /** 492 * Parses the output of the DCexecutable command. 493 * @return false if an error occured. 494 */ 495 virtual bool parseChangeExecutable(const char* output, QString& message) = 0; 496 497 /** 498 * Parses the output of the DCcorefile command. 499 * @return false if the core file was not loaded successfully. 500 */ 501 virtual bool parseCoreFile(const char* output) = 0; 502 503 enum StopFlags { 504 SFrefreshSource = 1, /* refresh of source code is needed */ 505 SFrefreshBreak = 2, /* refresh breakpoints */ 506 SFrefreshThreads = 4, /* refresh thread list */ 507 SFprogramActive = 128 /* program remains active */ 508 }; 509 /** 510 * Parses the output of commands that execute (a piece of) the program. 511 * \a haveCoreFile indicates whether the "stop" could be due to 512 * a core file being loaded. 513 * @return The inclusive OR of zero or more of the StopFlags. 514 */ 515 virtual uint parseProgramStopped(const char* output, bool haveCoreFile, 516 QString& message) = 0; 517 518 /** 519 * Parses the output of the DCsharedlibs command. 520 */ 521 virtual QStringList parseSharedLibs(const char* output) = 0; 522 523 /** 524 * Parses the output of the DCfindType command. 525 * @return true if a type was found. 526 */ 527 virtual bool parseFindType(const char* output, QString& type) = 0; 528 529 /** 530 * Parses the output of the DCinforegisters command. 531 */ 532 virtual std::list<RegisterInfo> parseRegisters(const char* output) = 0; 533 534 /** 535 * Parses the output of the DCinfoline command. Returns false if the 536 * two addresses could not be found. 537 */ 538 virtual bool parseInfoLine(const char* output, 539 QString& addrFrom, QString& addrTo) = 0; 540 541 /** 542 * Parses the ouput of the DCdisassemble command. 543 */ 544 virtual std::list<DisassembledCode> parseDisassemble(const char* output) = 0; 545 546 /** 547 * Parses a memory dump. Returns an empty string if no error was found; 548 * otherwise it contains an error message. 549 */ 550 virtual QString parseMemoryDump(const char* output, std::list<MemoryDump>& memdump) = 0; 551 552 /** 553 * Parses the output of the DCsetvariable command. Returns an empty 554 * string if no error was found; otherwise it contains an error 555 * message. 556 */ 557 virtual QString parseSetVariable(const char* output) = 0; 558 559 /** 560 * Returns a value that the user can edit. 561 */ 562 virtual QString editableValue(VarTree* value); 563 564 protected: 565 /** Removes all commands from the low-priority queue. */ 566 void flushLoPriQueue(); 567 /** Removes all commands from the high-priority queue. */ 568 void flushHiPriQueue(); 569 570 std::queue<CmdQueueItem*> m_hipriCmdQueue; 571 std::list<CmdQueueItem*> m_lopriCmdQueue; 572 /** 573 * The active command is kept separately from other pending commands. 574 */ 575 CmdQueueItem* m_activeCmd; 576 /** 577 * Helper function that queues the given command string in the 578 * low-priority queue. 579 */ 580 CmdQueueItem* queueCmdString(DbgCommand cmd, QString cmdString, 581 QueueMode mode); 582 /** 583 * Helper function that queues the given command string in the 584 * high-priority queue. 585 */ 586 CmdQueueItem* executeCmdString(DbgCommand cmd, QString cmdString, 587 bool clearLow); 588 void writeCommand(); 589 virtual void commandFinished(CmdQueueItem* cmd) = 0; 590 virtual QString makeCmdString(DbgCommand cmd) = 0; 591 virtual QString makeCmdString(DbgCommand cmd, QString strArg) = 0; 592 virtual QString makeCmdString(DbgCommand cmd, int intArg) = 0; 593 virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg) = 0; 594 virtual QString makeCmdString(DbgCommand cmd, QString strArg1, QString strArg2) = 0; 595 virtual QString makeCmdString(DbgCommand cmd, int intArg1, int intArg2) = 0; 596 virtual QString makeCmdString(DbgCommand cmd, QString strArg, int intArg1, int intArg2) = 0; 597 598 protected: 599 void processOutput(const QByteArray& data); 600 601 /** 602 * Returns the start of the prompt in \a output or -1. 603 * \a len specifies the size of \a output, but in addition, the contents 604 * of \a output are NUL-terminated, i.e., \c output[len] is zero. 605 */ 606 virtual int findPrompt(const QByteArray& output) const = 0; 607 608 // log file 609 QString m_logFileName; 610 QFile m_logFile; 611 612 public slots: 613 void dequeueCmdByVar(VarTree* var); 614 615 protected slots: 616 virtual void slotReceiveOutput(); 617 virtual void slotCommandRead(); 618 virtual void slotExited(); 619 620 signals: 621 /** 622 * This signal is emitted when the output of a command has been fully 623 * collected and is ready to be interpreted. 624 */ 625 void commandReceived(CmdQueueItem* cmd, const char* output); 626 627 /** 628 * This signal is emitted when the debugger recognizes that a specific 629 * location in a file ought to be displayed. 630 * 631 * Gdb's --fullname option supports this for the step, next, frame, and 632 * run commands (and possibly others). 633 * 634 * @param file specifies the file; this is not necessarily a full path 635 * name, and if it is relative, you won't know relative to what, you 636 * can only guess. 637 * @param lineNo specifies the line number (0-based!) (this may be 638 * negative, in which case the file should be activated, but the line 639 * should NOT be changed). 640 * @param address specifies the exact address of the PC or is empty. 641 */ 642 void activateFileLine(const QString& file, int lineNo, const DbgAddr& address); 643 644 /** 645 * This signal is emitted when a command that starts the inferior has 646 * been submitted to the debugger. 647 */ 648 void inferiorRunning(); 649 650 /** 651 * This signal is emitted when all output from the debugger has been 652 * consumed and no more commands are in the queues. 653 */ 654 void enterIdleState(); 655 }; 656 657 #endif // DBGDRIVER_H 658