Skip to content

Commit 4cf0844

Browse files
torusrxxxmrexodia
authored andcommitted
Browse dialog and goto dialog support auto-complete (x64dbg#1738)
* Browse dialog and goto dialog supports auto-complete * don't use unicode string size * Auto complete only when expression is valid symbol name * use dbgfunctions for better flexibility and performance * buffer last auto complete * disable auto completion
1 parent 3116b3d commit 4cf0844

16 files changed

+228
-4
lines changed

src/bridge/bridgemain.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ typedef enum
308308
DBG_GET_PEB_ADDRESS, // param1=DWORD ProcessId, param2=unused
309309
DBG_GET_TEB_ADDRESS, // param1=DWORD ThreadId, param2=unused
310310
DBG_ANALYZE_FUNCTION, // param1=BridgeCFGraphList* graph, param2=duint entry
311-
DBG_MENU_PREPARE, // param1=int hMenu, param2=unused
311+
DBG_MENU_PREPARE // param1=int hMenu, param2=unused
312312
} DBGMSG;
313313

314314
typedef enum

src/dbg/_dbgfunctions.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "comment.h"
3131
#include "exception.h"
3232
#include "database.h"
33+
#include "dbghelp_safe.h"
3334

3435
static DBGFUNCTIONS _dbgfunctions;
3536

