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"
2024-03-09 11:34:52 +08:00
# include "gdbmidebugger.h"
2021-07-17 19:32:23 +08:00
# include "utils.h"
2024-02-28 19:41:05 +08:00
# include "utils/parsearg.h"
2021-07-17 19:32:23 +08:00
# 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 ;
2024-03-08 22:06:10 +08:00
mClient = 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
}
2024-03-10 21:25:24 +08:00
bool Debugger : : startClient ( int compilerSetIndex ,
const QString & inferior ,
bool inferiorHasSymbols ,
bool inferiorHasBreakpoints ,
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
}
2023-08-08 12:44:46 +08:00
setForceUTF8 ( compilerSet - > forceUTF8 ( ) ) ;
setDebugInfosUsingUTF8 ( compilerSet - > isDebugInfoUsingUTF8 ( ) ) ;
2023-01-22 22:19:19 +08:00
if ( compilerSet - > debugger ( ) . endsWith ( LLDB_MI_PROGRAM ) )
setDebuggerType ( DebuggerType : : LLDB_MI ) ;
else
setDebuggerType ( DebuggerType : : GDB ) ;
2024-01-18 16:14:36 +08:00
// force to lldb-server if using lldb-mi, which creates new console but does not bind inferior’ s stdio to the new console on Windows.
2024-03-11 20:34:02 +08:00
setUseDebugServer ( pSettings - > debugger ( ) . useGDBServer ( ) | | mDebuggerType = = DebuggerType : : LLDB_MI ) ;
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
}
2024-01-18 16:14:36 +08:00
if ( useDebugServer ( ) ) {
2021-12-25 18:09:50 +08:00
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 ( ) ;
2024-01-18 16:14:36 +08:00
if ( useDebugServer ( ) ) {
2022-10-10 18:05:18 +08:00
//deleted when thread finished
2023-12-22 18:07:26 +08:00
QStringList params ;
2023-01-12 12:07:22 +08:00
if ( pSettings - > executor ( ) . useParams ( ) )
2024-02-28 19:41:05 +08:00
params = parseArgumentsWithoutVariables ( pSettings - > executor ( ) . params ( ) ) ;
2023-01-12 12:07:22 +08:00
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
2024-03-10 09:56:20 +08:00
mClient = new GDBMIDebuggerClient ( this , debuggerType ( ) ) ;
2024-03-08 22:06:10 +08:00
mClient - > addBinDirs ( binDirs ) ;
mClient - > addBinDir ( pSettings - > dirs ( ) . appDir ( ) ) ;
mClient - > setDebuggerPath ( debuggerPath ) ;
connect ( mClient , & QThread : : finished , this , & Debugger : : cleanUpReader ) ;
connect ( mClient , & QThread : : finished , mMemoryModel . get ( ) , & MemoryModel : : reset ) ;
connect ( mClient , & DebuggerClient : : parseFinished , this , & Debugger : : syncFinishedParsing , Qt : : BlockingQueuedConnection ) ;
connect ( mClient , & DebuggerClient : : changeDebugConsoleLastLine , this , & Debugger : : onChangeDebugConsoleLastline ) ;
connect ( mClient , & DebuggerClient : : cmdStarted , pMainWindow , & MainWindow : : disableDebugActions ) ;
connect ( mClient , & DebuggerClient : : cmdFinished , pMainWindow , & MainWindow : : enableDebugActions ) ;
connect ( mClient , & DebuggerClient : : inferiorStopped , pMainWindow , & MainWindow : : enableDebugActions ) ;
connect ( mClient , & DebuggerClient : : breakpointInfoGetted , mBreakpointModel . get ( ) ,
2021-11-21 08:38:03 +08:00
& BreakpointModel : : updateBreakpointNumber ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : localsUpdated , pMainWindow ,
2021-11-24 10:07:35 +08:00
& MainWindow : : onLocalsReady ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : memoryUpdated , this ,
2021-11-25 07:42:56 +08:00
& Debugger : : updateMemory ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : evalUpdated , this ,
2021-11-25 07:42:56 +08:00
& Debugger : : updateEval ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : disassemblyUpdate , this ,
2021-11-24 23:32:34 +08:00
& Debugger : : updateDisassembly ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : registerNamesUpdated , this ,
2021-11-25 09:05:45 +08:00
& Debugger : : updateRegisterNames ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : registerValuesUpdated , this ,
2021-11-25 09:05:45 +08:00
& Debugger : : updateRegisterValues ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : varCreated , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : updateVarInfo ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : prepareVarChildren , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : prepareVarChildren ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : addVarChild , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : addVarChild ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : varValueUpdated , mWatchModel . get ( ) ,
2021-11-25 20:26:43 +08:00
& WatchModel : : updateVarValue ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : varsValueUpdated , mWatchModel . get ( ) ,
2022-03-30 19:28:46 +08:00
& WatchModel : : updateAllHasMoreVars ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : inferiorContinued , pMainWindow ,
2021-11-24 21:22:01 +08:00
& MainWindow : : removeActiveBreakpoints ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : inferiorStopped , pMainWindow ,
2021-11-24 17:53:25 +08:00
& MainWindow : : setActiveBreakpoint ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : watchpointHitted , pMainWindow ,
2023-03-03 17:20:33 +08:00
& MainWindow : : onWatchpointHitted ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : errorNoSymbolTable , pMainWindow ,
2023-02-18 12:08:03 +08:00
& MainWindow : : stopDebugForNoSymbolTable ) ;
2024-03-08 22:06:10 +08:00
connect ( mClient , & DebuggerClient : : inferiorStopped , this ,
2022-01-11 22:29:03 +08:00
& Debugger : : refreshAll ) ;
2021-09-19 14:28:30 +08:00
2024-03-08 22:06:10 +08:00
mClient - > start ( ) ;
mClient - > waitStart ( ) ;
2021-07-25 00:26:13 +08:00
2024-03-10 21:25:24 +08:00
mClient - > initialize ( inferior , inferiorHasSymbols ) ;
includeOrSkipDirsInSymbolSearch ( compilerSet - > libDirs ( ) , pSettings - > debugger ( ) . skipCustomLibraries ( ) ) ;
includeOrSkipDirsInSymbolSearch ( compilerSet - > CIncludeDirs ( ) , pSettings - > debugger ( ) . skipCustomLibraries ( ) ) ;
includeOrSkipDirsInSymbolSearch ( compilerSet - > CppIncludeDirs ( ) , pSettings - > debugger ( ) . skipCustomLibraries ( ) ) ;
//gcc system libraries is auto loaded by gdb
if ( pSettings - > debugger ( ) . skipSystemLibraries ( ) ) {
includeOrSkipDirsInSymbolSearch ( compilerSet - > defaultCIncludeDirs ( ) , true ) ;
includeOrSkipDirsInSymbolSearch ( compilerSet - > defaultCIncludeDirs ( ) , true ) ;
includeOrSkipDirsInSymbolSearch ( compilerSet - > defaultCppIncludeDirs ( ) , true ) ;
}
2021-07-25 00:26:13 +08:00
2024-03-10 21:25:24 +08:00
sendAllBreakpointsToDebugger ( ) ;
pMainWindow - > updateAppTitle ( ) ;
mInferiorHasBreakpoints = inferiorHasBreakpoints ;
2021-08-20 12:43:01 +08:00
return true ;
2021-07-25 13:03:46 +08:00
}
2024-03-10 21:25:24 +08:00
void Debugger : : runInferior ( )
{
if ( mClient )
mClient - > runInferior ( mInferiorHasBreakpoints ) ;
}
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 ;
}
2024-03-08 22:06:10 +08:00
mClient - > stopDebug ( ) ;
2021-07-31 14:04:43 +08:00
}
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
2024-03-08 22:06:10 +08:00
mClient - > deleteLater ( ) ;
mClient = 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 ( ) ;
2024-03-10 09:56:20 +08:00
if ( mClient )
2024-03-09 23:08:23 +08:00
mClient - > refreshStackVariables ( ) ;
if ( memoryModel ( ) - > startAddress ( ) > 0
2024-03-10 09:56:20 +08:00
& & mClient )
2024-03-09 23:08:23 +08:00
mClient - > readMemory (
2024-03-10 11:15:10 +08:00
QString ( " %1 " ) . arg ( memoryModel ( ) - > startAddress ( ) ) ,
2024-03-09 23:08:23 +08:00
pSettings - > debugger ( ) . memoryViewRows ( ) ,
pSettings - > debugger ( ) . memoryViewColumns ( )
2022-07-21 15:28:07 +08:00
) ;
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-08-29 22:08:43 +08:00
bool Debugger : : commandRunning ( )
{
2024-03-10 09:56:20 +08:00
if ( mClient ) {
2024-03-08 22:06:10 +08:00
return mClient - > commandRunning ( ) ;
2021-08-29 22:08:43 +08:00
}
return false ;
}
2021-11-24 21:22:01 +08:00
bool Debugger : : inferiorRunning ( )
{
2024-03-10 09:56:20 +08:00
if ( mClient ) {
2024-03-08 22:06:10 +08:00
return mClient - > inferiorRunning ( ) ;
2021-11-24 21:22:01 +08:00
}
return false ;
}
2021-12-27 10:59:04 +08:00
void Debugger : : interrupt ( )
{
2024-03-10 11:15:10 +08:00
if ( mClient )
2024-03-09 23:08:23 +08:00
mClient - > interrupt ( ) ;
2024-03-10 11:15:10 +08:00
}
void Debugger : : stepOver ( )
{
if ( mClient )
mClient - > stepOver ( ) ;
}
void Debugger : : stepInto ( )
{
if ( mClient )
mClient - > stepInto ( ) ;
}
void Debugger : : stepOut ( )
{
if ( mClient )
mClient - > stepOut ( ) ;
}
void Debugger : : runTo ( const QString & filename , int line )
{
if ( mClient )
mClient - > runTo ( filename , line ) ;
}
void Debugger : : resume ( )
{
if ( mClient )
mClient - > resume ( ) ;
}
void Debugger : : stepOverInstruction ( )
{
if ( mClient )
mClient - > stepOverInstruction ( ) ;
}
void Debugger : : stepIntoInstruction ( )
{
if ( mClient )
mClient - > stepIntoInstruction ( ) ;
2021-12-27 10:59:04 +08:00
}
2024-03-10 21:25:24 +08:00
void Debugger : : runClientCommand ( const QString & command , const QString & params , DebugCommandSource source )
{
if ( ! mClient )
return ;
if ( mClient - > clientType ( ) ! = DebuggerType : : GDB
& & mClient - > clientType ( ) ! = DebuggerType : : LLDB_MI )
return ;
GDBMIDebuggerClient * gdbmiClient = dynamic_cast < GDBMIDebuggerClient * > ( mClient ) ;
gdbmiClient - > postCommand ( command , params , source ) ;
}
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 ) ;
2024-03-10 09:56:20 +08:00
if ( mClient )
2024-03-09 23:08:23 +08:00
mClient - > setBreakpointCondition ( breakpoint ) ;
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 ( ) ;
2024-03-10 09:56:20 +08:00
if ( mClient ) {
2024-03-09 23:08:23 +08:00
mClient - > addWatchpoint ( expression ) ;
2023-03-03 17:20:33 +08:00
}
}
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
2024-03-10 09:56:20 +08:00
sendWatchCommand ( var ) ;
2021-07-31 20:19:45 +08:00
}
2021-07-26 18:22:09 +08:00
}
void Debugger : : refreshWatchVars ( )
{
2024-03-10 09:56:20 +08:00
if ( mClient ) {
2021-11-25 20:26:43 +08:00
sendAllWatchVarsToDebugger ( ) ;
2023-01-22 22:19:19 +08:00
if ( mDebuggerType = = DebuggerType : : LLDB_MI ) {
for ( PWatchVar var : mWatchModel - > watchVars ( ) ) {
if ( ! var - > name . isEmpty ( ) )
2024-03-10 09:56:20 +08:00
mClient - > refreshWatch ( var ) ;
2023-01-22 22:19:19 +08:00
}
} else {
2024-03-10 09:56:20 +08:00
mClient - > refreshWatch ( ) ;
2023-01-22 22:19:19 +08:00
}
2021-11-25 20:26:43 +08:00
}
}
void Debugger : : fetchVarChildren ( const QString & varName )
{
2024-03-10 09:56:20 +08:00
if ( mClient ) {
mClient - > fetchWatchVarChildren ( varName ) ;
2021-07-31 20:19:45 +08:00
}
2021-07-26 18:22:09 +08:00
}
2024-01-18 16:14:36 +08:00
bool Debugger : : useDebugServer ( ) const
{
return mUseDebugServer ;
}
void Debugger : : setUseDebugServer ( bool newUseDebugServer )
{
mUseDebugServer = newUseDebugServer ;
}
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 ) ;
}
2024-03-10 11:15:10 +08:00
void Debugger : : readMemory ( const QString & startAddress , int rows , int cols )
{
if ( mClient )
mClient - > readMemory ( startAddress , rows , cols ) ;
}
2024-03-10 09:56:20 +08:00
void Debugger : : evalExpression ( const QString & expression )
{
if ( mClient )
mClient - > evalExpression ( expression ) ;
}
2024-03-10 12:57:50 +08:00
void Debugger : : selectFrame ( PTrace trace )
{
if ( mClient )
mClient - > selectFrame ( trace ) ;
}
2024-03-10 11:15:10 +08:00
void Debugger : : refreshFrame ( )
{
if ( mClient ) {
mClient - > refreshFrame ( ) ;
}
}
2024-03-10 12:57:50 +08:00
void Debugger : : refreshStackVariables ( )
{
if ( mClient )
mClient - > refreshStackVariables ( ) ;
}
2024-03-10 11:15:10 +08:00
void Debugger : : refreshRegisters ( )
{
if ( mClient )
mClient - > refreshRegisters ( ) ;
}
void Debugger : : disassembleCurrentFrame ( bool blendMode )
{
if ( mClient )
mClient - > disassembleCurrentFrame ( blendMode ) ;
}
void Debugger : : setDisassemblyLanguage ( bool isIntel )
{
if ( mClient )
mClient - > setDisassemblyLanguage ( isIntel ) ;
}
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
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > addWatch ( var - > expression ) ;
2021-07-31 20:19:45 +08:00
}
void Debugger : : sendRemoveWatchCommand ( PWatchVar var )
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > removeWatch ( var ) ;
2021-07-25 13:03:46 +08:00
}
void Debugger : : sendBreakpointCommand ( PBreakpoint breakpoint )
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > addBreakpoint ( breakpoint ) ;
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
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > removeBreakpoint ( breakpoint ) ;
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 ) ;
}
2024-03-10 21:25:24 +08:00
void Debugger : : includeOrSkipDirsInSymbolSearch ( const QStringList & dirs , bool skip )
{
if ( skip ) {
mClient - > skipDirectoriesInSymbolSearch ( dirs ) ;
} else {
mClient - > addSymbolSearchDirectories ( dirs ) ;
}
}
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.
2024-03-08 22:06:10 +08:00
if ( mClient - > 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 ( ) ) {
2024-03-08 22:06:10 +08:00
for ( const QString & line : mClient - > fullOutput ( ) ) {
2021-11-24 17:53:25 +08:00
pMainWindow - > addDebugOutput ( line ) ;
2021-07-26 11:47:54 +08:00
}
2024-03-13 19:19:10 +08:00
//pMainWindow->addDebugOutput("(gdb)");
2021-11-24 17:53:25 +08:00
} else {
2024-03-10 21:25:24 +08:00
// if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") {
// } else {
// for (const QString& line:mClient->consoleOutput()) {
// pMainWindow->addDebugOutput(line);
// }
// if (
// (mClient->currentCmd()
// && mClient->currentCmd()->source== DebugCommandSource::Console)
// || !mClient->consoleOutput().isEmpty() ) {
// pMainWindow->addDebugOutput("(gdb)");
// }
// }
2024-03-14 09:23:04 +08:00
if ( ! mClient - > consoleOutput ( ) . isEmpty ( ) ) {
for ( const QString & line : mClient - > consoleOutput ( ) ) {
pMainWindow - > addDebugOutput ( line ) ;
}
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
2024-03-08 22:06:10 +08:00
if ( mClient - > processExited ( ) ) {
2021-11-24 21:22:01 +08:00
stop ( ) ;
return ;
}
2024-03-08 22:06:10 +08:00
if ( mClient - > signalReceived ( )
& & mClient - > signalName ( ) ! = " SIGINT "
& & mClient - > 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 (
2024-03-08 22:06:10 +08:00
tr ( " Signal \" %1 \" Received: " ) . arg ( mClient - > signalName ( ) )
2021-11-25 09:05:45 +08:00
+ " <br /> "
2024-03-08 22:06:10 +08:00
+ mClient - > signalMeaning ( ) ) ;
2021-11-25 09:05:45 +08:00
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!
2024-03-08 22:06:10 +08:00
if ( ( mClient - > 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 )
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > writeMemory ( address , data ) ;
2022-01-11 22:29:03 +08:00
refreshAll ( ) ;
}
2022-01-12 17:14:39 +08:00
void Debugger : : setWatchVarValue ( const QString & name , const QString & value )
{
2024-03-10 09:56:20 +08:00
if ( mClient )
mClient - > writeWatchVar ( name , value ) ;
2022-01-12 17:14:39 +08:00
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 ;
}
2024-03-08 22:06:10 +08:00
DebuggerClient : : DebuggerClient ( 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-07-31 20:19:45 +08:00
mCmdRunning = false ;
2021-07-03 21:57:50 +08:00
}
2024-03-08 22:06:10 +08:00
const QStringList & DebuggerClient : : binDirs ( ) const
2022-06-16 21:34:31 +08:00
{
return mBinDirs ;
}
2024-03-08 22:06:10 +08:00
void DebuggerClient : : addBinDirs ( const QStringList & binDirs )
2022-06-16 21:34:31 +08:00
{
mBinDirs . append ( binDirs ) ;
}
2024-03-08 22:06:10 +08:00
void DebuggerClient : : addBinDir ( const QString & binDir )
2022-06-16 21:34:31 +08:00
{
mBinDirs . append ( binDir ) ;
}
2024-03-08 22:06:10 +08:00
const QString & DebuggerClient : : signalMeaning ( ) const
2021-11-25 09:05:45 +08:00
{
return mSignalMeaning ;
}
2024-03-08 22:06:10 +08:00
const QString & DebuggerClient : : signalName ( ) const
2021-11-25 09:05:45 +08:00
{
return mSignalName ;
}
2024-03-08 22:06:10 +08:00
bool DebuggerClient : : inferiorRunning ( ) const
2021-11-24 21:22:01 +08:00
{
return mInferiorRunning ;
}
2024-03-08 22:06:10 +08:00
const QStringList & DebuggerClient : : 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
}
2024-03-08 22:06:10 +08:00
bool DebuggerClient : : 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
}
2024-03-08 22:06:10 +08:00
bool DebuggerClient : : updateCPUInfo ( ) const
2021-11-23 21:08:33 +08:00
{
return mUpdateCPUInfo ;
}
2024-03-08 22:06:10 +08:00
const QStringList & DebuggerClient : : consoleOutput ( ) const
2021-11-23 21:08:33 +08:00
{
return mConsoleOutput ;
}
2024-03-08 22:06:10 +08:00
bool DebuggerClient : : signalReceived ( ) const
2021-11-23 21:08:33 +08:00
{
return mSignalReceived ;
}
2024-03-08 22:06:10 +08:00
bool DebuggerClient : : processExited ( ) const
2021-11-10 17:05:37 +08:00
{
return mProcessExited ;
}
2024-03-08 22:06:10 +08:00
QString DebuggerClient : : debuggerPath ( ) const
2021-07-25 00:26:13 +08:00
{
return mDebuggerPath ;
}
2024-03-08 22:06:10 +08:00
void DebuggerClient : : setDebuggerPath ( const QString & debuggerPath )
2021-07-25 00:26:13 +08:00
{
mDebuggerPath = debuggerPath ;
}
2024-03-08 22:06:10 +08:00
void DebuggerClient : : waitStart ( )
2021-11-10 17:05:37 +08:00
{
mStartSemaphore . acquire ( 1 ) ;
}
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 ) ) {
2024-03-12 20:28:38 +08:00
if ( expr = = QString ( " \" %1 \" " ) . arg ( 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-12-22 18:07:26 +08:00
const QStringList & 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
2024-01-18 16:14:36 +08:00
QStringList execArgs ;
if ( mGDBServer . endsWith ( LLDB_SERVER_PROGRAM ) )
execArgs = QStringList {
mGDBServer ,
" gdbserver " ,
QString ( " localhost:%1 " ) . arg ( mPort ) ,
2024-03-11 20:34:02 +08:00
//mInferior,
2024-01-18 16:14:36 +08:00
} + mArguments ;
else
execArgs = QStringList {
mGDBServer ,
QString ( " localhost:%1 " ) . arg ( mPort ) ,
mInferior ,
} + mArguments ;
2021-12-25 18:09:50 +08:00
QString cmd ;
2023-12-22 18:07:26 +08:00
QStringList arguments ;
std : : unique_ptr < QTemporaryFile > fileOwner ;
2021-12-25 18:09:50 +08:00
# ifdef Q_OS_WIN
2023-12-22 18:07:26 +08:00
if ( pSettings - > environment ( ) . useCustomTerminal ( ) ) {
std : : tie ( cmd , arguments , fileOwner ) = wrapCommandForTerminalEmulator (
pSettings - > environment ( ) . terminalPath ( ) ,
pSettings - > environment ( ) . terminalArgumentsPattern ( ) ,
execArgs
) ;
} else {
cmd = execArgs [ 0 ] ;
arguments = execArgs . mid ( 1 ) ;
}
2021-12-25 18:09:50 +08:00
# else
2023-12-22 18:07:26 +08:00
std : : tie ( cmd , arguments , fileOwner ) = wrapCommandForTerminalEmulator (
pSettings - > environment ( ) . terminalPath ( ) ,
pSettings - > environment ( ) . terminalArgumentsPattern ( ) ,
execArgs
) ;
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 ) ;
2023-12-22 18:07:26 +08:00
mProcess - > setArguments ( 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 ) {
2024-03-09 11:34:52 +08:00
emit processFailed ( mProcess - > error ( ) ) ;
2021-12-25 18:09:50 +08:00
}
}
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 ( ) ;
}