work save

This commit is contained in:
royqh1979 2021-07-17 19:32:23 +08:00
parent a87ef64a1c
commit f1c3ac1063
5 changed files with 727 additions and 11 deletions

View File

@ -1,4 +1,6 @@
#include "debugger.h"
#include "utils.h"
#include "mainwindow.h"
Debugger::Debugger(QObject *parent) : QObject(parent)
{
@ -42,7 +44,7 @@ AnnotationType DebugReader::getAnnotation(const QString &s)
AnnotationType result = AnnotationType::TPostPrompt;
int IndexBackup = mIndex;
QString t = GetNextFilledLine();
QString t = getNextFilledLine();
int mIndex = IndexBackup;
//hack to catch local
@ -132,10 +134,471 @@ AnnotationType DebugReader::getAnnotation(const QString &s)
return AnnotationType::TSignalString;
} else if (s == "signal-string-end") {
return AnnotationType::TSignalStringEnd;
} else if (mOutput[mIndex] == 0) {
} else if (mIndex >= mOutput.length()) {
return AnnotationType::TEOF;
} else {
return AnnotationType::TUnknown;;
}
}
AnnotationType DebugReader::getLastAnnotation(const QString &text, int curpos, int len)
{
// Walk back until end of #26's
while ((curpos >= 0) && (text[curpos] != 26))
curpos--;
curpos++;
// Tiny rewrite of GetNextWord for special purposes
QString s = "";
while ((curpos < len) && (text[curpos]>32)) {
s = s + text[curpos];
curpos++;
}
return getAnnotation(s);
}
AnnotationType DebugReader::getNextAnnotation()
{
// Skip until end of #26's, i.e. GDB formatted output
skipToAnnotation();
// Get part this line, after #26#26
return getAnnotation(getNextWord());
}
QString DebugReader::getNextFilledLine()
{
// Walk up to an enter sequence
while (mIndex<mOutput.length() && mOutput[mIndex]!=13 && mOutput[mIndex]!=10 && mOutput[mIndex]!=0)
mIndex++;
// Skip enter sequences (CRLF, CR, LF, etc.)
while (mIndex<mOutput.length() && mOutput[mIndex]==13 && mOutput[mIndex]==10 && mOutput[mIndex]==0)
mIndex++;
// Return next line
return getRemainingLine();
}
QString DebugReader::getNextLine()
{
// Walk up to an enter sequence
while (mIndex<mOutput.length() && mOutput[mIndex]!=13 && mOutput[mIndex]!=10 && mOutput[mIndex]!=0)
mIndex++;
// End of output. Exit
if (mIndex>=mOutput.length())
return "";
// Skip ONE enter sequence (CRLF, CR, LF, etc.)
if ((mOutput[mIndex] == 13) && (mOutput[mIndex] == 10)) // DOS
mIndex+=2;
else if (mOutput[mIndex] == 13) // UNIX
mIndex++;
else if (mOutput[mIndex] == 10) // MAC
mIndex++;
// Return next line
return getRemainingLine();
}
QString DebugReader::getNextWord()
{
QString Result;
// Called when at a space? Skip over
skipSpaces();
// Skip until a space
while (mIndex<mOutput.length() && mOutput[mIndex]>32) {
Result += mOutput[mIndex];
mIndex++;
}
return Result;
}
QString DebugReader::getRemainingLine()
{
QString Result;
// Return part of line still ahead of us
while (mIndex<mOutput.length() && mOutput[mIndex]!=13 && mOutput[mIndex]!=10 && mOutput[mIndex]!=0) {
Result += mOutput[mIndex];
mIndex++;
}
return Result;
}
void DebugReader::handleDisassembly()
{
if (mDisassembly.isEmpty())
return;
// Get info message
QString s = getNextLine();
// the full function name will be saved at index 0
mDisassembly.append(s.mid(36));
s = getNextLine();
// Add lines of disassembly
while (!s.isEmpty() && (s != "End of assembler dump")) {
mDisassembly.append(s);
s = getNextLine();
}
dodisassemblerready = true;
}
void DebugReader::handleDisplay()
{
QString s = getNextLine(); // watch index
if (!findAnnotation(AnnotationType::TDisplayExpression))
return;
QString watchName = getNextLine(); // watch name
// Find parent we're talking about
auto result = mWatchVarList.find(watchName);
if (result != mWatchVarList.end()) {
PWatchVar watchVar = result.value();
// Advance up to the value
if (!findAnnotation(AnnotationType::TDisplayExpression))
return;;
// Refresh GDB index so we can undisplay this by index
watchVar->gdbIndex = s.toInt();
processWatchOutput(watchVar);
}
}
void DebugReader::handleError()
{
QString s = getNextLine(); // error text
if (s.startsWith("Cannot find bounds of current function")) {
//We have exited
handleExit();
} else if (s.startsWith("No symbol \"")) {
int head = s.indexOf('\"');
int tail = s.lastIndexOf('\"');
QString watchName = s.mid(head+1, tail-head-1);
// Update current...
auto result = mWatchVarList.find(watchName);
if (result != mWatchVarList.end()) {
PWatchVar watchVar = result.value();
//todo: update watch value to invalid
invalidateWatchVar(watchVar);
watchVar->gdbIndex = -1;
dorescanwatches = true;
}
}
}
void DebugReader::handleExit()
{
doprocessexited=true;
}
void DebugReader::handleFrames()
{
QString s = getNextLine();
// Is this a backtrace dump?
if (s.startsWith("#")) {
// Find function name
if (!findAnnotation(AnnotationType::TFrameFunctionName))
return;
PTrace trace = std::make_shared<Trace>();
trace->funcname = getNextLine();
// Find argument list start
if (!findAnnotation(AnnotationType::TFrameArgs))
return;
// Arguments are either () or detailed list
s = getNextLine();
while (peekNextAnnotation() == AnnotationType::TArgBegin) {
// argument name
if (!findAnnotation(AnnotationType::TArgBegin))
return;
s = s + getNextLine();
// =
if (!findAnnotation(AnnotationType::TArgNameEnd))
return;
s = s + ' ' + getNextLine() + ' '; // should be =
// argument value
if (!findAnnotation(AnnotationType::TArgValue))
return;
s = s + getNextLine();
// argument end
if (!findAnnotation(AnnotationType::TArgEnd))
return;
s = s + getNextLine();
}
trace->funcname = trace->funcname + s.trimmed();
// source info
if (peekNextAnnotation() == AnnotationType::TFrameSourceBegin) {
// Find filename
if (!findAnnotation(AnnotationType::TFrameSourceFile))
return;
trace->filename = getNextLine();
// find line
if (!findAnnotation(AnnotationType::TFrameSourceLine))
return;
trace->line = getNextLine().trimmed().toInt();
} else {
trace->filename = "";
trace->line = 0;
}
mBacktraceModel.addTrace(trace);
// Skip over the remaining frame part...
if (!findAnnotation(AnnotationType::TFrameEnd))
return;
// Not another one coming? Done!
if (peekNextAnnotation() != AnnotationType::TFrameBegin) {
// End of stack trace dump!
dobacktraceready = true;
}
} else
doupdatecpuwindow = true;
}
void DebugReader::handleLocalOutput()
{
// name(spaces)hexvalue(tab)decimalvalue
QString s = getNextFilledLine();
bool breakLine = false;
while (true) {
if (s.startsWith("\032\032")) {
s = TrimLeft(s);
if (s == "No locals.") {
return;
}
if (s == "No arguments.") {
return;
}
//todo: update local view
// if (breakLine and (MainForm.txtLocals.Lines.Count>0) then begin
// MainForm.txtLocals.Lines[MainForm.txtLocals.Lines.Count-1] := MainForm.txtLocals.Lines[MainForm.txtLocals.Lines.Count-1] + s;
// end else begin
// MainForm.txtLocals.Lines.Add(s);
// end;
breakLine=false;
} else {
breakLine = true;
}
s = getNextLine();
if (!breakLine && s.isEmpty())
break;
}
}
void DebugReader::handleLocals()
{
//todo: clear local view
handleLocalOutput();
}
void DebugReader::handleParams(){
handleLocalOutput();
}
void DebugReader::handleRegisters()
{
// name(spaces)hexvalue(tab)decimalvalue
QString s = getNextFilledLine();
while (true) {
PRegister reg = std::make_shared<Register>();
// Cut name from 1 to first space
int x = s.indexOf(' ');
reg->name = s.mid(0,x-1);
s.remove(0,x);
// Remove spaces
s = TrimLeft(s);
// Cut hex value from 1 to first tab
x = s.indexOf('\t');
if (x<0)
x = s.indexOf(' ');
reg->hexValue = s.mid(0,x - 1);
s.remove(0,x); // delete tab too
s = TrimLeft(s);
// Remaining part contains decimal value
reg->decValue = s;
mRegisters.append(reg);
s = getNextLine();
if (s.isEmpty())
break;
}
doregistersready := true;
}
int BreakpointModel::rowCount(const QModelIndex &) const
{
return mList.size();
}
int BreakpointModel::columnCount(const QModelIndex &) const
{
return 3;
}
QVariant BreakpointModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row()<0 || index.row() >= static_cast<int>(mList.size()))
return QVariant();
PBreakpoint breakpoint = mList[index.row()];
if (!breakpoint)
return QVariant();
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case 0:
return breakpoint->filename;
case 1:
if (breakpoint->line>0)
return breakpoint->line;
else
return "";
case 2:
return breakpoint->condition;
default:
return QVariant();
}
default:
return QVariant();
}
}
QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Filename");
case 1:
return tr("Line");
case 2:
return tr("Condition");
}
}
return QVariant();
}
void BreakpointModel::addBreakpoint(PBreakpoint p)
{
beginInsertRows(QModelIndex(),mList.size(),mList.size());
mList.push_back(p);
endInsertRows();
}
void BreakpointModel::clear()
{
beginRemoveRows(QModelIndex(),0,mList.size()-1);
mList.clear();
endRemoveRows();
}
void BreakpointModel::removeBreakpoint(int row)
{
beginRemoveRows(QModelIndex(),row,row);
mList.removeAt(row);
endRemoveRows();
}
int BacktraceModel::rowCount(const QModelIndex &) const
{
return mList.size();
}
int BacktraceModel::columnCount(const QModelIndex &) const
{
return 3;
}
QVariant BacktraceModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row()<0 || index.row() >= static_cast<int>(mList.size()))
return QVariant();
PTrace trace = mList[index.row()];
if (!trace)
return QVariant();
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case 0:
return trace->funcname;
case 1:
return trace->filename;
case 2:
if (trace->line>0)
return trace->line;
else
return "";
default:
return QVariant();
}
default:
return QVariant();
}
}
QVariant BacktraceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Function");
case 1:
return tr("Filename");
case 2:
return tr("Line");
}
}
return QVariant();
}
void BacktraceModel::addTrace(PTrace p)
{
beginInsertRows(QModelIndex(),mList.size(),mList.size());
mList.push_back(p);
endInsertRows();
}
void BacktraceModel::clear()
{
beginRemoveRows(QModelIndex(),0,mList.size()-1);
mList.clear();
endRemoveRows();
}
void BacktraceModel::removeTrace(int row)
{
beginRemoveRows(QModelIndex(),row,row);
mList.removeAt(row);
endRemoveRows();
}