@@ -370,6 +371,41 @@ static bool _modrelocationsinrange(duint addr, duint size, ListOf(DBGRELOCATIONI
370371
return true;
371372
}
372373

374+
typedef struct _SYMAUTOCOMPLETECALLBACKPARAM
375+
{
376+
char** Buffer;
377+
int* count;
378+
int MaxSymbols;
379+
} SYMAUTOCOMPLETECALLBACKPARAM;
380+
381+
static BOOL CALLBACK SymAutoCompleteCallback(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
382+
{
383+
SYMAUTOCOMPLETECALLBACKPARAM* param = reinterpret_cast<SYMAUTOCOMPLETECALLBACKPARAM*>(UserContext);
384+
if(param->Buffer)
385+
{
386+
param->Buffer[*param->count] = (char*)BridgeAlloc(pSymInfo->NameLen + 1);
387+
memcpy(param->Buffer[*param->count], pSymInfo->Name, pSymInfo->NameLen + 1);
388+
param->Buffer[*param->count][pSymInfo->NameLen] = 0;
389+
}
390+
if(++*param->count >= param->MaxSymbols)
391+
return FALSE;
392+
else
393+
return TRUE;
394+
}
395+
396+
static int SymAutoComplete(const char* Search, char** Buffer, int MaxSymbols)
397+
{
398+
//debug
399+
int count = 0;
400+
SYMAUTOCOMPLETECALLBACKPARAM param;
401+
param.Buffer = Buffer;
402+
param.count = &count;
403+
param.MaxSymbols = MaxSymbols;
404+
if(!SafeSymEnumSymbols(fdProcessInfo->hProcess, 0, Search, SymAutoCompleteCallback, &param))
405+
dputs(QT_TRANSLATE_NOOP("DBG", "SymEnumSymbols failed!"));
406+
return count;
407+
}
408+
373409
void dbgfunctionsinit()
374410
{
375411
_dbgfunctions.AssembleAtEx = _assembleatex;
@@ -441,4 +477,5 @@ void dbgfunctionsinit()
441477
_dbgfunctions.ModRelocationAtAddr = (MODRELOCATIONATADDR)ModRelocationAtAddr;
442478
_dbgfunctions.ModRelocationsInRange = _modrelocationsinrange;
443479
_dbgfunctions.DbGetHash = DbGetHash;
480+
_dbgfunctions.SymAutoComplete = SymAutoComplete;
444481
}

src/dbg/_dbgfunctions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ typedef bool(*MODRELOCATIONSFROMADDR)(duint addr, ListOf(DBGRELOCATIONINFO) relo
196196
typedef bool(*MODRELOCATIONATADDR)(duint addr, DBGRELOCATIONINFO* relocation);
197197
typedef bool(*MODRELOCATIONSINRANGE)(duint addr, duint size, ListOf(DBGRELOCATIONINFO) relocations);
198198
typedef duint(*DBGETHASH)();
199+
typedef int(*SYMAUTOCOMPLETE)(const char* Search, char** Buffer, int MaxSymbols);
199200

200201
//The list of all the DbgFunctions() return value.
201202
//WARNING: This list is append only. Do not insert things in the middle or plugins would break.
@@ -270,6 +271,7 @@ typedef struct DBGFUNCTIONS_
270271
MODRELOCATIONATADDR ModRelocationAtAddr;
271272
MODRELOCATIONSINRANGE ModRelocationsInRange;
272273
DBGETHASH DbGetHash;
274+
SYMAUTOCOMPLETE SymAutoComplete;
273275
} DBGFUNCTIONS;
274276

275277
#ifdef BUILD_DBG

src/gui/Src/BasicView/HistoryLineEdit.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ void HistoryLineEdit::saveSettings(QString sectionPrefix)
3737

3838
void HistoryLineEdit::addLineToHistory(QString parLine)
3939
{
40-
mCmdHistory.prepend(parLine);
41-
4240
if(mCmdHistory.size() > mCmdHistoryMaxSize)
4341
mCmdHistory.removeLast();
4442

43+
mCmdHistory.prepend(parLine);
44+
4545
mCmdIndex = -1;
4646
}
4747

src/gui/Src/Gui/BrowseDialog.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "BrowseDialog.h"
22
#include "ui_BrowseDialog.h"
33
#include "MiscUtil.h"
4+
#include <QDirModel>
5+
#include <QCompleter>
46
#include <QFileDialog>
57
#include <Configuration.h>
68

@@ -13,6 +15,9 @@ BrowseDialog::BrowseDialog(QWidget* parent, const QString & title, const QString
1315
setWindowTitle(title);
1416
ui->label->setText(text);
1517
ui->lineEdit->setText(QDir::toNativeSeparators(defaultPath));
18+
QCompleter* completer = new QCompleter(ui->lineEdit);
19+
completer->setModel(new QDirModel(completer));
20+
ui->lineEdit->setCompleter(completer);
1621
Config()->setupWindowPos(this);
1722
}
1823

src/gui/Src/Gui/GotoDialog.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include "ui_GotoDialog.h"
44
#include "StringUtil.h"
55
#include "Configuration.h"
6+
#include "QCompleter"
7+
#include "SymbolAutoCompleteModel.h"
68

79
GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowInvalidAddress)
810
: QDialog(parent),
@@ -22,6 +24,13 @@ GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowI
2224
ui->labelError->setText(tr("<font color='red'><b>Invalid expression...</b></font>"));
2325
setOkEnabled(false);
2426
ui->editExpression->setFocus();
27+
completer = new QCompleter(this);
28+
completer->setModel(new SymbolAutoCompleteModel([this]
29+
{
30+
return ui->editExpression->text();
31+
}, completer));
32+
if(!Config()->getBool("Gui", "DisableAutoComplete"))
33+
ui->editExpression->setCompleter(completer);
2534
validRangeStart = 0;
2635
validRangeEnd = ~0;
2736
fileOffset = false;
@@ -31,6 +40,7 @@ GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowI
3140
connect(mValidateThread, SIGNAL(expressionChanged(bool, bool, dsint)), this, SLOT(expressionChanged(bool, bool, dsint)));
3241
connect(ui->editExpression, SIGNAL(textChanged(QString)), mValidateThread, SLOT(textChanged(QString)));
3342
connect(this, SIGNAL(finished(int)), this, SLOT(finishedSlot(int)));
43+
connect(Config(), SIGNAL(disableAutoCompleteUpdated()), this, SLOT(disableAutoCompleteUpdated()));
3444

3545
Config()->setupWindowPos(this);
3646
}
@@ -175,3 +185,11 @@ void GotoDialog::finishedSlot(int result)
175185
ui->editExpression->setText("");
176186
ui->editExpression->setFocus();
177187
}
188+
189+
void GotoDialog::disableAutoCompleteUpdated()
190+
{
191+
if(Config()->getBool("Gui", "DisableAutoComplete"))
192+
ui->editExpression->setCompleter(nullptr);
193+
else
194+
ui->editExpression->setCompleter(completer);
195+
}

