1
0
Fork 0

Synchronize branch (#1043)

* New Splitter Widget

* DLL breakpoint interface

* Conditional DLL Breakpoint

* maintain translation file

* Don't animate when it stops

* fixed some issues
This commit is contained in:
Torusrxxx 2016-09-04 17:33:59 +00:00 committed by Duncan Ogilvie
parent 1e170f01ff
commit d3bb316080
19 changed files with 1690 additions and 1239 deletions

View File

@ -121,7 +121,8 @@ typedef enum
bp_none = 0,
bp_normal = 1,
bp_hardware = 2,
bp_memory = 4
bp_memory = 4,
bp_dll = 8
} BPXTYPE;
typedef enum

View File

@ -575,6 +575,9 @@ extern "C" DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* bpmap)
case bp_memory:
currentBpType = BPMEMORY;
break;
case bp_dll:
currentBpType = BPDLL;
break;
default:
return 0;
}

View File

@ -18,6 +18,8 @@ static void setBpActive(BREAKPOINT & bp)
{
if(bp.type == BPHARDWARE) //TODO: properly implement this (check debug registers)
bp.active = true;
else if(bp.type == BPDLL)
bp.active = true;
else
bp.active = MemIsValidReadPtr(bp.addr);
}
@ -27,7 +29,11 @@ BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, duint Address)
//
// NOTE: THIS DOES _NOT_ USE LOCKS
//
auto found = breakpoints.find(BreakpointKey(Type, ModHashFromAddr(Address)));
std::map<BreakpointKey, BREAKPOINT>::iterator found;
if(Type != BPDLL)
found = breakpoints.find(BreakpointKey(Type, ModHashFromAddr(Address)));
else
found = breakpoints.find(BreakpointKey(Type, Address)); // Address = ModHashFromName(ModuleName)
// Was the module found with this address?
if(found == breakpoints.end())
@ -48,7 +54,8 @@ int BpGetList(std::vector<BREAKPOINT>* List)
for(auto & i : breakpoints)
{
BREAKPOINT currentBp = i.second;
currentBp.addr += ModBaseFromName(currentBp.mod);
if(currentBp.type != BPDLL)
currentBp.addr += ModBaseFromName(currentBp.mod);
setBpActive(currentBp);
List->push_back(currentBp);
@ -91,8 +98,29 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
// Insert new entry to the global list
EXCLUSIVE_ACQUIRE(LockBreakpoints);
breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp));
return true;
return breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp)).second;
}
bool BpNewDll(const char* module, bool Enable, bool Singleshot, DWORD TitanType, const char* Name)
{
// Default to an empty name if one wasn't supplied
if(!Name)
Name = "";
BREAKPOINT bp;
memset(&bp, 0, sizeof(BREAKPOINT));
strcpy_s(bp.mod, module);
strcpy_s(bp.name, Name);
bp.active = true;
bp.enabled = Enable;
bp.singleshoot = Singleshot;
bp.titantype = TitanType;
bp.type = BPDLL;
// Insert new entry to the global list
EXCLUSIVE_ACQUIRE(LockBreakpoints);
return breakpoints.insert(std::make_pair(BreakpointKey(BPDLL, ModHashFromName(bp.mod)), bp)).second;
}
bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
@ -115,7 +143,8 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
return true;
*Bp = *bpInfo;
Bp->addr += ModBaseFromAddr(Address);
if(bpInfo->type != BPDLL)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
return true;
}
@ -131,7 +160,8 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
if(Bp)
{
*Bp = i.second;
Bp->addr += ModBaseFromAddr(Address);
if(i.second.type != BPDLL)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
}
@ -144,12 +174,51 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
bool BpGetAny(BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
{
if(BpGet(0, Type, Name, Bp))
return true;
duint addr;
if(valfromstring(Name, &addr))
if(BpGet(addr, Type, 0, Bp))
if(Type != BPDLL)
{
if(BpGet(0, Type, Name, Bp))
return true;
duint addr;
if(valfromstring(Name, &addr))
if(BpGet(addr, Type, 0, Bp))
return true;
}
else
{
if(BpGet(ModHashFromName(Name), Type, Name, Bp))
return true;
}
return false;
}
bool BpUpdateDllPath(const char* module1, BREAKPOINT** newBpInfo)
{
const char* dashPos1 = max(strrchr(module1, '\\'), strrchr(module1, '/'));
EXCLUSIVE_ACQUIRE(LockBreakpoints);
for(auto & i : breakpoints)
{
if(i.second.type == BPDLL)
{
if(_stricmp(i.second.mod, module1) == 0)
{
strcpy_s(i.second.mod, module1);
*newBpInfo = &i.second;
return true;
}
const char* dashPos = max(strrchr(i.second.mod, '\\'), strrchr(i.second.mod, '/'));
if(dashPos == nullptr)
dashPos = i.second.mod;
else
dashPos += 1;
if(dashPos1 != nullptr && _stricmp(dashPos, dashPos1 + 1) == 0) // filename matches
{
strcpy_s(i.second.mod, module1);
*newBpInfo = &i.second;
return true;
}
}
}
*newBpInfo = nullptr;
return false;
}
@ -159,7 +228,10 @@ bool BpDelete(duint Address, BP_TYPE Type)
EXCLUSIVE_ACQUIRE(LockBreakpoints);
// Erase the index from the global list
return (breakpoints.erase(BreakpointKey(Type, ModHashFromAddr(Address))) > 0);
if(Type != BPDLL)
return (breakpoints.erase(BreakpointKey(Type, ModHashFromAddr(Address))) > 0);
else
return (breakpoints.erase(BreakpointKey(BPDLL, Address)) > 0);
}
bool BpEnable(duint Address, BP_TYPE Type, bool Enable)
@ -359,10 +431,13 @@ bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module, duint base)
}
BREAKPOINT bpInfo = j->second;
if(base) //workaround for some Windows bullshit with compatibility mode
bpInfo.addr += base;
else
bpInfo.addr += ModBaseFromName(bpInfo.mod);
if(bpInfo.type != BPDLL)
{
if(base) //workaround for some Windows bullshit with compatibility mode
bpInfo.addr += base;
else
bpInfo.addr += ModBaseFromName(bpInfo.mod);
}
setBpActive(bpInfo);
// Lock must be released due to callback sub-locks
@ -485,6 +560,21 @@ void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
case BPMEMORY:
BridgeBp->type = bp_memory;
break;
case BPDLL:
BridgeBp->type = bp_dll;
switch(Bp->titantype)
{
case UE_ON_LIB_LOAD:
BridgeBp->slot = 0;
break;
case UE_ON_LIB_UNLOAD:
BridgeBp->slot = 1;
break;
case UE_ON_LIB_ALL:
BridgeBp->slot = 2;
break;
}
break;
default:
BridgeBp->type = bp_none;
break;