View File

@ -1,8 +1,10 @@
#ifndef DEBUGGER_H
#define DEBUGGER_H
#include <QAbstractTableModel>
#include <QList>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QObject>
#include <QQueue>
@ -44,6 +46,13 @@ struct DebugCommand{
using PDebugCommand = std::shared_ptr<DebugCommand>;
struct WatchVar {
QString name;
int gdbIndex;
};
using PWatchVar = std::shared_ptr<WatchVar>;
struct Breakpoint {
int line;
QString filename;
@ -62,11 +71,41 @@ using PTrace = std::shared_ptr<Trace>;
struct Register {
QString name;
int value;
QString hexValue;
QString decValue;
};
using PRegister = std::shared_ptr<Register>;
class BreakpointModel: public QAbstractTableModel {
// QAbstractItemModel interface
public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void addBreakpoint(PBreakpoint p);
void clear();
void removeBreakpoint(int row);
private:
QList<PBreakpoint> mList;
};
class BacktraceModel : public QAbstractTableModel {
// QAbstractItemModel interface
public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void addTrace(PTrace p);
void clear();
void removeTrace(int row);
private:
QList<PTrace> mList;
};
class DebugReader;
class Debugger : public QObject
@ -94,8 +133,21 @@ private:
void clearCmdQueue();
bool findAnnotation(AnnotationType annotation);
AnnotationType getAnnotation(const QString& s);
AnnotationType getLastAnnotation(const QString& text,int curpos, int len;
AnnotationType getLastAnnotation(const QString& text,int curpos, int len);
AnnotationType getNextAnnotation();
QString getNextFilledLine();
QString getNextLine();
QString getNextWord();
QString getRemainingLine();
void handleDisassembly();
void handleDisplay();
void handleError();
void handleExit();
void handleFrames();
void handleLocalOutput();
void handleLocals();
void handleParams();
void handleRegisters();
private:
QMutex mMutex;
QQueue<PDebugCommand> mCmdQueue;
@ -107,9 +159,9 @@ private:
PDebugCommand mCurrentCmd;
QList<PRegister> mRegisters;
QStringList mDisassembly;
QList<PTrace> mBacktrace;
QList<PBreakpoint> mBreakpoints;
//fWatchVarList: TList; // contains all parents
BacktraceModel mBacktraceModel;
QMap<QString,PWatchVar> mWatchVarList; // contains all parents
//fWatchView: TTreeView;
int mIndex;
int mBreakPointLine;

View File

@ -173,7 +173,7 @@
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>3</number>
</property>
<widget class="QWidget" name="tabIssues">
<attribute name="icon">
@ -283,6 +283,197 @@
<attribute name="title">
<string>Debug</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QFrame" name="frmEvaluate">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lblEvaluate">
<property name="text">
<string>Evaluate:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbEvaluate">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="txtEvalOutput">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QTabWidget" name="debugViews">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tabDebugConsole">
<attribute name="title">
<string>Debug Console</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QConsole" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabStackTrace">
<attribute name="title">
<string>Call Stack</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTableView" name="tblStackTrace"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabBreakpoints">
<attribute name="title">
<string>Breakpoints</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTableView" name="tblBreakpoints"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLocals">
<attribute name="title">
<string>Locals</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="txtLocals"/>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabSearch">
<attribute name="icon">
@ -715,6 +906,12 @@
<extends>QTableView</extends>
<header>widgets/issuestable.h</header>
</customwidget>
<customwidget>
<class>QConsole</class>
<extends>QFrame</extends>
<header location="global">widgets/qconsole.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -371,7 +371,8 @@ QString TrimRight(const QString &s)
if (s.isEmpty())
return s;
int i = s.length()-1;
while ((i>=0) && ((s[i] == '\r') || (s[i]=='\n') || (s[i] == '\t') || (s[i]==' '))) {
// while ((i>=0) && ((s[i] == '\r') || (s[i]=='\n') || (s[i] == '\t') || (s[i]==' '))) {
while ((i>=0) && (s[i]<=32)) {
i--;
};
if (i>=0) {
@ -395,7 +396,10 @@ QString TrimLeft(const QString &s)
if (s.isEmpty())
return s;
int i=0;
while ((i<s.length()) && ((s[i] == '\r') || (s[i]=='\n') || (s[i] == '\t') || (s[i]==' '))) {
// while ((i<s.length()) && ((s[i] == '\r') || (s[i]=='\n') || (s[i] == '\t') || (s[i]==' '))) {
// i++;
// };
while ((i<s.length()) && (s[i]<=32)) {
i++;
};
if (i<s.length()) {

View File

@ -36,7 +36,7 @@ IssuesModel::IssuesModel(QObject *parent):
void IssuesModel::addIssue(PCompileIssue issue)
{
beginInsertColumns(QModelIndex(),mIssues.size(),mIssues.size());
beginInsertRows(QModelIndex(),mIssues.size(),mIssues.size());
mIssues.push_back(issue);
endInsertRows();
}