src/gui/Src/Gui/GotoDialog.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "Imports.h"
66

77
class ValidateExpressionThread;
8+
class QCompleter;
89

910
namespace Ui
1011
{
@@ -32,12 +33,14 @@ class GotoDialog : public QDialog
3233

3334
private slots:
3435
void expressionChanged(bool validExpression, bool validPointer, dsint value);
36+
void disableAutoCompleteUpdated();
3537
void on_buttonOk_clicked();
3638
void finishedSlot(int result);
3739

3840
private:
3941
Ui::GotoDialog* ui;
4042
ValidateExpressionThread* mValidateThread;
43+
QCompleter* completer;
4144
bool IsValidMemoryRange(duint addr);
4245
void setOkEnabled(bool enabled);
4346
};

src/gui/Src/Gui/SettingsDialog.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SettingsDialog::SettingsDialog(QWidget* parent) :
1515
setModal(true);
1616
adjustSize();
1717
bTokenizerConfigUpdated = false;
18+
bDisableAutoCompleteUpdated = false;
1819
LoadSettings(); //load settings from file
1920
connect(Bridge::getBridge(), SIGNAL(setLastException(uint)), this, SLOT(setLastException(uint)));
2021
lastException = 0;
@@ -74,6 +75,7 @@ void SettingsDialog::LoadSettings()
7475
settings.disasmNoSourceLineAutoComments = false;
7576
settings.disasmMaxModuleSize = -1;
7677
settings.guiNoForegroundWindow = true;
78+
settings.guiDisableAutoComplete = false;
7779

7880
//Events tab
7981
GetSettingBool("Events", "SystemBreakpoint", &settings.eventSystemBreakpoint);
@@ -225,6 +227,7 @@ void SettingsDialog::LoadSettings()
225227
GetSettingBool("Gui", "LoadSaveTabOrder", &settings.guiLoadSaveTabOrder);
226228
GetSettingBool("Gui", "ShowGraphRva", &settings.guiShowGraphRva);
227229
GetSettingBool("Gui", "ShowExitConfirmation", &settings.guiShowExitConfirmation);
230+
GetSettingBool("Gui", "DisableAutoComplete", &settings.guiDisableAutoComplete);
228231
ui->chkFpuRegistersLittleEndian->setChecked(settings.guiFpuRegistersLittleEndian);
229232
ui->chkSaveColumnOrder->setChecked(settings.guiSaveColumnOrder);
230233
ui->chkNoCloseDialog->setChecked(settings.guiNoCloseDialog);
@@ -234,6 +237,7 @@ void SettingsDialog::LoadSettings()
234237
ui->chkSaveLoadTabOrder->setChecked(settings.guiLoadSaveTabOrder);
235238
ui->chkShowGraphRva->setChecked(settings.guiShowGraphRva);
236239
ui->chkShowExitConfirmation->setChecked(settings.guiShowExitConfirmation);
240+
ui->chkDisableAutoComplete->setChecked(settings.guiDisableAutoComplete);
237241

238242
//Misc tab
239243
if(DbgFunctions()->GetJit)
@@ -370,6 +374,7 @@ void SettingsDialog::SaveSettings()
370374
BridgeSettingSetUint("Gui", "LoadSaveTabOrder", settings.guiLoadSaveTabOrder);
371375
BridgeSettingSetUint("Gui", "ShowGraphRva", settings.guiShowGraphRva);
372376
BridgeSettingSetUint("Gui", "ShowExitConfirmation", settings.guiShowExitConfirmation);
377+
BridgeSettingSetUint("Gui", "DisableAutoComplete", settings.guiDisableAutoComplete);
373378

374379
//Misc tab
375380
if(DbgFunctions()->GetJit)
@@ -407,6 +412,11 @@ void SettingsDialog::SaveSettings()
407412
Config()->emitTokenizerConfigUpdated();
408413
bTokenizerConfigUpdated = false;
409414
}
415+
if(bDisableAutoCompleteUpdated)
416+
{
417+
Config()->emitDisableAutoCompleteUpdated();
418+
bDisableAutoCompleteUpdated = false;
419+
}
410420
DbgSettingsUpdated();
411421
GuiUpdateAllViews();
412422
}
@@ -831,6 +841,12 @@ void SettingsDialog::on_chkShowExitConfirmation_toggled(bool checked)
831841
settings.guiShowExitConfirmation = checked;
832842
}
833843