View File

@ -14,7 +14,8 @@ enum BP_TYPE
{
BPNORMAL = 0,
BPHARDWARE = 1,
BPMEMORY = 2
BPMEMORY = 2,
BPDLL = 3
};
struct BREAKPOINT
@ -44,6 +45,7 @@ typedef bool (*BPENUMCALLBACK)(const BREAKPOINT* bp);
BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, duint Address);
int BpGetList(std::vector<BREAKPOINT>* List);
bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name);
bool BpNewDll(const char* module, bool Enable, bool Singleshot, DWORD TitanType, const char* Name);
bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
bool BpGetAny(BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
bool BpDelete(duint Address, BP_TYPE Type);
@ -67,5 +69,6 @@ void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp);
void BpCacheSave(JSON Root);
void BpCacheLoad(JSON Root);
void BpClear();
bool BpUpdateDllPath(const char* module1, BREAKPOINT** newBpInfo);
#endif // _BREAKPOINT_H

File diff suppressed because it is too large Load Diff

View File

@ -574,6 +574,30 @@ static void printMemBpInfo(const BREAKPOINT & bp, const void* ExceptionAddress)
free(bptype);
}
static void printDllBpInfo(const BREAKPOINT & bp)
{
char* bptype;
switch(bp.titantype)
{
case UE_ON_LIB_LOAD:
bptype = _strdup(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "DLL Load")));
break;
case UE_ON_LIB_UNLOAD:
bptype = _strdup(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "DLL Unload")));
break;
case UE_ON_LIB_ALL:
bptype = _strdup(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "DLL Load and unload")));
break;
default:
bptype = _strdup("");
}
if(*bp.name)
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Breakpoint %s(%s):Module %s"), bp.name, bptype, bp.mod);
else
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Breakpoint(%s):Module %s"), bptype, bp.mod);
free(bptype);
}
static bool getConditionValue(const char* expression)
{
auto word = *(uint16*)expression;
@ -630,6 +654,9 @@ static void handleBreakCondition(const BREAKPOINT & bp, const void* ExceptionAdd
case BPMEMORY:
printMemBpInfo(bp, ExceptionAddress);
break;
case BPDLL:
printDllBpInfo(bp);
break;
default:
break;
}
@ -658,23 +685,32 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
break;
case BPMEMORY:
bpPtr = BpInfoFromAddr(bptype, MemFindBaseAddr(duint(ExceptionAddress), nullptr, true));
break;
case BPDLL:
bpPtr = BpInfoFromAddr(BPDLL, ModHashFromName(reinterpret_cast<const char*>(ExceptionAddress)));
break;
default:
break;
}
if(!(bpPtr && bpPtr->enabled)) //invalid / disabled breakpoint hit (most likely a bug)
{
SHARED_RELEASE();
dputs(QT_TRANSLATE_NOOP("DBG", "Breakpoint reached not in list!"));
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
// Plugin callback
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
wait(WAITID_RUN);
return;
if(bptype != BPDLL || !BpUpdateDllPath(reinterpret_cast<const char*>(ExceptionAddress), &bpPtr))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Breakpoint reached not in list!"));
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
// Plugin callback
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
wait(WAITID_RUN);
return;
}
else if(bptype == BPDLL)
SHARED_REACQUIRE();
}
// increment hit count
@ -1513,9 +1549,13 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
callbackInfo.modname = modname;
plugincbcall(CB_LOADDLL, &callbackInfo);
if(bBreakOnNextDll || settingboolget("Events", "DllLoad"))
if(bBreakOnNextDll)
{
bBreakOnNextDll = false;
cbGenericBreakpoint(BPDLL, DLLDebugFileName);
}
else if(settingboolget("Events", "DllLoad"))
{
//update GUI
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
@ -1543,9 +1583,13 @@ static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base);
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Unloaded: %p %s\n"), base, modname);
if(bBreakOnNextDll || settingboolget("Events", "DllUnload"))
if(bBreakOnNextDll)
{
bBreakOnNextDll = false;
cbGenericBreakpoint(BPDLL, modname);
}
else if(settingboolget("Events", "DllUnload"))
{
//update GUI
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
@ -1859,8 +1903,17 @@ bool cbBreakpointList(const BREAKPOINT* bp)
type = "HW";
else if(bp->type == BPMEMORY)
type = "GP";
else if(bp->type == BPDLL)
type = "DLL";
bool enabled = bp->enabled;
if(*bp->name)
if(bp->type == BPDLL)
{
if(*bp->name)
dprintf_untranslated("%d:%s:\"%s\":\"%s\"\n", enabled, type, bp->mod, bp->name);
else
dprintf_untranslated("%d:%s:\"%s\"\n", enabled, type, bp->mod);
}
else if(*bp->name)
dprintf_untranslated("%d:%s:%p:\"%s\"\n", enabled, type, bp->addr, bp->name);
else
dprintf_untranslated("%d:%s:%p\n", enabled, type, bp->addr);

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,17 @@ CMDRESULT cbDebugSetBPXMemoryFastResume(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemorySingleshoot(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemorySilent(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXMemoryHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLName(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLLog(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLLogCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLCommand(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLCommandCondition(int argc, char* argv[]);
CMDRESULT cbDebugGetBPXDLLHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLFastResume(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLSingleshoot(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLSilent(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXDLLHitCount(int argc, char* argv[]);
CMDRESULT cbDebugBplist(int argc, char* argv[]);
CMDRESULT cbDebugStepInto(int argc, char* argv[]);
CMDRESULT cbDebugeStepInto(int argc, char* argv[]);

View File

@ -173,6 +173,17 @@ static void registercommands()
dbgcmdnew("SetMemoryBreakpointSilent", cbDebugSetBPXMemorySilent, true); //set breakpoint fast resume
dbgcmdnew("SetMemoryGetBreakpointHitCount", cbDebugGetBPXMemoryHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetMemoryBreakpointHitCount", cbDebugResetBPXMemoryHitCount, true); //reset breakpoint hit count
dbgcmdnew("SetLibrarianBreakpointName", cbDebugSetBPXDLLName, true); //set breakpoint name
dbgcmdnew("SetLibrarianBreakpointCondition", cbDebugSetBPXMemoryCondition, true); //set breakpoint breakCondition
dbgcmdnew("SetLibrarianBreakpointLog", cbDebugSetBPXMemoryLog, true); //set breakpoint log
dbgcmdnew("SetLibrarianBreakpointLogCondition", cbDebugSetBPXMemoryLogCondition, true); //set breakpoint logCondition
dbgcmdnew("SetLibrarianBreakpointCommand", cbDebugSetBPXMemoryCommand, true); //set breakpoint command on hit
dbgcmdnew("SetLibrarianBreakpointCommandCondition", cbDebugSetBPXMemoryCommandCondition, true); //set breakpoint commandCondition
dbgcmdnew("SetLibrarianBreakpointFastResume", cbDebugSetBPXMemoryFastResume, true); //set breakpoint fast resume
dbgcmdnew("SetLibrarianBreakpointSingleshoot", cbDebugSetBPXMemorySingleshoot, true); //set breakpoint singleshoot
dbgcmdnew("SetLibrarianBreakpointSilent", cbDebugSetBPXMemorySilent, true); //set breakpoint fast resume
dbgcmdnew("SetLibrarianGetBreakpointHitCount", cbDebugGetBPXMemoryHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetLibrarianBreakpointHitCount", cbDebugResetBPXMemoryHitCount, true); //reset breakpoint hit count
dbgcmdnew("bpgoto", cbDebugSetBPGoto, true);

View File

@ -37,6 +37,7 @@
<ClCompile Include="assemble.cpp" />
<ClCompile Include="bookmark.cpp" />
<ClCompile Include="breakpoint.cpp" />
<ClCompile Include="breakpoint_commands.cpp" />
<ClCompile Include="command.cpp" />
<ClCompile Include="commandline.cpp" />
<ClCompile Include="commandparser.cpp" />

View File

@ -350,6 +350,9 @@
<ClCompile Include="animate.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
<ClCompile Include="breakpoint_commands.cpp">
<Filter>Source Files\Debugger Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="x64_dbg.h">

View File

@ -0,0 +1,157 @@
#include "LabeledSplitter.h"
#include <QPainter>
#include <QpaintEvent>
#include "bridge.h"
//LabeledSplitterHandle class
LabeledSplitterHandle::LabeledSplitterHandle(Qt::Orientation o, LabeledSplitter* parent) : QSplitterHandle(o, parent)
{
charHeight = QFontMetrics(font()).height();
setMouseTracking(true);
originalSize = 0;
}
QSize LabeledSplitterHandle::sizeHint() const
{
QSize size;
size.setHeight(charHeight + 2);
return std::move(size);
}
QSize LabeledSplitterHandle::minimumSizeHint() const
{
return sizeHint();
}
LabeledSplitter* LabeledSplitterHandle::getParent() const
{
return qobject_cast<LabeledSplitter*>(parent());
}
int LabeledSplitterHandle::getIndex()
{
return getParent()->indexOf(this);
}
void LabeledSplitterHandle::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
const QRect & rect = event->rect();
painter.fillRect(rect, Qt::gray);
painter.setPen(Qt::black);
LabeledSplitter* parent = getParent();
int index = parent->indexOf(this);
if(parent->sizes().at(index) != 0)
{
//hidden
QPoint points[3] = {QPoint(charHeight / 5, charHeight / 3), QPoint(charHeight * 4 / 5, charHeight / 3), QPoint(charHeight / 2, charHeight * 2 / 3)};
painter.setPen(Qt::black);
painter.setBrush(Qt::green);
painter.drawConvexPolygon(points, 3);
}
else
{
QPoint points[3] = {QPoint(charHeight / 5, charHeight * 2 / 3), QPoint(charHeight * 4 / 5, charHeight * 2 / 3), QPoint(charHeight / 2, charHeight / 3)};
painter.setPen(Qt::black);
painter.setBrush(Qt::green);
painter.drawConvexPolygon(points, 3);
painter.drawLine(rect.left(), rect.height() - 1, rect.right(), rect.height() - 1);
}
QRect textRect(rect.left() + charHeight, rect.top(), rect.width() - charHeight, rect.height());
painter.drawText(textRect, 0, parent->getName(index));
}
void LabeledSplitterHandle::mouseMoveEvent(QMouseEvent* event)
{
if(event->x() <= charHeight)
{
this->setCursor(QCursor(Qt::ArrowCursor));
event->accept();
}
else
{
this->setCursor(QCursor(Qt::SplitVCursor));
QSplitterHandle::mouseMoveEvent(event);
}
}
void LabeledSplitterHandle::mousePressEvent(QMouseEvent* event)
{
if(event->x() <= charHeight)
{
LabeledSplitter* parent = getParent();
auto sizes = parent->sizes();
int index = parent->indexOf(this);
int index2;
for(index2 = index - 1; sizes.at(index2) == 0 && index2 != 0; index2--);
if(sizes.at(index) == 0)
{
if(originalSize == 0)
originalSize = 100;
if(sizes[index2] > originalSize)
sizes[index2] -= originalSize;
sizes[index] = originalSize;
}
else
{
originalSize = sizes[index];
sizes[index] = 0;
sizes[index2] += originalSize;
}
parent->setSizes(sizes);
event->accept();
}
else
QSplitterHandle::mousePressEvent(event);
}
// LabeledSplitter class
LabeledSplitter::LabeledSplitter(QWidget* parent) : QSplitter(Qt::Vertical, parent)
{
}
QSplitterHandle* LabeledSplitter::createHandle()
{
return new LabeledSplitterHandle(orientation(), this);
}
void LabeledSplitter::addWidget(QWidget* widget, const QString & name)
{
names.push_back(name);
addWidget(widget);
}
void LabeledSplitter::addWidget(QWidget* widget)
{
QSplitter::addWidget(widget);
}
void LabeledSplitter::collapseLowerTabs()
{
if(count() > 2)
{
auto size = sizes();
size[0] = 1;
size[1] = 1;
for(int i = 2; i < size.count(); i++)
size[i] = 0;
setSizes(size);
}
}
void LabeledSplitter::insertWidget(int index, QWidget* widget, const QString & name)
{
names.insert(index, name);
insertWidget(index, widget);
}
void LabeledSplitter::insertWidget(int index, QWidget* widget)
{
QSplitter::insertWidget(index, widget);
}
QString LabeledSplitter::getName(int index) const
{
return names.at(index);
}

View File

@ -0,0 +1,42 @@
#ifndef LABELEDSPLITTER_H
#define LABELEDSPLITTER_H
#include <QSplitter>
class LabeledSplitter;
class LabeledSplitterHandle : public QSplitterHandle
{
Q_OBJECT
public:
LabeledSplitterHandle(Qt::Orientation o, LabeledSplitter* parent);
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void paintEvent(QPaintEvent* event) override;
protected:
int getIndex();
int charHeight;
int originalSize;
LabeledSplitter* getParent() const;
};
class LabeledSplitter : public QSplitter
{
Q_OBJECT
public:
LabeledSplitter(QWidget* parent);
void addWidget(QWidget* widget, const QString & name);
void insertWidget(int index, QWidget* widget, const QString & name);
void collapseLowerTabs();
QString getName(int index) const;
protected:
void setOrientation(Qt::Orientation o); // LabeledSplitter is always vertical
void addWidget(QWidget* widget);
void insertWidget(int index, QWidget* widget);
QSplitterHandle* createHandle() override;
QList<QString> names;
};
#endif //LABELEDSPLITTER_H

View File

@ -1,9 +1,11 @@
#include <QVBoxLayout>
#include "BreakpointsView.h"
#include "Configuration.h"
#include "Bridge.h"
#include "Breakpoints.h"
#include "LineEditDialog.h"
#include "StdTable.h"
#include "LabeledSplitter.h"
BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
{
@ -54,11 +56,11 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
mMemBPTable->loadColumnFromConfig("MemoryBreakpoint");
// Splitter
mSplitter = new QSplitter(this);
mSplitter->setOrientation(Qt::Vertical);
mSplitter->addWidget(mSoftBPTable);
mSplitter->addWidget(mHardBPTable);
mSplitter->addWidget(mMemBPTable);
mSplitter = new LabeledSplitter(this);
mSplitter->addWidget(mSoftBPTable, tr("Software breakpoint"));
mSplitter->addWidget(mHardBPTable, tr("Hardware breakpoint"));
mSplitter->addWidget(mMemBPTable, tr("Memory breakpoint"));
mSplitter->collapseLowerTabs();
// Layout
mVertLayout = new QVBoxLayout;

View File

@ -2,11 +2,11 @@
#define BREAKPOINTSVIEW_H
#include <QWidget>
#include <QVBoxLayout>
#include <QSplitter>
#include "Imports.h"
class StdTable;
class QVBoxLayout;
class LabeledSplitter;
class BreakpointsView : public QWidget
{
@ -63,7 +63,7 @@ public slots:
private:
QVBoxLayout* mVertLayout;
QSplitter* mSplitter ;
LabeledSplitter* mSplitter;
StdTable* mHardBPTable;
StdTable* mSoftBPTable;
StdTable* mMemBPTable;

View File

@ -2,8 +2,8 @@
#include "Bridge.h"
#include "VersionHelpers.h"
#include "StdTable.h"
#include "LabeledSplitter.h"
#include <QVBoxLayout>
#include <QSplitter>
HandlesView::HandlesView(QWidget* parent) : QWidget(parent)
{
@ -34,11 +34,10 @@ HandlesView::HandlesView(QWidget* parent) : QWidget(parent)
mPrivilegesTable->loadColumnFromConfig("Privilege");
// Splitter
mSplitter = new QSplitter(this);
mSplitter->setOrientation(Qt::Vertical);
mSplitter->addWidget(mHandlesTable);
mSplitter->addWidget(mTcpConnectionsTable);
mSplitter->addWidget(mPrivilegesTable);
mSplitter = new LabeledSplitter(this);
mSplitter->addWidget(mHandlesTable, tr("Handles"));
mSplitter->addWidget(mTcpConnectionsTable, tr("TCP Connections"));
mSplitter->addWidget(mPrivilegesTable, tr("Privileges"));
// Layout
mVertLayout = new QVBoxLayout;

View File

@ -6,7 +6,7 @@
class StdTable;
class QVBoxLayout;
class QSplitter;
class LabeledSplitter;
class HandlesView : public QWidget
{
@ -31,7 +31,7 @@ public slots:
private:
QVBoxLayout* mVertLayout;
QSplitter* mSplitter;
LabeledSplitter* mSplitter;
StdTable* mHandlesTable;
StdTable* mTcpConnectionsTable;
StdTable* mPrivilegesTable;

View File

@ -168,7 +168,8 @@ SOURCES += \
Src/Gui/BrowseDialog.cpp \
Src/Gui/DisassemblerGraphView.cpp \
Src/Gui/DisassemblyPopup.cpp \
Src/Gui/VirtualModDialog.cpp
Src/Gui/VirtualModDialog.cpp \
Src/BasicView/LabeledSplitter.cpp
HEADERS += \
@ -273,7 +274,8 @@ HEADERS += \
Src/Gui/DisassemblerGraphView.h \
Src/Utils/ActionHelpers.h \
Src/Gui/DisassemblyPopup.h \
Src/Gui/VirtualModDialog.h
Src/Gui/VirtualModDialog.h \
Src/BasicView/LabeledSplitter.h
FORMS += \

View File

@ -189,7 +189,9 @@ SOURCES += \
dbg/analysis/LinearPass.cpp \
dbg/analysis/recursiveanalysis.cpp \
dbg/analysis/xrefsanalysis.cpp \
dbg/animate.cpp
dbg/animate.cpp \
gui/Src/BasicView/LabeledSplitter.cpp \
dbg/breakpoint_commands.cpp
TRANSLATIONS = \
gui/Translations/x64dbg.ts
@ -395,7 +397,8 @@ HEADERS += \
dbg/analysis/LinearPass.h \
dbg/analysis/recursiveanalysis.h \
dbg/analysis/xrefsanalysis.h \
dbg/animate.h
dbg/animate.h \
gui/Src/BasicView/LabeledSplitter.h
FORMS += \
gui/Src/Gui/AppearanceDialog.ui \