misc improvments
This commit is contained in:
parent
c6bf7b6570
commit
886511fdcd
|
@ -1403,7 +1403,7 @@ bool valapifromstring(const char* name, duint* value, int* value_size, bool prin
|
|||
if(szBaseName)
|
||||
{
|
||||
szBaseName++;
|
||||
HMODULE hModule = LoadLibraryExW(szModuleName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
||||
HMODULE hModule = LoadLibraryExW(szModuleName, 0, DONT_RESOLVE_DLL_REFERENCES);
|
||||
if(hModule)
|
||||
{
|
||||
ULONG_PTR funcAddress = (ULONG_PTR)GetProcAddress(hModule, name);
|
||||
|
@ -1448,6 +1448,21 @@ bool valapifromstring(const char* name, duint* value, int* value_size, bool prin
|
|||
return true;
|
||||
}
|
||||
|
||||
bool valenvfromstring(const char* string, duint* Address)
|
||||
{
|
||||
if(scmp(string, "peb"))
|
||||
{
|
||||
*Address = (duint)GetPEBLocation(fdProcessInfo->hProcess);
|
||||
return true;
|
||||
}
|
||||
else if(scmp(string, "teb"))
|
||||
{
|
||||
*Address = (duint)GetTEBLocation(hActiveThread);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Check if a string is a valid decimal number. This function also accepts "-" or "." as prefix.
|
||||
\param string The string to check.
|
||||
|
@ -1515,6 +1530,11 @@ bool convertLongLongNumber(const char* str, unsigned long long & result, int rad
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Check if a character is a valid hexadecimal digit that is smaller than the size of a pointer.
|
||||
\param digit The character to check.
|
||||
\return true if the character is a valid hexadecimal digit.
|
||||
*/
|
||||
static bool isdigitduint(char digit)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
|
@ -1609,7 +1629,8 @@ bool valfromstring_noexpr(const char* string, duint* value, bool silent, bool ba
|
|||
|
||||
if(!valfromstring(ptrstring.c_str(), value, silent, baseonly))
|
||||
{
|
||||
dprintf("noexpr failed on %s\n", ptrstring.c_str());
|
||||
if(!silent)
|
||||
dprintf("noexpr failed on %s\n", ptrstring.c_str());
|
||||
return false;
|
||||
}
|
||||
duint addr = *value;
|
||||
|
@ -1702,6 +1723,8 @@ bool valfromstring_noexpr(const char* string, duint* value, bool silent, bool ba
|
|||
*isvar = true;
|
||||
return true;
|
||||
}
|
||||
else if(valenvfromstring(string, value)) //environment block
|
||||
return true;
|
||||
else if(strstr(string, "sub_") == string) //then come sub_ functions
|
||||
{
|
||||
auto result = sscanf(string, "sub_%" fext "X", value) == 1;
|
||||
|
|
|
@ -444,6 +444,37 @@ void StdTable::setupCopyMenu(QMenu* copyMenu)
|
|||
}
|
||||
}
|
||||
|
||||
void StdTable::setupCopyMenu(MenuBuilder *copyMenu)
|
||||
{
|
||||
if(!getColumnCount())
|
||||
return;
|
||||
//Copy->Whole Line
|
||||
copyMenu->addAction(makeAction(tr("&Line"), SLOT(copyLineSlot())));
|
||||
//Copy->Cropped Table
|
||||
copyMenu->addAction(makeAction(tr("Cropped &Table"), SLOT(copyTableSlot())));
|
||||
//Copy->Full Table
|
||||
copyMenu->addAction(makeAction(tr("&Full Table"), SLOT(copyTableResizeSlot())));
|
||||
//Copy->Separator
|
||||
copyMenu->addSeparator();
|
||||
//Copy->ColName
|
||||
copyMenu->addBuilder(new MenuBuilder(this, [this](QMenu* menu)
|
||||
{
|
||||
for(int i = 0; i < getColumnCount(); i++)
|
||||
{
|
||||
if(!getCellContent(getInitialSelection(), i).length()) //skip empty cells
|
||||
continue;
|
||||
QString title = mCopyTitles.at(i);
|
||||
if(!title.length()) //skip empty copy titles
|
||||
continue;
|
||||
QAction* action = new QAction(title, menu);
|
||||
action->setObjectName(QString::number(i));
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(copyEntrySlot()));
|
||||
menu->addAction(action);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
void StdTable::setCopyMenuOnly(bool bSet, bool bDebugOnly)
|
||||
{
|
||||
mCopyMenuOnly = bSet;
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
|
||||
//context menu helpers
|
||||
void setupCopyMenu(QMenu* copyMenu);
|
||||
void setupCopyMenu(MenuBuilder* copyMenu);
|
||||
void setCopyMenuOnly(bool bSet, bool bDebugOnly = true);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -1311,7 +1311,7 @@ void CPUDisassembly::yaraSlot()
|
|||
YaraRuleSelectionDialog yaraDialog(this);
|
||||
if(yaraDialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
QString addrText = QString("%1").arg(rvaToVa(getInitialSelection()), sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
QString addrText = ToPtrString(rvaToVa(getInitialSelection()));
|
||||
DbgCmdExec(QString("yara \"%0\",%1").arg(yaraDialog.getSelectedFile()).arg(addrText).toUtf8().constData());
|
||||
emit displayReferencesWidget();
|
||||
}
|
||||
|
|
|
@ -193,6 +193,7 @@ void CPUSideBar::paintEvent(QPaintEvent* event)
|
|||
#endif //_WIN64
|
||||
|
||||
std::vector<JumpLine> jumpLines;
|
||||
std::vector<LabelArrow> labelArrows;
|
||||
|
||||
for(int line = 0; line < viewableRows; line++)
|
||||
{
|
||||
|
@ -270,7 +271,7 @@ void CPUSideBar::paintEvent(QPaintEvent* event)
|
|||
if(regLabelText.size())
|
||||
{
|
||||
regLabelText.chop(1);
|
||||
drawLabel(&painter, line, regLabelText);
|
||||
labelArrows.push_back(drawLabel(&painter, line, regLabelText));
|
||||
}
|
||||
|
||||
//debug
|
||||
|
@ -291,10 +292,16 @@ void CPUSideBar::paintEvent(QPaintEvent* event)
|
|||
}
|
||||
if(jumpLines.size())
|
||||
{
|
||||
AllocateJumpOffsets(jumpLines);
|
||||
AllocateJumpOffsets(jumpLines, labelArrows);
|
||||
for(auto i : jumpLines)
|
||||
drawJump(&painter, i.line, i.destLine, i.jumpOffset, i.isConditional, i.isJumpGoingToExecute, i.isSelected);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto i = labelArrows.begin(); i != labelArrows.end(); i++)
|
||||
i->endX = viewport()->width() - 1 - 11 - (isFoldingGraphicsPresent(i->line) != 0 ? mBulletRadius + fontHeight : 0);
|
||||
}
|
||||
drawLabelArrows(&painter, labelArrows);
|
||||
}
|
||||
|
||||
void CPUSideBar::mouseReleaseEvent(QMouseEvent* e)
|
||||
|
@ -599,7 +606,7 @@ void CPUSideBar::drawBullets(QPainter* painter, int line, bool isbp, bool isbpdi
|
|||
painter->restore();
|
||||
}
|
||||
|
||||
void CPUSideBar::drawLabel(QPainter* painter, int Line, const QString & Text)
|
||||
CPUSideBar::LabelArrow CPUSideBar::drawLabel(QPainter* painter, int Line, const QString & Text)
|
||||
{
|
||||
painter->save();
|
||||
const int LineCoordinate = fontHeight * (1 + Line);
|
||||
|
@ -630,7 +637,29 @@ void CPUSideBar::drawLabel(QPainter* painter, int Line, const QString & Text)
|
|||
painter->setBrush(QBrush(IPLabelBG));
|
||||
drawStraightArrow(painter, rect.right() + 2, y, this->viewport()->width() - x - 11 - (isFoldingGraphicsPresent(Line) != 0 ? mBulletRadius + fontHeight : 0), y);*/
|
||||
|
||||
LabelArrow labelArrow;
|
||||
labelArrow.line = Line;
|
||||
labelArrow.startX = rect.right() + 2;
|
||||
labelArrow.endX = 0;
|
||||
|
||||
painter->restore();
|
||||
|
||||
return labelArrow;
|
||||
}
|
||||
|
||||
void CPUSideBar::drawLabelArrows(QPainter* painter, const std::vector<LabelArrow> & labelArrows)
|
||||
{
|
||||
if(!labelArrows.empty())
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(QPen(mCipLabelBackgroundColor, 2.0));
|
||||
for(auto i : labelArrows)
|
||||
{
|
||||
int y = fontHeight * (1 + i.line) - 0.5 * fontHeight;
|
||||
drawStraightArrow(painter, i.startX, y, i.endX, y);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUSideBar::drawFoldingCheckbox(QPainter* painter, int y, bool state)
|
||||
|
@ -660,10 +689,10 @@ void CPUSideBar::drawStraightArrow(QPainter* painter, int x1, int y1, int x2, in
|
|||
painter->drawLine(x2 - 1, y2, x2 - ArrowSizeX, y2 + ArrowSizeY - 1);// Arrow bottom
|
||||
}
|
||||
|
||||
void CPUSideBar::AllocateJumpOffsets(std::vector<JumpLine> & jumpLines)
|
||||
void CPUSideBar::AllocateJumpOffsets(std::vector<JumpLine> & jumpLines, std::vector<LabelArrow> & labelArrows)
|
||||
{
|
||||
unsigned int* numLines = new unsigned int[viewableRows];
|
||||
memset(numLines, 0, sizeof(unsigned int) * viewableRows);
|
||||
unsigned int* numLines = new unsigned int[viewableRows * 2]; // Low:jump offsets of the vertical jumping line, High:jump offsets of the horizontal jumping line.
|
||||
memset(numLines, 0, sizeof(unsigned int) * viewableRows * 2);
|
||||
// preprocessing
|
||||
for(size_t i = 0; i < jumpLines.size(); i++)
|
||||
{
|
||||
|
@ -707,6 +736,20 @@ void CPUSideBar::AllocateJumpOffsets(std::vector<JumpLine> & jumpLines)
|
|||
for(int j = jmp.line; j >= jmp.destLine && j >= 0; j--)
|
||||
numLines[j] = jmp.jumpOffset;
|
||||
}
|
||||
if(jmp.line >= 0 && jmp.line < viewableRows)
|
||||
numLines[jmp.line + viewableRows] = jmp.jumpOffset;
|
||||
if(jmp.destLine >= 0 && jmp.destLine < viewableRows)
|
||||
numLines[jmp.destLine + viewableRows] = jmp.jumpOffset;
|
||||
}
|
||||
// set label arrows according to jump offsets
|
||||
auto viewportWidth = viewport()->width();
|
||||
const int JumpPadding = 11;
|
||||
for(auto i = labelArrows.begin(); i != labelArrows.end(); i++)
|
||||
{
|
||||
if(numLines[i->line + viewableRows] != 0)
|
||||
i->endX = viewportWidth - numLines[i->line + viewableRows] * JumpPadding - 15 - fontHeight; // This expression should be consistent with drawJump
|
||||
else
|
||||
i->endX = viewportWidth - 1- 11 - (isFoldingGraphicsPresent(i->line) != 0 ? mBulletRadius + fontHeight : 0);
|
||||
}
|
||||
delete[] numLines;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ protected:
|
|||
void mouseReleaseEvent(QMouseEvent* e);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
void drawLabel(QPainter* painter, int Line, const QString & Text);
|
||||
void drawBullets(QPainter* painter, int line, bool ispb, bool isbpdisabled, bool isbookmark);
|
||||
bool isJump(int i) const;
|
||||
void drawJump(QPainter* painter, int startLine, int endLine, int jumpoffset, bool conditional, bool isexecute, bool isactive);
|
||||
|
@ -68,12 +67,21 @@ private:
|
|||
{
|
||||
int line;
|
||||
int destLine;
|
||||
int jumpOffset;
|
||||
unsigned int jumpOffset;
|
||||
bool isSelected;
|
||||
bool isConditional;
|
||||
bool isJumpGoingToExecute;
|
||||
};
|
||||
void AllocateJumpOffsets(std::vector<JumpLine> & jumpLines);
|
||||
struct LabelArrow
|
||||
{
|
||||
int line;
|
||||
int startX;
|
||||
int endX;
|
||||
};
|
||||
|
||||
void AllocateJumpOffsets(std::vector<JumpLine> & jumpLines, std::vector<LabelArrow> & labelArrows);
|
||||
LabelArrow drawLabel(QPainter* painter, int Line, const QString & Text);
|
||||
void drawLabelArrows(QPainter* painter, const std::vector<LabelArrow> & labelArrows);
|
||||
|
||||
// Configuration
|
||||
QColor mBackgroundColor;
|
||||
|
|
|
@ -310,13 +310,10 @@ void CPUStack::refreshShortcutsSlot()
|
|||
|
||||
void CPUStack::getColumnRichText(int col, dsint rva, RichTextPainter::List & richText)
|
||||
{
|
||||
// Compute RVA
|
||||
dsint wRva = rva;
|
||||
duint wVa = rvaToVa(wRva);
|
||||
// Compute VA
|
||||
duint wVa = rvaToVa(rva);
|
||||
|
||||
bool wActiveStack = true;
|
||||
if(wVa < mCsp) //inactive stack
|
||||
wActiveStack = false;
|
||||
bool wActiveStack = (wVa >= mCsp); //inactive stack
|
||||
|
||||
STACK_COMMENT comment;
|
||||
RichTextPainter::CustomRichText_t curData;
|
||||
|
@ -337,7 +334,7 @@ void CPUStack::getColumnRichText(int col, dsint rva, RichTextPainter::List & ric
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(col && DbgStackCommentGet(rvaToVa(wRva), &comment)) //paint stack comments
|
||||
else if(col && DbgStackCommentGet(wVa, &comment)) //paint stack comments
|
||||
{
|
||||
if(wActiveStack)
|
||||
{
|
||||
|
@ -407,7 +404,7 @@ QString CPUStack::paintContent(QPainter* painter, dsint rowBase, int rowOffset,
|
|||
if(background.alpha())
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(background)); //fill background when defined
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, makeAddrText(wVa));
|
||||
return "";
|
||||
return QString();
|
||||
}
|
||||
return HexDump::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);;
|
||||
}
|
||||
|
|
|
@ -13,22 +13,31 @@ CallStackView::CallStackView(StdTable* parent) : StdTable(parent)
|
|||
|
||||
connect(Bridge::getBridge(), SIGNAL(updateCallStack()), this, SLOT(updateCallStack()));
|
||||
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
|
||||
connect(this, SIGNAL(doubleClickedSignal()), this, SLOT(doubleClickedSlot()));
|
||||
connect(this, SIGNAL(doubleClickedSignal()), this, SLOT(followTo()));
|
||||
|
||||
setupContextMenu();
|
||||
}
|
||||
|
||||
void CallStackView::setupContextMenu()
|
||||
{
|
||||
mFollowAddress = new QAction(tr("Follow &Address"), this);
|
||||
connect(mFollowAddress, SIGNAL(triggered()), this, SLOT(followAddress()));
|
||||
mFollowTo = new QAction(tr("Follow &To"), this);
|
||||
mMenuBuilder = new MenuBuilder(this, [](QMenu*)
|
||||
{
|
||||
return DbgIsDebugging();
|
||||
});
|
||||
mMenuBuilder->addAction(makeAction(tr("Follow &Address"), SLOT(followAddress())));
|
||||
QAction* mFollowTo = mMenuBuilder->addAction(makeAction(tr("Follow &To"), SLOT(followTo())));
|
||||
mFollowTo->setShortcutContext(Qt::WidgetShortcut);
|
||||
mFollowTo->setShortcut(QKeySequence("enter"));
|
||||
connect(mFollowTo, SIGNAL(triggered()), this, SLOT(followTo()));
|
||||
connect(this, SIGNAL(enterPressedSignal()), this, SLOT(followTo()));
|
||||
mFollowFrom = new QAction(tr("Follow &From"), this);
|
||||
connect(mFollowFrom, SIGNAL(triggered()), this, SLOT(followFrom()));
|
||||
mMenuBuilder->addAction(makeAction(tr("Follow &From"), SLOT(followFrom())), [this](QMenu*)
|
||||
{
|
||||
return !getCellContent(getInitialSelection(), 2).isEmpty();
|
||||
});
|
||||
MenuBuilder* mCopyMenu = new MenuBuilder(this);
|
||||
setupCopyMenu(mCopyMenu);
|
||||
// Column count cannot be zero
|
||||
mMenuBuilder->addSeparator();
|
||||
mMenuBuilder->addMenu(makeMenu(DIcon("copy.png"), tr("&Copy")), mCopyMenu);
|
||||
}
|
||||
|
||||
void CallStackView::updateCallStack()
|
||||
|
@ -41,13 +50,13 @@ void CallStackView::updateCallStack()
|
|||
setRowCount(callstack.total);
|
||||
for(int i = 0; i < callstack.total; i++)
|
||||
{
|
||||
QString addrText = QString("%1").arg((duint)callstack.entries[i].addr, sizeof(duint) * 2, 16, QChar('0')).toUpper();
|
||||
QString addrText = ToPtrString(callstack.entries[i].addr);
|
||||
setCellContent(i, 0, addrText);
|
||||
addrText = QString("%1").arg((duint)callstack.entries[i].to, sizeof(duint) * 2, 16, QChar('0')).toUpper();
|
||||
addrText = ToPtrString(callstack.entries[i].to);
|
||||
setCellContent(i, 1, addrText);
|
||||
if(callstack.entries[i].from)
|
||||
{
|
||||
addrText = QString("%1").arg((duint)callstack.entries[i].from, sizeof(duint) * 2, 16, QChar('0')).toUpper();
|
||||
addrText = ToPtrString(callstack.entries[i].from);
|
||||
setCellContent(i, 2, addrText);
|
||||
}
|
||||
setCellContent(i, 3, callstack.entries[i].comment);
|
||||
|
@ -59,29 +68,11 @@ void CallStackView::updateCallStack()
|
|||
|
||||
void CallStackView::contextMenuSlot(const QPoint pos)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
QMenu wMenu(this); //create context menu
|
||||
wMenu.addAction(mFollowAddress);
|
||||
wMenu.addAction(mFollowTo);
|
||||
QString wStr = getCellContent(getInitialSelection(), 2);
|
||||
if(wStr.length())
|
||||
wMenu.addAction(mFollowFrom);
|
||||
QMenu wCopyMenu(tr("&Copy"), this);
|
||||
setupCopyMenu(&wCopyMenu);
|
||||
if(wCopyMenu.actions().length())
|
||||
{
|
||||
wMenu.addSeparator();
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
}
|
||||
mMenuBuilder->build(&wMenu);
|
||||
wMenu.exec(mapToGlobal(pos)); //execute context menu
|
||||
}
|
||||
|
||||
void CallStackView::doubleClickedSlot()
|
||||
{
|
||||
followTo();
|
||||
}
|
||||
|
||||
void CallStackView::followAddress()
|
||||
{
|
||||
QString addrText = getCellContent(getInitialSelection(), 0);
|
||||
|
|
|
@ -16,15 +16,12 @@ signals:
|
|||
protected slots:
|
||||
void updateCallStack();
|
||||
void contextMenuSlot(const QPoint pos);
|
||||
void doubleClickedSlot();
|
||||
void followAddress();
|
||||
void followTo();
|
||||
void followFrom();
|
||||
|
||||
private:
|
||||
QAction* mFollowAddress;
|
||||
QAction* mFollowTo;
|
||||
QAction* mFollowFrom;
|
||||
MenuBuilder* mMenuBuilder;
|
||||
};
|
||||
|
||||
#endif // CALLSTACKVIEW_H
|
||||
|
|
|
@ -1407,7 +1407,8 @@ void MainWindow::changeCommandLine()
|
|||
void MainWindow::displayManual()
|
||||
{
|
||||
// Open the Windows CHM in the upper directory
|
||||
QDesktopServices::openUrl(QUrl(QUrl::fromLocalFile(QString("%1/../x64dbg.chm").arg(QCoreApplication::applicationDirPath()))));
|
||||
if(!QDesktopServices::openUrl(QUrl(QUrl::fromLocalFile(QString("%1/../x64dbg.chm").arg(QCoreApplication::applicationDirPath())))))
|
||||
SimpleErrorBox(this, tr("Error"), tr("Manual cannot be opened. Please check if x64dbg.chm exists and ensure there is no other problems with your system."));
|
||||
}
|
||||
|
||||
void MainWindow::decompileAt(dsint start, dsint end)
|
||||
|
|
|
@ -97,6 +97,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool empty() const
|
||||
{
|
||||
return _containers.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Container
|
||||
{
|
||||
|
@ -109,7 +114,8 @@ private:
|
|||
};
|
||||
|
||||
inline Container()
|
||||
: type(Separator)
|
||||
: type(Separator),
|
||||
action(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue