Commit f0f9635d authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Compile CCDB manual test.

parent ff9c5976
......@@ -830,6 +830,11 @@ quint64 CoreEngine::getSourceLineAddress(const QString &file,
return rc;
}
void CoreEngine::outputVersion()
{
m_cif.debugControl->OutputVersionInformation(DEBUG_OUTCTL_ALL_CLIENTS);
}
bool CoreEngine::autoDetectPath(QString *outPath,
QStringList *checkedDirectories /* = 0 */)
{
......
......@@ -168,6 +168,9 @@ signals:
// feature of the engine.
void modulesLoaded();
public slots:
void outputVersion();
protected:
virtual void timerEvent(QTimerEvent* te);
......
......@@ -34,17 +34,18 @@
#include "debugeventcallback.h"
#include "symbolgroupcontext.h"
#include "stacktracecontext.h"
#include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtCore/QDebug>
#include <cstdio>
#include <cerrno>
const char usage[] =
"CDB command line test tool\n\n"
"ccdb <Options>\n"
"Options: -p engine path\n";
"Options: -p engine path\n"
" -c initial_command_file\n";
class PrintfOutputHandler : public CdbCore::DebugOutputBase
{
......@@ -72,7 +73,8 @@ CdbApplication::~CdbApplication()
CdbApplication::InitResult CdbApplication::init()
{
if (!parseOptions()) {
FILE *inputFile;
if (!parseOptions(&inputFile)) {
printf(usage);
return InitUsageShown;
}
......@@ -91,7 +93,7 @@ CdbApplication::InitResult CdbApplication::init()
connect(m_engine.data(), SIGNAL(watchTimerDebugEvent()), this, SLOT(debugEvent()));
std::printf("Succeded.\n");
// Prompt
m_promptThread = new CdbPromptThread(this);
m_promptThread = new CdbPromptThread(inputFile, this);
connect(m_promptThread, SIGNAL(finished()), this, SLOT(promptThreadTerminated()));
connect(m_promptThread, SIGNAL(asyncCommand(int,QString)),
this, SLOT(asyncCommand(int,QString)), Qt::QueuedConnection);
......@@ -99,7 +101,8 @@ CdbApplication::InitResult CdbApplication::init()
this, SLOT(syncCommand(int,QString)), Qt::BlockingQueuedConnection);
connect(m_promptThread, SIGNAL(executionCommand(int,QString)),
this, SLOT(executionCommand(int,QString)), Qt::BlockingQueuedConnection);
connect(m_engine.data(), SIGNAL(watchTimerDebugEvent()), m_promptThread, SLOT(notifyDebugEvent()),
Qt::QueuedConnection);
m_promptThread->start();
return InitOk;
}
......@@ -113,23 +116,41 @@ void CdbApplication::promptThreadTerminated()
quit();
}
bool CdbApplication::parseOptions()
bool CdbApplication::parseOptions(FILE **inputFile)
{
*inputFile = NULL;
const QStringList args = QCoreApplication::arguments();
const QStringList::const_iterator cend = args.constEnd();
QStringList::const_iterator it = args.constBegin();
for (++it; it != cend ; ++it) {
const QString &a = *it;
if (a == QLatin1String("-p")) {
++it;
if (it == cend) {
std::fprintf(stderr, "Option -p is missing an argument.\n");
if (a.startsWith(QLatin1Char('-')) && a.size() >= 2) {
switch (a.at(1).toAscii()) {
case 'p':
++it;
if (it == cend) {
std::fprintf(stderr, "Option -p is missing an argument.\n");
return false;
}
m_engineDll = *it;
break;
case 'c':
++it;
if (it == cend) {
std::fprintf(stderr, "Option -c is missing an argument.\n");
return false;
}
*inputFile = std::fopen( it->toLocal8Bit().constData(), "r");
if (*inputFile == NULL) {
std::fprintf(stderr, "Cannot open %s: %s\n", qPrintable(*it), std::strerror(errno));
return false;
}
break;
default:
std::fprintf(stderr, "Invalid option %s\n", qPrintable(a));
return false;
}
m_engineDll = *it;
} else {
std::fprintf(stderr, "Invalid option %s\n", qPrintable(a));
return false;
}
}
return true;
......@@ -252,6 +273,11 @@ void CdbApplication::syncCommand(int command, const QString &arg)
case Sync_PrintFrame:
printFrame(arg);
break;
case Sync_OutputVersion:
m_engine->outputVersion();
break;
case Sync_Python:
break;
case Unknown:
std::printf("Executing '%s' in code level %d, syntax %d\n",
qPrintable(arg), m_engine->codeLevel(), m_engine->expressionSyntax());
......@@ -286,7 +312,7 @@ void CdbApplication::executionCommand(int command, const QString &arg)
}
if (ok) {
m_engine->startWatchTimer();
m_stackTrace.reset();
m_stackTrace = QSharedPointer<CdbCore::StackTraceContext>();
} else {
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
}
......@@ -297,11 +323,17 @@ void CdbApplication::debugEvent()
QString errorMessage;
std::printf("Debug event\n");
CdbCore::StackTraceContext::ThreadIdFrameMap threads;
QVector<CdbCore::Thread> threads;
QVector<CdbCore::StackFrame> threadFrames;
ULONG currentThreadId;
if (CdbCore::StackTraceContext::getThreads(m_engine->interfaces(), &threads,
&currentThreadId, &errorMessage)) {
printf("%s\n", qPrintable(CdbCore::StackTraceContext::formatThreads(threads)));
if (CdbCore::StackTraceContext::getThreadList(m_engine->interfaces(), &threads, &currentThreadId, &errorMessage)
&& CdbCore::StackTraceContext::getStoppedThreadFrames(m_engine->interfaces(), currentThreadId, threads, &threadFrames, &errorMessage)) {
const int count = threadFrames.size();
for (int i = 0; i < count; i++) {
printf("Thread #%02d ID %10d SYSID %10d %s\n", i,
threads.at(i).id, threads.at(i).systemId, qPrintable(threadFrames.at(i).toString()));
}
} else {
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
}
......@@ -310,7 +342,7 @@ void CdbApplication::debugEvent()
CdbCore::StackTraceContext::create(&m_engine->interfaces(),
0xFFFF, &errorMessage);
if (trace) {
m_stackTrace.reset(trace);
m_stackTrace = QSharedPointer<CdbCore::StackTraceContext>(trace);
printf("%s\n", qPrintable(m_stackTrace->toString()));
} else {
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
......
......@@ -37,6 +37,8 @@
#include <QtCore/QScopedPointer>
#include <QtCore/QStringList>
#include <cstdio>
namespace CdbCore {
class CoreEngine;
class StackTraceContext;
......@@ -65,13 +67,13 @@ private slots:
void processAttached(void *handle);
private:
bool parseOptions();
bool parseOptions(FILE **inputFile);
void printFrame(const QString &arg);
quint64 addQueuedBreakPoint(const QString &arg, QString *errorMessage);
QString m_engineDll;
QSharedPointer<CdbCore::CoreEngine> m_engine;
QScopedPointer<CdbCore::StackTraceContext> m_stackTrace;
QSharedPointer<CdbCore::StackTraceContext> m_stackTrace;
CdbPromptThread *m_promptThread;
QStringList m_queuedCommands;
QStringList m_queuedBreakPoints;
......
......@@ -29,13 +29,12 @@
#include "cdbpromptthread.h"
#include <cstdio>
#include <QtCore/QDebug>
static const char help[] =
"Special commands:\n\n"
"H Display Help\n"
"q Quit\n"
"V Output version\n"
"E expression Evaluate C++expression\n"
"S binary args Start binary\n"
"I Interrupt\n"
......@@ -46,11 +45,17 @@ static const char help[] =
"B Clear breakpoint queue\n"
"L List breakpoints\n"
"F <n> Print stack frame <n>, 0 being top\n"
"P <cmd> Run Python command\n"
"W Synchronous wait for debug event\n"
"\nThe remaining commands are passed to CDB.\n";
CdbPromptThread::CdbPromptThread(QObject *parent) :
QThread(parent)
CdbPromptThread::CdbPromptThread(FILE *file, QObject *parent) :
QThread(parent),
m_waitingForDebugEvent(false),
m_inputFile(file)
{
if (!m_inputFile)
m_inputFile = stdin;
}
void CdbPromptThread::run()
......@@ -60,9 +65,17 @@ void CdbPromptThread::run()
QString cmd;
char buf[bufSize];
std::putc('>', stdout);
// When reading from an input file, switch to stdin after reading it out
while (true) {
if (std::fgets(buf, bufSize, stdin) == NULL)
break;
if (std::fgets(buf, bufSize, m_inputFile) == NULL) {
if (m_inputFile == stdin) {
break;
} else {
fclose(m_inputFile);
m_inputFile = stdin;
continue;
}
}
cmd += QString::fromLatin1(buf);
if (cmd.endsWith(QLatin1Char('\n'))) {
cmd.truncate(cmd.size() - 1);
......@@ -72,6 +85,8 @@ void CdbPromptThread::run()
}
std::putc('>', stdout);
}
if (m_inputFile != stdin)
fclose(m_inputFile);
}
// Determine the command
......@@ -95,6 +110,12 @@ static Command evaluateCommand(const QString &cmdToken)
return Execution_StartBinary;
case 'F':
return Sync_PrintFrame;
case 'P':
return Sync_Python;
case 'V':
return Sync_OutputVersion;
case 'W':
return WaitCommand;
default:
break;
}
......@@ -126,6 +147,12 @@ static Command parseCommand(QString *s)
return rc;
}
void CdbPromptThread::notifyDebugEvent()
{
if (m_waitingForDebugEvent)
m_debugEventWaitCondition.wakeAll();
}
bool CdbPromptThread::handleCommand(QString cmd)
{
if (cmd == QLatin1String("q"))
......@@ -135,6 +162,16 @@ bool CdbPromptThread::handleCommand(QString cmd)
return true;
}
const Command c = parseCommand(&cmd);
if (c == WaitCommand) {
std::fputs("Waiting for debug event\n", stdout);
m_debugEventMutex.lock();
m_waitingForDebugEvent = true;
m_debugEventWaitCondition.wait(&m_debugEventMutex);
m_debugEventMutex.unlock();
std::fputs("Debug event received\n", stdout);
m_waitingForDebugEvent = false;
return true;
}
if (c & AsyncCommand) {
emit asyncCommand(c, cmd);
return true;
......
......@@ -31,6 +31,10 @@
#define PROMPTTHREAD_H
#include <QtCore/QThread>
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>
#include <cstdio>
enum CommandTypeFlags {
// Interrupt or something.
......@@ -51,18 +55,24 @@ enum Command {
Sync_QueueBreakPoint = SyncCommand|3,
Sync_ListBreakPoints = SyncCommand|4,
Sync_PrintFrame = SyncCommand|5,
Sync_OutputVersion = SyncCommand|6,
Sync_Python = SyncCommand|7,
Execution_Go = ExecutionCommand|1,
Execution_StartBinary = ExecutionCommand|2
Execution_StartBinary = ExecutionCommand|2,
WaitCommand = 0xFFFF
};
class CdbPromptThread : public QThread
{
Q_OBJECT
public:
explicit CdbPromptThread(QObject *parent = 0);
explicit CdbPromptThread(FILE *file, QObject *parent = 0);
virtual void run();
public slots:
void notifyDebugEvent();
signals:
void asyncCommand(int command, const QString &arg);
void syncCommand(int command, const QString &arg);
......@@ -70,6 +80,10 @@ signals:
private:
bool handleCommand(QString);
QWaitCondition m_debugEventWaitCondition;
QMutex m_debugEventMutex;
bool m_waitingForDebugEvent;
FILE *m_inputFile;
};
#endif // PROMPTTHREAD_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment