2021-12-26 23:18:28 +08:00
/*
* Copyright ( C ) 2020 - 2022 Roy Qu ( royqh1979 @ gmail . com )
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
*/
2021-07-03 21:57:50 +08:00
# include "debugger.h"
2021-07-17 19:32:23 +08:00
# include "utils.h"
# include "mainwindow.h"
2021-07-24 11:18:25 +08:00
# include "editor.h"
2021-07-25 00:26:13 +08:00
# include "settings.h"
2021-08-01 23:24:37 +08:00
# include "widgets/cpudialog.h"
2021-10-12 19:39:24 +08:00
# include "systemconsts.h"
2023-07-02 11:09:34 +08:00
# include "editorlist.h"
2021-07-25 00:26:13 +08:00
# include <QFile>
# include <QFileInfo>
# include <QMessageBox>
2021-08-01 10:00:27 +08:00
# include <QPlainTextEdit>
2021-08-01 01:06:43 +08:00
# include <QDebug>
2021-10-13 17:20:31 +08:00
# include <QDir>
2021-11-23 21:08:33 +08:00
# include <QJsonDocument>
# include <QJsonArray>
# include <QJsonObject>
2021-11-25 09:05:45 +08:00
# include "widgets/signalmessagedialog.h"
2021-07-03 21:57:50 +08:00
2022-05-15 17:14:22 +08:00
Debugger : : Debugger ( QObject * parent ) : QObject ( parent ) ,
2022-10-16 23:10:57 +08:00
mForceUTF8 ( false ) ,
2023-01-22 22:19:19 +08:00
mDebuggerType ( DebuggerType : : GDB ) ,
2022-10-16 23:10:57 +08:00
mLastLoadtime ( 0 ) ,
mProjectLastLoadtime ( 0 )
2021-07-03 21:57:50 +08:00
{
2022-10-10 18:05:18 +08:00
//models deleted in the destructor
2022-10-16 23:10:57 +08:00
mBreakpointModel = std : : make_shared < BreakpointModel > ( this ) ;
mBacktraceModel = std : : make_shared < BacktraceModel > ( this ) ;
mWatchModel = std : : make_shared < WatchModel > ( this ) ;
mRegisterModel = std : : make_shared < RegisterModel > ( this ) ;
2023-02-25 21:42:30 +08:00
mMemoryModel = std : : make_shared < MemoryModel > ( 16 , this ) ;
2022-10-10 18:05:18 +08:00
2022-10-16 23:10:57 +08:00
connect ( mMemoryModel . get ( ) , & MemoryModel : : setMemoryData ,
2022-01-11 22:29:03 +08:00
this , & Debugger : : setMemoryData ) ;
2022-10-16 23:10:57 +08:00
connect ( mWatchModel . get ( ) , & WatchModel : : setWatchVarValue ,
2022-01-12 17:14:39 +08:00
this , & Debugger : : setWatchVarValue ) ;
2021-07-27 00:14:24 +08:00
mExecuting = false ;
mReader = nullptr ;
2021-12-25 18:09:50 +08:00
mTarget = nullptr ;
2021-07-27 00:14:24 +08:00
mCommandChanged = false ;
mLeftPageIndexBackup = - 1 ;
2021-11-25 20:26:43 +08:00
2022-10-16 23:10:57 +08:00
connect ( mWatchModel . get ( ) , & WatchModel : : fetchChildren ,
2021-11-25 20:26:43 +08:00
this , & Debugger : : fetchVarChildren ) ;
2022-10-16 23:10:57 +08:00
setIsForProject ( false ) ;
2021-07-24 11:18:25 +08:00
}
2022-10-10 18:05:18 +08:00
Debugger : : ~ Debugger ( )
{
2022-10-16 23:10:57 +08:00
// delete mBreakpointModel;
// delete mBacktraceModel;
// delete mWatchModel;
// delete mRegisterModel;
// delete mMemoryModel;
2022-10-10 18:05:18 +08:00
}
2023-02-21 09:34:40 +08:00
bool Debugger : : start ( int compilerSetIndex , const QString & inferior , const QStringList & binDirs , const QString & sourceFile )
2021-07-25 00:26:13 +08:00
{
2023-02-21 09:34:40 +08:00
mCurrentSourceFile = sourceFile ;
2022-05-15 17:14:22 +08:00
Settings : : PCompilerSet compilerSet = pSettings - > compilerSets ( ) . getSet ( compilerSetIndex ) ;
if ( ! compilerSet ) {
compilerSet = pSettings - > compilerSets ( ) . defaultSet ( ) ;
}
2021-07-25 00:26:13 +08:00
if ( ! compilerSet ) {
QMessageBox : : critical ( pMainWindow ,
tr ( " No compiler set " ) ,
tr ( " No compiler set is configured. " ) + tr ( " Can't start debugging. " ) ) ;
2021-08-20 12:43:01 +08:00
return false ;
2021-07-25 00:26:13 +08:00
}
2022-05-15 17:14:22 +08:00
setForceUTF8 ( CompilerInfoManager : : forceUTF8InDebugger ( compilerSet - > compilerType ( ) ) ) ;
2023-06-27 11:50:43 +08:00
setDebugInfosUsingUTF8 ( false ) ;
# ifdef Q_OS_WIN
bool isOk ;
int productVersion = QSysInfo : : productVersion ( ) . toInt ( & isOk ) ;
// qDebug()<<productVersion<<isOk;
if ( ! isOk ) {
if ( QSysInfo : : productVersion ( ) . startsWith ( " 7 " ) )
productVersion = 7 ;
else if ( QSysInfo : : productVersion ( ) . startsWith ( " 10 " ) )
productVersion = 10 ;
else if ( QSysInfo : : productVersion ( ) . startsWith ( " 11 " ) )
productVersion = 11 ;
else
productVersion = 10 ;
}
if ( compilerSet - > mainVersion ( ) > = 13 & & compilerSet - > compilerType ( ) = = CompilerType : : GCC
& & productVersion > = 10 )
setDebugInfosUsingUTF8 ( true ) ;
# endif
2023-01-22 22:19:19 +08:00
if ( compilerSet - > debugger ( ) . endsWith ( LLDB_MI_PROGRAM ) )
setDebuggerType ( DebuggerType : : LLDB_MI ) ;
else
setDebuggerType ( DebuggerType : : GDB ) ;
2021-07-26 22:29:47 +08:00
mExecuting = true ;
2021-07-25 00:26:13 +08:00
QString debuggerPath = compilerSet - > debugger ( ) ;
2021-10-02 21:46:34 +08:00
//QFile debuggerProgram(debuggerPath);
2022-03-30 20:45:08 +08:00
// if (!isTextAllAscii(debuggerPath)) {
// mExecuting = false;
// QMessageBox::critical(pMainWindow,
// tr("Debugger path error"),
// tr("Debugger's path \"%1\" contains non-ascii characters.")
// .arg(debuggerPath)
// + "<br />"
// + tr("This prevents it from executing."));
// return false;
// }
2021-10-02 21:46:34 +08:00
if ( ! fileExists ( debuggerPath ) ) {
2021-08-20 12:43:01 +08:00
mExecuting = false ;
2021-07-25 00:26:13 +08:00
QMessageBox : : critical ( pMainWindow ,
tr ( " Debugger not exists " ) ,
2022-12-16 11:10:46 +08:00
tr ( " Can''t find debugger (gdb) in : \" %1 \" " ) . arg ( debuggerPath )
+ " <br /> "
+ tr ( " Please check the \" program \" page of compiler settings. " ) ) ;
2021-08-20 12:43:01 +08:00
return false ;
2021-07-25 00:26:13 +08:00
}
2021-12-25 18:09:50 +08:00
if ( pSettings - > debugger ( ) . useGDBServer ( ) ) {
if ( ! isTextAllAscii ( compilerSet - > debugServer ( ) ) ) {
mExecuting = false ;
QMessageBox : : critical ( pMainWindow ,
tr ( " GDB Server path error " ) ,
tr ( " GDB Server's path \" %1 \" contains non-ascii characters. " )
. arg ( compilerSet - > debugServer ( ) )
+ " <br /> "
+ tr ( " This prevents it from executing. " ) ) ;
return false ;
}
if ( ! fileExists ( compilerSet - > debugServer ( ) ) ) {
mExecuting = false ;
QMessageBox : : critical ( pMainWindow ,
tr ( " GDB Server not exists " ) ,
tr ( " Can''t find gdb server in : \" %1 \" " ) . arg ( compilerSet - > debugServer ( ) ) ) ;
return false ;
}
}
2022-01-11 22:29:03 +08:00
mMemoryModel - > reset ( ) ;
2021-11-25 20:26:43 +08:00
mWatchModel - > resetAllVarInfos ( ) ;
2021-12-25 18:09:50 +08:00
if ( pSettings - > debugger ( ) . useGDBServer ( ) ) {
2022-10-10 18:05:18 +08:00
//deleted when thread finished
2023-01-12 12:07:22 +08:00
QString params ;
if ( pSettings - > executor ( ) . useParams ( ) )
params = pSettings - > executor ( ) . params ( ) ;
mTarget = new DebugTarget ( inferior , compilerSet - > debugServer ( ) , pSettings - > debugger ( ) . GDBServerPort ( ) , params ) ;
2022-01-12 18:47:50 +08:00
if ( pSettings - > executor ( ) . redirectInput ( ) )
mTarget - > setInputFile ( pSettings - > executor ( ) . inputFilename ( ) ) ;
2021-12-25 19:22:29 +08:00
connect ( mTarget , & QThread : : finished , [ this ] ( ) {
if ( mExecuting ) {
stop ( ) ;
}
mTarget - > deleteLater ( ) ;
mTarget = nullptr ;
} ) ;
2022-06-16 21:56:07 +08:00
mTarget - > addBinDirs ( binDirs ) ;
mTarget - > addBinDir ( pSettings - > dirs ( ) . appDir ( ) ) ;
2021-12-25 18:09:50 +08:00
mTarget - > start ( ) ;
mTarget - > waitStart ( ) ;
}
2022-10-10 18:05:18 +08:00
//delete when thread finished
2021-07-26 00:22:08 +08:00
mReader = new DebugReader ( this ) ;
2022-06-16 21:34:31 +08:00
mReader - > addBinDirs ( binDirs ) ;
mReader - > addBinDir ( pSettings - > dirs ( ) . appDir ( ) ) ;
2021-07-25 00:26:13 +08:00
mReader - > setDebuggerPath ( debuggerPath ) ;
2021-12-25 19:22:29 +08:00
connect ( mReader , & QThread : : finished , this , & Debugger : : cleanUpReader ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & QThread : : finished , mMemoryModel . get ( ) , & MemoryModel : : reset ) ;
2021-07-26 11:47:54 +08:00
connect ( mReader , & DebugReader : : parseFinished , this , & Debugger : : syncFinishedParsing , Qt : : BlockingQueuedConnection ) ;
2021-08-01 12:02:28 +08:00
connect ( mReader , & DebugReader : : changeDebugConsoleLastLine , this , & Debugger : : onChangeDebugConsoleLastline ) ;
2021-09-19 14:28:30 +08:00
connect ( mReader , & DebugReader : : cmdStarted , pMainWindow , & MainWindow : : disableDebugActions ) ;
connect ( mReader , & DebugReader : : cmdFinished , pMainWindow , & MainWindow : : enableDebugActions ) ;
2021-11-24 21:22:01 +08:00
connect ( mReader , & DebugReader : : inferiorStopped , pMainWindow , & MainWindow : : enableDebugActions ) ;
2021-11-23 21:08:33 +08:00
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : breakpointInfoGetted , mBreakpointModel . get ( ) ,
2021-11-21 08:38:03 +08:00
& BreakpointModel : : updateBreakpointNumber ) ;
2021-11-24 10:07:35 +08:00
connect ( mReader , & DebugReader : : localsUpdated , pMainWindow ,
& MainWindow : : onLocalsReady ) ;
2021-11-25 07:42:56 +08:00
connect ( mReader , & DebugReader : : memoryUpdated , this ,
& Debugger : : updateMemory ) ;
connect ( mReader , & DebugReader : : evalUpdated , this ,
& Debugger : : updateEval ) ;
2021-11-24 23:32:34 +08:00
connect ( mReader , & DebugReader : : disassemblyUpdate , this ,
& Debugger : : updateDisassembly ) ;
2021-11-25 09:05:45 +08:00
connect ( mReader , & DebugReader : : registerNamesUpdated , this ,
& Debugger : : updateRegisterNames ) ;
connect ( mReader , & DebugReader : : registerValuesUpdated , this ,
& Debugger : : updateRegisterValues ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : varCreated , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : updateVarInfo ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : prepareVarChildren , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : prepareVarChildren ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : addVarChild , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : addVarChild ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : varValueUpdated , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : updateVarValue ) ;
2022-10-16 23:10:57 +08:00
connect ( mReader , & DebugReader : : varsValueUpdated , mWatchModel . get ( ) ,
2022-03-30 19:28:46 +08:00
& WatchModel : : updateAllHasMoreVars ) ;
2021-11-24 21:22:01 +08:00
connect ( mReader , & DebugReader : : inferiorContinued , pMainWindow ,
& MainWindow : : removeActiveBreakpoints ) ;
2021-11-24 17:53:25 +08:00
connect ( mReader , & DebugReader : : inferiorStopped , pMainWindow ,
& MainWindow : : setActiveBreakpoint ) ;
2023-03-03 17:20:33 +08:00
connect ( mReader , & DebugReader : : watchpointHitted , pMainWindow ,
& MainWindow : : onWatchpointHitted ) ;
2023-02-18 12:08:03 +08:00
connect ( mReader , & DebugReader : : errorNoSymbolTable , pMainWindow ,
& MainWindow : : stopDebugForNoSymbolTable ) ;
2021-11-25 20:26:43 +08:00
connect ( mReader , & DebugReader : : inferiorStopped , this ,
2022-01-11 22:29:03 +08:00
& Debugger : : refreshAll ) ;
2021-09-19 14:28:30 +08:00
2021-11-24 21:22:01 +08:00
mReader - > registerInferiorStoppedCommand ( " -stack-list-frames " , " " ) ;
2021-07-25 00:26:13 +08:00
mReader - > start ( ) ;
2021-11-10 17:05:37 +08:00
mReader - > waitStart ( ) ;
2021-07-25 00:26:13 +08:00
2021-07-26 00:22:08 +08:00
pMainWindow - > updateAppTitle ( ) ;
2021-07-25 00:26:13 +08:00
2021-07-25 13:03:46 +08:00
//Application.HintHidePause := 5000;
2021-08-20 12:43:01 +08:00
return true ;
2021-07-25 13:03:46 +08:00
}
2021-07-31 14:04:43 +08:00
void Debugger : : stop ( ) {
if ( mExecuting ) {
2021-12-25 19:22:29 +08:00
if ( mTarget ) {
mTarget - > stopDebug ( ) ;
mTarget = nullptr ;
}
2021-07-31 14:04:43 +08:00
mReader - > stopDebug ( ) ;
}
2023-02-21 09:34:40 +08:00
mCurrentSourceFile = " " ;
2021-07-31 14:04:43 +08:00
}
2021-12-25 19:22:29 +08:00
void Debugger : : cleanUpReader ( )
2021-07-25 13:03:46 +08:00
{
if ( mExecuting ) {
mExecuting = false ;
2021-07-26 00:22:08 +08:00
//stop debugger
mReader - > deleteLater ( ) ;
mReader = nullptr ;
2021-07-31 14:04:43 +08:00
2021-08-01 23:24:37 +08:00
if ( pMainWindow - > cpuDialog ( ) ! = nullptr ) {
pMainWindow - > cpuDialog ( ) - > close ( ) ;
}
2021-07-25 13:03:46 +08:00
// Free resources
2021-07-26 00:22:08 +08:00
pMainWindow - > removeActiveBreakpoints ( ) ;
2021-07-25 13:03:46 +08:00
2021-08-01 10:00:27 +08:00
pMainWindow - > txtLocals ( ) - > clear ( ) ;
2021-07-26 00:22:08 +08:00
pMainWindow - > updateAppTitle ( ) ;
2021-07-25 13:03:46 +08:00
2021-08-01 23:24:37 +08:00
pMainWindow - > updateDebugEval ( " " ) ;
2021-07-26 11:47:54 +08:00
mBacktraceModel - > clear ( ) ;
2021-07-25 13:03:46 +08:00
2021-11-25 20:26:43 +08:00
mWatchModel - > clearAllVarInfos ( ) ;
mBreakpointModel - > invalidateAllBreakpointNumbers ( ) ;
2021-08-01 12:02:28 +08:00
pMainWindow - > updateEditorActions ( ) ;
2021-07-25 13:03:46 +08:00
}
2021-07-25 00:26:13 +08:00
}
2021-11-25 09:05:45 +08:00
void Debugger : : updateRegisterNames ( const QStringList & registerNames )
{
mRegisterModel - > updateNames ( registerNames ) ;
}
void Debugger : : updateRegisterValues ( const QHash < int , QString > & values )
{
mRegisterModel - > updateValues ( values ) ;
}
2022-01-11 22:29:03 +08:00
void Debugger : : refreshAll ( )
{
refreshWatchVars ( ) ;
sendCommand ( " -stack-list-variables " , " --all-values " ) ;
if ( memoryModel ( ) - > startAddress ( ) > 0 )
2022-07-21 15:28:07 +08:00
sendCommand ( " -data-read-memory " , QString ( " %1 x 1 %2 %3 " )
. arg ( memoryModel ( ) - > startAddress ( ) )
. arg ( pSettings - > debugger ( ) . memoryViewRows ( ) )
. arg ( pSettings - > debugger ( ) . memoryViewColumns ( ) )
) ;
2022-01-11 22:29:03 +08:00
}
2022-10-16 23:10:57 +08:00
std : : shared_ptr < RegisterModel > Debugger : : registerModel ( ) const
2021-08-01 23:24:37 +08:00
{
return mRegisterModel ;
}
2022-10-16 23:10:57 +08:00
std : : shared_ptr < WatchModel > Debugger : : watchModel ( ) const
2021-08-01 01:06:43 +08:00
{
return mWatchModel ;
}
2021-11-24 17:53:25 +08:00
void Debugger : : sendCommand ( const QString & command , const QString & params , DebugCommandSource source )
2021-07-24 11:18:25 +08:00
{
if ( mExecuting & & mReader ) {
2021-11-24 17:53:25 +08:00
mReader - > postCommand ( command , params , source ) ;
2021-07-24 11:18:25 +08:00
}
}
2021-08-29 22:08:43 +08:00
bool Debugger : : commandRunning ( )
{
if ( mExecuting & & mReader ) {
return mReader - > commandRunning ( ) ;
}
return false ;
}
2021-11-24 21:22:01 +08:00
bool Debugger : : inferiorRunning ( )
{
if ( mExecuting & & mReader ) {
return mReader - > inferiorRunning ( ) ;
}
return false ;
}
2021-12-27 10:59:04 +08:00
void Debugger : : interrupt ( )
{
sendCommand ( " -exec-interrupt " , " " ) ;
}
2022-10-16 23:10:57 +08:00
bool Debugger : : isForProject ( ) const
{
return mBreakpointModel - > isForProject ( ) ;
}
void Debugger : : setIsForProject ( bool newIsForProject )
{
if ( ! executing ( ) ) {
mBreakpointModel - > setIsForProject ( newIsForProject ) ;
mWatchModel - > setIsForProject ( newIsForProject ) ;
}
}
2022-10-23 00:39:24 +08:00
void Debugger : : clearForProject ( )
{
mBreakpointModel - > clear ( true ) ;
mWatchModel - > clear ( true ) ;
}
2021-07-24 11:18:25 +08:00
void Debugger : : addBreakpoint ( int line , const Editor * editor )
{
2022-10-16 23:10:57 +08:00
addBreakpoint ( line , editor - > filename ( ) , editor - > inProject ( ) ) ;
2021-07-24 11:18:25 +08:00
}
2021-07-03 21:57:50 +08:00
2022-10-16 23:10:57 +08:00
void Debugger : : addBreakpoint ( int line , const QString & filename , bool forProject )
2021-07-24 11:18:25 +08:00
{
PBreakpoint bp = std : : make_shared < Breakpoint > ( ) ;
2021-11-20 07:53:39 +08:00
bp - > number = - 1 ;
2021-07-24 11:18:25 +08:00
bp - > line = line ;
bp - > filename = filename ;
bp - > condition = " " ;
2021-10-21 19:33:11 +08:00
bp - > enabled = true ;
2022-01-02 11:43:23 +08:00
bp - > breakpointType = BreakpointType : : Breakpoint ;
2022-10-16 23:10:57 +08:00
bp - > timestamp = QDateTime : : currentMSecsSinceEpoch ( ) ;
mBreakpointModel - > addBreakpoint ( bp , forProject ) ;
2021-07-25 13:03:46 +08:00
if ( mExecuting ) {
2023-02-21 09:34:40 +08:00
if ( forProject & & mBreakpointModel - > isForProject ( ) ) {
sendBreakpointCommand ( bp ) ;
} else if ( filename = = mCurrentSourceFile ) {
sendBreakpointCommand ( bp ) ;
}
2021-07-25 13:03:46 +08:00
}
2021-07-24 11:18:25 +08:00
}
2022-10-16 23:10:57 +08:00
void Debugger : : deleteBreakpoints ( const QString & filename , bool forProject )
2021-07-24 11:18:25 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & list = mBreakpointModel - > breakpoints ( forProject ) ;
for ( int i = list . size ( ) - 1 ; i > = 0 ; i - - ) {
PBreakpoint bp = list [ i ] ;
2021-07-24 11:18:25 +08:00
if ( bp - > filename = = filename ) {
2022-10-16 23:10:57 +08:00
mBreakpointModel - > removeBreakpoint ( i , forProject ) ;
2021-07-24 11:18:25 +08:00
}
}
}
void Debugger : : deleteBreakpoints ( const Editor * editor )
{
2022-10-16 23:10:57 +08:00
deleteBreakpoints ( editor - > filename ( ) , editor - > inProject ( ) ) ;
2021-07-24 11:18:25 +08:00
}
2022-10-16 23:10:57 +08:00
void Debugger : : deleteBreakpoints ( bool forProject )
2021-09-05 22:16:54 +08:00
{
2022-10-16 23:10:57 +08:00
mBreakpointModel - > clear ( forProject ) ;
// for (int i=mBreakpointModel->breakpoints().size()-1;i>=0;i--) {
// removeBreakpoint(i);
2023-02-22 08:59:00 +08:00
// }
}
void Debugger : : deleteInvalidProjectBreakpoints ( const QSet < QString > unitFiles )
{
for ( int i = mBreakpointModel - > breakpoints ( true ) . count ( ) - 1 ; i > = 0 ; i - - ) {
const PBreakpoint & bp = mBreakpointModel - > breakpoint ( i , true ) ;
if ( ! unitFiles . contains ( bp - > filename ) )
mBreakpointModel - > removeBreakpoint ( i , true ) ;
}
2021-09-05 22:16:54 +08:00
}
2021-07-24 11:18:25 +08:00
void Debugger : : removeBreakpoint ( int line , const Editor * editor )
{
2022-10-16 23:10:57 +08:00
removeBreakpoint ( line , editor - > filename ( ) , editor - > inProject ( ) ) ;
2021-07-24 11:18:25 +08:00
}
2022-10-16 23:10:57 +08:00
void Debugger : : removeBreakpoint ( int line , const QString & filename , bool forProject )
2021-07-24 11:18:25 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & breakpoints = mBreakpointModel - > breakpoints ( forProject ) ;
for ( int i = breakpoints . size ( ) - 1 ; i > = 0 ; i - - ) {
PBreakpoint bp = breakpoints [ i ] ;
2021-07-24 11:18:25 +08:00
if ( bp - > filename = = filename & & bp - > line = = line ) {
2022-10-16 23:10:57 +08:00
removeBreakpoint ( i , forProject ) ;
2021-07-24 11:18:25 +08:00
}
}
}
2022-10-16 23:10:57 +08:00
void Debugger : : removeBreakpoint ( int index , bool forProject )
2021-07-24 11:18:25 +08:00
{
2022-10-16 23:10:57 +08:00
sendClearBreakpointCommand ( index , forProject ) ;
mBreakpointModel - > removeBreakpoint ( index , forProject ) ;
2021-07-24 11:18:25 +08:00
}
2022-10-16 23:10:57 +08:00
PBreakpoint Debugger : : breakpointAt ( int line , const QString & filename , int * index , bool forProject )
2021-09-03 10:30:08 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & breakpoints = mBreakpointModel - > breakpoints ( forProject ) ;
for ( * index = 0 ; * index < breakpoints . count ( ) ; ( * index ) + + ) {
PBreakpoint breakpoint = breakpoints [ * index ] ;
2021-09-03 10:30:08 +08:00
if ( breakpoint - > line = = line
& & breakpoint - > filename = = filename )
return breakpoint ;
}
2022-10-16 23:10:57 +08:00
* index = - 1 ;
2021-09-03 10:30:08 +08:00
return PBreakpoint ( ) ;
}
2022-10-16 23:10:57 +08:00
PBreakpoint Debugger : : breakpointAt ( int line , const Editor * editor , int * index )
2021-09-03 10:30:08 +08:00
{
2022-10-16 23:10:57 +08:00
return breakpointAt ( line , editor - > filename ( ) , index , editor - > inProject ( ) ) ;
2021-09-03 10:30:08 +08:00
}
2022-10-16 23:10:57 +08:00
void Debugger : : setBreakPointCondition ( int index , const QString & condition , bool forProject )
2021-07-24 11:18:25 +08:00
{
2022-10-16 23:10:57 +08:00
PBreakpoint breakpoint = mBreakpointModel - > setBreakPointCondition ( index , condition , forProject ) ;
2021-07-24 11:18:25 +08:00
if ( condition . isEmpty ( ) ) {
2021-11-10 12:29:02 +08:00
sendCommand ( " -break-condition " ,
2022-03-01 08:13:51 +08:00
QString ( " %1 " ) . arg ( breakpoint - > number ) ) ;
2021-07-24 11:18:25 +08:00
} else {
2021-11-10 12:29:02 +08:00
sendCommand ( " -break-condition " ,
2022-03-01 08:13:51 +08:00
QString ( " %1 %2 " ) . arg ( breakpoint - > number ) . arg ( condition ) ) ;
2021-07-24 11:18:25 +08:00
}
2021-07-03 21:57:50 +08:00
}
2021-07-25 13:03:46 +08:00
void Debugger : : sendAllBreakpointsToDebugger ( )
{
2022-10-16 23:10:57 +08:00
for ( PBreakpoint breakpoint : mBreakpointModel - > breakpoints ( mBreakpointModel - > isForProject ( ) ) ) {
2023-02-21 09:34:40 +08:00
if ( mBreakpointModel - > isForProject ( ) ) {
sendBreakpointCommand ( breakpoint ) ;
} else if ( breakpoint - > filename = = mCurrentSourceFile ) {
sendBreakpointCommand ( breakpoint ) ;
}
2021-07-25 13:03:46 +08:00
}
}
2022-10-16 23:10:57 +08:00
void Debugger : : saveForNonproject ( const QString & filename )
{
save ( filename , QString ( ) ) ;
}
void Debugger : : saveForProject ( const QString & filename , const QString & projectFolder )
{
save ( filename , projectFolder ) ;
}
void Debugger : : loadForNonproject ( const QString & filename )
{
bool forProject = false ;
2022-10-17 23:23:05 +08:00
mLastLoadtime = 0 ;
2022-10-16 23:10:57 +08:00
PDebugConfig pConfig = load ( filename , forProject ) ;
if ( pConfig - > timestamp > 0 ) {
mBreakpointModel - > setBreakpoints ( pConfig - > breakpoints , forProject ) ;
mWatchModel - > setWatchVars ( pConfig - > watchVars , forProject ) ;
}
}
void Debugger : : loadForProject ( const QString & filename , const QString & projectFolder )
{
2022-10-17 23:23:05 +08:00
bool forProject = true ;
mProjectLastLoadtime = 0 ;
2022-10-16 23:10:57 +08:00
PDebugConfig pConfig = load ( filename , forProject ) ;
if ( pConfig - > timestamp > 0 ) {
foreach ( const PBreakpoint & breakpoint , pConfig - > breakpoints ) {
2022-11-16 09:24:42 +08:00
breakpoint - > filename = generateAbsolutePath ( projectFolder , breakpoint - > filename ) ;
2022-10-16 23:10:57 +08:00
}
mBreakpointModel - > setBreakpoints ( pConfig - > breakpoints , forProject ) ;
mWatchModel - > setWatchVars ( pConfig - > watchVars , forProject ) ;
}
}
2023-03-03 17:20:33 +08:00
void Debugger : : addWatchpoint ( const QString & expression )
{
QString s = expression . trimmed ( ) ;
if ( ! s . isEmpty ( ) ) {
sendCommand ( " -break-watch " , s , DebugCommandSource : : Other ) ;
}
}
2021-11-25 20:26:43 +08:00
void Debugger : : addWatchVar ( const QString & expression )
2021-07-26 18:22:09 +08:00
{
2021-07-31 20:19:45 +08:00
// Don't allow duplicates...
2021-11-25 20:26:43 +08:00
PWatchVar oldVar = mWatchModel - > findWatchVar ( expression ) ;
2021-07-31 20:19:45 +08:00
if ( oldVar )
return ;
2021-07-26 18:22:09 +08:00
2021-07-31 20:19:45 +08:00
PWatchVar var = std : : make_shared < WatchVar > ( ) ;
2022-10-16 23:10:57 +08:00
var - > parent = PWatchVar ( ) ;
2021-11-25 20:26:43 +08:00
var - > expression = expression ;
2021-09-19 09:45:03 +08:00
var - > value = tr ( " Execute to evaluate " ) ;
2021-11-25 11:24:38 +08:00
var - > numChild = 0 ;
var - > hasMore = false ;
2022-10-16 23:10:57 +08:00
var - > timestamp = QDateTime : : currentMSecsSinceEpoch ( ) ;
2021-07-26 18:22:09 +08:00
2022-10-17 23:23:05 +08:00
addWatchVar ( var , isForProject ( ) ) ;
2021-07-26 18:22:09 +08:00
}
2021-11-25 20:26:43 +08:00
void Debugger : : modifyWatchVarExpression ( const QString & oldExpr , const QString & newExpr )
2021-07-26 18:22:09 +08:00
{
2021-07-31 20:19:45 +08:00
// check if name already exists;
2021-11-25 20:26:43 +08:00
PWatchVar var = mWatchModel - > findWatchVar ( newExpr ) ;
2021-07-31 20:19:45 +08:00
if ( var )
return ;
2021-11-25 20:26:43 +08:00
var = mWatchModel - > findWatchVar ( oldExpr ) ;
2021-07-31 20:19:45 +08:00
if ( var ) {
2021-11-25 20:26:43 +08:00
if ( mExecuting & & ! var - > expression . isEmpty ( ) )
2021-08-01 01:06:43 +08:00
sendRemoveWatchCommand ( var ) ;
2021-11-25 20:26:43 +08:00
var - > expression = newExpr ;
var - > type . clear ( ) ;
var - > value . clear ( ) ;
var - > hasMore = false ;
var - > numChild = 0 ;
var - > name . clear ( ) ;
var - > children . clear ( ) ;
2021-07-31 20:19:45 +08:00
if ( mExecuting ) {
sendWatchCommand ( var ) ;
}
}
2021-07-26 18:22:09 +08:00
}
void Debugger : : refreshWatchVars ( )
{
2021-11-25 20:26:43 +08:00
if ( mExecuting ) {
sendAllWatchVarsToDebugger ( ) ;
2023-01-22 22:19:19 +08:00
if ( mDebuggerType = = DebuggerType : : LLDB_MI ) {
for ( PWatchVar var : mWatchModel - > watchVars ( ) ) {
if ( ! var - > name . isEmpty ( ) )
sendCommand ( " -var-update " , QString ( " --all-values %1 " ) . arg ( var - > name ) ) ;
}
} else {
sendCommand ( " -var-update " , " --all-values * " ) ;
}
2021-11-25 20:26:43 +08:00
}
}
void Debugger : : fetchVarChildren ( const QString & varName )
{
if ( mExecuting ) {
sendCommand ( " -var-list-children " , varName ) ;
2021-07-31 20:19:45 +08:00
}
2021-07-26 18:22:09 +08:00
}
2023-06-27 11:50:43 +08:00
bool Debugger : : debugInfosUsingUTF8 ( ) const
{
return mDebugInfosUsingUTF8 ;
}
void Debugger : : setDebugInfosUsingUTF8 ( bool newDebugInfosUsingUTF8 )
{
mDebugInfosUsingUTF8 = newDebugInfosUsingUTF8 ;
}
2023-01-22 22:19:19 +08:00
DebuggerType Debugger : : debuggerType ( ) const
{
return mDebuggerType ;
}
void Debugger : : setDebuggerType ( DebuggerType newDebuggerType )
{
mDebuggerType = newDebuggerType ;
}
2022-05-15 17:14:22 +08:00
bool Debugger : : forceUTF8 ( ) const
{
return mForceUTF8 ;
}
void Debugger : : setForceUTF8 ( bool newForceUTF8 )
{
mForceUTF8 = newForceUTF8 ;
}
2022-10-16 23:10:57 +08:00
std : : shared_ptr < MemoryModel > Debugger : : memoryModel ( ) const
2022-01-11 22:29:03 +08:00
{
return mMemoryModel ;
}
2021-08-31 11:13:12 +08:00
void Debugger : : removeWatchVars ( bool deleteparent )
2021-07-26 18:22:09 +08:00
{
2021-07-31 20:19:45 +08:00
if ( deleteparent ) {
mWatchModel - > clear ( ) ;
} else {
2021-08-31 11:13:12 +08:00
for ( const PWatchVar & var : mWatchModel - > watchVars ( ) ) {
2021-07-31 20:19:45 +08:00
sendRemoveWatchCommand ( var ) ;
}
2021-11-25 20:26:43 +08:00
mWatchModel - > clearAllVarInfos ( ) ;
2021-07-31 20:19:45 +08:00
}
2021-07-26 18:22:09 +08:00
}
2021-08-31 11:13:12 +08:00
void Debugger : : removeWatchVar ( const QModelIndex & index )
{
2021-11-25 20:26:43 +08:00
PWatchVar var = mWatchModel - > findWatchVar ( index ) ;
if ( ! var )
return ;
sendRemoveWatchCommand ( var ) ;
2021-08-31 11:13:12 +08:00
mWatchModel - > removeWatchVar ( index ) ;
}
2021-11-25 20:26:43 +08:00
void Debugger : : sendAllWatchVarsToDebugger ( )
2021-07-26 18:22:09 +08:00
{
2021-07-31 20:19:45 +08:00
for ( PWatchVar var : mWatchModel - > watchVars ( ) ) {
2021-11-25 20:26:43 +08:00
if ( var - > name . isEmpty ( ) )
sendWatchCommand ( var ) ;
2021-09-19 01:58:09 +08:00
}
2021-08-01 01:06:43 +08:00
}
2021-11-25 20:26:43 +08:00
PWatchVar Debugger : : findWatchVar ( const QString & expression )
2021-08-01 01:06:43 +08:00
{
2021-11-25 20:26:43 +08:00
return mWatchModel - > findWatchVar ( expression ) ;
2021-08-01 01:06:43 +08:00
}
2022-05-30 16:40:45 +08:00
PWatchVar Debugger : : watchVarAt ( const QModelIndex & index )
{
return mWatchModel - > findWatchVar ( index ) ;
}
2021-09-19 02:00:25 +08:00
//void Debugger::notifyWatchVarUpdated(PWatchVar var)
//{
// mWatchModel->notifyUpdated(var);
//}
2022-10-16 23:10:57 +08:00
std : : shared_ptr < BacktraceModel > Debugger : : backtraceModel ( )
2021-07-24 08:12:51 +08:00
{
return mBacktraceModel ;
}
2022-10-16 23:10:57 +08:00
std : : shared_ptr < BreakpointModel > Debugger : : breakpointModel ( )
2021-07-24 11:18:25 +08:00
{
return mBreakpointModel ;
}
2021-07-31 20:19:45 +08:00
void Debugger : : sendWatchCommand ( PWatchVar var )
2021-07-24 11:18:25 +08:00
{
2021-11-25 20:26:43 +08:00
sendCommand ( " -var-create " , var - > expression ) ;
2021-07-31 20:19:45 +08:00
}
void Debugger : : sendRemoveWatchCommand ( PWatchVar var )
{
2021-11-25 11:24:38 +08:00
sendCommand ( " -var-delete " , QString ( " %1 " ) . arg ( var - > name ) ) ;
2021-07-25 13:03:46 +08:00
}
void Debugger : : sendBreakpointCommand ( PBreakpoint breakpoint )
{
if ( breakpoint & & mExecuting ) {
// break "filename":linenum
QString condition ;
if ( ! breakpoint - > condition . isEmpty ( ) ) {
2021-11-10 12:29:02 +08:00
condition = " -c " + breakpoint - > condition ;
2021-07-25 13:03:46 +08:00
}
QString filename = breakpoint - > filename ;
filename . replace ( ' \\ ' , ' / ' ) ;
2023-01-22 22:19:19 +08:00
if ( debuggerType ( ) = = DebuggerType : : LLDB_MI ) {
sendCommand ( " -break-insert " ,
QString ( " %1 \" %2:%3 \" " )
. arg ( condition , filename )
. arg ( breakpoint - > line ) ) ;
} else {
2023-01-26 11:07:46 +08:00
sendCommand ( " -break-insert " ,
QString ( " %1 --source \" %2 \" --line %3 " )
. arg ( condition , filename )
. arg ( breakpoint - > line ) ) ;
2023-01-22 22:19:19 +08:00
}
2021-07-24 11:18:25 +08:00
}
}
2022-10-16 23:10:57 +08:00
void Debugger : : sendClearBreakpointCommand ( int index , bool forProject )
2021-07-25 13:03:46 +08:00
{
2022-10-16 23:10:57 +08:00
sendClearBreakpointCommand ( mBreakpointModel - > breakpoints ( forProject ) [ index ] ) ;
2021-07-25 13:03:46 +08:00
}
void Debugger : : sendClearBreakpointCommand ( PBreakpoint breakpoint )
2021-07-24 11:18:25 +08:00
{
// Debugger already running? Remove it from GDB
2021-11-20 07:53:39 +08:00
if ( breakpoint & & breakpoint - > number > = 0 & & mExecuting ) {
2021-07-24 11:18:25 +08:00
//clear "filename":linenum
QString filename = breakpoint - > filename ;
filename . replace ( ' \\ ' , ' / ' ) ;
2021-11-20 07:53:39 +08:00
sendCommand ( " -break-delete " ,
QString ( " %1 " ) . arg ( breakpoint - > number ) ) ;
2021-07-24 11:18:25 +08:00
}
}
2022-10-16 23:10:57 +08:00
QJsonArray BreakpointModel : : toJson ( const QString & projectFolder )
{
bool forProject = ! projectFolder . isEmpty ( ) ;
QJsonArray array ;
foreach ( const PBreakpoint & breakpoint , breakpoints ( forProject ) ) {
QJsonObject obj ;
if ( forProject )
obj [ " filename " ] = extractRelativePath ( projectFolder , breakpoint - > filename ) ;
else
obj [ " filename " ] = breakpoint - > filename ;
obj [ " line " ] = breakpoint - > line ;
obj [ " condition " ] = breakpoint - > condition ;
obj [ " enabled " ] = breakpoint - > enabled ;
obj [ " breakpoint_type " ] = static_cast < int > ( breakpoint - > breakpointType ) ;
obj [ " timestamp " ] = QString ( " %1 " ) . arg ( breakpoint - > timestamp ) ;
array . append ( obj ) ;
}
return array ;
}
void BreakpointModel : : setBreakpoints ( const QList < PBreakpoint > & list , bool forProject )
{
if ( mIsForProject = = forProject )
beginResetModel ( ) ;
if ( forProject ) {
mProjectBreakpoints = list ;
} else {
mBreakpoints = list ;
}
if ( mIsForProject = = forProject )
endResetModel ( ) ;
}
void Debugger : : save ( const QString & filename , const QString & projectFolder )
{
bool forProject = ! projectFolder . isEmpty ( ) ;
QList < PBreakpoint > breakpoints ;
QList < PWatchVar > watchVars = mWatchModel - > watchVars ( forProject ) ;
QSet < QString > breakpointCompareSet ;
QSet < QString > watchVarCompareSet ;
if ( forProject ) {
//convert project file's absolute path to relative path
foreach ( const PBreakpoint & breakpoint , mBreakpointModel - > breakpoints ( forProject ) ) {
QString filename = extractRelativePath ( projectFolder , breakpoint - > filename ) ;
QString key = QString ( " %1-%2 " ) . arg ( filename ) . arg ( breakpoint - > line ) ;
breakpointCompareSet . insert ( key ) ;
}
} else {
foreach ( const PBreakpoint & breakpoint , mBreakpointModel - > breakpoints ( forProject ) ) {
QString key = QString ( " %1-%2 " ) . arg ( breakpoint - > filename ) . arg ( breakpoint - > line ) ;
breakpointCompareSet . insert ( key ) ;
}
}
foreach ( const PWatchVar & watchVar , watchVars ) {
watchVarCompareSet . insert ( watchVar - > expression ) ;
}
2023-04-25 19:28:17 +08:00
std : : shared_ptr < DebugConfig > pConfig ;
try {
pConfig = load ( filename , forProject ) ;
} catch ( FileError & e ) {
}
2022-10-16 23:10:57 +08:00
QFile file ( filename ) ;
if ( file . open ( QFile : : WriteOnly | QFile : : Truncate ) ) {
foreach ( const PBreakpoint & breakpoint , pConfig - > breakpoints ) {
QString key = QString ( " %1-%2 " ) . arg ( breakpoint - > filename ) . arg ( breakpoint - > line ) ;
if ( ! breakpointCompareSet . contains ( key ) ) {
breakpointCompareSet . insert ( key ) ;
if ( forProject )
2022-11-16 09:24:42 +08:00
breakpoint - > filename = generateAbsolutePath ( projectFolder , breakpoint - > filename ) ;
2022-10-16 23:10:57 +08:00
mBreakpointModel - > addBreakpoint ( breakpoint , forProject ) ;
}
}
foreach ( const PWatchVar & watchVar , pConfig - > watchVars ) {
QString key = watchVar - > expression ;
if ( ! watchVarCompareSet . contains ( key ) ) {
watchVarCompareSet . insert ( key ) ;
2022-10-17 23:23:05 +08:00
addWatchVar ( watchVar , forProject ) ;
2022-10-16 23:10:57 +08:00
}
}
qint64 saveTimestamp = QDateTime : : currentMSecsSinceEpoch ( ) ; ;
if ( forProject ) {
mProjectLastLoadtime = saveTimestamp ;
} else {
mLastLoadtime = saveTimestamp ;
}
QJsonObject rootObj ;
rootObj [ " timestamp " ] = QString ( " %1 " ) . arg ( saveTimestamp ) ;
2023-02-21 09:34:40 +08:00
if ( forProject ) {
rootObj [ " breakpoints " ] = mBreakpointModel - > toJson ( projectFolder ) ;
}
2022-10-16 23:10:57 +08:00
rootObj [ " watchvars " ] = mWatchModel - > toJson ( forProject ) ;
QJsonDocument doc ;
doc . setObject ( rootObj ) ;
if ( file . write ( doc . toJson ( ) ) < 0 ) {
throw FileError ( tr ( " Save file '%1' failed. " )
. arg ( filename ) ) ;
}
} else {
throw FileError ( tr ( " Can't open file '%1' for write. " )
. arg ( filename ) ) ;
}
}
PDebugConfig Debugger : : load ( const QString & filename , bool forProject )
{
qint64 criteriaTimestamp ;
if ( forProject ) {
criteriaTimestamp = mProjectLastLoadtime ;
} else {
criteriaTimestamp = mLastLoadtime ;
}
std : : shared_ptr < DebugConfig > pConfig = std : : make_shared < DebugConfig > ( ) ;
pConfig - > timestamp = 0 ;
QFile file ( filename ) ;
if ( ! file . exists ( ) )
return pConfig ;
if ( file . open ( QFile : : ReadOnly ) ) {
2023-05-29 10:52:17 +08:00
QByteArray content = file . readAll ( ) . trimmed ( ) ;
if ( content . isEmpty ( ) )
return pConfig ;
QJsonParseError error ;
2022-10-16 23:10:57 +08:00
QJsonDocument doc ( QJsonDocument : : fromJson ( content , & error ) ) ;
2023-05-29 12:07:27 +08:00
if ( error . error ! = QJsonParseError : : NoError ) {
2022-10-16 23:10:57 +08:00
throw FileError ( tr ( " Error in json file '%1':%2 : %3 " )
. arg ( filename )
. arg ( error . offset )
. arg ( error . errorString ( ) ) ) ;
}
QJsonObject rootObject = doc . object ( ) ;
qint64 timestamp = rootObject [ " timestamp " ] . toString ( ) . toLongLong ( ) ;
if ( timestamp < = criteriaTimestamp )
return pConfig ;
pConfig - > timestamp = timestamp ;
pConfig - > breakpoints = mBreakpointModel - > loadJson ( rootObject [ " breakpoints " ] . toArray ( ) , criteriaTimestamp ) ;
pConfig - > watchVars = mWatchModel - > loadJson ( rootObject [ " watchvars " ] . toArray ( ) , criteriaTimestamp ) ;
if ( forProject ) {
mProjectLastLoadtime = QDateTime : : currentMSecsSinceEpoch ( ) ;
} else {
mLastLoadtime = QDateTime : : currentMSecsSinceEpoch ( ) ;
}
} else {
throw FileError ( tr ( " Can't open file '%1' for read. " )
. arg ( filename ) ) ;
}
return pConfig ;
}
2022-10-17 23:23:05 +08:00
void Debugger : : addWatchVar ( const PWatchVar & watchVar , bool forProject )
{
mWatchModel - > addWatchVar ( watchVar , forProject ) ;
if ( forProject = = isForProject ( ) )
sendWatchCommand ( watchVar ) ;
}
2021-07-26 11:47:54 +08:00
void Debugger : : syncFinishedParsing ( )
{
bool spawnedcpuform = false ;
// GDB determined that the source code is more recent than the executable. Ask the user if he wants to rebuild.
2021-11-24 10:07:35 +08:00
if ( mReader - > receivedSFWarning ( ) ) {
2021-07-26 11:47:54 +08:00
if ( QMessageBox : : question ( pMainWindow ,
tr ( " Compile " ) ,
tr ( " Source file is more recent than executable. " ) + " <BR /><BR /> " + tr ( " Recompile? " ) ,
QMessageBox : : Yes | QMessageBox : : No ,
QMessageBox : : Yes
) = = QMessageBox : : Yes ) {
stop ( ) ;
pMainWindow - > compile ( ) ;
return ;
}
}
// show command output
2021-11-25 10:18:21 +08:00
if ( pSettings - > debugger ( ) . enableDebugConsole ( ) ) {
if ( pSettings - > debugger ( ) . showDetailLog ( ) ) {
2021-11-24 17:53:25 +08:00
for ( const QString & line : mReader - > fullOutput ( ) ) {
pMainWindow - > addDebugOutput ( line ) ;
2021-07-26 11:47:54 +08:00
}
2021-11-24 17:53:25 +08:00
} else {
2021-11-25 23:41:40 +08:00
if ( mReader - > currentCmd ( ) & & mReader - > currentCmd ( ) - > command = = " disas " ) {
} else {
for ( const QString & line : mReader - > consoleOutput ( ) ) {
pMainWindow - > addDebugOutput ( line ) ;
}
if (
( mReader - > currentCmd ( )
& & mReader - > currentCmd ( ) - > source = = DebugCommandSource : : Console )
| | ! mReader - > consoleOutput ( ) . isEmpty ( ) ) {
pMainWindow - > addDebugOutput ( " (gdb) " ) ;
}
2021-07-26 11:47:54 +08:00
}
}
}
2021-11-24 21:22:01 +08:00
// The program to debug has stopped. Stop the debugger
if ( mReader - > processExited ( ) ) {
stop ( ) ;
return ;
}
2021-12-27 10:59:04 +08:00
if ( mReader - > signalReceived ( )
& & mReader - > signalName ( ) ! = " SIGINT "
& & mReader - > signalName ( ) ! = " SIGTRAP " ) {
2021-11-25 09:05:45 +08:00
SignalMessageDialog dialog ( pMainWindow ) ;
2021-11-25 10:18:21 +08:00
dialog . setOpenCPUInfo ( pSettings - > debugger ( ) . openCPUInfoWhenSignaled ( ) ) ;
2021-11-25 09:05:45 +08:00
dialog . setMessage (
tr ( " Signal \" %1 \" Received: " ) . arg ( mReader - > signalName ( ) )
+ " <br /> "
+ mReader - > signalMeaning ( ) ) ;
int result = dialog . exec ( ) ;
if ( result = = QDialog : : Accepted & & dialog . openCPUInfo ( ) ) {
pMainWindow - > showCPUInfoDialog ( ) ;
}
2021-07-26 11:47:54 +08:00
}
// CPU form updates itself when spawned, don't update twice!
2021-11-23 21:08:33 +08:00
if ( ( mReader - > updateCPUInfo ( ) & & ! spawnedcpuform ) & & ( pMainWindow - > cpuDialog ( ) ! = nullptr ) ) {
2021-08-01 23:24:37 +08:00
pMainWindow - > cpuDialog ( ) - > updateInfo ( ) ;
2021-07-26 11:47:54 +08:00
}
}
2022-01-11 22:29:03 +08:00
void Debugger : : setMemoryData ( qulonglong address , unsigned char data )
{
sendCommand ( " -data-write-memory-bytes " , QString ( " %1 \" %2 \" " ) . arg ( address ) . arg ( data , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
refreshAll ( ) ;
}
2022-01-12 17:14:39 +08:00
void Debugger : : setWatchVarValue ( const QString & name , const QString & value )
{
sendCommand ( " -var-assign " , QString ( " %1 %2 " ) . arg ( name , value ) ) ;
refreshAll ( ) ;
}
2021-11-25 07:42:56 +08:00
void Debugger : : updateMemory ( const QStringList & value )
{
2022-01-11 22:29:03 +08:00
mMemoryModel - > updateMemory ( value ) ;
2021-11-25 07:42:56 +08:00
emit memoryExamineReady ( value ) ;
}
void Debugger : : updateEval ( const QString & value )
{
emit evalValueReady ( value ) ;
}
void Debugger : : updateDisassembly ( const QString & file , const QString & func , const QStringList & value )
2021-11-24 23:32:34 +08:00
{
if ( pMainWindow - > cpuDialog ( ) ) {
2023-03-03 17:20:33 +08:00
pMainWindow - > cpuDialog ( ) - > setDisassembly ( file , func , value , mBacktraceModel - > backtraces ( ) ) ;
2021-11-24 23:32:34 +08:00
}
}
2021-11-24 10:07:35 +08:00
void Debugger : : onChangeDebugConsoleLastline ( const QString & text )
2021-07-30 23:28:58 +08:00
{
//pMainWindow->changeDebugOutputLastline(text);
pMainWindow - > addDebugOutput ( text ) ;
}
2021-07-26 18:22:09 +08:00
int Debugger : : leftPageIndexBackup ( ) const
{
return mLeftPageIndexBackup ;
}
void Debugger : : setLeftPageIndexBackup ( int leftPageIndexBackup )
{
mLeftPageIndexBackup = leftPageIndexBackup ;
}
2021-07-26 11:47:54 +08:00
bool Debugger : : executing ( ) const
{
return mExecuting ;
}
2021-07-27 00:14:24 +08:00
DebugReader : : DebugReader ( Debugger * debugger , QObject * parent ) : QThread ( parent ) ,
2022-11-10 09:05:34 +08:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
mCmdQueueMutex ( ) ,
# else
2022-01-04 16:50:54 +08:00
mCmdQueueMutex ( QMutex : : Recursive ) ,
2022-11-10 09:05:34 +08:00
# endif
2021-07-27 00:14:24 +08:00
mStartSemaphore ( 0 )
2021-07-03 21:57:50 +08:00
{
2021-07-25 00:26:13 +08:00
mDebugger = debugger ;
2021-12-25 20:02:53 +08:00
mProcess = std : : make_shared < QProcess > ( ) ;
2021-07-31 20:19:45 +08:00
mCmdRunning = false ;
2021-12-27 21:32:30 +08:00
mAsyncUpdated = false ;
2021-07-03 21:57:50 +08:00
}
2021-11-24 17:53:25 +08:00
void DebugReader : : postCommand ( const QString & Command , const QString & Params ,
DebugCommandSource Source )
2021-07-19 23:02:32 +08:00
{
QMutexLocker locker ( & mCmdQueueMutex ) ;
PDebugCommand pCmd = std : : make_shared < DebugCommand > ( ) ;
pCmd - > command = Command ;
pCmd - > params = Params ;
pCmd - > source = Source ;
mCmdQueue . enqueue ( pCmd ) ;
2021-07-30 23:28:58 +08:00
// if (!mCmdRunning)
2021-11-24 17:53:25 +08:00
// runNextCmd();
2021-07-19 23:02:32 +08:00
}
2021-11-24 17:53:25 +08:00
void DebugReader : : registerInferiorStoppedCommand ( const QString & Command , const QString & Params )
2021-07-03 21:57:50 +08:00
{
2021-07-19 23:02:32 +08:00
QMutexLocker locker ( & mCmdQueueMutex ) ;
2021-11-24 17:53:25 +08:00
PDebugCommand pCmd = std : : make_shared < DebugCommand > ( ) ;
pCmd - > command = Command ;
pCmd - > params = Params ;
pCmd - > source = DebugCommandSource : : Other ;
mInferiorStoppedHookCommands . append ( pCmd ) ;
2021-07-18 00:18:07 +08:00
}
2021-11-24 17:53:25 +08:00
void DebugReader : : clearCmdQueue ( )
2021-07-18 00:18:07 +08:00
{
2021-11-24 17:53:25 +08:00
QMutexLocker locker ( & mCmdQueueMutex ) ;
mCmdQueue . clear ( ) ;
2021-07-18 00:18:07 +08:00
}
2021-11-12 10:51:00 +08:00
void DebugReader : : processConsoleOutput ( const QByteArray & line )
2021-07-18 00:18:07 +08:00
{
2021-11-10 17:05:37 +08:00
if ( line . length ( ) > 3 & & line . startsWith ( " ~ \" " ) & & line . endsWith ( " \" " ) ) {
2021-11-24 23:32:34 +08:00
QByteArray s = line . mid ( 2 , line . length ( ) - 3 ) ;
QByteArray stringValue ;
const char * p = s . data ( ) ;
while ( * p ! = 0 ) {
if ( * p = = ' \\ ' & & * ( p + 1 ) ! = 0 ) {
p + + ;
switch ( * p ) {
case ' \' ' :
stringValue + = 0x27 ;
p + + ;
break ;
case ' " ' :
stringValue + = 0x22 ;
p + + ;
break ;
case ' ? ' :
stringValue + = 0x3f ;
p + + ;
break ;
case ' \\ ' :
stringValue + = 0x5c ;
p + + ;
break ;
case ' a ' :
stringValue + = 0x07 ;
p + + ;
break ;
case ' b ' :
stringValue + = 0x08 ;
p + + ;
break ;
case ' f ' :
stringValue + = 0x0c ;
p + + ;
break ;
case ' n ' :
stringValue + = 0x0a ;
p + + ;
break ;
case ' r ' :
stringValue + = 0x0d ;
p + + ;
break ;
case ' t ' :
stringValue + = 0x09 ;
p + + ;
break ;
case ' v ' :
stringValue + = 0x0b ;
p + + ;
break ;
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
{
int i = 0 ;
for ( i = 0 ; i < 3 ; i + + ) {
if ( * ( p + i ) < ' 0 ' | | * ( p + i ) > ' 7 ' )
break ;
}
QByteArray numStr ( p , i ) ;
bool ok ;
unsigned char ch = numStr . toInt ( & ok , 8 ) ;
stringValue + = ch ;
p + = i ;
break ;
}
}
} else {
stringValue + = * p ;
p + + ;
}
}
2023-03-09 16:09:05 +08:00
//mConsoleOutput.append(QString::fromLocal8Bit(stringValue));
mConsoleOutput . append ( QString : : fromUtf8 ( stringValue ) ) ;
2021-11-10 17:05:37 +08:00
}
}
2023-07-02 11:09:34 +08:00
void DebugReader : : processLogOutput ( const QByteArray & line )
{
if ( mDebugger - > debugInfosUsingUTF8 ( ) & & line . endsWith ( " : No such file or directory. \n \" " ) ) {
QByteArray newLine = line ;
newLine [ 0 ] = ' ~ ' ;
int p = newLine . lastIndexOf ( ' : ' ) ;
if ( p > 0 ) {
newLine = newLine . left ( p ) ;
qDebug ( ) < < newLine ;
processConsoleOutput ( newLine ) ;
}
}
}
2021-11-12 10:51:00 +08:00
void DebugReader : : processResult ( const QByteArray & result )
2021-11-10 17:05:37 +08:00
{
2021-11-20 07:53:39 +08:00
GDBMIResultParser parser ;
GDBMIResultType resultType ;
2021-11-24 22:16:40 +08:00
GDBMIResultParser : : ParseObject multiValues ;
if ( ! mCurrentCmd )
return ;
bool parseOk = parser . parse ( result , mCurrentCmd - > command , resultType , multiValues ) ;
2021-11-20 07:53:39 +08:00
if ( ! parseOk )
return ;
switch ( resultType ) {
2021-11-23 21:08:33 +08:00
case GDBMIResultType : : BreakpointTable :
case GDBMIResultType : : Locals :
break ;
2021-11-20 07:53:39 +08:00
case GDBMIResultType : : Breakpoint :
2021-11-24 22:16:40 +08:00
handleBreakpoint ( multiValues [ " bkpt " ] . object ( ) ) ;
2021-11-20 07:53:39 +08:00
return ;
2023-03-03 17:20:33 +08:00
case GDBMIResultType : : Frame :
handleFrame ( multiValues [ " frame " ] ) ;
return ;
2021-11-23 21:08:33 +08:00
case GDBMIResultType : : FrameStack :
2021-11-24 22:16:40 +08:00
handleStack ( multiValues [ " stack " ] . array ( ) ) ;
2021-11-23 21:08:33 +08:00
return ;
case GDBMIResultType : : LocalVariables :
2021-11-24 22:16:40 +08:00
handleLocalVariables ( multiValues [ " variables " ] . array ( ) ) ;
2021-11-23 21:08:33 +08:00
return ;
case GDBMIResultType : : Evaluation :
2021-11-24 22:16:40 +08:00
handleEvaluation ( multiValues [ " value " ] . value ( ) ) ;
return ;
case GDBMIResultType : : Memory :
handleMemory ( multiValues [ " memory " ] . array ( ) ) ;
2021-11-23 21:08:33 +08:00
return ;
2021-11-25 09:05:45 +08:00
case GDBMIResultType : : RegisterNames :
handleRegisterNames ( multiValues [ " register-names " ] . array ( ) ) ;
return ;
case GDBMIResultType : : RegisterValues :
handleRegisterValue ( multiValues [ " register-values " ] . array ( ) ) ;
return ;
2021-11-25 20:26:43 +08:00
case GDBMIResultType : : CreateVar :
handleCreateVar ( multiValues ) ;
return ;
case GDBMIResultType : : ListVarChildren :
handleListVarChildren ( multiValues ) ;
return ;
case GDBMIResultType : : UpdateVarValue :
handleUpdateVarValue ( multiValues [ " changelist " ] . array ( ) ) ;
return ;
2022-07-04 11:39:06 +08:00
default :
return ;
2021-11-20 07:53:39 +08:00
}
2021-11-10 17:05:37 +08:00
}
2021-11-21 10:36:50 +08:00
void DebugReader : : processExecAsyncRecord ( const QByteArray & line )
2021-11-10 17:05:37 +08:00
{
2021-11-21 10:36:50 +08:00
QByteArray result ;
GDBMIResultParser : : ParseObject multiValues ;
GDBMIResultParser parser ;
if ( ! parser . parseAsyncResult ( line , result , multiValues ) )
return ;
if ( result = = " running " ) {
2021-11-24 10:07:35 +08:00
mInferiorRunning = true ;
2021-11-24 17:53:25 +08:00
mCurrentAddress = 0 ;
mCurrentFile . clear ( ) ;
mCurrentLine = - 1 ;
2021-11-25 07:42:56 +08:00
mCurrentFunc . clear ( ) ;
2021-11-24 10:07:35 +08:00
emit inferiorContinued ( ) ;
2021-11-10 17:05:37 +08:00
return ;
}
2021-11-24 17:53:25 +08:00
if ( result = = " stopped " ) {
2021-11-24 10:07:35 +08:00
mInferiorRunning = false ;
2021-11-21 10:36:50 +08:00
QByteArray reason = multiValues [ " reason " ] . value ( ) ;
if ( reason = = " exited " ) {
//inferior exited, gdb should terminate too
mProcessExited = true ;
2021-11-10 17:05:37 +08:00
return ;
2021-11-21 10:36:50 +08:00
}
if ( reason = = " exited-normally " ) {
2021-11-10 17:05:37 +08:00
//inferior exited, gdb should terminate too
mProcessExited = true ;
return ;
}
2021-11-24 10:07:35 +08:00
if ( reason = = " exited-signalled " ) {
//inferior exited, gdb should terminate too
mProcessExited = true ;
mSignalReceived = true ;
return ;
}
2021-11-23 21:08:33 +08:00
mUpdateCPUInfo = true ;
2023-03-03 17:20:33 +08:00
handleFrame ( multiValues [ " frame " ] ) ;
2021-11-21 10:36:50 +08:00
if ( reason = = " signal-received " ) {
2021-11-23 21:08:33 +08:00
mSignalReceived = true ;
2021-11-25 09:05:45 +08:00
mSignalName = multiValues [ " signal-name " ] . value ( ) ;
mSignalMeaning = multiValues [ " signal-meaning " ] . value ( ) ;
2023-03-03 17:20:33 +08:00
} else if ( reason = = " watchpoint-trigger " ) {
QString var , oldVal , newVal ;
GDBMIResultParser : : ParseValue wpt = multiValues [ " wpt " ] ;
if ( wpt . isValid ( ) ) {
GDBMIResultParser : : ParseObject wptObj = wpt . object ( ) ;
var = wptObj [ " exp " ] . value ( ) ;
}
GDBMIResultParser : : ParseValue varValue = multiValues [ " value " ] ;
if ( varValue . isValid ( ) ) {
GDBMIResultParser : : ParseObject valueObj = varValue . object ( ) ;
oldVal = valueObj [ " old " ] . value ( ) ;
newVal = valueObj [ " new " ] . value ( ) ;
}
if ( ! var . isEmpty ( ) ) {
emit watchpointHitted ( var , oldVal , newVal ) ;
}
2021-11-10 17:05:37 +08:00
}
2021-11-24 17:53:25 +08:00
runInferiorStoppedHook ( ) ;
2023-03-08 18:31:47 +08:00
if ( reason . isEmpty ( ) ) {
QMutexLocker locker ( & mCmdQueueMutex ) ;
foreach ( const PDebugCommand & cmd , mCmdQueue ) {
//gdb-server connected, just ignore it
if ( cmd - > command = = " -exec-continue " )
return ;
}
2023-03-08 18:01:10 +08:00
}
2021-11-24 17:53:25 +08:00
if ( mCurrentCmd & & mCurrentCmd - > source = = DebugCommandSource : : Console )
2023-03-03 17:20:33 +08:00
emit inferiorStopped ( mCurrentFile , mCurrentLine , false ) ;
2021-11-24 17:53:25 +08:00
else
2023-03-03 17:20:33 +08:00
emit inferiorStopped ( mCurrentFile , mCurrentLine , true ) ;
2021-11-10 17:05:37 +08:00
}
}
2021-11-12 10:51:00 +08:00
void DebugReader : : processError ( const QByteArray & errorLine )
2021-11-10 17:05:37 +08:00
{
2023-02-18 12:08:03 +08:00
QString s = QString : : fromLocal8Bit ( errorLine ) ;
mConsoleOutput . append ( s ) ;
int idx = s . indexOf ( " ,msg= \" No symbol table is loaded " ) ;
if ( idx > 0 ) {
emit errorNoSymbolTable ( ) ;
return ;
}
2021-07-18 00:18:07 +08:00
}
2023-07-02 11:09:34 +08:00
static QRegularExpression reGdbSourceLine ( " ^( \\ d) + \ \ s + in \ \ s + ( . + ) $ " ) ;
2021-07-18 00:18:07 +08:00
2021-11-12 10:51:00 +08:00
void DebugReader : : processResultRecord ( const QByteArray & line )
2021-11-10 12:57:18 +08:00
{
if ( line . startsWith ( " ^exit " ) ) {
2021-11-10 17:05:37 +08:00
mProcessExited = true ;
return ;
}
if ( line . startsWith ( " ^error " ) ) {
processError ( line ) ;
return ;
}
if ( line . startsWith ( " ^done " )
| | line . startsWith ( " ^running " ) ) {
int pos = line . indexOf ( ' , ' ) ;
if ( pos > = 0 ) {
2021-11-12 10:51:00 +08:00
QByteArray result = line . mid ( pos + 1 ) ;
2021-11-10 17:05:37 +08:00
processResult ( result ) ;
2021-11-24 23:32:34 +08:00
} else if ( mCurrentCmd & & ! ( mCurrentCmd - > command . startsWith ( ' - ' ) ) ) {
if ( mCurrentCmd - > command = = " disas " ) {
2023-03-09 16:09:05 +08:00
QStringList disOutput = mConsoleOutput ;
2021-11-25 07:42:56 +08:00
if ( disOutput . length ( ) > = 3 ) {
2021-11-24 23:32:34 +08:00
disOutput . pop_back ( ) ;
disOutput . pop_front ( ) ;
2021-11-25 07:42:56 +08:00
disOutput . pop_front ( ) ;
2021-11-24 23:32:34 +08:00
}
2023-07-02 11:09:34 +08:00
if ( mDebugger - > debugInfosUsingUTF8 ( ) ) {
QStringList newOutput ;
foreach ( const QString & s , disOutput ) {
QString line = s ;
if ( ! s . isEmpty ( ) & & s . front ( ) . isDigit ( ) ) {
QRegularExpressionMatch match = reGdbSourceLine . match ( s ) ;
// qDebug()<<s;
if ( match . hasMatch ( ) ) {
bool isOk ;
int lineno = match . captured ( 1 ) . toInt ( & isOk ) - 1 ; ;
QString filename = match . captured ( 2 ) . trimmed ( ) ;
if ( isOk & & fileExists ( filename ) ) {
QStringList contents ;
if ( mFileCache . contains ( filename ) )
contents = mFileCache . value ( filename ) ;
else {
if ( ! pMainWindow - > editorList ( ) - > getContentFromOpenedEditor ( filename , contents ) )
contents = readFileToLines ( filename ) ;
mFileCache [ filename ] = contents ;
}
if ( lineno > = 0 & & lineno < contents . size ( ) ) {
line = QString ( " %1 \t %2 " ) . arg ( lineno + 1 ) . arg ( contents [ lineno ] ) ;
}
}
}
}
newOutput . append ( line ) ;
}
disOutput = newOutput ;
}
2021-11-25 07:42:56 +08:00
emit disassemblyUpdate ( mCurrentFile , mCurrentFunc , disOutput ) ;
2021-11-24 23:32:34 +08:00
}
2021-11-10 17:05:37 +08:00
}
return ;
}
if ( line . startsWith ( " ^connected " ) ) {
//TODO: connected to remote target
2021-11-10 12:57:18 +08:00
return ;
}
}
2021-11-12 10:51:00 +08:00
void DebugReader : : processDebugOutput ( const QByteArray & debugOutput )
2021-07-18 00:18:07 +08:00
{
// Only update once per update at most
2021-07-18 08:52:53 +08:00
//WatchView.Items.BeginUpdate;
emit parseStarted ( ) ;
2021-11-10 17:05:37 +08:00
mConsoleOutput . clear ( ) ;
2021-11-24 17:53:25 +08:00
mFullOutput . clear ( ) ;
2021-11-10 17:05:37 +08:00
2021-11-23 21:08:33 +08:00
mSignalReceived = false ;
mUpdateCPUInfo = false ;
2021-11-24 10:07:35 +08:00
mReceivedSFWarning = false ;
2021-11-24 23:32:34 +08:00
QList < QByteArray > lines = splitByteArrayToLines ( debugOutput ) ;
for ( int i = 0 ; i < lines . count ( ) ; i + + ) {
QByteArray line = lines [ i ] ;
2021-11-25 23:41:40 +08:00
if ( pSettings - > debugger ( ) . showDetailLog ( ) )
mFullOutput . append ( line ) ;
2021-11-24 23:32:34 +08:00
line = removeToken ( line ) ;
if ( line . isEmpty ( ) ) {
continue ;
}
switch ( line [ 0 ] ) {
case ' ~ ' : // console stream output
processConsoleOutput ( line ) ;
break ;
case ' @ ' : // target stream output
2023-07-02 11:09:34 +08:00
break ;
2021-11-24 23:32:34 +08:00
case ' & ' : // log stream output
2023-07-02 11:09:34 +08:00
processLogOutput ( line ) ;
2021-11-24 23:32:34 +08:00
break ;
case ' ^ ' : // result record
processResultRecord ( line ) ;
break ;
case ' * ' : // exec async output
processExecAsyncRecord ( line ) ;
break ;
case ' + ' : // status async output
case ' = ' : // notify async output
break ;
}
}
emit parseFinished ( ) ;
mConsoleOutput . clear ( ) ;
mFullOutput . clear ( ) ;
2021-07-18 08:52:53 +08:00
}
2021-11-24 17:53:25 +08:00
void DebugReader : : runInferiorStoppedHook ( )
{
2023-03-08 18:31:47 +08:00
QMutexLocker locker ( & mCmdQueueMutex ) ;
2021-11-24 17:53:25 +08:00
foreach ( const PDebugCommand & cmd , mInferiorStoppedHookCommands ) {
mCmdQueue . push_front ( cmd ) ;
}
}
2021-07-19 23:02:32 +08:00
void DebugReader : : runNextCmd ( )
{
QMutexLocker locker ( & mCmdQueueMutex ) ;
if ( mCurrentCmd ) {
2022-01-01 09:17:12 +08:00
DebugCommandSource commandSource = mCurrentCmd - > source ;
2021-12-27 21:32:30 +08:00
mCurrentCmd = nullptr ;
2022-01-01 09:17:12 +08:00
if ( commandSource ! = DebugCommandSource : : HeartBeat )
emit cmdFinished ( ) ;
2021-07-19 23:02:32 +08:00
}
2021-12-27 21:32:30 +08:00
if ( mCmdQueue . isEmpty ( ) ) {
if ( pSettings - > debugger ( ) . useGDBServer ( ) & & mInferiorRunning & & ! mAsyncUpdated ) {
mAsyncUpdated = true ;
2022-01-01 09:17:12 +08:00
QTimer : : singleShot ( 50 , this , & DebugReader : : asyncUpdate ) ;
2021-12-27 21:32:30 +08:00
}
2021-11-24 17:53:25 +08:00
return ;
2021-12-27 21:32:30 +08:00
}
2021-07-19 23:02:32 +08:00
PDebugCommand pCmd = mCmdQueue . dequeue ( ) ;
mCmdRunning = true ;
2022-01-01 09:17:12 +08:00
mCurrentCmd = pCmd ;
if ( pCmd - > source ! = DebugCommandSource : : HeartBeat )
emit cmdStarted ( ) ;
2021-07-19 23:02:32 +08:00
QByteArray s ;
2021-11-25 20:26:43 +08:00
QByteArray params ;
2021-11-10 21:28:08 +08:00
s = pCmd - > command . toLocal8Bit ( ) ;
2021-07-19 23:02:32 +08:00
if ( ! pCmd - > params . isEmpty ( ) ) {
2021-11-25 20:26:43 +08:00
params = pCmd - > params . toLocal8Bit ( ) ;
}
2022-05-15 17:14:22 +08:00
//clang compatibility
2023-01-22 22:19:19 +08:00
if ( mDebugger - > forceUTF8 ( ) ) {
2022-05-15 17:14:22 +08:00
params = pCmd - > params . toUtf8 ( ) ;
2023-06-27 11:50:43 +08:00
} else if ( mDebugger - > debugInfosUsingUTF8 ( ) & &
( pCmd - > command = = " -break-insert "
| | pCmd - > command = = " -var-create "
| | pCmd - > command = = " -data-read-memory "
| | pCmd - > command = = " -data-evaluate-expression "
) ) {
params = pCmd - > params . toUtf8 ( ) ;
2022-05-15 17:14:22 +08:00
}
2021-11-25 20:26:43 +08:00
if ( pCmd - > command = = " -var-create " ) {
//hack for variable creation,to easy remember var expression
2023-01-22 22:19:19 +08:00
if ( mDebugger - > debuggerType ( ) = = DebuggerType : : LLDB_MI )
params = " - * " + params ;
else
params = " - @ " + params ;
2021-11-25 20:26:43 +08:00
} else if ( pCmd - > command = = " -var-list-children " ) {
//hack for list variable children,to easy remember var expression
2021-11-25 21:44:08 +08:00
params = " --all-values \" " + params + ' \" ' ;
2021-07-19 23:02:32 +08:00
}
2021-11-25 20:26:43 +08:00
s + = " " + params ;
2021-07-19 23:02:32 +08:00
s + = " \n " ;
2021-07-27 00:14:24 +08:00
if ( mProcess - > write ( s ) < 0 ) {
2021-07-19 23:02:32 +08:00
emit writeToDebugFailed ( ) ;
}
// if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin
2021-11-25 10:18:21 +08:00
if ( pSettings - > debugger ( ) . enableDebugConsole ( ) ) {
2021-07-19 23:02:32 +08:00
//update debug console
2021-11-25 23:41:40 +08:00
if ( pSettings - > debugger ( ) . showDetailLog ( )
& & pCmd - > source ! = DebugCommandSource : : Console ) {
2021-11-25 20:26:43 +08:00
emit changeDebugConsoleLastLine ( pCmd - > command + ' ' + params ) ;
2021-07-19 23:02:32 +08:00
}
}
}
2021-09-19 09:45:03 +08:00
QStringList DebugReader : : tokenize ( const QString & s )
{
QStringList result ;
int tStart , tEnd ;
int i = 0 ;
while ( i < s . length ( ) ) {
QChar ch = s [ i ] ;
if ( ch = = ' ' | | ch = = ' \t '
| | ch = = ' \r '
| | ch = = ' \n ' ) {
// if (!current.isEmpty()) {
// result.append(current);
// current = "";
// }
i + + ;
continue ;
} else if ( ch = = ' \' ' ) {
tStart = i ;
i + + ; //skip \'
while ( i < s . length ( ) ) {
if ( s [ i ] = = ' \' ' ) {
i + + ;
break ;
} else if ( s [ i ] = = ' \\ ' ) {
i + = 2 ;
2021-09-19 14:28:30 +08:00
continue ;
2021-09-19 09:45:03 +08:00
}
i + + ;
}
tEnd = std : : min ( i , s . length ( ) ) ;
result . append ( s . mid ( tStart , tEnd - tStart ) ) ;
2021-09-19 14:28:30 +08:00
} else if ( ch = = ' \" ' ) {
2021-09-19 09:45:03 +08:00
tStart = i ;
i + + ; //skip \'
while ( i < s . length ( ) ) {
if ( s [ i ] = = ' \" ' ) {
i + + ;
break ;
} else if ( s [ i ] = = ' \\ ' ) {
i + = 2 ;
2021-09-19 14:28:30 +08:00
continue ;
}
i + + ;
}
tEnd = std : : min ( i , s . length ( ) ) ;
result . append ( s . mid ( tStart , tEnd - tStart ) ) ;
} else if ( ch = = ' < ' ) {
tStart = i ;
i + + ;
while ( i < s . length ( ) ) {
if ( s [ i ] = = ' > ' ) {
i + + ;
2021-09-19 09:45:03 +08:00
break ;
}
i + + ;
}
tEnd = std : : min ( i , s . length ( ) ) ;
result . append ( s . mid ( tStart , tEnd - tStart ) ) ;
2021-09-29 20:45:03 +08:00
} else if ( ch = = ' ( ' ) {
tStart = i ;
i + + ;
while ( i < s . length ( ) ) {
if ( s [ i ] = = ' ) ' ) {
i + + ;
break ;
}
i + + ;
}
tEnd = std : : min ( i , s . length ( ) ) ;
result . append ( s . mid ( tStart , tEnd - tStart ) ) ;
2021-09-29 19:40:03 +08:00
} else if ( ch = = ' _ ' | |
ch = = ' . ' | |
ch = = ' + ' | |
ch = = ' - ' | |
ch . isLetterOrNumber ( ) ) {
2021-09-19 09:45:03 +08:00
tStart = i ;
while ( i < s . length ( ) ) {
2021-09-29 19:40:03 +08:00
ch = s [ i ] ;
if ( ! ( ch = = ' _ ' | |
ch = = ' . ' | |
ch = = ' + ' | |
ch = = ' - ' | |
ch . isLetterOrNumber ( ) ) )
2021-09-19 09:45:03 +08:00
break ;
i + + ;
}
tEnd = std : : min ( i , s . length ( ) ) ;
result . append ( s . mid ( tStart , tEnd - tStart ) ) ;
} else {
result . append ( s [ i ] ) ;
i + + ;
}
}
return result ;
}
2021-11-24 17:53:25 +08:00
bool DebugReader : : outputTerminated ( const QByteArray & text )
{
QStringList lines = textToLines ( QString : : fromUtf8 ( text ) ) ;
foreach ( const QString & line , lines ) {
if ( line . trimmed ( ) = = " (gdb) " )
return true ;
}
return false ;
}
2021-11-21 08:38:03 +08:00
void DebugReader : : handleBreakpoint ( const GDBMIResultParser : : ParseObject & breakpoint )
2021-11-12 10:51:00 +08:00
{
2022-05-15 17:14:22 +08:00
QString filename ;
2021-11-21 08:38:03 +08:00
// gdb use system encoding for file path
2023-06-27 11:50:43 +08:00
if ( mDebugger - > forceUTF8 ( ) | | mDebugger - > debugInfosUsingUTF8 ( ) )
2022-05-15 17:14:22 +08:00
filename = breakpoint [ " fullname " ] . utf8PathValue ( ) ;
else
filename = breakpoint [ " fullname " ] . pathValue ( ) ;
2021-11-21 08:38:03 +08:00
int line = breakpoint [ " line " ] . intValue ( ) ;
int number = breakpoint [ " number " ] . intValue ( ) ;
emit breakpointInfoGetted ( filename , line , number ) ;
2021-11-12 10:51:00 +08:00
}
2023-03-03 17:20:33 +08:00
void DebugReader : : handleFrame ( const GDBMIResultParser : : ParseValue & frame )
{
if ( frame . isValid ( ) ) {
GDBMIResultParser : : ParseObject frameObj = frame . object ( ) ;
bool ok ;
mCurrentAddress = frameObj [ " addr " ] . hexValue ( ok ) ;
if ( ! ok )
mCurrentAddress = 0 ;
mCurrentLine = frameObj [ " line " ] . intValue ( ) ;
2023-06-27 11:50:43 +08:00
if ( mDebugger - > forceUTF8 ( )
| | mDebugger - > debugInfosUsingUTF8 ( ) )
2023-03-03 17:20:33 +08:00
mCurrentFile = frameObj [ " fullname " ] . utf8PathValue ( ) ;
else
mCurrentFile = frameObj [ " fullname " ] . pathValue ( ) ;
mCurrentFunc = frameObj [ " func " ] . value ( ) ;
}
}
2021-11-23 21:08:33 +08:00
void DebugReader : : handleStack ( const QList < GDBMIResultParser : : ParseValue > & stack )
{
mDebugger - > backtraceModel ( ) - > clear ( ) ;
foreach ( const GDBMIResultParser : : ParseValue & frameValue , stack ) {
GDBMIResultParser : : ParseObject frameObject = frameValue . object ( ) ;
PTrace trace = std : : make_shared < Trace > ( ) ;
trace - > funcname = frameObject [ " func " ] . value ( ) ;
2023-06-27 11:50:43 +08:00
if ( mDebugger - > forceUTF8 ( ) | | mDebugger - > debugInfosUsingUTF8 ( ) )
2022-05-15 17:14:22 +08:00
trace - > filename = frameObject [ " fullname " ] . utf8PathValue ( ) ;
else
trace - > filename = frameObject [ " fullname " ] . pathValue ( ) ;
2021-11-24 21:22:01 +08:00
trace - > line = frameObject [ " line " ] . intValue ( ) ;
2021-11-23 21:08:33 +08:00
trace - > level = frameObject [ " level " ] . intValue ( 0 ) ;
trace - > address = frameObject [ " addr " ] . value ( ) ;
mDebugger - > backtraceModel ( ) - > addTrace ( trace ) ;
}
}
void DebugReader : : handleLocalVariables ( const QList < GDBMIResultParser : : ParseValue > & variables )
{
2021-11-24 10:07:35 +08:00
QStringList locals ;
2021-11-23 21:08:33 +08:00
foreach ( const GDBMIResultParser : : ParseValue & varValue , variables ) {
GDBMIResultParser : : ParseObject varObject = varValue . object ( ) ;
2022-01-04 16:50:54 +08:00
locals . append (
QString ( " %1 = %2 " )
. arg (
QString ( varObject [ " name " ] . value ( ) ) ,
QString ( varObject [ " value " ] . value ( ) )
) ) ;
2021-11-23 21:08:33 +08:00
}
2021-11-24 10:07:35 +08:00
emit localsUpdated ( locals ) ;
2021-11-23 21:08:33 +08:00
}
void DebugReader : : handleEvaluation ( const QString & value )
{
2021-11-24 10:07:35 +08:00
emit evalUpdated ( value ) ;
2021-11-23 21:08:33 +08:00
}
void DebugReader : : handleMemory ( const QList < GDBMIResultParser : : ParseValue > & rows )
{
2021-11-24 10:07:35 +08:00
QStringList memory ;
2021-11-23 21:08:33 +08:00
foreach ( const GDBMIResultParser : : ParseValue & row , rows ) {
GDBMIResultParser : : ParseObject rowObject = row . object ( ) ;
QList < GDBMIResultParser : : ParseValue > data = rowObject [ " data " ] . array ( ) ;
QStringList values ;
foreach ( const GDBMIResultParser : : ParseValue & val , data ) {
values . append ( val . value ( ) ) ;
}
2021-11-24 10:07:35 +08:00
memory . append ( QString ( " %1 %2 " )
2021-11-23 21:08:33 +08:00
. arg ( rowObject [ " addr " ] . value ( ) , values . join ( " " ) ) ) ;
}
2021-11-24 10:07:35 +08:00
emit memoryUpdated ( memory ) ;
2021-11-23 21:08:33 +08:00
}
2021-11-25 09:05:45 +08:00
void DebugReader : : handleRegisterNames ( const QList < GDBMIResultParser : : ParseValue > & names )
{
QStringList nameList ;
foreach ( const GDBMIResultParser : : ParseValue & nameValue , names ) {
2022-12-02 10:19:03 +08:00
// QString text = nameValue.value().trimmed();
// if (!text.isEmpty())
nameList . append ( nameValue . value ( ) ) ;
2021-11-25 09:05:45 +08:00
}
emit registerNamesUpdated ( nameList ) ;
}
void DebugReader : : handleRegisterValue ( const QList < GDBMIResultParser : : ParseValue > & values )
{
QHash < int , QString > result ;
foreach ( const GDBMIResultParser : : ParseValue & val , values ) {
GDBMIResultParser : : ParseObject obj = val . object ( ) ;
int number = obj [ " number " ] . intValue ( ) ;
QString value = obj [ " value " ] . value ( ) ;
bool ok ;
long long intVal ;
intVal = value . toLongLong ( & ok , 10 ) ;
if ( ok ) {
value = QString ( " 0x%1 " ) . arg ( intVal , 0 , 16 ) ;
}
result . insert ( number , value ) ;
}
emit registerValuesUpdated ( result ) ;
}
2021-11-25 20:26:43 +08:00
void DebugReader : : handleCreateVar ( const GDBMIResultParser : : ParseObject & multiVars )
{
if ( ! mCurrentCmd )
return ;
QString expression = mCurrentCmd - > params ;
QString name = multiVars [ " name " ] . value ( ) ;
int numChild = multiVars [ " numchild " ] . intValue ( 0 ) ;
QString value = multiVars [ " value " ] . value ( ) ;
QString type = multiVars [ " type " ] . value ( ) ;
bool hasMore = multiVars [ " has_more " ] . value ( ) ! = " 0 " ;
emit varCreated ( expression , name , numChild , value , type , hasMore ) ;
}
void DebugReader : : handleListVarChildren ( const GDBMIResultParser : : ParseObject & multiVars )
{
if ( ! mCurrentCmd )
return ;
QString parentName = mCurrentCmd - > params ;
int parentNumChild = multiVars [ " numchild " ] . intValue ( 0 ) ;
QList < GDBMIResultParser : : ParseValue > children = multiVars [ " children " ] . array ( ) ;
bool hasMore = multiVars [ " has_more " ] . value ( ) ! = " 0 " ;
emit prepareVarChildren ( parentName , parentNumChild , hasMore ) ;
foreach ( const GDBMIResultParser : : ParseValue & child , children ) {
GDBMIResultParser : : ParseObject childObj = child . object ( ) ;
QString name = childObj [ " name " ] . value ( ) ;
QString exp = childObj [ " exp " ] . value ( ) ;
int numChild = childObj [ " numchild " ] . intValue ( 0 ) ;
QString value = childObj [ " value " ] . value ( ) ;
QString type = childObj [ " type " ] . value ( ) ;
bool hasMore = childObj [ " has_more " ] . value ( ) ! = " 0 " ;
emit addVarChild ( parentName ,
name ,
exp ,
numChild ,
value ,
type ,
hasMore ) ;
}
}
void DebugReader : : handleUpdateVarValue ( const QList < GDBMIResultParser : : ParseValue > & changes )
{
foreach ( const GDBMIResultParser : : ParseValue & value , changes ) {
GDBMIResultParser : : ParseObject obj = value . object ( ) ;
QString name = obj [ " name " ] . value ( ) ;
QString val = obj [ " value " ] . value ( ) ;
QString inScope = obj [ " in_scope " ] . value ( ) ;
bool typeChanged = ( obj [ " type_changed " ] . value ( ) = = " true " ) ;
QString newType = obj [ " new_type " ] . value ( ) ;
int newNumChildren = obj [ " new_num_children " ] . intValue ( - 1 ) ;
bool hasMore = ( obj [ " has_more " ] . value ( ) = = " 1 " ) ;
emit varValueUpdated ( name , val , inScope , typeChanged , newType , newNumChildren ,
hasMore ) ;
}
2022-03-30 19:28:46 +08:00
//todo: -var-list-children will freeze if the var is not correctly initialized
//emit varsValueUpdated();
2021-11-25 20:26:43 +08:00
}
2021-11-12 10:51:00 +08:00
QByteArray DebugReader : : removeToken ( const QByteArray & line )
2021-11-10 17:05:37 +08:00
{
int p = 0 ;
while ( p < line . length ( ) ) {
2021-11-10 22:00:01 +08:00
QChar ch = line [ p ] ;
if ( ch < ' 0 ' | | ch > ' 9 ' ) {
break ;
}
p + + ;
2021-11-10 17:05:37 +08:00
}
2021-11-10 22:00:01 +08:00
if ( p < line . length ( ) )
return line . mid ( p ) ;
return line ;
2021-11-10 17:05:37 +08:00
}
2021-12-27 21:32:30 +08:00
void DebugReader : : asyncUpdate ( )
{
QMutexLocker locker ( & mCmdQueueMutex ) ;
2023-01-22 22:19:19 +08:00
if ( mCmdQueue . isEmpty ( ) ) {
2022-01-01 09:17:12 +08:00
postCommand ( " -var-update " , " --all-values * " , DebugCommandSource : : HeartBeat ) ;
2023-01-22 22:19:19 +08:00
}
2021-12-27 21:32:30 +08:00
mAsyncUpdated = false ;
}
2022-06-16 21:34:31 +08:00
const QStringList & DebugReader : : binDirs ( ) const
{
return mBinDirs ;
}
void DebugReader : : addBinDirs ( const QStringList & binDirs )
{
mBinDirs . append ( binDirs ) ;
}
void DebugReader : : addBinDir ( const QString & binDir )
{
mBinDirs . append ( binDir ) ;
}
2021-11-25 09:05:45 +08:00
const QString & DebugReader : : signalMeaning ( ) const
{
return mSignalMeaning ;
}
const QString & DebugReader : : signalName ( ) const
{
return mSignalName ;
}
2021-11-24 21:22:01 +08:00
bool DebugReader : : inferiorRunning ( ) const
{
return mInferiorRunning ;
}
2021-11-24 17:53:25 +08:00
const QStringList & DebugReader : : fullOutput ( ) const
2021-11-23 21:08:33 +08:00
{
2021-11-24 17:53:25 +08:00
return mFullOutput ;
2021-11-23 21:08:33 +08:00
}
2021-11-24 17:53:25 +08:00
bool DebugReader : : receivedSFWarning ( ) const
2021-11-23 21:08:33 +08:00
{
2021-11-24 17:53:25 +08:00
return mReceivedSFWarning ;
2021-11-23 21:08:33 +08:00
}
bool DebugReader : : updateCPUInfo ( ) const
{
return mUpdateCPUInfo ;
}
const PDebugCommand & DebugReader : : currentCmd ( ) const
{
return mCurrentCmd ;
}
const QStringList & DebugReader : : consoleOutput ( ) const
{
return mConsoleOutput ;
}
bool DebugReader : : signalReceived ( ) const
{
return mSignalReceived ;
}
2021-11-10 17:05:37 +08:00
bool DebugReader : : processExited ( ) const
{
return mProcessExited ;
}
2021-07-25 00:26:13 +08:00
QString DebugReader : : debuggerPath ( ) const
{
return mDebuggerPath ;
}
void DebugReader : : setDebuggerPath ( const QString & debuggerPath )
{
mDebuggerPath = debuggerPath ;
}
void DebugReader : : stopDebug ( )
{
mStop = true ;
}
2021-08-29 22:08:43 +08:00
bool DebugReader : : commandRunning ( )
{
return ! mCmdQueue . isEmpty ( ) ;
}
2021-11-24 17:53:25 +08:00
void DebugReader : : waitStart ( )
2021-11-10 17:05:37 +08:00
{
mStartSemaphore . acquire ( 1 ) ;
}
2021-07-19 23:02:32 +08:00
void DebugReader : : run ( )
{
mStop = false ;
2021-11-24 10:07:35 +08:00
mInferiorRunning = false ;
2021-11-10 17:05:37 +08:00
mProcessExited = false ;
2021-12-25 20:02:53 +08:00
mErrorOccured = false ;
2021-07-25 00:26:13 +08:00
QString cmd = mDebuggerPath ;
2021-10-13 17:20:31 +08:00
// QString arguments = "--annotate=2";
2021-11-10 12:29:02 +08:00
QString arguments = " --interpret=mi --silent " ;
2021-07-25 00:26:13 +08:00
QString workingDir = QFileInfo ( mDebuggerPath ) . path ( ) ;
2021-12-25 18:09:50 +08:00
mProcess = std : : make_shared < QProcess > ( ) ;
2021-12-25 20:02:53 +08:00
auto action = finally ( [ & ] {
mProcess . reset ( ) ;
} ) ;
2021-07-27 00:14:24 +08:00
mProcess - > setProgram ( cmd ) ;
2022-01-04 16:50:54 +08:00
mProcess - > setArguments ( splitProcessCommand ( arguments ) ) ;
2021-10-13 17:20:31 +08:00
mProcess - > setProcessChannelMode ( QProcess : : MergedChannels ) ;
2022-06-16 21:34:31 +08:00
QProcessEnvironment env = QProcessEnvironment : : systemEnvironment ( ) ;
QString path = env . value ( " PATH " ) ;
QStringList pathAdded = mBinDirs ;
if ( ! path . isEmpty ( ) ) {
path = pathAdded . join ( PATH_SEPARATOR ) + PATH_SEPARATOR + path ;
} else {
path = pathAdded . join ( PATH_SEPARATOR ) ;
}
2021-10-12 19:39:24 +08:00
QString cmdDir = extractFileDir ( cmd ) ;
if ( ! cmdDir . isEmpty ( ) ) {
2022-06-16 21:34:31 +08:00
path = cmdDir + PATH_SEPARATOR + path ;
2021-10-12 19:39:24 +08:00
}
2022-06-16 21:34:31 +08:00
env . insert ( " PATH " , path ) ;
mProcess - > setProcessEnvironment ( env ) ;
2021-07-27 00:14:24 +08:00
mProcess - > setWorkingDirectory ( workingDir ) ;
2021-07-19 23:02:32 +08:00
2021-12-25 18:09:50 +08:00
connect ( mProcess . get ( ) , & QProcess : : errorOccurred ,
2021-07-19 23:02:32 +08:00
[ & ] ( ) {
2021-12-25 20:02:53 +08:00
mErrorOccured = true ;
2021-07-19 23:02:32 +08:00
} ) ;
2021-10-13 17:20:31 +08:00
QByteArray buffer ;
QByteArray readed ;
2021-07-27 00:14:24 +08:00
mProcess - > start ( ) ;
mProcess - > waitForStarted ( 5000 ) ;
mStartSemaphore . release ( 1 ) ;
2021-07-19 23:02:32 +08:00
while ( true ) {
2021-08-01 01:06:43 +08:00
mProcess - > waitForFinished ( 1 ) ;
2021-07-27 00:14:24 +08:00
if ( mProcess - > state ( ) ! = QProcess : : Running ) {
2021-07-19 23:02:32 +08:00
break ;
}
if ( mStop ) {
2021-07-27 00:14:24 +08:00
mProcess - > terminate ( ) ;
2021-08-01 23:24:37 +08:00
mProcess - > kill ( ) ;
2021-07-31 14:04:43 +08:00
break ;
2021-07-19 23:02:32 +08:00
}
2021-12-25 20:02:53 +08:00
if ( mErrorOccured )
2021-07-19 23:02:32 +08:00
break ;
2021-07-30 23:28:58 +08:00
readed = mProcess - > readAll ( ) ;
buffer + = readed ;
2021-11-10 12:29:02 +08:00
2021-11-24 21:22:01 +08:00
if ( readed . endsWith ( " \n " ) & & outputTerminated ( buffer ) ) {
2021-11-12 10:51:00 +08:00
processDebugOutput ( buffer ) ;
2021-07-30 23:28:58 +08:00
buffer . clear ( ) ;
2021-07-19 23:02:32 +08:00
mCmdRunning = false ;
runNextCmd ( ) ;
2021-07-30 23:28:58 +08:00
} else if ( ! mCmdRunning & & readed . isEmpty ( ) ) {
runNextCmd ( ) ;
2021-08-01 01:06:43 +08:00
} else if ( readed . isEmpty ( ) ) {
2021-11-25 23:41:40 +08:00
msleep ( 1 ) ;
2021-07-19 23:02:32 +08:00
}
}
2021-12-25 20:02:53 +08:00
if ( mErrorOccured ) {
2021-07-27 00:14:24 +08:00
emit processError ( mProcess - > error ( ) ) ;
2021-07-19 23:02:32 +08:00
}
}
2022-10-19 09:23:55 +08:00
BreakpointModel : : BreakpointModel ( QObject * parent ) : QAbstractTableModel ( parent ) ,
mIsForProject ( false )
2021-07-24 11:18:25 +08:00
{
}
2021-07-17 19:32:23 +08:00
int BreakpointModel : : rowCount ( const QModelIndex & ) const
{
2022-10-16 23:10:57 +08:00
return breakpoints ( mIsForProject ) . size ( ) ;
2021-07-17 19:32:23 +08:00
}
int BreakpointModel : : columnCount ( const QModelIndex & ) const
{
return 3 ;
}
QVariant BreakpointModel : : data ( const QModelIndex & index , int role ) const
{
if ( ! index . isValid ( ) )
return QVariant ( ) ;
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & list = breakpoints ( mIsForProject ) ;
if ( index . row ( ) < 0 | | index . row ( ) > = static_cast < int > ( list . size ( ) ) )
2021-07-17 19:32:23 +08:00
return QVariant ( ) ;
2022-10-16 23:10:57 +08:00
PBreakpoint breakpoint = list [ index . row ( ) ] ;
2021-07-17 19:32:23 +08:00
if ( ! breakpoint )
return QVariant ( ) ;
switch ( role ) {
case Qt : : DisplayRole :
2021-09-03 10:30:08 +08:00
switch ( index . column ( ) ) {
case 0 : {
2021-09-10 12:37:02 +08:00
return extractFileName ( breakpoint - > filename ) ;
2021-09-03 10:30:08 +08:00
}
case 1 :
if ( breakpoint - > line > 0 )
return breakpoint - > line ;
else
return " " ;
case 2 :
return breakpoint - > condition ;
default :
return QVariant ( ) ;
}
case Qt : : ToolTipRole :
2021-07-17 19:32:23 +08:00
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 :
2022-01-03 20:18:53 +08:00
return tr ( " Filename " ) ;
2021-07-17 19:32:23 +08:00
case 1 :
return tr ( " Line " ) ;
case 2 :
return tr ( " Condition " ) ;
}
}
return QVariant ( ) ;
}
2022-10-16 23:10:57 +08:00
void BreakpointModel : : addBreakpoint ( PBreakpoint p , bool forProject )
2021-07-17 19:32:23 +08:00
{
2022-10-16 23:10:57 +08:00
if ( forProject ) {
if ( forProject = = mIsForProject )
beginInsertRows ( QModelIndex ( ) , mProjectBreakpoints . count ( ) , mProjectBreakpoints . count ( ) ) ;
mProjectBreakpoints . push_back ( p ) ;
} else {
if ( forProject = = mIsForProject )
beginInsertRows ( QModelIndex ( ) , mBreakpoints . count ( ) , mBreakpoints . count ( ) ) ;
mBreakpoints . push_back ( p ) ;
}
if ( forProject = = mIsForProject )
endInsertRows ( ) ;
2021-07-17 19:32:23 +08:00
}
2022-10-16 23:10:57 +08:00
void BreakpointModel : : clear ( bool forProject )
2021-07-17 19:32:23 +08:00
{
2022-10-16 23:10:57 +08:00
if ( forProject = = mIsForProject )
beginResetModel ( ) ;
if ( forProject )
mProjectBreakpoints . clear ( ) ;
else
mBreakpoints . clear ( ) ;
if ( forProject = = mIsForProject )
endResetModel ( ) ;
2021-07-17 19:32:23 +08:00
}
2022-10-16 23:10:57 +08:00
void BreakpointModel : : removeBreakpoint ( int row , bool forProject )
2021-07-17 19:32:23 +08:00
{
2022-10-16 23:10:57 +08:00
if ( forProject = = mIsForProject )
beginRemoveRows ( QModelIndex ( ) , row , row ) ;
if ( forProject )
mProjectBreakpoints . removeAt ( row ) ;
else
mBreakpoints . removeAt ( row ) ;
if ( forProject = = mIsForProject )
endRemoveRows ( ) ;
2021-07-17 19:32:23 +08:00
}
2022-11-07 21:44:12 +08:00
void BreakpointModel : : removeBreakpointsInFile ( const QString & fileName , bool forProject )
{
QList < PBreakpoint > & lst = forProject ? mProjectBreakpoints : mBreakpoints ;
for ( int i = lst . count ( ) - 1 ; i > = 0 ; i - - ) {
if ( lst [ i ] - > filename = = fileName )
removeBreakpoint ( i , forProject ) ;
}
}
void BreakpointModel : : renameBreakpointFilenames ( const QString & oldFileName , const QString & newFileName , bool forProject )
{
QList < PBreakpoint > & lst = forProject ? mProjectBreakpoints : mBreakpoints ;
for ( int i = lst . count ( ) - 1 ; i > = 0 ; i - - ) {
if ( lst [ i ] - > filename = = oldFileName ) {
lst [ i ] - > filename = newFileName ;
if ( forProject = = mIsForProject ) {
QModelIndex index = createIndex ( i , 0 ) ;
emit dataChanged ( index , index ) ;
}
}
}
}
2021-11-21 08:38:03 +08:00
void BreakpointModel : : invalidateAllBreakpointNumbers ( )
{
2022-10-16 23:10:57 +08:00
foreach ( PBreakpoint bp , mBreakpoints ) {
bp - > number = - 1 ;
}
foreach ( PBreakpoint bp , mProjectBreakpoints ) {
2021-11-21 08:38:03 +08:00
bp - > number = - 1 ;
}
//emit dateChanged(createIndex(0,0),)
}
2022-10-16 23:10:57 +08:00
PBreakpoint BreakpointModel : : setBreakPointCondition ( int index , const QString & condition , bool forProject )
2021-07-24 11:18:25 +08:00
{
2022-10-16 23:10:57 +08:00
PBreakpoint breakpoint = breakpoints ( forProject ) [ index ] ;
2021-07-24 11:18:25 +08:00
breakpoint - > condition = condition ;
2022-10-16 23:10:57 +08:00
if ( forProject = = mIsForProject )
emit dataChanged ( createIndex ( index , 0 ) , createIndex ( index , 2 ) ) ;
2021-07-24 11:18:25 +08:00
return breakpoint ;
}
2022-10-16 23:10:57 +08:00
PBreakpoint BreakpointModel : : breakpoint ( int index , bool forProject ) const
2021-09-05 21:05:38 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > list = breakpoints ( forProject ) ;
if ( index < 0 & & index > = list . count ( ) )
2021-09-05 21:05:38 +08:00
return PBreakpoint ( ) ;
2022-10-16 23:10:57 +08:00
return list [ index ] ;
2021-10-21 19:33:11 +08:00
}
2021-11-24 10:07:35 +08:00
void BreakpointModel : : updateBreakpointNumber ( const QString & filename , int line , int number )
2021-11-21 08:38:03 +08:00
{
2022-10-16 23:10:57 +08:00
foreach ( PBreakpoint bp , breakpoints ( mIsForProject ) ) {
2021-11-21 10:36:50 +08:00
if ( bp - > filename = = filename & & bp - > line = = line ) {
2021-11-21 08:38:03 +08:00
bp - > number = number ;
2021-11-23 21:08:33 +08:00
return ;
2021-11-21 08:38:03 +08:00
}
}
}
2022-10-16 23:10:57 +08:00
void BreakpointModel : : onFileDeleteLines ( const QString & filename , int startLine , int count , bool forProject )
2021-09-05 22:16:54 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & list = breakpoints ( forProject ) ;
for ( int i = list . count ( ) - 1 ; i > = 0 ; i - - ) {
PBreakpoint breakpoint = list [ i ] ;
2021-09-05 22:16:54 +08:00
if ( breakpoint - > filename = = filename
& & breakpoint - > line > = startLine ) {
if ( breakpoint - > line > = startLine + count ) {
breakpoint - > line - = count ;
2022-10-16 23:10:57 +08:00
if ( forProject = = mIsForProject )
emit dataChanged ( createIndex ( i , 0 ) , createIndex ( i , 2 ) ) ;
2021-09-05 22:16:54 +08:00
} else {
2022-10-16 23:10:57 +08:00
removeBreakpoint ( i , forProject ) ;
2021-09-05 22:16:54 +08:00
}
}
}
}
2022-10-16 23:10:57 +08:00
void BreakpointModel : : onFileInsertLines ( const QString & filename , int startLine , int count , bool forProject )
2021-09-05 22:16:54 +08:00
{
2022-10-16 23:10:57 +08:00
const QList < PBreakpoint > & list = breakpoints ( forProject ) ;
for ( int i = list . count ( ) - 1 ; i > = 0 ; i - - ) {
PBreakpoint breakpoint = list [ i ] ;
2021-09-05 22:16:54 +08:00
if ( breakpoint - > filename = = filename
& & breakpoint - > line > = startLine ) {
breakpoint - > line + = count ;
2022-10-16 23:10:57 +08:00
if ( forProject = = mIsForProject )
emit dataChanged ( createIndex ( i , 0 ) , createIndex ( i , 2 ) ) ;
2021-09-05 22:16:54 +08:00
}
}
}
2022-10-16 23:10:57 +08:00
bool BreakpointModel : : isForProject ( ) const
{
return mIsForProject ;
}
void BreakpointModel : : setIsForProject ( bool newIsForProject )
{
if ( mIsForProject ! = newIsForProject ) {
beginResetModel ( ) ;
mIsForProject = newIsForProject ;
endResetModel ( ) ;
}
}
QList < PBreakpoint > BreakpointModel : : loadJson ( const QJsonArray & jsonArray , qint64 criteriaTime )
{
QList < PBreakpoint > result ;
for ( int i = 0 ; i < jsonArray . count ( ) ; i + + ) {
QJsonValue value = jsonArray [ i ] ;
QJsonObject obj = value . toObject ( ) ;
bool ok ;
qint64 timestamp = obj [ " timestamp " ] . toString ( ) . toLongLong ( & ok ) ;
if ( ok & & timestamp > criteriaTime ) {
PBreakpoint breakpoint = std : : make_shared < Breakpoint > ( ) ;
2022-10-17 23:23:05 +08:00
breakpoint - > filename = obj [ " filename " ] . toString ( ) ;
2022-10-16 23:10:57 +08:00
breakpoint - > line = obj [ " line " ] . toInt ( ) ;
breakpoint - > condition = obj [ " condition " ] . toString ( ) ;
breakpoint - > enabled = obj [ " enabled " ] . toBool ( ) ;
breakpoint - > breakpointType = static_cast < BreakpointType > ( obj [ " breakpoint_type " ] . toInt ( ) ) ;
breakpoint - > timestamp = timestamp ;
result . append ( breakpoint ) ;
}
}
return result ;
}
2021-07-24 11:18:25 +08:00
BacktraceModel : : BacktraceModel ( QObject * parent ) : QAbstractTableModel ( parent )
{
}
2021-07-17 19:32:23 +08:00
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 ( )
{
2021-12-09 21:04:53 +08:00
beginResetModel ( ) ;
2021-07-17 19:32:23 +08:00
mList . clear ( ) ;
2021-12-09 21:04:53 +08:00
endResetModel ( ) ;
2021-07-17 19:32:23 +08:00
}
void BacktraceModel : : removeTrace ( int row )
{
beginRemoveRows ( QModelIndex ( ) , row , row ) ;
mList . removeAt ( row ) ;
endRemoveRows ( ) ;
}
2021-07-24 11:18:25 +08:00
const QList < PTrace > & BacktraceModel : : backtraces ( ) const
{
return mList ;
}
2021-07-31 14:04:43 +08:00
2021-09-05 21:05:38 +08:00
PTrace BacktraceModel : : backtrace ( int index ) const
{
if ( index > = 0 & & index < mList . count ( ) ) {
return mList [ index ] ;
}
return PTrace ( ) ;
}
2021-07-31 20:19:45 +08:00
WatchModel : : WatchModel ( QObject * parent ) : QAbstractItemModel ( parent )
{
2021-09-19 01:58:09 +08:00
mUpdateCount = 0 ;
2022-10-16 23:10:57 +08:00
mIsForProject = false ;
2021-07-31 20:19:45 +08:00
}
QVariant WatchModel : : data ( const QModelIndex & index , int role ) const
{
if ( ! index . isValid ( ) ) {
return QVariant ( ) ;
}
WatchVar * item = static_cast < WatchVar * > ( index . internalPointer ( ) ) ;
switch ( role ) {
case Qt : : DisplayRole :
2021-09-19 09:45:03 +08:00
switch ( index . column ( ) ) {
case 0 :
2021-11-25 11:24:38 +08:00
return item - > expression ;
2021-09-19 09:45:03 +08:00
case 1 :
2021-11-25 11:24:38 +08:00
return item - > type ;
case 2 :
2021-09-19 09:45:03 +08:00
return item - > value ;
}
2021-07-31 20:19:45 +08:00
}
return QVariant ( ) ;
}
2021-07-31 14:04:43 +08:00
QModelIndex WatchModel : : index ( int row , int column , const QModelIndex & parent ) const
{
if ( ! hasIndex ( row , column , parent ) )
return QModelIndex ( ) ;
WatchVar * parentItem ;
PWatchVar pChild ;
if ( ! parent . isValid ( ) ) {
parentItem = nullptr ;
2022-10-16 23:10:57 +08:00
pChild = watchVars ( mIsForProject ) [ row ] ;
2021-07-31 14:04:43 +08:00
} else {
parentItem = static_cast < WatchVar * > ( parent . internalPointer ( ) ) ;
pChild = parentItem - > children [ row ] ;
}
2021-09-19 01:58:09 +08:00
if ( pChild ) {
2021-07-31 14:04:43 +08:00
return createIndex ( row , column , pChild . get ( ) ) ;
2021-09-19 01:58:09 +08:00
}
2021-07-31 14:04:43 +08:00
return QModelIndex ( ) ;
}
2022-10-16 23:10:57 +08:00
static int getWatchIndex ( WatchVar * var , const QList < PWatchVar > & list ) {
2021-07-31 14:04:43 +08:00
for ( int i = 0 ; i < list . size ( ) ; i + + ) {
PWatchVar v = list [ i ] ;
if ( v . get ( ) = = var ) {
return i ;
}
}
2021-08-27 23:51:42 +08:00
return - 1 ;
2021-07-31 14:04:43 +08:00
}
QModelIndex WatchModel : : parent ( const QModelIndex & index ) const
{
if ( ! index . isValid ( ) ) {
return QModelIndex ( ) ;
}
WatchVar * childItem = static_cast < WatchVar * > ( index . internalPointer ( ) ) ;
2022-10-16 23:10:57 +08:00
PWatchVar parentItem = childItem - > parent . lock ( ) ;
2021-07-31 14:04:43 +08:00
//parent is root
if ( parentItem = = nullptr ) {
return QModelIndex ( ) ;
}
int row ;
2022-10-16 23:10:57 +08:00
PWatchVar grandItem = parentItem - > parent . lock ( ) ;
2021-07-31 14:04:43 +08:00
if ( grandItem = = nullptr ) {
2022-10-16 23:10:57 +08:00
row = getWatchIndex ( parentItem . get ( ) , watchVars ( mIsForProject ) ) ;
2021-07-31 14:04:43 +08:00
} else {
2022-10-16 23:10:57 +08:00
row = getWatchIndex ( parentItem . get ( ) , grandItem - > children ) ;
2021-07-31 14:04:43 +08:00
}
2022-10-16 23:10:57 +08:00
return createIndex ( row , 0 , parentItem . get ( ) ) ;
2021-07-31 14:04:43 +08:00
}
int WatchModel : : rowCount ( const QModelIndex & parent ) const
{
if ( ! parent . isValid ( ) ) {
2022-10-16 23:10:57 +08:00
return watchVars ( mIsForProject ) . count ( ) ;
2021-07-31 14:04:43 +08:00
} else {
WatchVar * parentItem = static_cast < WatchVar * > ( parent . internalPointer ( ) ) ;
return parentItem - > children . count ( ) ;
}
}
2021-07-31 20:19:45 +08:00
int WatchModel : : columnCount ( const QModelIndex & ) const
2021-07-31 14:04:43 +08:00
{
2021-11-25 11:24:38 +08:00
return 3 ;
2021-07-31 14:04:43 +08:00
}
2022-10-17 23:23:05 +08:00
void WatchModel : : addWatchVar ( PWatchVar watchVar , bool forProject )
2021-07-31 14:04:43 +08:00
{
2022-10-17 23:23:05 +08:00
QList < PWatchVar > & vars = ( forProject ? mProjectWatchVars : mWatchVars ) ;
2022-10-16 23:10:57 +08:00
for ( PWatchVar var : vars ) {
2021-11-25 11:24:38 +08:00
if ( watchVar - > expression = = var - > expression ) {
2021-07-31 14:04:43 +08:00
return ;
}
}
2022-10-17 23:23:05 +08:00
if ( forProject = = mIsForProject )
beginInsertRows ( QModelIndex ( ) , vars . count ( ) , vars . count ( ) ) ;
2022-10-16 23:10:57 +08:00
vars . append ( watchVar ) ;
2022-10-17 23:23:05 +08:00
if ( forProject = = mIsForProject )
endInsertRows ( ) ;
2021-07-31 14:04:43 +08:00
}
2022-10-16 23:10:57 +08:00
void WatchModel : : setWatchVars ( const QList < PWatchVar > list , bool forProject )
{
if ( mIsForProject = = forProject )
beginResetModel ( ) ;
if ( forProject ) {
mProjectWatchVars = list ;
} else {
mWatchVars = list ;
}
if ( mIsForProject = = forProject )
endResetModel ( ) ;
}
2021-11-25 11:24:38 +08:00
void WatchModel : : removeWatchVar ( const QString & express )
2021-07-31 14:04:43 +08:00
{
2022-10-16 23:10:57 +08:00
QList < PWatchVar > & vars = ( mIsForProject ? mProjectWatchVars : mWatchVars ) ;
for ( int i = vars . size ( ) - 1 ; i > = 0 ; i - - ) {
PWatchVar var = vars [ i ] ;
2021-11-25 11:24:38 +08:00
if ( express = = var - > expression ) {
2022-10-16 23:10:57 +08:00
QModelIndex parentIndex = index ( var - > parent . lock ( ) ) ;
beginRemoveRows ( parentIndex , i , i ) ;
2021-11-25 20:26:43 +08:00
if ( mVarIndex . contains ( var - > name ) )
mVarIndex . remove ( var - > name ) ;
2022-10-16 23:10:57 +08:00
vars . removeAt ( i ) ;
endRemoveRows ( ) ;
2021-07-31 14:04:43 +08:00
}
}
}
2021-08-31 11:13:12 +08:00
void WatchModel : : removeWatchVar ( const QModelIndex & index )
{
int r = index . row ( ) ;
2022-10-16 23:10:57 +08:00
beginRemoveRows ( QModelIndex ( ) , r , r ) ;
QList < PWatchVar > & vars = ( mIsForProject ? mProjectWatchVars : mWatchVars ) ;
PWatchVar var = vars [ r ] ;
2021-11-25 20:26:43 +08:00
if ( mVarIndex . contains ( var - > name ) )
mVarIndex . remove ( var - > name ) ;
2022-10-16 23:10:57 +08:00
vars . removeAt ( r ) ;
endRemoveRows ( ) ;
2021-08-31 11:13:12 +08:00
}
2021-07-31 14:04:43 +08:00
void WatchModel : : clear ( )
{
2022-10-16 23:10:57 +08:00
beginResetModel ( ) ;
QList < PWatchVar > & vars = ( mIsForProject ? mProjectWatchVars : mWatchVars ) ;
vars . clear ( ) ;
endResetModel ( ) ;
2021-07-31 14:04:43 +08:00
}
2022-10-23 00:39:24 +08:00
void WatchModel : : clear ( bool forProject )
{
if ( mIsForProject = = forProject )
beginResetModel ( ) ;
QList < PWatchVar > & vars = ( forProject ? mProjectWatchVars : mWatchVars ) ;
vars . clear ( ) ;
if ( mIsForProject = = forProject )
endResetModel ( ) ;
}
2022-10-16 23:10:57 +08:00
const QList < PWatchVar > & WatchModel : : watchVars ( ) const
2021-07-31 14:04:43 +08:00
{
2022-10-16 23:10:57 +08:00
return watchVars ( mIsForProject ) ;
2021-07-31 14:04:43 +08:00
}
2021-11-25 20:26:43 +08:00
PWatchVar WatchModel : : findWatchVar ( const QModelIndex & index )
{
if ( ! index . isValid ( ) )
return PWatchVar ( ) ;
int r = index . row ( ) ;
2022-10-16 23:10:57 +08:00
return watchVars ( mIsForProject ) [ r ] ;
2021-11-25 20:26:43 +08:00
}
PWatchVar WatchModel : : findWatchVar ( const QString & expr )
2021-07-31 14:04:43 +08:00
{
2022-10-16 23:10:57 +08:00
foreach ( const PWatchVar & var , watchVars ( mIsForProject ) ) {
2021-11-25 20:26:43 +08:00
if ( expr = = var - > expression ) {
2021-07-31 14:04:43 +08:00
return var ;
}
}
2021-07-31 20:19:45 +08:00
return PWatchVar ( ) ;
2021-07-31 14:04:43 +08:00
}
2021-11-25 20:26:43 +08:00
void WatchModel : : resetAllVarInfos ( )
2021-07-31 14:04:43 +08:00
{
2021-11-25 20:26:43 +08:00
beginResetModel ( ) ;
2022-10-16 23:10:57 +08:00
foreach ( PWatchVar var , watchVars ( mIsForProject ) ) {
2021-11-25 20:26:43 +08:00
var - > name . clear ( ) ;
var - > value = tr ( " Not Valid " ) ;
var - > numChild = 0 ;
var - > hasMore = false ;
var - > type . clear ( ) ;
var - > children . clear ( ) ;
}
mVarIndex . clear ( ) ;
endResetModel ( ) ;
}
void WatchModel : : updateVarInfo ( const QString & expression , const QString & name , int numChild , const QString & value , const QString & type , bool hasMore )
{
PWatchVar var = findWatchVar ( expression ) ;
if ( ! var )
return ;
var - > name = name ;
var - > value = value ;
var - > numChild = numChild ;
var - > hasMore = hasMore ;
var - > type = type ;
mVarIndex . insert ( name , var ) ;
QModelIndex idx = index ( var ) ;
if ( ! idx . isValid ( ) )
return ;
emit dataChanged ( idx , createIndex ( idx . row ( ) , 2 , var . get ( ) ) ) ;
}
void WatchModel : : prepareVarChildren ( const QString & parentName , int numChild , bool hasMore )
{
PWatchVar var = mVarIndex . value ( parentName , PWatchVar ( ) ) ;
if ( var ) {
var - > numChild = numChild ;
var - > hasMore = hasMore ;
2021-11-25 21:44:08 +08:00
if ( var - > children . count ( ) > 0 ) {
beginRemoveRows ( index ( var ) , 0 , var - > children . count ( ) - 1 ) ;
var - > children . clear ( ) ;
endRemoveRows ( ) ;
}
2021-07-31 14:04:43 +08:00
}
2021-11-25 20:26:43 +08:00
}
void WatchModel : : addVarChild ( const QString & parentName , const QString & name ,
const QString & exp , int numChild , const QString & value ,
const QString & type , bool hasMore )
{
PWatchVar var = mVarIndex . value ( parentName , PWatchVar ( ) ) ;
if ( ! var )
return ;
beginInsertRows ( index ( var ) , var - > children . count ( ) , var - > children . count ( ) ) ;
PWatchVar child = std : : make_shared < WatchVar > ( ) ;
child - > name = name ;
child - > expression = exp ;
child - > numChild = numChild ;
child - > value = value ;
child - > type = type ;
child - > hasMore = hasMore ;
2022-10-16 23:10:57 +08:00
child - > parent = var ;
child - > timestamp = QDateTime : : currentMSecsSinceEpoch ( ) ;
2021-11-25 20:26:43 +08:00
var - > children . append ( child ) ;
endInsertRows ( ) ;
mVarIndex . insert ( name , child ) ;
}
void WatchModel : : updateVarValue ( const QString & name , const QString & val , const QString & inScope , bool typeChanged , const QString & newType , int newNumChildren , bool hasMore )
{
PWatchVar var = mVarIndex . value ( name , PWatchVar ( ) ) ;
if ( ! var )
return ;
if ( inScope = = " true " ) {
var - > value = val ;
} else {
var - > value = tr ( " Not Valid " ) ;
}
if ( typeChanged ) {
var - > type = newType ;
}
QModelIndex idx = index ( var ) ;
2021-11-25 21:44:08 +08:00
bool oldHasMore = var - > hasMore ;
var - > hasMore = hasMore ;
2021-11-25 20:26:43 +08:00
if ( newNumChildren > = 0
& & var - > numChild ! = newNumChildren ) {
var - > numChild = newNumChildren ;
2021-11-25 21:44:08 +08:00
fetchMore ( idx ) ;
} else if ( ! oldHasMore & & hasMore ) {
fetchMore ( idx ) ;
2021-11-25 20:26:43 +08:00
}
emit dataChanged ( idx , createIndex ( idx . row ( ) , 2 , var . get ( ) ) ) ;
}
2022-03-30 19:28:46 +08:00
void WatchModel : : updateAllHasMoreVars ( )
{
foreach ( const PWatchVar & var , mVarIndex . values ( ) ) {
if ( var - > hasMore ) {
QModelIndex idx = index ( var ) ;
fetchMore ( idx ) ;
}
}
}
2022-10-16 23:10:57 +08:00
bool WatchModel : : isForProject ( ) const
{
return mIsForProject ;
}
void WatchModel : : setIsForProject ( bool newIsForProject )
{
if ( newIsForProject ! = mIsForProject ) {
beginResetModel ( ) ;
mVarIndex . clear ( ) ;
mIsForProject = newIsForProject ;
endResetModel ( ) ;
}
}
const QList < PWatchVar > & WatchModel : : watchVars ( bool forProject ) const
{
return forProject ? mProjectWatchVars : mWatchVars ;
}
2021-11-25 20:26:43 +08:00
void WatchModel : : clearAllVarInfos ( )
{
beginResetModel ( ) ;
2022-10-16 23:10:57 +08:00
foreach ( PWatchVar var , watchVars ( mIsForProject ) ) {
2021-11-25 20:26:43 +08:00
var - > name . clear ( ) ;
var - > value = tr ( " Execute to evaluate " ) ;
var - > numChild = 0 ;
var - > hasMore = false ;
var - > type . clear ( ) ;
var - > children . clear ( ) ;
}
mVarIndex . clear ( ) ;
endResetModel ( ) ;
2021-07-31 20:19:45 +08:00
}
2021-09-19 01:58:09 +08:00
void WatchModel : : beginUpdate ( )
{
if ( mUpdateCount = = 0 ) {
beginResetModel ( ) ;
}
mUpdateCount + + ;
}
void WatchModel : : endUpdate ( )
{
mUpdateCount - - ;
if ( mUpdateCount = = 0 ) {
endResetModel ( ) ;
}
}
2021-07-31 20:19:45 +08:00
void WatchModel : : notifyUpdated ( PWatchVar var )
{
if ( ! var )
return ;
int row ;
2022-10-16 23:10:57 +08:00
PWatchVar parent = var - > parent . lock ( ) ;
if ( parent = = nullptr ) {
row = watchVars ( mIsForProject ) . indexOf ( var ) ;
2021-07-31 20:19:45 +08:00
} else {
2022-10-16 23:10:57 +08:00
row = parent - > children . indexOf ( var ) ;
2021-07-31 20:19:45 +08:00
}
if ( row < 0 )
return ;
2021-09-17 08:01:02 +08:00
//qDebug()<<"dataChanged"<<row<<":"<<var->text;
2021-07-31 20:19:45 +08:00
emit dataChanged ( createIndex ( row , 0 , var . get ( ) ) , createIndex ( row , 0 , var . get ( ) ) ) ;
2021-07-31 14:04:43 +08:00
}
2021-08-01 23:24:37 +08:00
2022-10-16 23:10:57 +08:00
QJsonArray WatchModel : : toJson ( bool forProject )
2021-10-21 19:33:11 +08:00
{
2022-10-16 23:10:57 +08:00
QJsonArray array ;
foreach ( const PWatchVar & watchVar , watchVars ( forProject ) ) {
QJsonObject obj ;
obj [ " expression " ] = watchVar - > expression ;
obj [ " timestamp " ] = QString ( " %1 " ) . arg ( watchVar - > timestamp ) ;
array . append ( obj ) ;
2021-10-21 19:33:11 +08:00
}
2022-10-16 23:10:57 +08:00
return array ;
2021-10-21 19:33:11 +08:00
}
2021-11-25 20:26:43 +08:00
QModelIndex WatchModel : : index ( PWatchVar var ) const
{
if ( ! var )
return QModelIndex ( ) ;
return index ( var . get ( ) ) ;
}
QModelIndex WatchModel : : index ( WatchVar * pVar ) const {
if ( pVar = = nullptr )
return QModelIndex ( ) ;
2022-10-16 23:10:57 +08:00
PWatchVar parent = pVar - > parent . lock ( ) ;
if ( parent ) {
2021-11-25 20:26:43 +08:00
int row = - 1 ;
2022-10-16 23:10:57 +08:00
for ( int i = 0 ; i < parent - > children . count ( ) ; i + + ) {
if ( parent - > children [ i ] . get ( ) = = pVar ) {
2021-11-25 20:26:43 +08:00
row = i ;
break ;
}
}
if ( row < 0 )
return QModelIndex ( ) ;
return createIndex ( row , 0 , pVar ) ;
} else {
2022-10-16 23:10:57 +08:00
const QList < PWatchVar > & vars = watchVars ( mIsForProject ) ;
2021-11-25 20:26:43 +08:00
int row = - 1 ;
2022-10-16 23:10:57 +08:00
for ( int i = 0 ; i < vars . count ( ) ; i + + ) {
if ( vars [ i ] . get ( ) = = pVar ) {
2021-11-25 20:26:43 +08:00
row = i ;
break ;
}
}
if ( row < 0 )
return QModelIndex ( ) ;
return createIndex ( row , 0 , pVar ) ;
}
}
2022-10-16 23:10:57 +08:00
QList < PWatchVar > WatchModel : : loadJson ( const QJsonArray & jsonArray , qint64 criteriaTimestamp )
{
QList < PWatchVar > result ;
QJsonArray array = jsonArray ;
for ( int i = 0 ; i < jsonArray . count ( ) ; i + + ) {
QJsonValue value = array [ i ] ;
QJsonObject obj = value . toObject ( ) ;
bool ok ;
qint64 timestamp = obj [ " timestamp " ] . toString ( ) . toLongLong ( & ok ) ;
if ( ok & & timestamp > criteriaTimestamp ) {
PWatchVar var = std : : make_shared < WatchVar > ( ) ;
var - > parent = PWatchVar ( ) ;
var - > expression = obj [ " expression " ] . toString ( ) ;
var - > value = tr ( " Execute to evaluate " ) ;
var - > numChild = 0 ;
var - > hasMore = false ;
var - > timestamp = timestamp ;
result . append ( var ) ;
}
}
return result ;
}
2022-01-12 17:14:39 +08:00
bool WatchModel : : setData ( const QModelIndex & index , const QVariant & value , int role )
{
if ( ! index . isValid ( ) ) {
return false ;
}
if ( index . column ( ) = = 2 & & role = = Qt : : EditRole ) {
WatchVar * item = static_cast < WatchVar * > ( index . internalPointer ( ) ) ;
emit setWatchVarValue ( item - > name , value . toString ( ) ) ;
}
return false ;
}
Qt : : ItemFlags WatchModel : : flags ( const QModelIndex & index ) const
{
Qt : : ItemFlags flags = Qt : : ItemIsEnabled | Qt : : ItemIsSelectable ;
if ( ! index . isValid ( ) ) {
return Qt : : ItemIsEnabled ;
}
if ( index . column ( ) = = 2 ) {
WatchVar * item = static_cast < WatchVar * > ( index . internalPointer ( ) ) ;
if ( item - > numChild = = 0 & & ! item - > type . isEmpty ( ) )
flags | = Qt : : ItemIsEditable ;
}
return flags ;
}
2021-10-21 19:33:11 +08:00
2021-09-19 14:28:30 +08:00
QVariant WatchModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
if ( orientation = = Qt : : Horizontal & & role = = Qt : : DisplayRole ) {
switch ( section ) {
case 0 :
return tr ( " Expression " ) ;
case 1 :
2021-11-25 11:24:38 +08:00
return tr ( " Type " ) ;
case 2 :
2021-09-19 14:28:30 +08:00
return tr ( " Value " ) ;
}
}
return QVariant ( ) ;
}
2021-11-25 11:24:38 +08:00
void WatchModel : : fetchMore ( const QModelIndex & parent )
{
2021-11-25 20:26:43 +08:00
if ( ! parent . isValid ( ) ) {
return ;
}
WatchVar * item = static_cast < WatchVar * > ( parent . internalPointer ( ) ) ;
item - > hasMore = false ;
item - > numChild = item - > children . count ( ) ;
emit fetchChildren ( item - > name ) ;
2021-11-25 11:24:38 +08:00
}
bool WatchModel : : canFetchMore ( const QModelIndex & parent ) const
{
if ( ! parent . isValid ( ) ) {
return false ;
}
WatchVar * item = static_cast < WatchVar * > ( parent . internalPointer ( ) ) ;
2021-11-25 20:26:43 +08:00
return item - > numChild > item - > children . count ( ) | | item - > hasMore ;
2021-11-25 11:24:38 +08:00
}
bool WatchModel : : hasChildren ( const QModelIndex & parent ) const
{
if ( ! parent . isValid ( ) ) {
2021-11-25 20:26:43 +08:00
return true ;
2021-11-25 11:24:38 +08:00
}
WatchVar * item = static_cast < WatchVar * > ( parent . internalPointer ( ) ) ;
2022-03-30 20:15:15 +08:00
return item - > numChild > 0 | | item - > hasMore ;
2021-11-25 11:24:38 +08:00
}
2021-08-01 23:24:37 +08:00
RegisterModel : : RegisterModel ( QObject * parent ) : QAbstractTableModel ( parent )
{
2023-02-27 20:08:24 +08:00
# if defined(ARCH_X86_64) || defined(ARCH_X86)
//https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
2023-02-25 21:19:14 +08:00
mRegisterDescriptions . insert ( " rax " , tr ( " 64-bit " ) + " " + tr ( " Accumulator for operands and results data " ) ) ;
mRegisterDescriptions . insert ( " rbx " , tr ( " 64-bit " ) + " " + tr ( " Pointer to data in the DS segment " ) ) ;
mRegisterDescriptions . insert ( " rcx " , tr ( " 64-bit " ) + " " + tr ( " Counter for string and loop operations " ) ) ;
mRegisterDescriptions . insert ( " rdx " , tr ( " 64-bit " ) + " " + tr ( " I/O pointer " ) ) ;
mRegisterDescriptions . insert ( " rsi " , tr ( " 64-bit " ) + " " + tr ( " Source index for string operations; Pointer to data in the segment pointed to by the DS register " ) ) ;
mRegisterDescriptions . insert ( " rdi " , tr ( " 64-bit " ) + " " + tr ( " Destination index for string operations; Pointer to data (or destination) in the segment pointed to by the ES register " ) ) ;
mRegisterDescriptions . insert ( " rsp " , tr ( " 64-bit " ) + " " + tr ( " Stack pointer (in the SS segment) " ) ) ;
mRegisterDescriptions . insert ( " rbp " , tr ( " 64-bit " ) + " " + tr ( " Pointer to data on the stack (in the SS segment) " ) ) ;
mRegisterDescriptions . insert ( " r8 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r9 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r10 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r11 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r12 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r13 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r14 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r15 " , tr ( " 64-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " rip " , tr ( " 64-bit " ) + " " + tr ( " Instruction pointer " ) ) ;
mRegisterDescriptions . insert ( " rflags " , tr ( " Flags " ) ) ;
mRegisterDescriptions . insert ( " eflags " , tr ( " Flags " ) ) ;
mRegisterDescriptions . insert ( " eax " , tr ( " 32-bit " ) + " " + tr ( " Accumulator for operands and results data " ) ) ;
mRegisterDescriptions . insert ( " ebx " , tr ( " 32-bit " ) + " " + tr ( " Pointer to data in the DS segment " ) ) ;
mRegisterDescriptions . insert ( " ecx " , tr ( " 32-bit " ) + " " + tr ( " Counter for string and loop operations " ) ) ;
mRegisterDescriptions . insert ( " edx " , tr ( " 32-bit " ) + " " + tr ( " I/O pointer " ) ) ;
mRegisterDescriptions . insert ( " esi " , tr ( " 32-bit " ) + " " + tr ( " Source index for string operations; Pointer to data in the segment pointed to by the DS register " ) ) ;
mRegisterDescriptions . insert ( " edi " , tr ( " 32-bit " ) + " " + tr ( " Destination index for string operations; Pointer to data (or destination) in the segment pointed to by the ES register " ) ) ;
mRegisterDescriptions . insert ( " esp " , tr ( " 32-bit " ) + " " + tr ( " Stack pointer (in the SS segment) " ) ) ;
mRegisterDescriptions . insert ( " ebp " , tr ( " 32-bit " ) + " " + tr ( " Pointer to data on the stack (in the SS segment) " ) ) ;
mRegisterDescriptions . insert ( " r8d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r9d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r10d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r11d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r12d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r13d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r14d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " r15d " , tr ( " 32-bit " ) + " " + tr ( " General purpose " ) ) ;
mRegisterDescriptions . insert ( " eip " , tr ( " 32-bit " ) + " " + tr ( " Instruction pointer " ) ) ;
mRegisterDescriptions . insert ( " ax " , tr ( " lower 16 bits of %1 " ) . arg ( " rax/eax " ) ) ;
mRegisterDescriptions . insert ( " bx " , tr ( " lower 16 bits of %1 " ) . arg ( " rbx/rbx " ) ) ;
mRegisterDescriptions . insert ( " cx " , tr ( " lower 16 bits of %1 " ) . arg ( " rcx/ecx " ) ) ;
mRegisterDescriptions . insert ( " dx " , tr ( " lower 16 bits of %1 " ) . arg ( " rdx/edx " ) ) ;
mRegisterDescriptions . insert ( " si " , tr ( " lower 16 bits of %1 " ) . arg ( " rsi/esi " ) ) ;
mRegisterDescriptions . insert ( " di " , tr ( " lower 16 bits of %1 " ) . arg ( " rdi/edi " ) ) ;
mRegisterDescriptions . insert ( " sp " , tr ( " lower 16 bits of %1 " ) . arg ( " rsp/esp " ) ) ;
mRegisterDescriptions . insert ( " bp " , tr ( " lower 16 bits of %1 " ) . arg ( " rbp/esp " ) ) ;
mRegisterDescriptions . insert ( " r8w " , tr ( " lower 16 bits of %1 " ) . arg ( " r8 " ) ) ;
mRegisterDescriptions . insert ( " r9w " , tr ( " lower 16 bits of %1 " ) . arg ( " r9 " ) ) ;
mRegisterDescriptions . insert ( " r10w " , tr ( " lower 16 bits of %1 " ) . arg ( " r10 " ) ) ;
mRegisterDescriptions . insert ( " r11w " , tr ( " lower 16 bits of %1 " ) . arg ( " r11 " ) ) ;
mRegisterDescriptions . insert ( " r12w " , tr ( " lower 16 bits of %1 " ) . arg ( " r12 " ) ) ;
mRegisterDescriptions . insert ( " r13w " , tr ( " lower 16 bits of %1 " ) . arg ( " r13 " ) ) ;
mRegisterDescriptions . insert ( " r14w " , tr ( " lower 16 bits of %1 " ) . arg ( " r14 " ) ) ;
mRegisterDescriptions . insert ( " r15w " , tr ( " lower 16 bits of %1 " ) . arg ( " r15 " ) ) ;
mRegisterDescriptions . insert ( " ip " , tr ( " lower 16 bits of %1 " ) . arg ( " rip/eip " ) ) ;
mRegisterDescriptions . insert ( " al " , tr ( " lower 8 bits of %1 " ) . arg ( " rax/eax " ) ) ;
mRegisterDescriptions . insert ( " bl " , tr ( " lower 8 bits of %1 " ) . arg ( " rbx/rbx " ) ) ;
mRegisterDescriptions . insert ( " cl " , tr ( " lower 8 bits of %1 " ) . arg ( " rcx/ecx " ) ) ;
mRegisterDescriptions . insert ( " dl " , tr ( " lower 8 bits of %1 " ) . arg ( " rdx/edx " ) ) ;
mRegisterDescriptions . insert ( " sil " , tr ( " lower 8 bits of %1 " ) . arg ( " rsi/esi " ) ) ;
mRegisterDescriptions . insert ( " dil " , tr ( " lower 8 bits of %1 " ) . arg ( " rdi/edi " ) ) ;
mRegisterDescriptions . insert ( " spl " , tr ( " lower 8 bits of %1 " ) . arg ( " rsp/esp " ) ) ;
mRegisterDescriptions . insert ( " bpl " , tr ( " lower 8 bits of %1 " ) . arg ( " rbp/esp " ) ) ;
mRegisterDescriptions . insert ( " r8b " , tr ( " lower 8 bits of %1 " ) . arg ( " r8 " ) ) ;
mRegisterDescriptions . insert ( " r9b " , tr ( " lower 8 bits of %1 " ) . arg ( " r9 " ) ) ;
mRegisterDescriptions . insert ( " r10b " , tr ( " lower 8 bits of %1 " ) . arg ( " r10 " ) ) ;
mRegisterDescriptions . insert ( " r11b " , tr ( " lower 8 bits of %1 " ) . arg ( " r11 " ) ) ;
mRegisterDescriptions . insert ( " r12b " , tr ( " lower 8 bits of %1 " ) . arg ( " r12 " ) ) ;
mRegisterDescriptions . insert ( " r13b " , tr ( " lower 8 bits of %1 " ) . arg ( " r13 " ) ) ;
mRegisterDescriptions . insert ( " r14b " , tr ( " lower 8 bits of %1 " ) . arg ( " r14 " ) ) ;
mRegisterDescriptions . insert ( " r15b " , tr ( " lower 8 bits of %1 " ) . arg ( " r15 " ) ) ;
mRegisterDescriptions . insert ( " ah " , tr ( " 8 high bits of lower 16 bits of %1 " ) . arg ( " rax/eax " ) ) ;
mRegisterDescriptions . insert ( " bh " , tr ( " 8 high bits of lower 16 bits of %1 " ) . arg ( " rbx/rbx " ) ) ;
mRegisterDescriptions . insert ( " ch " , tr ( " 8 high bits of lower 16 bits of %1 " ) . arg ( " rcx/ecx " ) ) ;
mRegisterDescriptions . insert ( " dh " , tr ( " 8 high bits of lower 16 bits of %1 " ) . arg ( " rdx/edx " ) ) ;
mRegisterDescriptions . insert ( " cs " , tr ( " 16-bit " ) + " " + tr ( " Code segment selector " ) ) ;
mRegisterDescriptions . insert ( " ds " , tr ( " 16-bit " ) + " " + tr ( " Data segment selector " ) ) ;
mRegisterDescriptions . insert ( " es " , tr ( " 16-bit " ) + " " + tr ( " Extra data segment selector " ) ) ;
mRegisterDescriptions . insert ( " fs " , tr ( " 16-bit " ) + " " + tr ( " Extra data segment selector " ) ) ;
mRegisterDescriptions . insert ( " gs " , tr ( " 16-bit " ) + " " + tr ( " Extra data segment selector " ) ) ;
mRegisterDescriptions . insert ( " ss " , tr ( " 16-bit " ) + " " + tr ( " Stack segment selector " ) ) ;
//x87 fpu
mRegisterDescriptions . insert ( " st0 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st1 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st2 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st3 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st4 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st5 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st6 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " st7 " , tr ( " Floating-point data " ) ) ;
mRegisterDescriptions . insert ( " fctrl " , tr ( " Floating-point control " ) ) ;
mRegisterDescriptions . insert ( " fstat " , tr ( " Floating-point status " ) ) ;
mRegisterDescriptions . insert ( " ftag " , tr ( " Floating-point tag word " ) ) ;
mRegisterDescriptions . insert ( " fop " , tr ( " Floating-point operation " ) ) ;
mRegisterDescriptions . insert ( " fiseg " , tr ( " Floating-point last instruction segment " ) ) ;
mRegisterDescriptions . insert ( " fioff " , tr ( " Floating-point last instruction offset " ) ) ;
mRegisterDescriptions . insert ( " foseg " , tr ( " Floating-point last operand segment " ) ) ;
mRegisterDescriptions . insert ( " fooff " , tr ( " Floating-point last operand offset " ) ) ;
mRegisterDescriptions . insert ( " mm0 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm1 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm2 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm3 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm4 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm5 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm6 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " mm7 " , tr ( " 64-bit " ) + " " + " MMX " ) ;
mRegisterDescriptions . insert ( " xmm0 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm1 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm2 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm3 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm4 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm5 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm6 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm7 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm8 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm9 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm11 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm12 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm13 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm14 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
mRegisterDescriptions . insert ( " xmm15 " , tr ( " 128-bit " ) + " " + " XMM " ) ;
2023-03-04 12:47:49 +08:00
mRegisterDescriptions . insert ( " ymm0 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm1 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm2 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm3 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm4 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm5 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm6 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm7 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm8 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm9 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm11 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm12 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm13 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm14 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
mRegisterDescriptions . insert ( " ymm15 " , tr ( " 256-bit " ) + " " + " YMM " ) ;
2023-02-25 21:19:14 +08:00
mRegisterDescriptions . insert ( " mxscr " , tr ( " SSE status and control " ) ) ;
2021-08-01 23:24:37 +08:00
2023-02-27 20:08:24 +08:00
# endif
2021-08-01 23:24:37 +08:00
}
2021-10-20 18:05:43 +08:00
int RegisterModel : : rowCount ( const QModelIndex & ) const
2021-08-01 23:24:37 +08:00
{
2021-11-25 09:05:45 +08:00
return mRegisterNames . count ( ) ;
2021-08-01 23:24:37 +08:00
}
2021-10-20 18:05:43 +08:00
int RegisterModel : : columnCount ( const QModelIndex & ) const
2021-08-01 23:24:37 +08:00
{
2021-11-25 09:05:45 +08:00
return 2 ;
2021-08-01 23:24:37 +08:00
}
QVariant RegisterModel : : data ( const QModelIndex & index , int role ) const
{
if ( ! index . isValid ( ) )
return QVariant ( ) ;
2021-11-25 09:05:45 +08:00
if ( index . row ( ) < 0 | | index . row ( ) > = static_cast < int > ( mRegisterNames . size ( ) ) )
2021-08-01 23:24:37 +08:00
return QVariant ( ) ;
switch ( role ) {
case Qt : : DisplayRole :
switch ( index . column ( ) ) {
case 0 :
2021-11-25 09:05:45 +08:00
return mRegisterNames [ index . row ( ) ] ;
2021-08-01 23:24:37 +08:00
case 1 :
2022-12-02 10:19:03 +08:00
return mRegisterValues . value (
mRegisterNameIndex . value ( index . row ( ) , - 1 )
, " " ) ;
2021-08-01 23:24:37 +08:00
}
2023-02-25 21:19:14 +08:00
break ;
case Qt : : ToolTipRole :
switch ( index . column ( ) ) {
case 0 :
return mRegisterDescriptions . value ( mRegisterNames [ index . row ( ) ] , " " ) ;
case 1 :
return mRegisterValues . value (
mRegisterNameIndex . value ( index . row ( ) , - 1 )
, " " ) ;
}
break ;
2021-08-01 23:24:37 +08:00
default :
2023-02-25 21:19:14 +08:00
break ;
2021-08-01 23:24:37 +08:00
}
2023-02-25 21:19:14 +08:00
return QVariant ( ) ;
2021-08-01 23:24:37 +08:00
}
QVariant RegisterModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
if ( orientation = = Qt : : Horizontal & & role = = Qt : : DisplayRole ) {
switch ( section ) {
case 0 :
return tr ( " Register " ) ;
case 1 :
2021-11-25 09:05:45 +08:00
return tr ( " Value " ) ;
2021-08-01 23:24:37 +08:00
}
}
return QVariant ( ) ;
}
2021-11-25 09:05:45 +08:00
void RegisterModel : : updateNames ( const QStringList & regNames )
2021-08-01 23:24:37 +08:00
{
beginResetModel ( ) ;
2022-12-02 10:19:03 +08:00
mRegisterNameIndex . clear ( ) ;
mRegisterNames . clear ( ) ;
for ( int i = 0 ; i < regNames . length ( ) ; i + + ) {
QString regName = regNames [ i ] . trimmed ( ) ;
if ( ! regName . isEmpty ( ) ) {
mRegisterNames . append ( regNames [ i ] ) ;
mRegisterNameIndex . insert ( mRegisterNames . count ( ) - 1 , i ) ;
}
}
2021-08-01 23:24:37 +08:00
endResetModel ( ) ;
}
2021-11-25 09:05:45 +08:00
void RegisterModel : : updateValues ( const QHash < int , QString > registerValues )
{
mRegisterValues = registerValues ;
emit dataChanged ( createIndex ( 0 , 1 ) ,
createIndex ( mRegisterNames . count ( ) - 1 , 1 ) ) ;
}
2021-08-01 23:24:37 +08:00
void RegisterModel : : clear ( )
{
beginResetModel ( ) ;
2021-11-25 09:05:45 +08:00
mRegisterNames . clear ( ) ;
mRegisterValues . clear ( ) ;
2021-08-01 23:24:37 +08:00
endResetModel ( ) ;
}
2021-12-25 18:09:50 +08:00
DebugTarget : : DebugTarget (
const QString & inferior ,
const QString & GDBServer ,
int port ,
2023-01-12 12:07:22 +08:00
const QString & arguments ,
2021-12-25 18:09:50 +08:00
QObject * parent ) :
QThread ( parent ) ,
mInferior ( inferior ) ,
2023-01-12 12:07:22 +08:00
mArguments ( arguments ) ,
2021-12-25 18:09:50 +08:00
mGDBServer ( GDBServer ) ,
mPort ( port ) ,
mStop ( false ) ,
2021-12-25 20:02:53 +08:00
mStartSemaphore ( 0 ) ,
mErrorOccured ( false )
2021-12-25 18:09:50 +08:00
{
2021-12-25 20:02:53 +08:00
mProcess = nullptr ;
2021-12-25 18:09:50 +08:00
}
2022-01-12 18:47:50 +08:00
void DebugTarget : : setInputFile ( const QString & inputFile )
{
mInputFile = inputFile ;
}
2021-12-25 18:09:50 +08:00
void DebugTarget : : stopDebug ( )
{
mStop = true ;
}
void DebugTarget : : waitStart ( )
{
mStartSemaphore . acquire ( 1 ) ;
}
2022-06-16 21:56:07 +08:00
const QStringList & DebugTarget : : binDirs ( ) const
{
return mBinDirs ;
}
void DebugTarget : : addBinDirs ( const QStringList & binDirs )
{
mBinDirs . append ( binDirs ) ;
}
void DebugTarget : : addBinDir ( const QString & binDir )
{
mBinDirs . append ( binDir ) ;
}
2021-12-25 18:09:50 +08:00
void DebugTarget : : run ( )
{
mStop = false ;
2021-12-25 20:02:53 +08:00
mErrorOccured = false ;
2021-12-25 18:09:50 +08:00
//find first available port
QString cmd ;
QString arguments ;
# ifdef Q_OS_WIN
cmd = mGDBServer ;
2023-01-12 12:07:22 +08:00
arguments = QString ( " localhost:%1 \" %2 \" %3 " ) . arg ( mPort ) . arg ( mInferior , mArguments ) ;
2021-12-25 18:09:50 +08:00
# else
2023-03-04 18:44:39 +08:00
cmd = pSettings - > environment ( ) . terminalPathForExec ( ) ;
2022-01-12 18:47:50 +08:00
arguments = QString ( " -e \" %1 \" localhost:%2 \" %3 \" " ) . arg ( mGDBServer ) . arg ( mPort ) . arg ( mInferior ) ;
2021-12-25 18:09:50 +08:00
# endif
QString workingDir = QFileInfo ( mInferior ) . path ( ) ;
mProcess = std : : make_shared < QProcess > ( ) ;
2021-12-25 20:02:53 +08:00
auto action = finally ( [ & ] {
mProcess . reset ( ) ;
} ) ;
2021-12-25 18:09:50 +08:00
mProcess - > setProgram ( cmd ) ;
2022-01-04 16:50:54 +08:00
mProcess - > setArguments ( splitProcessCommand ( arguments ) ) ;
2021-12-25 18:09:50 +08:00
mProcess - > setProcessChannelMode ( QProcess : : MergedChannels ) ;
2022-06-16 21:56:07 +08:00
QProcessEnvironment env = QProcessEnvironment : : systemEnvironment ( ) ;
QString path = env . value ( " PATH " ) ;
QStringList pathAdded = mBinDirs ;
if ( ! path . isEmpty ( ) ) {
path = pathAdded . join ( PATH_SEPARATOR ) + PATH_SEPARATOR + path ;
} else {
path = pathAdded . join ( PATH_SEPARATOR ) ;
}
2021-12-25 18:09:50 +08:00
QString cmdDir = extractFileDir ( cmd ) ;
if ( ! cmdDir . isEmpty ( ) ) {
2022-06-16 21:56:07 +08:00
path = cmdDir + PATH_SEPARATOR + path ;
2021-12-25 18:09:50 +08:00
}
2022-06-16 21:56:07 +08:00
env . insert ( " PATH " , path ) ;
mProcess - > setProcessEnvironment ( env ) ;
2021-12-25 18:09:50 +08:00
mProcess - > setWorkingDirectory ( workingDir ) ;
# ifdef Q_OS_WIN
mProcess - > setCreateProcessArgumentsModifier ( [ this ] ( QProcess : : CreateProcessArguments * args ) {
if ( programHasConsole ( mInferior ) ) {
args - > flags | = CREATE_NEW_CONSOLE ;
args - > flags & = ~ CREATE_NO_WINDOW ;
}
2022-01-12 18:47:50 +08:00
if ( mInputFile . isEmpty ( ) ) {
args - > startupInfo - > dwFlags & = ~ STARTF_USESTDHANDLES ;
2022-01-12 19:25:37 +08:00
} else {
args - > startupInfo - > hStdOutput = NULL ;
args - > startupInfo - > hStdError = NULL ;
2022-01-12 18:47:50 +08:00
}
2022-01-12 19:25:37 +08:00
2021-12-25 18:09:50 +08:00
} ) ;
# endif
connect ( mProcess . get ( ) , & QProcess : : errorOccurred ,
[ & ] ( ) {
2021-12-25 20:02:53 +08:00
mErrorOccured = true ;
2021-12-25 18:09:50 +08:00
} ) ;
mProcess - > start ( ) ;
mProcess - > waitForStarted ( 5000 ) ;
mStartSemaphore . release ( 1 ) ;
2022-01-12 18:47:50 +08:00
if ( mProcess - > state ( ) = = QProcess : : Running & & ! mInputFile . isEmpty ( ) ) {
mProcess - > write ( readFileToByteArray ( mInputFile ) ) ;
2022-03-31 09:56:49 +08:00
mProcess - > waitForFinished ( 0 ) ;
2022-01-12 18:47:50 +08:00
}
2022-03-31 09:56:49 +08:00
bool writeChannelClosed = false ;
2021-12-25 18:09:50 +08:00
while ( true ) {
2022-03-31 09:56:49 +08:00
if ( mProcess - > bytesToWrite ( ) = = 0 & & ! writeChannelClosed ) {
writeChannelClosed = true ;
mProcess - > closeWriteChannel ( ) ;
}
2021-12-25 18:09:50 +08:00
mProcess - > waitForFinished ( 1 ) ;
if ( mProcess - > state ( ) ! = QProcess : : Running ) {
break ;
}
if ( mStop ) {
mProcess - > terminate ( ) ;
mProcess - > kill ( ) ;
break ;
}
2021-12-25 20:02:53 +08:00
if ( mErrorOccured )
2021-12-25 18:09:50 +08:00
break ;
msleep ( 1 ) ;
}
2021-12-25 20:02:53 +08:00
if ( mErrorOccured ) {
2021-12-25 18:09:50 +08:00
emit processError ( mProcess - > error ( ) ) ;
}
}
2022-01-11 22:29:03 +08:00
MemoryModel : : MemoryModel ( int dataPerLine , QObject * parent ) :
QAbstractTableModel ( parent ) ,
mDataPerLine ( dataPerLine ) ,
mStartAddress ( 0 )
{
}
void MemoryModel : : updateMemory ( const QStringList & value )
{
2022-07-21 15:28:07 +08:00
int maxDataPerLine = - 1 ;
2022-01-11 22:29:03 +08:00
QRegExp delimiter ( " ( \\ s+) " ) ;
QList < PMemoryLine > newModel ;
for ( int i = 0 ; i < value . length ( ) ; i + + ) {
QString line = value [ i ] . trimmed ( ) ;
2022-07-24 11:19:11 +08:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
2022-07-04 11:39:06 +08:00
QStringList dataLst = line . split ( delimiter , Qt : : SkipEmptyParts ) ;
# else
2022-01-11 22:29:03 +08:00
QStringList dataLst = line . split ( delimiter , QString : : SkipEmptyParts ) ;
2022-07-04 11:39:06 +08:00
# endif
2022-01-11 22:29:03 +08:00
PMemoryLine memoryLine = std : : make_shared < MemoryLine > ( ) ;
memoryLine - > startAddress = - 1 ;
if ( dataLst . length ( ) > 0 ) {
2022-07-04 11:39:06 +08:00
bool isOk ;
memoryLine - > startAddress = stringToHex ( dataLst [ 0 ] , isOk ) ;
if ( isOk ) {
2022-07-21 15:28:07 +08:00
if ( dataLst . length ( ) - 1 > maxDataPerLine )
maxDataPerLine = dataLst . length ( ) - 1 ;
2022-07-04 11:39:06 +08:00
for ( int j = 1 ; j < dataLst . length ( ) ; j + + ) {
qulonglong data = stringToHex ( dataLst [ j ] , isOk ) ;
if ( isOk )
memoryLine - > datas . append ( ( unsigned char ) data ) ;
else
memoryLine - > datas . append ( 0 ) ;
}
} else {
memoryLine - > startAddress = 0 ;
2022-01-11 22:29:03 +08:00
}
2022-07-04 11:39:06 +08:00
2022-01-11 22:29:03 +08:00
}
newModel . append ( memoryLine ) ;
}
if ( newModel . count ( ) > 0 & & newModel . count ( ) = = mLines . count ( ) & &
2022-07-21 15:28:07 +08:00
newModel [ 0 ] - > startAddress = = mLines [ 0 ] - > startAddress & &
maxDataPerLine = = mDataPerLine ) {
2022-01-11 22:29:03 +08:00
for ( int i = 0 ; i < newModel . count ( ) ; i + + ) {
PMemoryLine newLine = newModel [ i ] ;
PMemoryLine oldLine = mLines [ i ] ;
for ( int j = 0 ; j < newLine - > datas . count ( ) ; j + + ) {
if ( j > = oldLine - > datas . count ( ) )
break ;
if ( newLine - > datas [ j ] ! = oldLine - > datas [ j ] )
newLine - > changedDatas . insert ( j ) ;
}
}
mLines = newModel ;
emit dataChanged ( createIndex ( 0 , 0 ) ,
createIndex ( mLines . count ( ) - 1 , mDataPerLine - 1 ) ) ;
} else {
beginResetModel ( ) ;
2022-07-21 15:28:07 +08:00
if ( maxDataPerLine > 0 )
mDataPerLine = maxDataPerLine ;
2022-01-11 22:29:03 +08:00
mLines = newModel ;
endResetModel ( ) ;
}
if ( mLines . count ( ) > 0 ) {
mStartAddress = mLines [ 0 ] - > startAddress ;
} else {
mStartAddress = 0 ;
}
}
2022-07-04 11:39:06 +08:00
int MemoryModel : : rowCount ( const QModelIndex & /*parent*/ ) const
2022-01-11 22:29:03 +08:00
{
return mLines . count ( ) ;
}
2022-07-04 11:39:06 +08:00
int MemoryModel : : columnCount ( const QModelIndex & /*parent*/ ) const
2022-01-11 22:29:03 +08:00
{
2023-02-25 21:42:30 +08:00
return mDataPerLine + 1 ;
2022-01-11 22:29:03 +08:00
}
QVariant MemoryModel : : data ( const QModelIndex & index , int role ) const
{
if ( ! index . isValid ( ) )
return QVariant ( ) ;
if ( index . row ( ) < 0 | | index . row ( ) > = mLines . count ( ) )
return QVariant ( ) ;
PMemoryLine line = mLines [ index . row ( ) ] ;
int col = index . column ( ) ;
2023-02-25 21:42:30 +08:00
if ( col < 0 | | col > line - > datas . count ( ) )
2022-01-11 22:29:03 +08:00
return QVariant ( ) ;
2023-02-25 21:42:30 +08:00
if ( role = = Qt : : DisplayRole ) {
if ( col = = line - > datas . count ( ) ) {
QString s ;
foreach ( unsigned char ch , line - > datas ) {
if ( ch < ' ' | | ch > = 128 )
s + = ' . ' ;
else
s + = ch ;
}
return s ;
} else
return QString ( " %1 " ) . arg ( line - > datas [ col ] , 2 , 16 , QChar ( ' 0 ' ) ) ;
2023-03-03 17:20:33 +08:00
} else if ( role = = Qt : : ToolTipRole ) {
if ( col < line - > datas . count ( ) ) {
2023-03-04 18:23:57 +08:00
QString s =
tr ( " addr: %1 " ) . arg ( line - > startAddress + col , 0 , 16 )
+ " <br/> "
+ tr ( " dec: %1 " ) . arg ( line - > datas [ col ] )
2023-03-04 12:47:49 +08:00
+ " <br/> "
+ tr ( " oct: %1 " ) . arg ( line - > datas [ col ] , 0 , 8 )
+ " <br/> "
+ tr ( " bin: %1 " ) . arg ( line - > datas [ col ] , 8 , 2 , QChar ( ' 0 ' ) )
+ " <br/> " ;
2023-03-03 17:20:33 +08:00
QString chVal ;
if ( line - > datas [ col ] = = 0 ) {
chVal = " \\ 0 " ;
} else if ( line - > datas [ col ] = = ' \n ' ) {
chVal = " \\ n " ;
} else if ( line - > datas [ col ] = = ' \t ' ) {
chVal = " \\ t " ;
} else if ( line - > datas [ col ] = = ' \r ' ) {
chVal = " \\ r " ;
2023-03-04 12:47:49 +08:00
} else if ( line - > datas [ col ] > = ' ' & & line - > datas [ col ] < 127 ) {
2023-03-03 17:20:33 +08:00
chVal = QChar ( line - > datas [ col ] ) ;
}
if ( ! chVal . isEmpty ( ) ) {
2023-03-04 12:47:49 +08:00
s + = tr ( " ascii: \' %1 \' " ) . arg ( chVal )
+ " <br/> " ;
2023-03-03 17:20:33 +08:00
}
return s ;
}
2023-02-25 21:42:30 +08:00
}
2022-01-11 22:29:03 +08:00
return QVariant ( ) ;
}
QVariant MemoryModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
if ( orientation = = Qt : : Vertical & & role = = Qt : : DisplayRole ) {
if ( section < 0 | | section > = mLines . count ( ) )
return QVariant ( ) ;
PMemoryLine line = mLines [ section ] ;
return QString ( " 0x%1 " ) . arg ( line - > startAddress , 0 , 16 , QChar ( ' 0 ' ) ) ;
}
return QVariant ( ) ;
}
bool MemoryModel : : setData ( const QModelIndex & index , const QVariant & value , int role )
{
if ( ! index . isValid ( ) )
return false ;
if ( index . row ( ) < 0 | | index . row ( ) > = mLines . count ( ) )
return false ;
PMemoryLine line = mLines [ index . row ( ) ] ;
int col = index . column ( ) ;
if ( col < 0 | | col > = line - > datas . count ( ) )
return false ;
if ( role = = Qt : : EditRole & & mStartAddress > 0 ) {
bool ok ;
unsigned char val = ( " 0x " + value . toString ( ) ) . toUInt ( & ok , 16 ) ;
2022-07-04 11:39:06 +08:00
if ( ! ok )
2022-01-11 22:29:03 +08:00
return false ;
emit setMemoryData ( mStartAddress + mDataPerLine * index . row ( ) + col , val ) ;
return true ;
}
return false ;
}
2022-07-04 11:39:06 +08:00
Qt : : ItemFlags MemoryModel : : flags ( const QModelIndex & /*index*/ ) const
2022-01-11 22:29:03 +08:00
{
Qt : : ItemFlags flags = Qt : : ItemIsEnabled | Qt : : ItemIsSelectable ;
if ( mStartAddress ! = 0 )
flags | = Qt : : ItemIsEditable ;
return flags ;
}
qulonglong MemoryModel : : startAddress ( ) const
{
return mStartAddress ;
}
void MemoryModel : : reset ( )
{
mStartAddress = 0 ;
mLines . clear ( ) ;
}