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:
parent
1e170f01ff
commit
d3bb316080
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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[]);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 += \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
Loading…
Reference in New Issue