844+
void SettingsDialog::on_chkDisableAutoComplete_toggled(bool checked)
845+
{
846+
settings.guiDisableAutoComplete = checked;
847+
bDisableAutoCompleteUpdated = true;
848+
}
849+
834850
void SettingsDialog::on_chkUseLocalHelpFile_toggled(bool checked)
835851
{
836852
settings.miscUseLocalHelpFile = checked;

src/gui/Src/Gui/SettingsDialog.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private slots:
8282
void on_chkSidebarWatchLabels_stateChanged(int arg1);
8383
void on_chkNoForegroundWindow_toggled(bool checked);
8484
void on_chkShowExitConfirmation_toggled(bool checked);
85+
void on_chkDisableAutoComplete_toggled(bool checked);
8586
//Misc tab
8687
void on_chkSetJIT_stateChanged(int arg1);
8788
void on_chkConfirmBeforeAtt_stateChanged(int arg1);
@@ -177,6 +178,7 @@ private slots:
177178
bool guiLoadSaveTabOrder;
178179
bool guiShowGraphRva;
179180
bool guiShowExitConfirmation;
181+
bool guiDisableAutoComplete;
180182
//Misc Tab
181183
bool miscSetJIT;
182184
bool miscSetJITAuto;
@@ -195,6 +197,7 @@ private slots:
195197
bool bJitOld;
196198
bool bJitAutoOld;
197199
bool bTokenizerConfigUpdated;
200+
bool bDisableAutoCompleteUpdated;
198201

199202
//functions
200203
void GetSettingBool(const char* section, const char* name, bool* set);

src/gui/Src/Gui/SettingsDialog.ui

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<bool>true</bool>
3434
</property>
3535
<property name="currentIndex">
36-
<number>0</number>
36+
<number>4</number>
3737
</property>
3838
<widget class="QWidget" name="tabEvents">
3939
<attribute name="title">
@@ -685,6 +685,13 @@
685685
</property>
686686
</widget>
687687
</item>
688+
<item>
689+
<widget class="QCheckBox" name="chkDisableAutoComplete">
690+
<property name="text">
691+
<string>Disable auto completion in goto dialog</string>
692+
</property>
693+
</widget>
694+
</item>
688695
<item>
689696
<spacer name="verticalSpacer_7">
690697
<property name="orientation">

src/gui/Src/Utils/Configuration.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
273273
guiBool.insert("LoadSaveTabOrder", false);
274274
guiBool.insert("ShowGraphRva", false);
275275
guiBool.insert("ShowExitConfirmation", true);
276+
guiBool.insert("DisableAutoComplete", false);
276277
//Named menu settings
277278
insertMenuBuilderBools(&guiBool, "CPUDisassembly", 50); //CPUDisassembly
278279
insertMenuBuilderBools(&guiBool, "CPUDump", 50); //CPUDump
@@ -663,6 +664,11 @@ void Configuration::emitTokenizerConfigUpdated()
663664
emit tokenizerConfigUpdated();
664665
}
665666

667+
void Configuration::emitDisableAutoCompleteUpdated()
668+
{
669+
emit disableAutoCompleteUpdated();
670+
}
671+
666672
void Configuration::readBools()
667673
{
668674
Bools = defaultBools;

src/gui/Src/Utils/Configuration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class Configuration : public QObject
4949
void writeColors();
5050
void emitColorsUpdated();
5151
void emitTokenizerConfigUpdated();
52+
void emitDisableAutoCompleteUpdated();
5253
void readBools();
5354
void writeBools();
5455
void readUints();
@@ -115,6 +116,7 @@ class Configuration : public QObject
115116
void fontsUpdated();
116117
void shortcutsUpdated();
117118
void tokenizerConfigUpdated();
119+
void disableAutoCompleteUpdated();
118120

119121
private:
120122
QColor colorFromConfig(const QString id);

0 commit comments

Comments
 (0)