From 5797dae1c3d8b83cc3ff932ba0798c6bb14ea279 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sat, 26 Aug 2023 13:58:54 +0200 Subject: [PATCH] Update Zydis in the UI and remove DisassemblyPopup --- src/gui/Src/BasicView/AbstractStdTable.cpp | 155 ++-- src/gui/Src/BasicView/AbstractStdTable.h | 46 +- src/gui/Src/BasicView/AbstractTableView.cpp | 815 +++++++++--------- src/gui/Src/BasicView/AbstractTableView.h | 208 +++-- src/gui/Src/BasicView/Disassembly.cpp | 658 +++++++------- src/gui/Src/BasicView/Disassembly.h | 83 +- src/gui/Src/BasicView/StdSearchListView.cpp | 6 - src/gui/Src/BasicView/StdSearchListView.h | 1 - src/gui/Src/Bridge/Bridge.cpp | 24 +- src/gui/Src/Bridge/Bridge.h | 18 +- src/gui/Src/Disassembler/Architecture.cpp | 1 + src/gui/Src/Disassembler/Architecture.h | 17 + src/gui/Src/Disassembler/QBeaEngine.h | 75 -- .../{QBeaEngine.cpp => QZydis.cpp} | 259 +++--- src/gui/Src/Disassembler/QZydis.h | 78 ++ src/gui/Src/Disassembler/ZydisTokenizer.cpp | 292 ++++--- src/gui/Src/Disassembler/ZydisTokenizer.h | 49 +- src/gui/Src/Gui/BreakpointsView.cpp | 16 +- src/gui/Src/Gui/BreakpointsView.h | 10 +- src/gui/Src/Gui/CPUInfoBox.cpp | 4 +- src/gui/Src/Gui/CPUInfoBox.h | 4 +- src/gui/Src/Gui/DisassemblerGraphView.cpp | 8 +- src/gui/Src/Gui/DisassemblerGraphView.h | 6 +- src/gui/Src/Gui/DisassemblyPopup.cpp | 173 +++- src/gui/Src/Gui/DisassemblyPopup.h | 52 +- src/gui/Src/Gui/MemoryMapView.cpp | 46 +- src/gui/Src/Gui/ScriptView.cpp | 17 +- src/gui/Src/Gui/SymbolView.cpp | 17 +- src/gui/Src/Tracer/TraceBrowser.cpp | 22 +- src/gui/Src/Tracer/TraceBrowser.h | 4 +- src/gui/Src/Tracer/TraceFileReader.cpp | 4 +- src/gui/Src/Tracer/TraceFileReader.h | 4 +- src/gui/Src/Tracer/TraceFileReaderInternal.h | 4 +- src/gui/Src/main.cpp | 3 - src/gui/x64dbg.pro | 11 +- src/zydis_wrapper/zydis_wrapper.cpp | 30 + src/zydis_wrapper/zydis_wrapper.h | 1 + 37 files changed, 1691 insertions(+), 1530 deletions(-) create mode 100644 src/gui/Src/Disassembler/Architecture.cpp create mode 100644 src/gui/Src/Disassembler/Architecture.h delete mode 100644 src/gui/Src/Disassembler/QBeaEngine.h rename src/gui/Src/Disassembler/{QBeaEngine.cpp => QZydis.cpp} (55%) create mode 100644 src/gui/Src/Disassembler/QZydis.h diff --git a/src/gui/Src/BasicView/AbstractStdTable.cpp b/src/gui/Src/BasicView/AbstractStdTable.cpp index 37d25214..2618b26f 100644 --- a/src/gui/Src/BasicView/AbstractStdTable.cpp +++ b/src/gui/Src/BasicView/AbstractStdTable.cpp @@ -8,7 +8,7 @@ AbstractStdTable::AbstractStdTable(QWidget* parent) : AbstractTableView(parent) connect(Bridge::getBridge(), SIGNAL(repaintTableView()), this, SLOT(reloadData())); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequestedSlot(QPoint))); - connect(this, SIGNAL(headerButtonPressed(int)), this, SLOT(headerButtonPressedSlot(int))); + connect(this, SIGNAL(headerButtonPressed(duint)), this, SLOT(headerButtonPressedSlot(duint))); Initialize(); @@ -22,27 +22,27 @@ AbstractStdTable::AbstractStdTable(QWidget* parent) : AbstractTableView(parent) mExportTableCSV = makeShortcutAction(DIcon("database-export"), tr("&Export Table"), SLOT(exportTableSlot()), "ActionExport"); } -QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) +QString AbstractStdTable::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) { bool isaddr = DbgIsDebugging() && getRowCount() > 0 && col == mAddressColumn; - bool wIsSelected = isSelected(rowBase, rowOffset); - QString text = getCellContent(rowBase + rowOffset, col); + bool rowSelected = isSelected(row); + QString text = getCellContent(row, col); - duint wVA = isaddr ? duint(text.toULongLong(&isaddr, 16)) : 0; - auto wIsTraced = isaddr && DbgFunctions()->GetTraceRecordHitCount(wVA) != 0; + duint va = isaddr ? duint(text.toULongLong(&isaddr, 16)) : 0; + auto rowTraced = isaddr && DbgFunctions()->GetTraceRecordHitCount(va) != 0; QColor lineBackgroundColor; bool isBackgroundColorSet; - if(wIsSelected && wIsTraced) + if(rowSelected && rowTraced) { lineBackgroundColor = mTracedSelectedAddressBackgroundColor; isBackgroundColorSet = true; } - else if(wIsSelected) + else if(rowSelected) { lineBackgroundColor = mSelectionColor; isBackgroundColorSet = true; } - else if(wIsTraced) + else if(rowTraced) { lineBackgroundColor = mTracedBackgroundColor; isBackgroundColorSet = true; @@ -57,16 +57,16 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row if(col == mAddressColumn && isaddr) { char label[MAX_LABEL_SIZE] = ""; - if(bAddressLabel && DbgGetLabelAt(wVA, SEG_DEFAULT, label)) //has label + if(bAddressLabel && DbgGetLabelAt(va, SEG_DEFAULT, label)) //has label { char module[MAX_MODULE_SIZE] = ""; - if(DbgGetModuleAt(wVA, module) && !QString(label).startsWith("JMP.&")) + if(DbgGetModuleAt(va, module) && !QString(label).startsWith("JMP.&")) text += " <" + QString(module) + "." + QString(label) + ">"; else text += " <" + QString(label) + ">"; } - BPXTYPE bpxtype = DbgGetBpxTypeAt(wVA); - bool isbookmark = DbgGetBookmarkAt(wVA); + BPXTYPE bpxtype = DbgGetBpxTypeAt(va); + bool isbookmark = DbgGetBookmarkAt(va); duint cip = Bridge::getBridge()->mLastCip; if(bCipBase) @@ -76,7 +76,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row cip = base; } - if(DbgIsDebugging() && wVA == cip) //debugging + cip + if(DbgIsDebugging() && va == cip) //debugging + cip { painter->fillRect(QRect(x, y, w, h), QBrush(mCipBackgroundColor)); if(!isbookmark) //no bookmark @@ -149,7 +149,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row if(bpxtype == bp_none) //no label, no breakpoint { QColor background; - if(wIsSelected) + if(rowSelected) { background = mSelectedAddressBackgroundColor; painter->setPen(mSelectedAddressColor); //black address (DisassemblySelectedAddressColor) @@ -177,7 +177,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row else //other cases (memory breakpoint in disassembly) -> do as normal { QColor background; - if(wIsSelected) + if(rowSelected) { background = mSelectedAddressBackgroundColor; painter->setPen(mSelectedAddressColor); //black address (DisassemblySelectedAddressColor) @@ -265,12 +265,12 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row } } while(index != -1); - QStringList split = text.split(QChar('\1'), QString::SkipEmptyParts, Qt::CaseInsensitive); + QStringList split = text.split(QChar('\1'), Qt::SkipEmptyParts, Qt::CaseInsensitive); //create rich text list RichTextPainter::CustomRichText_t curRichText; curRichText.flags = RichTextPainter::FlagColor; - QColor textColor = getCellColor(rowBase + rowOffset, col); + QColor textColor = getCellColor(row, col); QColor textBackgroundColor = Qt::transparent; QColor highlightColor = ConfigColor("SearchListViewHighlightColor"); QColor highlightBackgroundColor = ConfigColor("SearchListViewHighlightBackgroundColor"); @@ -344,6 +344,7 @@ void AbstractStdTable::mouseMoveEvent(QMouseEvent* event) else setSingleSelection(rowIndex); + // TODO: only update if the selection actually changed updateViewport(); accept = false; @@ -384,6 +385,7 @@ void AbstractStdTable::mousePressEvent(QMouseEvent* event) mGuiState = AbstractStdTable::MultiRowsSelectionState; + // TODO: only update if the selection actually changed updateViewport(); accept = true; @@ -413,8 +415,6 @@ void AbstractStdTable::mouseReleaseEvent(QMouseEvent* event) { mGuiState = AbstractStdTable::NoState; - updateViewport(); - accept = false; } } @@ -509,6 +509,7 @@ void AbstractStdTable::keyPressEvent(QKeyEvent* event) setTableOffset(getInitialSelection() - getNbrOfLineToPrint() + 2); } + // TODO: only update if the selection actually changed updateViewport(); } else @@ -530,19 +531,19 @@ void AbstractStdTable::enableColumnSorting(bool enabled) /************************************************************************************ Selection Management ************************************************************************************/ -void AbstractStdTable::expandSelectionUpTo(int to) +void AbstractStdTable::expandSelectionUpTo(duint to) { if(to < mSelection.firstSelectedIndex) { mSelection.fromIndex = to; mSelection.toIndex = mSelection.firstSelectedIndex; - emit selectionChangedSignal(to); + emit selectionChanged(to); } else if(to > mSelection.firstSelectedIndex) { mSelection.fromIndex = mSelection.firstSelectedIndex; mSelection.toIndex = to; - emit selectionChangedSignal(to); + emit selectionChanged(to); } else if(to == mSelection.firstSelectedIndex) { @@ -612,24 +613,24 @@ void AbstractStdTable::expandBottom() } } -void AbstractStdTable::setSingleSelection(int index) +void AbstractStdTable::setSingleSelection(duint index) { mSelection.firstSelectedIndex = index; mSelection.fromIndex = index; mSelection.toIndex = index; - emit selectionChangedSignal(index); + emit selectionChanged(index); } -int AbstractStdTable::getInitialSelection() const +duint AbstractStdTable::getInitialSelection() const { return mSelection.firstSelectedIndex; } -QList AbstractStdTable::getSelection() const +QList AbstractStdTable::getSelection() const { - QList selection; + QList selection; selection.reserve(mSelection.toIndex - mSelection.fromIndex); - for(int i = mSelection.fromIndex; i <= mSelection.toIndex; i++) + for(duint i = mSelection.fromIndex; i <= mSelection.toIndex; i++) { selection.append(i); } @@ -655,60 +656,56 @@ void AbstractStdTable::selectEnd() void AbstractStdTable::selectNext() { - int wNext = getInitialSelection() + 1; + // TODO: fix the signed/unsigned + duint next = getInitialSelection() + 1; // Bounding - wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext; - wNext = wNext < 0 ? 0 : wNext; + next = next > getRowCount() - 1 ? getRowCount() - 1 : next; + next = next < 0 ? 0 : next; - setSingleSelection(wNext); + setSingleSelection(next); } void AbstractStdTable::selectPrevious() { - int wNext = getInitialSelection() - 1; + duint next = getInitialSelection() - 1; // Bounding - wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext; - wNext = wNext < 0 ? 0 : wNext; + next = next > getRowCount() - 1 ? getRowCount() - 1 : next; + next = next < 0 ? 0 : next; - setSingleSelection(wNext); + setSingleSelection(next); } void AbstractStdTable::selectAll() { - int index = 0; - int indexEnd = getRowCount() - 1; + duint index = 0; + duint indexEnd = getRowCount() - 1; mSelection.firstSelectedIndex = index; mSelection.fromIndex = index; mSelection.toIndex = indexEnd; - emit selectionChangedSignal(index); + emit selectionChanged(index); } -bool AbstractStdTable::isSelected(int base, int offset) const +bool AbstractStdTable::isSelected(duint row) const { - int wIndex = base + offset; - - if(wIndex >= mSelection.fromIndex && wIndex <= mSelection.toIndex) - return true; - else - return false; + return row >= mSelection.fromIndex && row <= mSelection.toIndex; } -bool AbstractStdTable::scrollSelect(int offset) +bool AbstractStdTable::scrollSelect(duint row) { - if(!isValidIndex(offset, 0)) + if(!isValidIndex(row, 0)) return false; - int rangefrom = getTableOffset(); - int rangeto = rangefrom + getViewableRowsCount() - 1; - if(offset < rangefrom) //offset lays before the current view - setTableOffset(offset); - else if(offset > (rangeto - 1)) //offset lays after the current view - setTableOffset(offset - getViewableRowsCount() + 2); - setSingleSelection(offset); + auto rangefrom = getTableOffset(); + auto rangeto = rangefrom + getViewableRowsCount() - 1; + if(row < rangefrom) //offset lays before the current view + setTableOffset(row); + else if(row > (rangeto - 1)) //offset lays after the current view + setTableOffset(row - getViewableRowsCount() + 2); + setSingleSelection(row); return true; } @@ -735,15 +732,15 @@ void AbstractStdTable::deleteAllColumns() void AbstractStdTable::copyLineSlot() { - int colCount = getColumnCount(); + auto colCount = getColumnCount(); QString finalText = ""; if(colCount == 1) finalText = getCellContent(getInitialSelection(), 0); else { - for(int selected : getSelection()) + for(auto selected : getSelection()) { - for(int i = 0; i < colCount; i++) + for(duint i = 0; i < colCount; i++) { QString cellContent = getCellContent(selected, i); if(!cellContent.length()) //skip empty cells @@ -761,14 +758,14 @@ void AbstractStdTable::copyLineSlot() void AbstractStdTable::copyLineToLogSlot() { - int colCount = getColumnCount(); - int selected = getInitialSelection(); + auto colCount = getColumnCount(); + auto selected = getInitialSelection(); QString finalText = ""; if(colCount == 1) finalText = getCellContent(selected, 0); else { - for(int i = 0; i < colCount; i++) + for(duint i = 0; i < colCount; i++) { QString cellContent = getCellContent(selected, i); if(!cellContent.length()) //skip empty cells @@ -785,12 +782,12 @@ void AbstractStdTable::copyLineToLogSlot() QString AbstractStdTable::copyTable(const std::vector & colWidths) { - int colCount = getColumnCount(); - int rowCount = getRowCount(); + auto colCount = getColumnCount(); + auto rowCount = getRowCount(); QString finalText = ""; if(colCount == 1) { - for(int i = 0; i < rowCount; i++) + for(duint i = 0; i < rowCount; i++) { QString cellContent = getCellContent(i, 0); if(!cellContent.length()) //skip empty cells @@ -803,7 +800,7 @@ QString AbstractStdTable::copyTable(const std::vector & colWidths) //std::vector colWidths; //for(int i = 0; i < colCount; i++) // colWidths.push_back(getMaxColumnLength(i)); - for(int i = 0; i < colCount; i++) + for(duint i = 0; i < colCount; i++) { if(i) finalText += " "; @@ -855,11 +852,11 @@ void AbstractStdTable::copyTableToLogSlot() void AbstractStdTable::copyTableResizeSlot() { std::vector colWidths; - int rowCount = getRowCount(); - int colCount = getColumnCount(); - for(int i = 0; i < colCount; i++) + auto rowCount = getRowCount(); + auto colCount = getColumnCount(); + for(duint i = 0; i < colCount; i++) { - int max = getCellContent(0, i).length(); + auto max = getCellContent(0, i).length(); for(int j = 1; j < rowCount; j++) max = std::max(getCellContent(j, i).length(), max); colWidths.push_back(max); @@ -874,7 +871,7 @@ void AbstractStdTable::copyTableResizeToLogSlot() int colCount = getColumnCount(); for(int i = 0; i < colCount; i++) { - int max = getCellContent(0, i).length(); + auto max = getCellContent(0, i).length(); for(int j = 1; j < rowCount; j++) max = std::max(getCellContent(j, i).length(), max); colWidths.push_back(max); @@ -934,7 +931,7 @@ void AbstractStdTable::setupCopyMenu(QMenu* copyMenu) void AbstractStdTable::setupCopyColumnMenu(QMenu* copyMenu) { - for(int i = 0; i < getColumnCount(); i++) + for(duint i = 0; i < getColumnCount(); i++) { if(!getCellContent(getInitialSelection(), i).length()) //skip empty cells continue; @@ -1022,7 +1019,7 @@ void AbstractStdTable::contextMenuRequestedSlot(const QPoint & pos) } } -void AbstractStdTable::headerButtonPressedSlot(int col) +void AbstractStdTable::headerButtonPressedSlot(duint col) { if(!mIsColumnSortingAllowed) return; @@ -1046,22 +1043,16 @@ void AbstractStdTable::reloadData() AbstractTableView::reloadData(); } -duint AbstractStdTable::getDisassemblyPopupAddress(int mousex, int mousey) +duint AbstractStdTable::getAddressForPosition(int x, int y) { - if(!bDisassemblyPopupEnabled) //No disassembly popup is meaningful for this table - return 0; - int c = getColumnIndexFromX(mousex); - int r = getTableOffset() + getIndexOffsetFromY(transY(mousey)); + auto c = getColumnIndexFromX(x); + auto r = getTableOffset() + getIndexOffsetFromY(transY(y)); if(r < getRowCount()) { QString cell = getCellContent(r, c); duint addr; bool ok = false; -#ifdef _WIN64 addr = cell.toULongLong(&ok, 16); -#else //x86 - addr = cell.toULong(&ok, 16); -#endif //_WIN64 if(!ok) return 0; else diff --git a/src/gui/Src/BasicView/AbstractStdTable.h b/src/gui/Src/BasicView/AbstractStdTable.h index 9948d268..1ba3a203 100644 --- a/src/gui/Src/BasicView/AbstractStdTable.h +++ b/src/gui/Src/BasicView/AbstractStdTable.h @@ -7,7 +7,7 @@ class AbstractStdTable : public AbstractTableView Q_OBJECT public: explicit AbstractStdTable(QWidget* parent = 0); - QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override; + QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override; void updateColors() override; void reloadData() override; @@ -21,30 +21,29 @@ public: void enableColumnSorting(bool enabled); // Selection Management - void expandSelectionUpTo(int to); + void expandSelectionUpTo(duint to); void expandUp(); void expandDown(); void expandTop(); void expandBottom(); - void setSingleSelection(int index); - int getInitialSelection() const; - QList getSelection() const; + void setSingleSelection(duint index); + duint getInitialSelection() const; + QList getSelection() const; void selectStart(); void selectEnd(); void selectNext(); void selectPrevious(); void selectAll(); - bool isSelected(int base, int offset) const; - bool scrollSelect(int offset); + bool isSelected(duint row) const; + bool scrollSelect(duint row); // Data Management void addColumnAt(int width, QString title, bool isClickable, QString copyTitle = ""); void deleteAllColumns() override; - virtual QString getCellContent(int r, int c) = 0; - virtual bool isValidIndex(int r, int c) = 0; - virtual void sortRows(int column, bool ascending) = 0; - duint getDisassemblyPopupAddress(int mousex, int mousey) override; + virtual QString getCellContent(duint row, duint column) = 0; + virtual bool isValidIndex(duint row, duint column) = 0; + virtual void sortRows(duint column, bool ascending) = 0; //context menu helpers void setupCopyMenu(QMenu* copyMenu); @@ -54,13 +53,13 @@ public: void setCopyMenuOnly(bool bSet, bool bDebugOnly = true); //draw helpers - void setHighlightText(QString highlightText, int minCol = 0) + void setHighlightText(QString highlightText, duint minCol = 0) { mHighlightText = highlightText; mMinimumHighlightColumn = minCol; } - void setAddressColumn(int col, bool cipBase = false) + void setAddressColumn(duint col, bool cipBase = false) { mAddressColumn = col; bCipBase = cipBase; @@ -71,13 +70,8 @@ public: bAddressLabel = addressLabel; } - bool setDisassemblyPopupEnabled(bool enabled) - { - return bDisassemblyPopupEnabled = enabled; - } - signals: - void selectionChangedSignal(int index); + void selectionChanged(duint index); void keyPressedSignal(QKeyEvent* event); void doubleClickedSignal(); void contextMenuSignal(const QPoint & pos); @@ -92,21 +86,22 @@ public slots: void copyEntrySlot(); void exportTableSlot(); void contextMenuRequestedSlot(const QPoint & pos); - void headerButtonPressedSlot(int col); + void headerButtonPressedSlot(duint col); protected: QString copyTable(const std::vector & colWidths); + duint getAddressForPosition(int x, int y) override; struct SelectionData { - int firstSelectedIndex = 0; - int fromIndex = 0; - int toIndex = 0; + duint firstSelectedIndex = 0; + duint fromIndex = 0; + duint toIndex = 0; }; SelectionData mSelection; - enum + enum GuiState { NoState, MultiRowsSelectionState @@ -121,7 +116,7 @@ protected: struct SortData { - int column = -1; + duint column = -1; bool ascending = true; } mSort; @@ -146,7 +141,6 @@ protected: int mMinimumHighlightColumn = 0; int mAddressColumn = -1; bool bAddressLabel = true; - bool bDisassemblyPopupEnabled = true; QAction* mCopyLine; QAction* mCopyTable; diff --git a/src/gui/Src/BasicView/AbstractTableView.cpp b/src/gui/Src/BasicView/AbstractTableView.cpp index b58a117b..7d7d78a8 100644 --- a/src/gui/Src/BasicView/AbstractTableView.cpp +++ b/src/gui/Src/BasicView/AbstractTableView.cpp @@ -4,70 +4,39 @@ #include "ColumnReorderDialog.h" #include "CachedFontMetrics.h" #include "Bridge.h" -#include "DisassemblyPopup.h" #include "MethodInvoker.h" -int AbstractTableView::mMouseWheelScrollDelta = 0; - AbstractTableScrollBar::AbstractTableScrollBar(QScrollBar* scrollbar) { setOrientation(scrollbar->orientation()); setParent(scrollbar->parentWidget()); } -void AbstractTableScrollBar::enterEvent(QEvent* event) +bool AbstractTableScrollBar::event(QEvent* event) { - Q_UNUSED(event); - QApplication::setOverrideCursor(Qt::ArrowCursor); -} - -void AbstractTableScrollBar::leaveEvent(QEvent* event) -{ - Q_UNUSED(event); - QApplication::restoreOverrideCursor(); + switch(event->type()) + { + case QEvent::Enter: + QApplication::setOverrideCursor(Qt::ArrowCursor); + break; + case QEvent::Leave: + QApplication::restoreOverrideCursor(); + break; + default: + break; + } + return QScrollBar::event(event); } AbstractTableView::AbstractTableView(QWidget* parent) - : QAbstractScrollArea(parent), - mFontMetrics(nullptr), - mDisassemblyPopup(nullptr) + : QAbstractScrollArea(parent) { - // Class variable initialization - mTableOffset = 0; - mPrevTableOffset = mTableOffset + 1; - Header data; - data.isVisible = true; - data.height = 20; - data.activeButtonIndex = -1; - mHeader = data; - - // Paint cell content only when debugger is running - setDrawDebugOnly(true); - - mRowCount = 0; - - mHeaderButtonSytle.setObjectName("AbstractTableViewHeader"); - - mNbrOfLineToPrint = 0; - - memset(&mColResizeData, 0, sizeof(mColResizeData)); - - mGuiState = AbstractTableView::NoState; - - mShouldReload = true; - mAllowPainting = true; - mDrawDebugOnly = false; - mPopupEnabled = true; - mPopupTimer = 0; - // ScrollBar Init setVerticalScrollBar(new AbstractTableScrollBar(verticalScrollBar())); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); memset(&mScrollBarAttributes, 0, sizeof(mScrollBarAttributes)); horizontalScrollBar()->setRange(0, 0); - horizontalScrollBar()->setPageStep(650); - if(mMouseWheelScrollDelta == 0) - mMouseWheelScrollDelta = QApplication::wheelScrollLines(); + horizontalScrollBar()->setPageStep(650); // TODO: random value setMouseTracking(true); // Slots @@ -75,17 +44,16 @@ AbstractTableView::AbstractTableView(QWidget* parent) connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(updateColorsSlot())); connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(updateFontsSlot())); connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(updateShortcutsSlot())); - connect(Bridge::getBridge(), SIGNAL(shutdown()), this, SLOT(shutdownSlot())); + connect(Bridge::getBridge(), SIGNAL(close()), this, SLOT(closeSlot())); // todo: try Qt::QueuedConnection to init Initialize(); } -void AbstractTableView::shutdownSlot() +void AbstractTableView::closeSlot() { if(ConfigBool("Gui", "SaveColumnOrder")) saveColumnToConfig(); - setAllowPainting(false); } /************************************************************************************ @@ -105,11 +73,14 @@ void AbstractTableView::Initialize() void AbstractTableView::updateColors() { - mBackgroundColor = ConfigColor("AbstractTableViewBackgroundColor"); mTextColor = ConfigColor("AbstractTableViewTextColor"); - mSeparatorColor = ConfigColor("AbstractTableViewSeparatorColor"); + mBackgroundColor = ConfigColor("AbstractTableViewBackgroundColor"); + mHeaderTextColor = ConfigColor("AbstractTableViewHeaderTextColor"); + mHeaderBackgroundColor = ConfigColor("AbstractTableViewHeaderBackgroundColor"); + mSelectionColor = ConfigColor("AbstractTableViewSelectionColor"); + mSeparatorColor = ConfigColor("AbstractTableViewSeparatorColor"); } void AbstractTableView::updateFonts() @@ -119,10 +90,10 @@ void AbstractTableView::updateFonts() mHeader.height = mFontMetrics->height() + 4; } -QColor AbstractTableView::getCellColor(int r, int c) +QColor AbstractTableView::getCellColor(duint row, duint col) { - Q_UNUSED(r); - Q_UNUSED(c); + Q_UNUSED(row); + Q_UNUSED(col); return mTextColor; } @@ -144,7 +115,7 @@ void AbstractTableView::updateFontsSlot() auto newCharWidth = getCharWidth(); // Scale the column widths to the new font - for(int col = 0; col < getColumnCount(); col++) + for(duint col = 0; col < getColumnCount(); col++) { auto width = getColumnWidth(col); auto charCount = width / oldCharWidth; @@ -160,7 +131,7 @@ void AbstractTableView::updateShortcutsSlot() void AbstractTableView::loadColumnFromConfig(const QString & viewName) { - int columnCount = getColumnCount(); + duint columnCount = getColumnCount(); for(int i = 0; i < columnCount; i++) { duint width = ConfigUint("Gui", QString("%1ColumnWidth%2").arg(viewName).arg(i).toUtf8().constData()); @@ -202,9 +173,10 @@ void AbstractTableView::setupColumnConfigDefaultValue(QMap & map void AbstractTableView::editColumnDialog() { - ColumnReorderDialog reorderDialog(this); - reorderDialog.setWindowTitle(tr("Edit columns")); - reorderDialog.exec(); + delete mReorderDialog; + mReorderDialog = new ColumnReorderDialog(this); + mReorderDialog->setWindowTitle(tr("Edit columns")); + mReorderDialog->open(); } /************************************************************************************ @@ -219,49 +191,18 @@ void AbstractTableView::editColumnDialog() */ void AbstractTableView::paintEvent(QPaintEvent* event) { - Q_UNUSED(event); - - QPainter wPainter(this->viewport()); - wPainter.setFont(font()); - - // Paint background - if(mBackgroundColor.alpha() == 255) // The secret code to allow the user to set a background image in style.css - wPainter.fillRect(wPainter.viewport(), QBrush(mBackgroundColor)); - if(!mAllowPainting) return; - if(getColumnCount()) //make sure the last column is never smaller than the window - { - int totalWidth = 0; - int lastWidth = totalWidth; - int last = 0; - for(int i = 0; i < getColumnCount(); i++) - { - if(getColumnHidden(mColumnOrder[i])) - continue; - last = mColumnOrder[i]; - lastWidth = getColumnWidth(last); - totalWidth += lastWidth; - } - lastWidth = totalWidth - lastWidth; - int width = this->viewport()->width(); - lastWidth = width > lastWidth ? width - lastWidth : 0; - if(totalWidth < width) - setColumnWidth(last, lastWidth); - else - setColumnWidth(last, getColumnWidth(last)); - } - - int wViewableRowsCount = getViewableRowsCount(); + Q_UNUSED(event); + QPainter painter(this->viewport()); + painter.setFont(font()); + auto viewableRowsCount = getViewableRowsCount(); int scrollValue = -horizontalScrollBar()->value(); - int x = scrollValue; - int y = 0; - // Reload data if needed - if(mPrevTableOffset != mTableOffset || mShouldReload == true) + if(mPrevTableOffset != mTableOffset || mShouldReload) { updateScrollBarRange(getRowCount()); prepareData(); @@ -269,57 +210,82 @@ void AbstractTableView::paintEvent(QPaintEvent* event) mShouldReload = false; } - // Paint header - if(mHeader.isVisible == true) + // Paints background + if(mBackgroundColor.alpha() == 255) // The secret code to allow the user to set a background image in style.css + painter.fillRect(painter.viewport(), QBrush(mBackgroundColor)); + + // Paints header + if(mHeader.isVisible) { + int x = scrollValue; + int y = 0; + + QPen textPen(mHeaderTextColor); + QPen separatorPen(mSeparatorColor, 2); + QBrush backgroundBrush(mHeaderBackgroundColor); + for(int j = 0; j < getColumnCount(); j++) { int i = mColumnOrder[j]; if(getColumnHidden(i)) continue; int width = getColumnWidth(i); - QStyleOptionButton wOpt; - if((mColumnList[i].header.isPressed == true) && (mColumnList[i].header.isMouseOver == true) - || (mGuiState == AbstractTableView::HeaderButtonReordering && mColumnOrder[mHoveredColumnDisplayIndex] == i)) - wOpt.state = QStyle::State_Sunken; + int height = getHeaderHeight(); + + const auto isPressed = (mColumnList[i].header.isPressed && mColumnList[i].header.isMouseOver) + || (mGuiState == AbstractTableView::HeaderButtonReordering && mColumnOrder[mHoveredColumnDisplayIndex] == i); + + if(isPressed) + { + painter.fillRect(x, y, width, height, QBrush(mSeparatorColor)); + } else - wOpt.state = QStyle::State_Enabled; + { + painter.fillRect(x, y, width, height, backgroundBrush); + } - wOpt.rect = QRect(x, y, width, getHeaderHeight()); + painter.setPen(textPen); + painter.drawText(QRect(x + 4, y, width - 8, height), Qt::AlignVCenter | Qt::AlignLeft, mColumnList[i].title); - mHeaderButtonSytle.style()->drawControl(QStyle::CE_PushButton, &wOpt, &wPainter, &mHeaderButtonSytle); + if(isPressed) + { + painter.setPen(QPen(mTextColor, 2)); + } + else + { + painter.setPen(separatorPen); + } - wPainter.setPen(mHeaderTextColor); - wPainter.drawText(QRect(x + 4, y, width - 8, getHeaderHeight()), Qt::AlignVCenter | Qt::AlignLeft, mColumnList[i].title); + painter.drawLine(x, y + height - separatorPen.width(), x + width - separatorPen.width(), y + height - separatorPen.width()); + painter.drawLine(x + width - separatorPen.width() + 1, y, x + width - separatorPen.width() + 1, y + height - separatorPen.width()); x += width; } } - x = scrollValue; - y = getHeaderHeight(); + int x = scrollValue; + int y = getHeaderHeight(); // Iterate over all columns and cells - QString wStr; for(int k = 0; k < getColumnCount(); k++) { int j = mColumnOrder[k]; if(getColumnHidden(j)) continue; - for(int i = 0; i < wViewableRowsCount; i++) + for(duint i = 0; i < viewableRowsCount; i++) { - // Paints cell contents + // Paints cell contents if(i < mNbrOfLineToPrint) { // Don't draw cells if the flag is set, and no process is running if(!mDrawDebugOnly || DbgIsDebugging()) { - wStr = paintContent(&wPainter, mTableOffset, i, j, x, y, getColumnWidth(j), getRowHeight()); + QString str = paintContent(&painter, mTableOffset + i, j, x, y, getColumnWidth(j), getRowHeight()); - if(wStr.length()) + if(str.length()) { - wPainter.setPen(getCellColor(mTableOffset + i, j)); - wPainter.drawText(QRect(x + 4, y, getColumnWidth(j) - 5, getRowHeight()), Qt::AlignVCenter | Qt::AlignLeft, wStr); + painter.setPen(getCellColor(mTableOffset + i, j)); + painter.drawText(QRectF(x + 4, y, getColumnWidth(j) - 5, getRowHeight()), Qt::AlignVCenter | Qt::AlignLeft, str); } } } @@ -327,8 +293,8 @@ void AbstractTableView::paintEvent(QPaintEvent* event) if(getColumnCount() > 1) { // Paints cell right borders - wPainter.setPen(mSeparatorColor); - wPainter.drawLine(x + getColumnWidth(j) - 1, y, x + getColumnWidth(j) - 1, y + getRowHeight() - 1); + painter.setPen(mSeparatorColor); + painter.drawLine(x + getColumnWidth(j) - 1, y, x + getColumnWidth(j) - 1, y + getRowHeight() - 1); } // Update y for the next iteration @@ -356,13 +322,13 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) { if(getColumnCount() <= 1) return; - int wColIndex = getColumnIndexFromX(event->x()); - int wDisplayIndex = getColumnDisplayIndexFromX(event->x()); - int wStartPos = getColumnPosition(wDisplayIndex); // Position X of the start of column - int wEndPos = wStartPos + getColumnWidth(wColIndex); // Position X of the end of column - bool wHandle = ((wColIndex != 0) && (event->x() >= wStartPos) && (event->x() <= (wStartPos + 2))) || ((event->x() <= wEndPos) && (event->x() >= (wEndPos - 2))); - if(wColIndex == getColumnCount() - 1 && event->x() > viewport()->width()) //last column - wHandle = false; + int colIndex = getColumnIndexFromX(event->x()); + int displayIndex = getColumnDisplayIndexFromX(event->x()); + int startPos = getColumnPosition(displayIndex); // Position X of the start of column + int endPos = startPos + getColumnWidth(colIndex); // Position X of the end of column + bool onHandle = ((colIndex != 0) && (event->x() >= startPos) && (event->x() <= (startPos + 2))) || ((event->x() <= endPos) && (event->x() >= (endPos - 2))); + if(colIndex == getColumnCount() - 1 && event->x() > viewport()->width()) //last column + onHandle = false; switch(mGuiState) { @@ -370,29 +336,20 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) { if(event->buttons() == Qt::NoButton) { - bool wHasCursor = cursor().shape() == Qt::SplitHCursor ? true : false; + bool hasCursor = cursor().shape() == Qt::SplitHCursor ? true : false; - if((wHandle == true) && (wHasCursor == false)) + if(onHandle && !hasCursor) { setCursor(Qt::SplitHCursor); mColResizeData.splitHandle = true; mGuiState = AbstractTableView::ReadyToResize; } - else if((wHandle == false) && (wHasCursor == true)) + else if(!onHandle && hasCursor) { unsetCursor(); mColResizeData.splitHandle = false; mGuiState = AbstractTableView::NoState; } - else if(wHandle == false && wHasCursor == false) - { - if(event->y() > getHeaderHeight() && DbgIsDebugging()) - ShowDisassemblyPopup(getDisassemblyPopupAddress(event->x(), event->y()), event->x(), event->y()); - } - } - else - { - QAbstractScrollArea::mouseMoveEvent(event); } } break; @@ -401,7 +358,7 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) { if(event->buttons() == Qt::NoButton) { - if((wHandle == false) && (mGuiState == AbstractTableView::ReadyToResize)) + if(!onHandle && mGuiState == AbstractTableView::ReadyToResize) { unsetCursor(); mColResizeData.splitHandle = false; @@ -414,11 +371,11 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) case AbstractTableView::ResizeColumnState: { int delta = event->x() - mColResizeData.lastPosX; - bool bCanResize = (getColumnWidth(mColumnOrder[mColResizeData.index]) + delta) >= 20; + bool bCanResize = (getColumnWidth(mColumnOrder[mColResizeData.index]) + delta) >= mMinColumnWidth; if(bCanResize) { - int wNewSize = getColumnWidth(mColumnOrder[mColResizeData.index]) + delta; - setColumnWidth(mColumnOrder[mColResizeData.index], wNewSize); + int newSize = getColumnWidth(mColumnOrder[mColResizeData.index]) + delta; + setColumnWidth(mColumnOrder[mColResizeData.index], newSize); mColResizeData.lastPosX = event->x(); updateViewport(); } @@ -427,9 +384,9 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) case AbstractTableView::HeaderButtonPressed: { - int wColIndex = getColumnIndexFromX(event->x()); + int colIndex = getColumnIndexFromX(event->x()); - if(wColIndex == mHeader.activeButtonIndex) + if(colIndex == mHeader.activeButtonIndex) { mColumnList[mHeader.activeButtonIndex].header.isMouseOver = (event->y() <= getHeaderHeight()) && (event->y() >= 0); break; @@ -450,6 +407,8 @@ void AbstractTableView::mouseMoveEvent(QMouseEvent* event) default: break; } + + QAbstractScrollArea::mouseMoveEvent(event); } /** @@ -544,17 +503,15 @@ void AbstractTableView::mouseReleaseEvent(QMouseEvent* event) } else if(mGuiState == AbstractTableView::HeaderButtonReordering) { - int temp; - int wReorderFrom = getColumnDisplayIndexFromX(mReorderStartX); - int wReorderTo = getColumnDisplayIndexFromX(event->x()); - temp = mColumnOrder[wReorderFrom]; - mColumnOrder[wReorderFrom] = mColumnOrder[wReorderTo]; - mColumnOrder[wReorderTo] = temp; + int reorderFrom = getColumnDisplayIndexFromX(mReorderStartX); + int reorderTo = getColumnDisplayIndexFromX(event->x()); + std::swap(mColumnOrder[reorderFrom], mColumnOrder[reorderTo]); mGuiState = AbstractTableView::NoState; + updateLastColumnWidth(); } else { - QWidget::mouseReleaseEvent(event); + return; } // Release all buttons @@ -587,40 +544,122 @@ void AbstractTableView::mouseDoubleClickEvent(QMouseEvent* event) void AbstractTableView::wheelEvent(QWheelEvent* event) { - QPoint numDegrees = event->angleDelta() / 8; - QPoint numSteps = numDegrees / 15; + const auto lineAngleTick = 120 / QApplication::wheelScrollLines(); + mAngleScrollDelta += event->angleDelta(); + + auto linesY = mAngleScrollDelta.y() / lineAngleTick; + if(linesY != 0) + { + mAngleScrollDelta = QPoint(0, mAngleScrollDelta.y() % lineAngleTick); + } + + auto linesX = mAngleScrollDelta.x() / lineAngleTick; + if(linesX != 0) + { + mAngleScrollDelta = QPoint(mAngleScrollDelta.x() % lineAngleTick, 0); + } if(event->modifiers() == Qt::NoModifier) { - if(numSteps.y() > 0) +#ifdef Q_OS_DARWIN + const auto enableTouchPad = true; +#else + // For now this functionality is only enabled on macOS, because the Qt::ScrollBegin phase + // is only available there. Implementing this on another OS would require a timer to determine + // when the user stops scrolling. + const auto enableTouchPad = false; +#endif // Q_OS_DARWIN + +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + if(enableTouchPad && event->device()->type() == QInputDevice::DeviceType::TouchPad) +#else + if(enableTouchPad && event->source() == Qt::MouseEventSynthesizedBySystem) +#endif // QT_VERSION { - if(mMouseWheelScrollDelta > 0) - for(int i = 0; i < mMouseWheelScrollDelta * numSteps.y(); i++) + QPoint pixelDelta = event->pixelDelta(); + + // When a touchpad is used the scroll events are pixel-based (vs mouse wheels which are angle-based). + // The scroll direction is determined with a getRowHeight threshold and after that the direction is + // locked. Without doing this you get weird diagonal scrolling and a bad user experience. + if(event->phase() == Qt::ScrollBegin) + { + mPixelScrollDelta = pixelDelta; + mPixelScrollDirection = ScrollUnknown; + } + else + { + mPixelScrollDelta += pixelDelta; + } + + auto deltaY = mPixelScrollDelta.y(); + const auto tickY = getRowHeight(); + auto stepsY = deltaY / tickY; + if(stepsY != 0 && mPixelScrollDirection != ScrollHorizontal) + { + mPixelScrollDirection = ScrollVertical; + mPixelScrollDelta = QPoint(0, deltaY % tickY); + if(stepsY > 0) + { + for(int i = 0; i < stepsY; i++) + verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); + } + else + { + for(int i = 0; i < -stepsY; i++) + verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); + } + } + + auto deltaX = mPixelScrollDelta.x(); + const auto tickX = getRowHeight(); + if(mPixelScrollDirection == ScrollUnknown && (deltaX / tickX) != 0) + { + mPixelScrollDirection = ScrollHorizontal; + } + + if(mPixelScrollDirection == ScrollHorizontal) + { + if(deltaX > 0) + { + for(int i = 0; i < deltaX; i++) + horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); + } + else + { + for(int i = 0; i < -deltaX; i++) + horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); + } + mPixelScrollDelta = QPoint(0, 0); + } + } + else + { + if(linesY > 0) + { + for(int i = 0; i < linesY; i++) verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); - else // -1 : one screen at a time - verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); - } - else if(numSteps.y() < 0) - { - if(mMouseWheelScrollDelta > 0) - for(int i = 0; i < mMouseWheelScrollDelta * numSteps.y() * -1; i++) + } + else if(linesY < 0) + { + for(int i = 0; i < -linesY; i++) verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); - else // -1 : one screen at a time - verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); - } - else if(numSteps.x() > 0) - { - for(int i = 0; i < 20 * numSteps.x(); i++) - horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); - } - else if(numSteps.x() < 0) - { - for(int i = 0; i < 20 * numSteps.x() * -1; i++) - horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); + } + else if(linesX > 0) + { + for(int i = 0; i < linesX * 20; i++) + horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); + } + else if(linesX < 0) + { + for(int i = 0; i < -linesX * 20; i++) + horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); + } } } else if(event->modifiers() == Qt::ControlModifier) // Zoom + { Config()->zoomFont("AbstractTableView", event); + } } @@ -633,21 +672,19 @@ void AbstractTableView::wheelEvent(QWheelEvent* event) */ void AbstractTableView::resizeEvent(QResizeEvent* event) { + if(event->size().width() != event->oldSize().width()) + { + updateLastColumnWidth(); + } + if(event->size().height() != event->oldSize().height()) { - updateScrollBarRange(getRowCount()); emit viewableRowsChanged(getViewableRowsCount()); mShouldReload = true; } QAbstractScrollArea::resizeEvent(event); } -void AbstractTableView::leaveEvent(QEvent* event) -{ - ShowDisassemblyPopup(0, 0, 0); - QAbstractScrollArea::leaveEvent(event); -} - /************************************************************************************ Keyboard Management ************************************************************************************/ @@ -703,13 +740,12 @@ void AbstractTableView::keyPressEvent(QKeyEvent* event) */ void AbstractTableView::vertSliderActionSlot(int action) { - dsint wDelta = 0; - int wSliderPos = verticalScrollBar()->sliderPosition(); - int wNewScrollBarValue; + dsint delta = 0; + int sliderPos = verticalScrollBar()->sliderPosition(); // Bounding - wSliderPos = wSliderPos > verticalScrollBar()->maximum() ? verticalScrollBar()->maximum() : wSliderPos; - wSliderPos = wSliderPos < 0 ? 0 : wSliderPos; + sliderPos = sliderPos > verticalScrollBar()->maximum() ? verticalScrollBar()->maximum() : sliderPos; + sliderPos = sliderPos < 0 ? 0 : sliderPos; // Determine the delta switch(action) @@ -717,49 +753,42 @@ void AbstractTableView::vertSliderActionSlot(int action) case QAbstractSlider::SliderNoAction: break; case QAbstractSlider::SliderSingleStepAdd: - wDelta = 1; + delta = 1; break; case QAbstractSlider::SliderSingleStepSub: - wDelta = -1; + delta = -1; break; case QAbstractSlider::SliderPageStepAdd: - wDelta = 30; + delta = 30; break; case QAbstractSlider::SliderPageStepSub: - wDelta = -30; + delta = -30; break; case QAbstractSlider::SliderToMinimum: case QAbstractSlider::SliderToMaximum: case QAbstractSlider::SliderMove: -#ifdef _WIN64 - wDelta = scaleFromScrollBarRangeToUint64(wSliderPos) - mTableOffset; -#else - wDelta = wSliderPos - mTableOffset; -#endif + delta = scaleFromScrollBarRangeToUint64(sliderPos) - mTableOffset; break; default: break; } + // TODO: negative? // Call the hook (Usefull for disassembly) - mTableOffset = sliderMovedHook(action, mTableOffset, wDelta); + mTableOffset = sliderMovedHook((QScrollBar::SliderAction)action, mTableOffset, delta); //this emit causes massive lag in the GUI //emit tableOffsetChanged(mTableOffset); // Scale the new table offset to the 32bits scrollbar range -#ifdef _WIN64 - wNewScrollBarValue = scaleFromUint64ToScrollBarRange(mTableOffset); -#else - wNewScrollBarValue = mTableOffset; -#endif + auto newScrollBarValue = scaleFromUint64ToScrollBarRange(mTableOffset); //this emit causes massive lag in the GUI //emit repainted(); // Update scrollbar attributes - verticalScrollBar()->setValue(wNewScrollBarValue); - verticalScrollBar()->setSliderPosition(wNewScrollBarValue); + verticalScrollBar()->setValue(newScrollBarValue); + verticalScrollBar()->setSliderPosition(newScrollBarValue); } /** @@ -767,23 +796,25 @@ void AbstractTableView::vertSliderActionSlot(int action) * It allows changing the table offset according to the action type, the old table offset * and delta between the old and the new table offset. * - * @param[in] type Type of action (Refer to the QAbstractSlider::SliderAction enum) - * @param[in] value Old table offset - * @param[in] delta Scrollbar value delta compared to the previous state + * @param[in] action Type of action (Refer to the QAbstractSlider::SliderAction enum) + * @param[in] prevTableOffset Previous table offset + * @param[in] delta Scrollbar value delta compared to the previous state * * @return Return the value of the new table offset. */ -dsint AbstractTableView::sliderMovedHook(int type, dsint value, dsint delta) +duint AbstractTableView::sliderMovedHook(QScrollBar::SliderAction action, duint prevTableOffset, dsint delta) { - Q_UNUSED(type); - dsint wValue = value + delta; - dsint wMax = getRowCount() - getViewableRowsCount() + 1; + Q_UNUSED(action); + + // TODO: fix this signed/unsigned logic + dsint value = prevTableOffset + delta; + dsint maxTableOffset = getMaxTableOffset(); // Bounding - wValue = wValue > wMax ? wMax : wValue; - wValue = wValue < 0 ? 0 : wValue; + value = value > maxTableOffset ? maxTableOffset : value; + value = value < 0 ? 0 : value; - return wValue; + return value; } /** @@ -793,25 +824,33 @@ dsint AbstractTableView::sliderMovedHook(int type, dsint value, dsint delta) * * @return 32bits integer. */ -#ifdef _WIN64 -int AbstractTableView::scaleFromUint64ToScrollBarRange(dsint value) +int AbstractTableView::scaleFromUint64ToScrollBarRange(duint value) { - if(mScrollBarAttributes.is64 == true) + if(mScrollBarAttributes.is64) { - dsint wValue = ((dsint)value) >> mScrollBarAttributes.rightShiftCount; - dsint wValueMax = ((dsint)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; + // TODO: this needs to be rewritten + value = ((dsint)value) >> mScrollBarAttributes.rightShiftCount; + dsint valueMax = ((dsint)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; if(value == ((dsint)getRowCount() - 1)) - return (int)(verticalScrollBar()->maximum()); + { + return verticalScrollBar()->maximum(); + } else - return (int)((dsint)((dsint)verticalScrollBar()->maximum() * (dsint)wValue) / (dsint)wValueMax); + { + if(valueMax == 0) + { + printf("valueMax: %lli, value: %llu, rightShiftCount: %d\n", valueMax, value, mScrollBarAttributes.rightShiftCount); + } + // TODO: division by zero + return (int)((dsint)((dsint)verticalScrollBar()->maximum() * (dsint)value) / (dsint)valueMax); + } } else { return (int)value; } } -#endif /** * @brief This method scale the given 32bits integer to the table range (64bits). @@ -820,24 +859,22 @@ int AbstractTableView::scaleFromUint64ToScrollBarRange(dsint value) * * @return 64bits integer. */ -#ifdef _WIN64 -dsint AbstractTableView::scaleFromScrollBarRangeToUint64(int value) +duint AbstractTableView::scaleFromScrollBarRangeToUint64(int value) { - if(mScrollBarAttributes.is64 == true) + if(mScrollBarAttributes.is64) { - dsint wValueMax = ((dsint)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; + dsint valueMax = ((dsint)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; if(value == (int)0x7FFFFFFF) return (dsint)(getRowCount() - 1); else - return (dsint)(((dsint)((dsint)wValueMax * (dsint)value) / (dsint)0x7FFFFFFF) << mScrollBarAttributes.rightShiftCount); + return (dsint)(((dsint)((dsint)valueMax * (dsint)value) / (dsint)0x7FFFFFFF) << mScrollBarAttributes.rightShiftCount); } else { return (dsint)value; } } -#endif /** * @brief This method updates the vertical scrollbar range and pre-computes some attributes for the 32<->64bits conversion methods. @@ -846,57 +883,50 @@ dsint AbstractTableView::scaleFromScrollBarRangeToUint64(int value) * * @return none. */ -void AbstractTableView::updateScrollBarRange(dsint range) +void AbstractTableView::updateScrollBarRange(duint range) { - dsint wMax = range - getViewableRowsCount() + 1; - int rangeMin = 0, rangeMax = wMax; + int rangeMin = 0; + int rangeMax = 0; - if(wMax > 0) + auto viewableRows = getViewableRowsCount(); + if(range > viewableRows) { -#ifdef _WIN64 - if((duint)wMax < (duint)0x0000000080000000) + auto maxTableOffset = range - viewableRows + 1; // TODO: why +1? + if(maxTableOffset < (duint)INT_MAX + 1) { mScrollBarAttributes.is64 = false; mScrollBarAttributes.rightShiftCount = 0; + rangeMin = 0; - rangeMax = wMax; + rangeMax = maxTableOffset; } else { - duint wMask = 0x8000000000000000; - int wLeadingZeroCount; - // Count leading zeros - for(wLeadingZeroCount = 0; wLeadingZeroCount < 64; wLeadingZeroCount++) + int leadingZeroCount = 0; + for(duint mask = 0x8000000000000000; mask != 0; mask >>= 1) { - if((duint)wMax < wMask) + if((maxTableOffset & mask) != 0) { - wMask = wMask >> 1; + break; } else { - break; + leadingZeroCount++; } } mScrollBarAttributes.is64 = true; - mScrollBarAttributes.rightShiftCount = 32 - wLeadingZeroCount; + mScrollBarAttributes.rightShiftCount = 32 - leadingZeroCount; + rangeMin = 0; - rangeMax = 0x7FFFFFFF; + rangeMax = INT_MAX; } -#else - rangeMin = 0; - rangeMax = wMax; -#endif - } - else - { - rangeMin = 0; - rangeMax = 0; } + verticalScrollBar()->setRange(rangeMin, rangeMax); verticalScrollBar()->setSingleStep(getRowHeight()); - verticalScrollBar()->setPageStep(getViewableRowsCount() * getRowHeight()); + verticalScrollBar()->setPageStep(viewableRows * getRowHeight()); } /************************************************************************************ @@ -909,7 +939,7 @@ void AbstractTableView::updateScrollBarRange(dsint range) * * @return row index offset. */ -int AbstractTableView::getIndexOffsetFromY(int y) const +dsint AbstractTableView::getIndexOffsetFromY(int y) const { return (y / getRowHeight()); } @@ -921,7 +951,7 @@ int AbstractTableView::getIndexOffsetFromY(int y) const * * @return Column index. */ -int AbstractTableView::getColumnIndexFromX(int x) const +duint AbstractTableView::getColumnIndexFromX(int x) const { int scrollX = -horizontalScrollBar()->value(); duint colIndex = 0; @@ -982,6 +1012,46 @@ int AbstractTableView::getColumnDisplayIndexFromX(int x) return getColumnCount() - 1; } +void AbstractTableView::updateLastColumnWidth() +{ + // Make sure the last column is never smaller than the viewport + if(getColumnCount()) + { + int totalWidth = 0; + int lastWidth = totalWidth; + int last = 0; + for(int i = 0; i < getColumnCount(); i++) + { + if(getColumnHidden(mColumnOrder[i])) + continue; + last = mColumnOrder[i]; + auto & column = mColumnList[last]; + column.paintedWidth = -1; + lastWidth = column.width; + totalWidth += lastWidth; + } + + lastWidth = totalWidth - lastWidth; + int width = viewport()->width(); + lastWidth = width > lastWidth ? width - lastWidth : 0; + if(totalWidth < width) + mColumnList[last].paintedWidth = lastWidth; + } + + MethodInvoker::invokeMethod([this]() + { + int totalWidth = 0; + for(int i = 0; i < getColumnCount(); i++) + if(!getColumnHidden(i)) + totalWidth += getColumnWidth(i); + + if(totalWidth > viewport()->width()) + horizontalScrollBar()->setRange(0, totalWidth - viewport()->width()); + else + horizontalScrollBar()->setRange(0, 0); + }); +} + /** * @brief Returns the x coordinate of the beginning of the column at index index. * @@ -989,7 +1059,7 @@ int AbstractTableView::getColumnDisplayIndexFromX(int x) * * @return X coordinate of the column index. */ -int AbstractTableView::getColumnPosition(int index) const +int AbstractTableView::getColumnPosition(duint index) const { int posX = -horizontalScrollBar()->value(); @@ -1023,27 +1093,20 @@ int AbstractTableView::transY(int y) const * * @return Number of viewable rows. */ -int AbstractTableView::getViewableRowsCount() const +duint AbstractTableView::getViewableRowsCount() const { - int wTableHeight = this->viewport()->height() - getHeaderHeight(); - int wCount = wTableHeight / getRowHeight(); + auto tableHeight = viewport()->height() - getHeaderHeight(); + auto count = tableHeight / getRowHeight(); - wCount += (wTableHeight % getRowHeight()) > 0 ? 1 : 0; + count += (tableHeight % getRowHeight()) > 0 ? 1 : 0; - return wCount; + return count; } -/** - * @brief This virtual method returns the number of remaining lines to print. - * - * @return Number of remaining lines to print. - */ -int AbstractTableView::getLineToPrintcount() const +duint AbstractTableView::getMaxTableOffset() const { - int wViewableRowsCount = getViewableRowsCount(); - dsint wRemainingRowsCount = getRowCount() - mTableOffset; - int wCount = (dsint)wRemainingRowsCount > (dsint)wViewableRowsCount ? (int)wViewableRowsCount : (int)wRemainingRowsCount; - return wCount; + // TODO: is the +1 correct? + return getRowCount() - getViewableRowsCount() + 1; } /************************************************************************************ @@ -1058,32 +1121,25 @@ int AbstractTableView::getLineToPrintcount() const */ void AbstractTableView::addColumnAt(int width, const QString & title, bool isClickable) { - HeaderButton wHeaderButton; - Column wColumn; - int wCurrentCount; - - // Fix invisible columns near the edge of the screen - if(width < 20) - width = 20; - - wHeaderButton.isPressed = false; - wHeaderButton.isClickable = isClickable; - wHeaderButton.isMouseOver = false; - - wColumn.header = wHeaderButton; - wColumn.width = width; - wColumn.hidden = false; - wColumn.title = title; - wCurrentCount = mColumnList.length(); - mColumnList.append(wColumn); - mColumnOrder.append(wCurrentCount); + Column column; + column.header.isClickable = isClickable; + column.width = std::max(mMinColumnWidth, width); + column.hidden = false; + column.title = title; + mColumnOrder.append(mColumnList.length()); + mColumnList.append(column); } -void AbstractTableView::setRowCount(dsint count) +void AbstractTableView::setRowCount(duint count) { if(mRowCount != count) mShouldReload = true; mRowCount = count; + + MethodInvoker::invokeMethod([this]() + { + updateScrollBarRange(getRowCount()); + }); } void AbstractTableView::deleteAllColumns() @@ -1092,32 +1148,32 @@ void AbstractTableView::deleteAllColumns() mColumnOrder.clear(); } -void AbstractTableView::setColTitle(int index, const QString & title) +void AbstractTableView::setColTitle(duint col, const QString & title) { - if(mColumnList.size() > 0 && index >= 0 && index < mColumnList.size()) + if(mColumnList.size() > 0 && col >= 0 && col < mColumnList.size()) { - Column wColumn = mColumnList.takeAt(index); - wColumn.title = title; - mColumnList.insert(index - 1, wColumn); + Column column = mColumnList.takeAt(col); + column.title = title; + mColumnList.insert(col - 1, column); } } -QString AbstractTableView::getColTitle(int index) const +QString AbstractTableView::getColTitle(duint col) const { - if(mColumnList.size() > 0 && index >= 0 && index < mColumnList.size()) - return mColumnList[index].title; + if(mColumnList.size() > 0 && col >= 0 && col < mColumnList.size()) + return mColumnList[col].title; return QString(); } /************************************************************************************ Getter & Setter ************************************************************************************/ -dsint AbstractTableView::getRowCount() const +duint AbstractTableView::getRowCount() const { return mRowCount; } -int AbstractTableView::getColumnCount() const +duint AbstractTableView::getColumnCount() const { return mColumnList.size(); } @@ -1127,58 +1183,52 @@ int AbstractTableView::getRowHeight() const return mFontMetrics->height() | 1; } -int AbstractTableView::getColumnWidth(int index) const +int AbstractTableView::getColumnWidth(duint col) const { - if(index < 0) - return -1; - else if(index < getColumnCount()) - return mColumnList[index].width; + if(col < getColumnCount()) + { + const auto & column = mColumnList[col]; + if(column.paintedWidth != -1) + return column.paintedWidth; + else + return column.width; + } return 0; } -bool AbstractTableView::getColumnHidden(int col) const +bool AbstractTableView::getColumnHidden(duint col) const { - if(col < 0) - return true; - else if(col < getColumnCount()) + if(col < getColumnCount()) return mColumnList[col].hidden; else return true; } -void AbstractTableView::setColumnHidden(int col, bool hidden) +void AbstractTableView::setColumnHidden(duint col, bool hidden) { if(col < getColumnCount() && col >= 0) mColumnList[col].hidden = hidden; } -void AbstractTableView::setColumnWidth(int index, int width) +void AbstractTableView::setColumnWidth(duint col, int width) { - mColumnList[index].width = width; + if(col >= getColumnCount()) + return; - MethodInvoker::invokeMethod([this]() - { - int totalWidth = 0; - for(int i = 0; i < getColumnCount(); i++) - if(!getColumnHidden(i)) - totalWidth += getColumnWidth(i); + mColumnList[col].width = std::max(width, mMinColumnWidth); - if(totalWidth > viewport()->width()) - horizontalScrollBar()->setRange(0, totalWidth - viewport()->width()); - else - horizontalScrollBar()->setRange(0, 0); - }); + updateLastColumnWidth(); } -void AbstractTableView::setColumnOrder(int pos, int index) +void AbstractTableView::setColumnOrder(duint col, duint colNew) { - if(index != 0) - mColumnOrder[pos] = index - 1; + if(colNew != 0) + mColumnOrder[col] = colNew - 1; } -int AbstractTableView::getColumnOrder(int index) const +duint AbstractTableView::getColumnOrder(duint col) const { - return mColumnOrder[index] + 1; + return mColumnOrder[col] + 1; } int AbstractTableView::getHeaderHeight() const @@ -1194,17 +1244,17 @@ int AbstractTableView::getTableHeight() const return this->viewport()->height() - getHeaderHeight(); } -int AbstractTableView::getGuiState() const +AbstractTableView::GuiState AbstractTableView::getGuiState() const { return mGuiState; } -int AbstractTableView::getNbrOfLineToPrint() const +duint AbstractTableView::getNbrOfLineToPrint() const { return mNbrOfLineToPrint; } -void AbstractTableView::setNbrOfLineToPrint(int parNbrOfLineToPrint) +void AbstractTableView::setNbrOfLineToPrint(duint parNbrOfLineToPrint) { mNbrOfLineToPrint = parNbrOfLineToPrint; } @@ -1219,6 +1269,11 @@ int AbstractTableView::getCharWidth() const return mFontMetrics->width(' '); } +int AbstractTableView::calculateColumnWidth(int characterCount) const +{ + return 7 + getCharWidth() * characterCount; +} + /************************************************************************************ Content drawing control ************************************************************************************/ @@ -1246,21 +1301,22 @@ bool AbstractTableView::getAllowPainting() const /************************************************************************************ Table offset management ************************************************************************************/ -dsint AbstractTableView::getTableOffset() const +duint AbstractTableView::getTableOffset() const { return mTableOffset; } -void AbstractTableView::setTableOffset(dsint val) +void AbstractTableView::setTableOffset(duint val) { - dsint wMaxOffset = getRowCount() - getViewableRowsCount() + 1; - wMaxOffset = wMaxOffset > 0 ? getRowCount() : 0; - if(val > wMaxOffset) + auto rowCount = getRowCount(); + auto viewableRows = getViewableRowsCount(); + if(rowCount <= viewableRows) return; + auto maxTableOffset = getMaxTableOffset(); - // If val is within the last ViewableRows, then set RVA to rowCount - ViewableRows + 1 - if(wMaxOffset && val >= (getRowCount() - getViewableRowsCount() + 1)) - mTableOffset = (getRowCount() - getViewableRowsCount()) + 1; + // If val is within the last viewable rows + if(maxTableOffset > 0 && val >= maxTableOffset) + mTableOffset = maxTableOffset; else mTableOffset = val; @@ -1268,14 +1324,9 @@ void AbstractTableView::setTableOffset(dsint val) MethodInvoker::invokeMethod([this]() { -#ifdef _WIN64 - int wNewValue = scaleFromUint64ToScrollBarRange(mTableOffset); - verticalScrollBar()->setValue(wNewValue); - verticalScrollBar()->setSliderPosition(wNewValue); -#else - verticalScrollBar()->setValue(mTableOffset); - verticalScrollBar()->setSliderPosition(mTableOffset); -#endif + int newValue = scaleFromUint64ToScrollBarRange(mTableOffset); + verticalScrollBar()->setValue(newValue); + verticalScrollBar()->setSliderPosition(newValue); }); } @@ -1305,70 +1356,14 @@ void AbstractTableView::updateViewport() */ void AbstractTableView::prepareData() { - int wViewableRowsCount = getViewableRowsCount(); - dsint wRemainingRowsCount = getRowCount() - mTableOffset; - mNbrOfLineToPrint = (dsint)wRemainingRowsCount > (dsint)wViewableRowsCount ? (int)wViewableRowsCount : (int)wRemainingRowsCount; + auto viewableRowsCount = getViewableRowsCount(); + auto remainingRowsCount = getRowCount() - mTableOffset; + mNbrOfLineToPrint = qMin(remainingRowsCount, viewableRowsCount); } -/************************************************************************************ - DisassemblyPopup -************************************************************************************/ - -void AbstractTableView::setDisassemblyPopupEnabled(bool enable) +duint AbstractTableView::getAddressForPosition(int x, int y) { - mPopupEnabled = enable; -} - -duint AbstractTableView::getDisassemblyPopupAddress(int mousex, int mousey) -{ - Q_UNUSED(mousex) - Q_UNUSED(mousey) - return 0; //Default is no disassembly popup -} - -void AbstractTableView::ShowDisassemblyPopup(duint addr, int x, int y) -{ - if(!mPopupEnabled || !addr) - { - killTimer(mPopupTimer); - mPopupTimer = 0; - if(mDisassemblyPopup) - mDisassemblyPopup->hide(); - return; - } - if(!mDisassemblyPopup) - mDisassemblyPopup = new DisassemblyPopup(this); - if(mDisassemblyPopup->getAddress() == addr) - return; - if(DbgFunctions()->MemIsCodePage(addr, false)) - { - mDisassemblyPopup->move(mapToGlobal(QPoint(x + 20, y + fontMetrics().height() * 2))); - mDisassemblyPopup->setAddress(addr); - //mDisassemblyPopup->show(); - if(mPopupTimer == 0) - mPopupTimer = startTimer(QApplication::startDragTime()); - } - else - { - mDisassemblyPopup->hide(); - killTimer(mPopupTimer); - mPopupTimer = 0; - } -} - -void AbstractTableView::timerEvent(QTimerEvent* event) -{ - if(event->timerId() == mPopupTimer) - { - mDisassemblyPopup->show(); - killTimer(mPopupTimer); - mPopupTimer = 0; - } - QAbstractScrollArea::timerEvent(event); -} - -void AbstractTableView::hideEvent(QHideEvent* event) -{ - ShowDisassemblyPopup(0, 0, 0); - QAbstractScrollArea::hideEvent(event); + Q_UNUSED(x); + Q_UNUSED(y); + return 0; } diff --git a/src/gui/Src/BasicView/AbstractTableView.h b/src/gui/Src/BasicView/AbstractTableView.h index 8baf58ea..b095f2bd 100644 --- a/src/gui/Src/BasicView/AbstractTableView.h +++ b/src/gui/Src/BasicView/AbstractTableView.h @@ -14,7 +14,7 @@ #include "ActionHelpers.h" class CachedFontMetrics; -class DisassemblyPopup; +class ColumnReorderDialog; //Hacky class that fixes a really annoying cursor problem class AbstractTableScrollBar : public QScrollBar @@ -22,8 +22,7 @@ class AbstractTableScrollBar : public QScrollBar Q_OBJECT public: explicit AbstractTableScrollBar(QScrollBar* scrollbar); - void enterEvent(QEvent* event) override; - void leaveEvent(QEvent* event) override; + bool event(QEvent* event) override; }; class AbstractTableView; @@ -32,16 +31,6 @@ class AbstractTableView : public QAbstractScrollArea, public ActionHelper & map, const QString & viewName, int columnCount); // Table offset management - dsint getTableOffset() const; - void setTableOffset(dsint val); + duint getTableOffset() const; // TODO: duint + void setTableOffset(duint val); // TODO: duint // Update/Reload/Refresh/Repaint virtual void prepareData(); - virtual duint getDisassemblyPopupAddress(int mousex, int mousey); + virtual duint getAddressForPosition(int x, int y); signals: void enterPressedSignal(); - void headerButtonPressed(int col); - void headerButtonReleased(int col); - void tableOffsetChanged(dsint i); - void viewableRowsChanged(int rows); + void headerButtonPressed(duint col); + void headerButtonReleased(duint col); + void tableOffsetChanged(duint i); + void viewableRowsChanged(duint rowCount); void repainted(); public slots: @@ -145,96 +143,96 @@ public slots: void editColumnDialog(); -protected slots: - void ShowDisassemblyPopup(duint addr, int x, int y); // this should probably be a slot, but doesn't need emit fixes (it's already used correctly) - void timerEvent(QTimerEvent* event); - private slots: // Configuration void updateColorsSlot(); void updateFontsSlot(); void updateShortcutsSlot(); - void shutdownSlot(); + void closeSlot(); private: - struct ColumnResizingData + GuiState mGuiState = NoState; + + struct ColumnResizeState { - bool splitHandle; - int index; - int lastPosX; - }; + bool splitHandle = false; + int index = -1; + int lastPosX = -1; + } mColResizeData; struct HeaderButton { - bool isClickable; - bool isPressed; - bool isMouseOver; + bool isClickable = false; + bool isPressed = false; + bool isMouseOver = false; }; struct Column { - int width; - bool hidden; + int width = 0; + int paintedWidth = -1; + bool hidden = false; HeaderButton header; QString title; }; - struct Header + struct HeaderConfig { - bool isVisible; - int height; - int activeButtonIndex; - }; - - struct ScrollBar64 - { - bool is64; - int rightShiftCount; - }; - - GuiState mGuiState; - - Header mHeader; - QPushButton mHeaderButtonSytle; + bool isVisible = true; + int height = 20; + int activeButtonIndex = -1; + } mHeader; + int mMinColumnWidth = 5; QList mColumnList; - ColumnResizingData mColResizeData; + QList mColumnOrder; + int mReorderStartX = -1; + int mHoveredColumnDisplayIndex = -1; - QList mColumnOrder; - int mReorderStartX; - int mHoveredColumnDisplayIndex; + duint mRowCount = 0; + duint mTableOffset = 0; + duint mPrevTableOffset = -1; + duint mNbrOfLineToPrint = 0; - dsint mRowCount; - dsint mTableOffset; - dsint mPrevTableOffset; - int mNbrOfLineToPrint; + bool mShouldReload = true; + bool mDrawDebugOnly = false; - bool mShouldReload; - bool mDrawDebugOnly; - bool mPopupEnabled; - int mPopupTimer; + // State for accumulating scroll events + enum ScrollDirection + { + ScrollUnknown, + ScrollVertical, + ScrollHorizontal, + } mPixelScrollDirection = ScrollUnknown; + QPoint mPixelScrollDelta; + QPoint mAngleScrollDelta; - static int mMouseWheelScrollDelta; - ScrollBar64 mScrollBarAttributes; + struct ScrollBarAttributes + { + bool is64 = false; + int rightShiftCount = 0; + } mScrollBarAttributes; int getColumnDisplayIndexFromX(int x); friend class ColumnReorderDialog; -protected: - // Configuration - QColor mBackgroundColor; - QColor mTextColor; - QColor mSeparatorColor; - QColor mHeaderTextColor; - QColor mSelectionColor; - QString mViewName; + void updateLastColumnWidth(); - bool mAllowPainting; +protected: + bool mAllowPainting = true; + + // Configuration + QColor mTextColor; + QColor mBackgroundColor; + QColor mHeaderTextColor; + QColor mHeaderBackgroundColor; + QColor mSeparatorColor; + QColor mSelectionColor; + QString mViewName; // TODO: this is needed during construction // Font metrics - CachedFontMetrics* mFontMetrics; + CachedFontMetrics* mFontMetrics = nullptr; void invalidateCachedFont(); - // Disassembly Popup - DisassemblyPopup* mDisassemblyPopup; + ColumnReorderDialog* mReorderDialog = nullptr; }; diff --git a/src/gui/Src/BasicView/Disassembly.cpp b/src/gui/Src/BasicView/Disassembly.cpp index 1a9fd4da..0209b129 100644 --- a/src/gui/Src/BasicView/Disassembly.cpp +++ b/src/gui/Src/BasicView/Disassembly.cpp @@ -4,12 +4,14 @@ #include "EncodeMap.h" #include "Bridge.h" #include "CachedFontMetrics.h" -#include "QBeaEngine.h" +#include "QZydis.h" #include "MemoryPage.h" +#include "DisassemblyPopup.h" -Disassembly::Disassembly(QWidget* parent, bool isMain) +Disassembly::Disassembly(QWidget* parent, bool isMain, Architecture* architecture) : AbstractTableView(parent), - mIsMain(isMain) + mIsMain(isMain), + mArchitecture(architecture) { mMemPage = new MemoryPage(0, 0); @@ -18,8 +20,6 @@ Disassembly::Disassembly(QWidget* parent, bool isMain) historyClear(); - memset(&mSelection, 0, sizeof(SelectionData)); - mHighlightToken.text = ""; mHighlightingMode = false; mShowMnemonicBrief = false; @@ -27,7 +27,9 @@ Disassembly::Disassembly(QWidget* parent, bool isMain) int maxModuleSize = (int)ConfigUint("Disassembler", "MaxModuleSize"); Config()->writeUints(); - mDisasm = new QBeaEngine(maxModuleSize); + mDisasm = new QZydis(maxModuleSize, mArchitecture); + mDisassemblyPopup = new DisassemblyPopup(this, mArchitecture); + tokenizerConfigUpdatedSlot(); updateConfigSlot(); @@ -56,7 +58,7 @@ Disassembly::Disassembly(QWidget* parent, bool isMain) // Slots connect(Bridge::getBridge(), SIGNAL(updateDisassembly()), this, SLOT(reloadData())); connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChangedSlot(DBGSTATE))); - connect(this, SIGNAL(selectionChanged(dsint)), this, SLOT(selectionChangedSlot(dsint))); + connect(this, SIGNAL(selectionChanged(duint)), this, SLOT(selectionChangedSlot(duint))); connect(Config(), SIGNAL(tokenizerConfigUpdated()), this, SLOT(tokenizerConfigUpdatedSlot())); connect(Config(), SIGNAL(guiOptionsUpdated()), this, SLOT(updateConfigSlot())); @@ -135,7 +137,7 @@ void Disassembly::updateFonts() void Disassembly::updateConfigSlot() { - setDisassemblyPopupEnabled(!Config()->getBool("Disassembler", "NoBranchDisasmPreview")); + mDisassemblyPopup->setEnabled(!Config()->getBool("Disassembler", "NoBranchDisasmPreview")); } void Disassembly::tokenizerConfigUpdatedSlot() @@ -211,9 +213,9 @@ static void mnemonicBriefRichText(RichTextPainter::List & richText, const Instru * * @return String to paint. */ -QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) +QString Disassembly::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) { - Q_UNUSED(rowBase); + auto rowOffset = row - getTableOffset(); if(mHighlightingMode) { @@ -224,15 +226,14 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse rect.adjust(1, 1, -1, -1); painter->drawRect(rect); } - dsint wRVA = mInstBuffer.at(rowOffset).rva; - bool wIsSelected = isSelected(&mInstBuffer, rowOffset); - dsint cur_addr = rvaToVa(mInstBuffer.at(rowOffset).rva); - auto traceCount = DbgFunctions()->GetTraceRecordHitCount(cur_addr); + bool instSelected = isSelected(&mInstBuffer, rowOffset); + auto va = rvaToVa(mInstBuffer.at(rowOffset).rva); + auto traceCount = DbgFunctions()->GetTraceRecordHitCount(va); // Highlight if selected - if(wIsSelected && traceCount) + if(instSelected && traceCount) painter->fillRect(QRect(x, y, w, h), QBrush(mTracedSelectedAddressBackgroundColor)); - else if(wIsSelected) + else if(instSelected) painter->fillRect(QRect(x, y, w, h), QBrush(mSelectionColor)); else if(traceCount) { @@ -261,11 +262,11 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse richText.textColor = mTextColor; richText.flags = RichTextPainter::FlagColor; - char label[MAX_LABEL_SIZE] = ""; - QString addrText = getAddrText(cur_addr, label); + QString label; + QString addrText = getAddrText(va, label); richText.text = addrText; - BPXTYPE bpxtype = DbgGetBpxTypeAt(cur_addr); - bool isbookmark = DbgGetBookmarkAt(cur_addr); + BPXTYPE bpxtype = DbgGetBpxTypeAt(va); + bool isbookmark = DbgGetBookmarkAt(va); if(rvaToVa(mInstBuffer.at(rowOffset).rva) == mCipVa && !Bridge::getBridge()->mIsRunning && DbgMemFindBaseAddr(DbgValFromString("cip"), nullptr)) //cip + not running + valid cip { richText.textBackground = mCipBackgroundColor; @@ -308,7 +309,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse { if(!isbookmark) //no bookmark { - if(*label) //label + if(!label.isEmpty()) //label { if(bpxtype == bp_none) //label only : fill label background { @@ -338,7 +339,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse { if(bpxtype == bp_none) //no label, no breakpoint { - if(wIsSelected) + if(instSelected) { richText.textColor = mSelectedAddressColor; richText.textBackground = mSelectedAddressBackgroundColor; @@ -363,7 +364,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse } else //other cases (memory breakpoint in disassembly) -> do as normal { - if(wIsSelected) + if(instSelected) { richText.textColor = mSelectedAddressColor; richText.textBackground = mSelectedAddressBackgroundColor; @@ -379,7 +380,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse } else //bookmark { - if(*label) //label + bookmark + if(!label.isEmpty()) //label + bookmark { if(bpxtype == bp_none) //label + bookmark { @@ -449,8 +450,8 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse const Instruction_t & instr = mInstBuffer.at(rowOffset); //draw functions Function_t funcType; - FUNCTYPE funcFirst = DbgGetFunctionTypeAt(cur_addr); - FUNCTYPE funcLast = DbgGetFunctionTypeAt(cur_addr + instr.length - 1); + FUNCTYPE funcFirst = DbgGetFunctionTypeAt(va); + FUNCTYPE funcLast = DbgGetFunctionTypeAt(va + instr.length - 1); HANDLE_RANGE_TYPE(FUNC, funcFirst, funcLast); switch(funcFirst) { @@ -474,7 +475,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse painter->setPen(mFunctionPen); - XREFTYPE refType = DbgGetXrefTypeAt(cur_addr); + XREFTYPE refType = DbgGetXrefTypeAt(va); char indicator; if(refType == XREF_JMP) { @@ -498,12 +499,11 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse funcsize += charwidth; //draw jump arrows - Instruction_t::BranchType branchType = mInstBuffer.at(rowOffset).branchType; - int jumpsize = paintJumpsGraphic(painter, x + funcsize, y - 1, wRVA, branchType != Instruction_t::None && branchType != Instruction_t::Call); //jump line + int jumpsize = paintJumpsGraphic(painter, x + funcsize, y - 1, mInstBuffer.at(rowOffset)); //jump line //draw bytes - auto richBytes = getRichBytes(instr, wIsSelected); - paintRichText(x, y, getColumnWidth(col), getRowHeight(), jumpsize + funcsize, std::move(richBytes), rowOffset, col); + auto richBytes = getRichBytes(instr, instSelected); + paintRichText(x, y, w, h, jumpsize + funcsize, std::move(richBytes), rowOffset, col); } break; @@ -514,8 +514,8 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse while(1) //paint all loop depths { - LOOPTYPE loopFirst = DbgGetLoopTypeAt(cur_addr, depth); - LOOPTYPE loopLast = DbgGetLoopTypeAt(cur_addr + mInstBuffer.at(rowOffset).length - 1, depth); + LOOPTYPE loopFirst = DbgGetLoopTypeAt(va, depth); + LOOPTYPE loopLast = DbgGetLoopTypeAt(va + mInstBuffer.at(rowOffset).length - 1, depth); HANDLE_RANGE_TYPE(LOOP, loopFirst, loopLast); if(loopFirst == LOOP_NONE) break; @@ -551,7 +551,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse else ZydisTokenizer::TokenToRichText(token, richText, 0); int xinc = 4 + loopsize; - paintRichText(x, y, getColumnWidth(col), getRowHeight(), xinc, std::move(richText), rowOffset, col); + paintRichText(x, y, w, h, xinc, std::move(richText), rowOffset, col); token.x = x + loopsize + xinc; } break; @@ -571,8 +571,8 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse { //draw arguments Function_t funcType; - ARGTYPE argFirst = DbgGetArgTypeAt(cur_addr); - ARGTYPE argLast = DbgGetArgTypeAt(cur_addr + mInstBuffer.at(rowOffset).length - 1); + ARGTYPE argFirst = DbgGetArgTypeAt(va); + ARGTYPE argLast = DbgGetArgTypeAt(va + mInstBuffer.at(rowOffset).length - 1); HANDLE_RANGE_TYPE(ARG, argFirst, argLast); switch(argFirst) { @@ -604,7 +604,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse QString comment; bool autoComment = false; char label[MAX_LABEL_SIZE] = ""; - if(GetCommentFormat(cur_addr, comment, &autoComment)) + if(GetCommentFormat(va, comment, &autoComment)) { if(autoComment) { @@ -620,7 +620,7 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse richComment.text = std::move(comment); richText.emplace_back(std::move(richComment)); } - else if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) // label but no comment + else if(DbgGetLabelAt(va, SEG_DEFAULT, label)) // label but no comment { richComment.textColor = mLabelColor; richComment.textBackground = mLabelBackgroundColor; @@ -655,7 +655,6 @@ void Disassembly::mouseMoveEvent(QMouseEvent* event) { //qDebug() << "Disassembly::mouseMoveEvent"; - bool wAccept = true; int y = event->y(); if(mGuiState == Disassembly::MultiRowsSelectionState) @@ -664,32 +663,34 @@ void Disassembly::mouseMoveEvent(QMouseEvent* event) if((transY(y) >= 0) && (transY(y) <= this->getTableHeight())) { - int wI = getIndexOffsetFromY(transY(y)); + int i = getIndexOffsetFromY(transY(y)); if(mMemPage->getSize() > 0) { // Bound - wI = wI >= mInstBuffer.size() ? mInstBuffer.size() - 1 : wI; - wI = wI < 0 ? 0 : wI; + i = i >= mInstBuffer.size() ? mInstBuffer.size() - 1 : i; + i = i < 0 ? 0 : i; - if(wI >= mInstBuffer.size()) + if(i >= mInstBuffer.size()) return; - dsint wRowIndex = mInstBuffer.at(wI).rva; - dsint wInstrSize = getInstructionRVA(wRowIndex, 1) - wRowIndex - 1; + auto rowIndex = mInstBuffer.at(i).rva; + auto instrSize = getInstructionRVA(rowIndex, 1) - rowIndex - 1; - if(wRowIndex < getRowCount()) + if(rowIndex < getRowCount()) { setSingleSelection(getInitialSelection()); expandSelectionUpTo(getInstructionRVA(getInitialSelection(), 1) - 1); - if(wRowIndex > getInitialSelection()) //select down - expandSelectionUpTo(wRowIndex + wInstrSize); + if(rowIndex > getInitialSelection()) //select down + expandSelectionUpTo(rowIndex + instrSize); else - expandSelectionUpTo(wRowIndex); + expandSelectionUpTo(rowIndex); emit selectionExpanded(); + + // TODO: only update if the selection actually changed updateViewport(); - wAccept = false; + return; } } } @@ -703,11 +704,10 @@ void Disassembly::mouseMoveEvent(QMouseEvent* event) } } - if(wAccept == true) - AbstractTableView::mouseMoveEvent(event); + AbstractTableView::mouseMoveEvent(event); } -duint Disassembly::getDisassemblyPopupAddress(int mousex, int mousey) +duint Disassembly::getAddressForPosition(int mousex, int mousey) { if(mHighlightingMode) return 0; //Don't show this in highlight mode @@ -746,7 +746,7 @@ duint Disassembly::getDisassemblyPopupAddress(int mousex, int mousey) */ void Disassembly::mousePressEvent(QMouseEvent* event) { - bool wAccept = false; + bool accept = false; if(mHighlightingMode || mPermanentHighlightingMode) { @@ -790,37 +790,38 @@ void Disassembly::mousePressEvent(QMouseEvent* event) { if(event->y() > getHeaderHeight()) { - dsint wIndex = getIndexOffsetFromY(transY(event->y())); + dsint index = getIndexOffsetFromY(transY(event->y())); - if(mInstBuffer.size() > wIndex && wIndex >= 0) + if(mInstBuffer.size() > index && index >= 0) { - dsint wRowIndex = mInstBuffer.at(wIndex).rva; - dsint wInstrSize = mInstBuffer.at(wIndex).length - 1; + auto rowIndex = mInstBuffer.at(index).rva; + auto instrSize = mInstBuffer.at(index).length - 1; if(!(event->modifiers() & Qt::ShiftModifier)) //SHIFT pressed - setSingleSelection(wRowIndex); - if(getSelectionStart() > wRowIndex) //select up + setSingleSelection(rowIndex); + if(getSelectionStart() > rowIndex) //select up { setSingleSelection(getInitialSelection()); expandSelectionUpTo(getInstructionRVA(getInitialSelection(), 1) - 1); - expandSelectionUpTo(wRowIndex); + expandSelectionUpTo(rowIndex); } else //select down { setSingleSelection(getInitialSelection()); - expandSelectionUpTo(wRowIndex + wInstrSize); + expandSelectionUpTo(rowIndex + instrSize); } mGuiState = Disassembly::MultiRowsSelectionState; + // TODO: only update if the selection actually changed updateViewport(); - wAccept = true; + accept = true; } } } } - if(wAccept == false) + if(!accept) AbstractTableView::mousePressEvent(event); } @@ -834,7 +835,7 @@ void Disassembly::mousePressEvent(QMouseEvent* event) */ void Disassembly::mouseReleaseEvent(QMouseEvent* event) { - bool wAccept = true; + bool accept = true; if((event->buttons() & Qt::LeftButton) == 0) { @@ -842,23 +843,21 @@ void Disassembly::mouseReleaseEvent(QMouseEvent* event) { mGuiState = Disassembly::NoState; - updateViewport(); - - wAccept = false; + accept = false; } } if((event->button() & Qt::BackButton) != 0) { - wAccept = true; + accept = true; historyPrevious(); } else if((event->button() & Qt::ForwardButton) != 0) { - wAccept = true; + accept = true; historyNext(); } - if(wAccept == true) + if(accept) AbstractTableView::mouseReleaseEvent(event); } @@ -886,8 +885,6 @@ void Disassembly::keyPressEvent(QKeyEvent* event) if(event->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) { - ShowDisassemblyPopup(0, 0, 0); - if(key == Qt::Key_Left) { setTableOffset(getTableOffset() - 1); @@ -897,12 +894,11 @@ void Disassembly::keyPressEvent(QKeyEvent* event) setTableOffset(getTableOffset() + 1); } + // TODO: only update if the selection actually changed updateViewport(); } else if(key == Qt::Key_Up || key == Qt::Key_Down) { - ShowDisassemblyPopup(0, 0, 0); - dsint botRVA = getTableOffset(); dsint topRVA = getInstructionRVA(getTableOffset(), getNbrOfLineToPrint() - 1); @@ -926,14 +922,14 @@ void Disassembly::keyPressEvent(QKeyEvent* event) } else if(modifiedSelection >= topRVA) { - setTableOffset(getInstructionRVA(modifiedSelection, -getNbrOfLineToPrint() + 2)); + setTableOffset(getInstructionRVA(modifiedSelection, -(dsint)getNbrOfLineToPrint() + 2)); } + // TODO: only update if the selection actually changed updateViewport(); } else if(key == Qt::Key_Return || key == Qt::Key_Enter) { - ShowDisassemblyPopup(0, 0, 0); // Follow branch instruction duint dest = DbgGetBranchDestination(rvaToVa(getInitialSelection())); if(DbgMemIsValidReadPtr(dest)) @@ -941,6 +937,7 @@ void Disassembly::keyPressEvent(QKeyEvent* event) gotoAddress(dest); return; } +#ifdef X64DBG // Follow memory operand in dump DISASM_INSTR instr; DbgDisasmAt(rvaToVa(getInitialSelection()), &instr); @@ -972,6 +969,7 @@ void Disassembly::keyPressEvent(QKeyEvent* event) } } } +#endif // X64DBG } else AbstractTableView::keyPressEvent(event); @@ -991,26 +989,24 @@ void Disassembly::keyPressEvent(QKeyEvent* event) * * @return Return the value of the new table offset. */ -dsint Disassembly::sliderMovedHook(int type, dsint value, dsint delta) +duint Disassembly::sliderMovedHook(QScrollBar::SliderAction action, duint value, dsint delta) { - ShowDisassemblyPopup(0, 0, 0); - - // QAbstractSlider::SliderNoAction is used to disassembe at a specific address - if(type == QAbstractSlider::SliderNoAction) + // QAbstractSlider::SliderNoAction is used to disassemble at a specific address + if(action == QAbstractSlider::SliderNoAction) return value + delta; // If it's a slider action, disassemble one instruction back and one instruction next in order to be aligned on a real instruction - if(type == QAbstractSlider::SliderMove) + if(action == QAbstractSlider::SliderMove) { - dsint wNewValue = 0; + dsint newValue = 0; if(value + delta > 0) { - wNewValue = getInstructionRVA(value + delta, -1); - wNewValue = getInstructionRVA(wNewValue, 1); + newValue = getInstructionRVA(value + delta, -1); + newValue = getInstructionRVA(newValue, 1); } - return wNewValue; + return newValue; } // For other actions, disassemble according to the delta @@ -1031,45 +1027,48 @@ dsint Disassembly::sliderMovedHook(int type, dsint value, dsint delta) * * @return Nothing. */ -int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, bool isjmp) +int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, const Instruction_t & instruction) { - dsint selHeadRVA = mSelection.fromIndex; - dsint rva = addr; - duint curVa = rvaToVa(addr); - duint selVa = rvaToVa(mSelection.firstSelectedIndex); - Instruction_t instruction = DisassembleAt(selHeadRVA); - auto branchType = instruction.branchType; + auto isjmp = instruction.branchType != Instruction_t::None && instruction.branchType != Instruction_t::Call; + auto selHeadRVA = mSelection.fromIndex; + auto rva = instruction.rva; + auto curVa = rvaToVa(rva); + auto selVa = rvaToVa(mSelection.firstSelectedIndex); + + if(mSelectedInstruction.rva != selHeadRVA) + { + mSelectedInstruction = DisassembleAt(selHeadRVA); + } + + auto branchType = mSelectedInstruction.branchType; bool showXref = false; - GraphicDump wPict = GD_Nothing; + GraphicDump pict = GD_Nothing; if(branchType != Instruction_t::None && branchType != Instruction_t::Call) { - dsint base = mMemPage->getBase(); - dsint destVA = DbgGetBranchDestination(rvaToVa(selHeadRVA)); - - if(destVA >= base && destVA < base + (dsint)mMemPage->getSize()) + if(mMemPage->inRange(mSelectedInstruction.branchDestination)) { - destVA -= base; + auto destRVA = mSelectedInstruction.branchDestination - mMemPage->getBase(); - if(destVA < selHeadRVA) + if(destRVA < selHeadRVA) { - if(rva == destVA) - wPict = GD_HeadFromBottom; - else if(rva > destVA && rva < selHeadRVA) - wPict = GD_Vert; + if(rva == destRVA) + pict = GD_HeadFromBottom; + else if(rva > destRVA && rva < selHeadRVA) + pict = GD_Vert; else if(rva == selHeadRVA) - wPict = GD_FootToTop; + pict = GD_FootToTop; } - else if(destVA > selHeadRVA) + else if(destRVA > selHeadRVA) { if(rva == selHeadRVA) - wPict = GD_FootToBottom; - else if(rva > selHeadRVA && rva < destVA) - wPict = GD_Vert; - else if(rva == destVA) - wPict = GD_HeadFromTop; + pict = GD_FootToBottom; + else if(rva > selHeadRVA && rva < destRVA) + pict = GD_Vert; + else if(rva == destRVA) + pict = GD_HeadFromTop; } } } @@ -1085,7 +1084,7 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, continue; jmpcount++; if(curVa == mXrefInfo.references[i].addr) - wPict = GD_VertHori; + pict = GD_VertHori; if(mXrefInfo.references[i].addr > max) max = mXrefInfo.references[i].addr; if(mXrefInfo.references[i].addr < min) @@ -1097,28 +1096,28 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, { if(max == selVa) { - wPict = GD_HeadFromTop; + pict = GD_HeadFromTop; } else if(min == selVa) { - wPict = GD_HeadFromBottom; + pict = GD_HeadFromBottom; } else if(max > selVa && min < selVa) { - wPict = GD_HeadFromBoth; + pict = GD_HeadFromBoth; } } else if(curVa < selVa && curVa == min) { - wPict = GD_FootToBottom; + pict = GD_FootToBottom; } else if(curVa > selVa && curVa == max) { - wPict = GD_FootToTop; + pict = GD_FootToTop; } - if(wPict == GD_Nothing && curVa > min && curVa < max) - wPict = GD_Vert; + if(pict == GD_Nothing && curVa > min && curVa < max) + pict = GD_Vert; } } @@ -1126,45 +1125,75 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, if(isjmp) { - duint curInstDestination = DbgGetBranchDestination(curVa); + duint curInstDestination = instruction.branchDestination; if(curInstDestination == 0 || curVa == curInstDestination) { curInstDir = GJD_Nothing; } - else if(curInstDestination < curVa) + else if(curInstDestination >= mMemPage->getBase() && curInstDestination < mMemPage->getBase() + mMemPage->getSize()) { - curInstDir = GJD_Up; + if(curInstDestination < curVa) + { + curInstDir = GJD_Up; + } + else + { + curInstDir = GJD_Down; + } } else { - curInstDir = GJD_Down; + curInstDir = GJD_Out; } } int halfRow = getRowHeight() / 2 + 1; painter->setPen(mConditionalTruePen); - if(curInstDir == GJD_Up) + switch(curInstDir) { - QPoint wPoints[] = + case GJD_Nothing: + { + } + break; + + case GJD_Up: + { + QPoint points[] = { QPoint(x, y + halfRow + 1), QPoint(x + 2, y + halfRow - 1), QPoint(x + 4, y + halfRow + 1), }; - painter->drawPolyline(wPoints, 3); + painter->drawPolyline(points, 3); } - else if(curInstDir == GJD_Down) + break; + + case GJD_Down: { - QPoint wPoints[] = + QPoint points[] = { QPoint(x, y + halfRow - 1), QPoint(x + 2, y + halfRow + 1), QPoint(x + 4, y + halfRow - 1), }; - painter->drawPolyline(wPoints, 3); + painter->drawPolyline(points, 3); + } + break; + + case GJD_Out: + { + QPoint points[] = + { + QPoint(x, y + halfRow), + QPoint(x + 4, y + halfRow), + }; + + painter->drawPolyline(points, 2); + } + break; } x += 8; @@ -1175,8 +1204,7 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, } else { - bool bIsExecute = DbgIsJumpGoingToExecute(rvaToVa(instruction.rva)); - + bool bIsExecute = DbgIsJumpGoingToExecute(rvaToVa(mSelectedInstruction.rva)); if(branchType == Instruction_t::Unconditional) //unconditional { @@ -1191,25 +1219,23 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, } } - - - if(wPict == GD_Vert) + if(pict == GD_Vert) { painter->drawLine(x, y, x, y + getRowHeight()); } - else if(wPict == GD_FootToBottom) + else if(pict == GD_FootToBottom) { painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y + halfRow, x, y + getRowHeight()); } - else if(wPict == GD_FootToTop) + else if(pict == GD_FootToTop) { painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y, x, y + halfRow); } - else if(wPict == GD_HeadFromBottom) + else if(pict == GD_HeadFromBottom) { - QPoint wPoints[] = + QPoint points[] = { QPoint(x + 3, y + halfRow - 2), QPoint(x + 5, y + halfRow), @@ -1218,11 +1244,11 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y + halfRow, x, y + getRowHeight()); - painter->drawPolyline(wPoints, 3); + painter->drawPolyline(points, 3); } - else if(wPict == GD_HeadFromTop) + else if(pict == GD_HeadFromTop) { - QPoint wPoints[] = + QPoint points[] = { QPoint(x + 3, y + halfRow - 2), QPoint(x + 5, y + halfRow), @@ -1231,11 +1257,11 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y, x, y + halfRow); - painter->drawPolyline(wPoints, 3); + painter->drawPolyline(points, 3); } - else if(wPict == GD_HeadFromBoth) + else if(pict == GD_HeadFromBoth) { - QPoint wPoints[] = + QPoint points[] = { QPoint(x + 3, y + halfRow - 2), QPoint(x + 5, y + halfRow), @@ -1244,9 +1270,9 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y, x, y + getRowHeight()); - painter->drawPolyline(wPoints, 3); + painter->drawPolyline(points, 3); } - else if(wPict == GD_VertHori) + else if(pict == GD_VertHori) { painter->drawLine(x, y + halfRow, x + 5, y + halfRow); painter->drawLine(x, y, x, y + getRowHeight()); @@ -1381,33 +1407,31 @@ void Disassembly::paintRichText(int x, int y, int w, int h, int xinc, RichTextPa * * @return RVA of count-th instructions before the given instruction RVA. */ -dsint Disassembly::getPreviousInstructionRVA(dsint rva, duint count) +duint Disassembly::getPreviousInstructionRVA(duint rva, duint count) { - QByteArray wBuffer; - dsint wBottomByteRealRVA; - dsint wVirtualRVA; - dsint wMaxByteCountToRead; + QByteArray buffer; - wBottomByteRealRVA = (dsint)rva - 16 * (count + 3); + // TODO: fix sign check + auto bottomByteRealRVA = (dsint)rva - 16 * (count + 3); if(mCodeFoldingManager) { - if(mCodeFoldingManager->isFolded(rvaToVa(wBottomByteRealRVA))) + if(mCodeFoldingManager->isFolded(rvaToVa(bottomByteRealRVA))) { - wBottomByteRealRVA = mCodeFoldingManager->getFoldBegin(wBottomByteRealRVA) - mMemPage->getBase() - 16 * (count + 3); + bottomByteRealRVA = mCodeFoldingManager->getFoldBegin(bottomByteRealRVA) - mMemPage->getBase() - 16 * (count + 3); } } - wBottomByteRealRVA = wBottomByteRealRVA < 0 ? 0 : wBottomByteRealRVA; + bottomByteRealRVA = bottomByteRealRVA < 0 ? 0 : bottomByteRealRVA; - wVirtualRVA = (dsint)rva - wBottomByteRealRVA; + auto virtualRVA = (dsint)rva - bottomByteRealRVA; - wMaxByteCountToRead = wVirtualRVA + 1 + 16; - wBuffer.resize(wMaxByteCountToRead); + auto maxByteCountToRead = virtualRVA + 1 + 16; + buffer.resize(maxByteCountToRead); - mMemPage->read(wBuffer.data(), wBottomByteRealRVA, wBuffer.size()); + mMemPage->read(buffer.data(), bottomByteRealRVA, buffer.size()); - dsint addr = mDisasm->DisassembleBack((byte_t*)wBuffer.data(), rvaToVa(wBottomByteRealRVA), wBuffer.size(), wVirtualRVA, count); + dsint addr = mDisasm->DisassembleBack((uint8_t*)buffer.data(), rvaToVa(bottomByteRealRVA), buffer.size(), virtualRVA, count); - addr += rva - wVirtualRVA; + addr += rva - virtualRVA; return addr; } @@ -1421,39 +1445,37 @@ dsint Disassembly::getPreviousInstructionRVA(dsint rva, duint count) * * @return RVA of count-th instructions after the given instruction RVA. */ -dsint Disassembly::getNextInstructionRVA(dsint rva, duint count, bool isGlobal) +duint Disassembly::getNextInstructionRVA(duint rva, duint count, bool isGlobal) { - QByteArray wBuffer; - dsint wRemainingBytes; - dsint wMaxByteCountToRead; - dsint wNewRVA; + QByteArray buffer; + duint maxByteCountToRead = 0; if(!isGlobal) { if(mMemPage->getSize() < (duint)rva) return rva; - wRemainingBytes = mMemPage->getSize() - rva; + auto remainingBytes = mMemPage->getSize() - rva; - wMaxByteCountToRead = 16 * (count + 1); + maxByteCountToRead = 16 * (count + 1); if(mCodeFoldingManager) - wMaxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + wMaxByteCountToRead)); - wMaxByteCountToRead = wRemainingBytes > wMaxByteCountToRead ? wMaxByteCountToRead : wRemainingBytes; + maxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + maxByteCountToRead)); + maxByteCountToRead = remainingBytes > maxByteCountToRead ? maxByteCountToRead : remainingBytes; } else { - wMaxByteCountToRead = 16 * (count + 1); + maxByteCountToRead = 16 * (count + 1); if(mCodeFoldingManager) - wMaxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + wMaxByteCountToRead)); + maxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + maxByteCountToRead)); } - wBuffer.resize(wMaxByteCountToRead); + buffer.resize(maxByteCountToRead); - mMemPage->read(wBuffer.data(), rva, wBuffer.size()); + mMemPage->read(buffer.data(), rva, buffer.size()); - wNewRVA = mDisasm->DisassembleNext((byte_t*)wBuffer.data(), rvaToVa(rva), wBuffer.size(), 0, count); + auto newRVA = mDisasm->DisassembleNext((uint8_t*)buffer.data(), rvaToVa(rva), buffer.size(), 0, count); - wNewRVA += rva; + newRVA += rva; - return wNewRVA; + return newRVA; } /** @@ -1464,24 +1486,24 @@ dsint Disassembly::getNextInstructionRVA(dsint rva, duint count, bool isGlobal) * * @return RVA of count-th instructions before/after the given instruction RVA. */ -dsint Disassembly::getInstructionRVA(dsint index, dsint count) +duint Disassembly::getInstructionRVA(duint index, dsint count) { - dsint wAddr = 0; + duint addr = 0; if(count == 0) - wAddr = index; + addr = index; if(count < 0) - wAddr = getPreviousInstructionRVA(index, qAbs(count)); + addr = getPreviousInstructionRVA(index, qAbs(count)); else if(count > 0) - wAddr = getNextInstructionRVA(index, qAbs(count)); + addr = getNextInstructionRVA(index, qAbs(count)); - if(wAddr < 0) - wAddr = 0; - else if(wAddr > getRowCount() - 1) - wAddr = getRowCount() - 1; + if(addr < 0) + addr = 0; + else if(addr > getRowCount() - 1) + addr = getRowCount() - 1; - return wAddr; + return addr; } /** @@ -1491,33 +1513,33 @@ dsint Disassembly::getInstructionRVA(dsint index, dsint count) * * @return Return the disassembled instruction. */ -Instruction_t Disassembly::DisassembleAt(dsint rva) +Instruction_t Disassembly::DisassembleAt(duint rva) { if(mMemPage->getSize() < (duint)rva) return Instruction_t(); - QByteArray wBuffer; + QByteArray buffer; duint base = mMemPage->getBase(); - duint wMaxByteCountToRead = 16 * 2; + duint maxByteCountToRead = 16 * 2; // Bounding auto size = getSize(); if(!size) - size = rva + wMaxByteCountToRead * 2; + size = rva + maxByteCountToRead * 2; if(mCodeFoldingManager) - wMaxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + wMaxByteCountToRead)); + maxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + maxByteCountToRead)); - wMaxByteCountToRead = wMaxByteCountToRead > (size - rva) ? (size - rva) : wMaxByteCountToRead; - if(!wMaxByteCountToRead) + maxByteCountToRead = maxByteCountToRead > (size - rva) ? (size - rva) : maxByteCountToRead; + if(!maxByteCountToRead) return Instruction_t(); - wBuffer.resize(wMaxByteCountToRead); + buffer.resize(maxByteCountToRead); - if(!mMemPage->read(wBuffer.data(), rva, wBuffer.size())) + if(!mMemPage->read(buffer.data(), rva, buffer.size())) return Instruction_t(); - return mDisasm->DisassembleAt((byte_t*)wBuffer.data(), wBuffer.size(), base, rva); + return mDisasm->DisassembleAt((uint8_t*)buffer.data(), buffer.size(), base, rva); } /** @@ -1529,7 +1551,7 @@ Instruction_t Disassembly::DisassembleAt(dsint rva) * * @return Return the disassembled instruction. */ -Instruction_t Disassembly::DisassembleAt(dsint rva, dsint count) +Instruction_t Disassembly::DisassembleAt(duint rva, dsint count) { rva = getNextInstructionRVA(rva, count); return DisassembleAt(rva); @@ -1538,7 +1560,7 @@ Instruction_t Disassembly::DisassembleAt(dsint rva, dsint count) /************************************************************************************ Selection Management ************************************************************************************/ -void Disassembly::expandSelectionUpTo(dsint to) +void Disassembly::expandSelectionUpTo(duint to) { if(to < mSelection.firstSelectedIndex) { @@ -1554,7 +1576,7 @@ void Disassembly::expandSelectionUpTo(dsint to) } } -void Disassembly::setSingleSelection(dsint index) +void Disassembly::setSingleSelection(duint index) { mSelection.firstSelectedIndex = index; mSelection.fromIndex = index; @@ -1562,27 +1584,27 @@ void Disassembly::setSingleSelection(dsint index) emit selectionChanged(rvaToVa(index)); } -dsint Disassembly::getInitialSelection() const +duint Disassembly::getInitialSelection() const { return mSelection.firstSelectedIndex; } -dsint Disassembly::getSelectionSize() const +duint Disassembly::getSelectionSize() const { return mSelection.toIndex - mSelection.fromIndex + 1; } -dsint Disassembly::getSelectionStart() const +duint Disassembly::getSelectionStart() const { return mSelection.fromIndex; } -dsint Disassembly::getSelectionEnd() const +duint Disassembly::getSelectionEnd() const { return mSelection.toIndex; } -void Disassembly::selectionChangedSlot(dsint Va) +void Disassembly::selectionChangedSlot(duint Va) { if(mXrefInfo.refcount != 0) { @@ -1595,71 +1617,66 @@ void Disassembly::selectionChangedSlot(dsint Va) void Disassembly::selectNext(bool expand) { - dsint wAddr; - dsint wStart = getInstructionRVA(getSelectionStart(), 1) - 1; - dsint wInstrSize; + auto start = getInstructionRVA(getSelectionStart(), 1) - 1; if(expand) { - if(getSelectionEnd() == getInitialSelection() && wStart != getSelectionEnd()) //decrease down + if(getSelectionEnd() == getInitialSelection() && start != getSelectionEnd()) //decrease down { - wAddr = getInstructionRVA(getSelectionStart(), 1); - expandSelectionUpTo(wAddr); + auto addr = getInstructionRVA(getSelectionStart(), 1); + expandSelectionUpTo(addr); } else //expand down { - wAddr = getSelectionEnd() + 1; - wInstrSize = getInstructionRVA(wAddr, 1) - 1; - expandSelectionUpTo(wInstrSize); + auto addr = getSelectionEnd() + 1; + auto nextRva = getInstructionRVA(addr, 1) - 1; + expandSelectionUpTo(nextRva); } } else //select next instruction { - wAddr = getSelectionEnd() + 1; - setSingleSelection(wAddr); - wInstrSize = getInstructionRVA(wAddr, 1) - 1; - expandSelectionUpTo(wInstrSize); + auto addr = getSelectionEnd() + 1; + setSingleSelection(addr); + auto nextRva = getInstructionRVA(addr, 1) - 1; + expandSelectionUpTo(nextRva); } } void Disassembly::selectPrevious(bool expand) { - dsint wAddr; - dsint wStart; - dsint wInstrSize; - wStart = getInstructionRVA(getSelectionStart(), 1) - 1; + auto start = getInstructionRVA(getSelectionStart(), 1) - 1; if(expand) { - if(getSelectionStart() == getInitialSelection() && wStart != getSelectionEnd()) //decrease up + if(getSelectionStart() == getInitialSelection() && start != getSelectionEnd()) //decrease up { - wAddr = getInstructionRVA(getSelectionEnd() + 1, -2); - wInstrSize = getInstructionRVA(wAddr, 1) - 1; - expandSelectionUpTo(wInstrSize); + auto addr = getInstructionRVA(getSelectionEnd() + 1, -2); + auto nextRva = getInstructionRVA(addr, 1) - 1; + expandSelectionUpTo(nextRva); } else //expand up { - wAddr = getInstructionRVA(wStart + 1, -2); - expandSelectionUpTo(wAddr); + auto addr = getInstructionRVA(start + 1, -2); + expandSelectionUpTo(addr); } } else { - wAddr = getInstructionRVA(getSelectionStart(), -1); - setSingleSelection(wAddr); - wInstrSize = getInstructionRVA(wAddr, 1) - 1; - expandSelectionUpTo(wInstrSize); + auto addr = getInstructionRVA(getSelectionStart(), -1); + setSingleSelection(addr); + auto nextRva = getInstructionRVA(addr, 1) - 1; + expandSelectionUpTo(nextRva); } } -bool Disassembly::isSelected(dsint base, dsint offset) +bool Disassembly::isSelected(duint base, dsint offset) { - dsint wAddr = base; + auto addr = base; if(offset < 0) - wAddr = getPreviousInstructionRVA(getTableOffset(), offset); + addr = getPreviousInstructionRVA(getTableOffset(), offset); else if(offset > 0) - wAddr = getNextInstructionRVA(getTableOffset(), offset); + addr = getNextInstructionRVA(getTableOffset(), offset); - if(wAddr >= mSelection.fromIndex && wAddr <= mSelection.toIndex) + if(addr >= mSelection.fromIndex && addr <= mSelection.toIndex) return true; else return false; @@ -1669,7 +1686,7 @@ bool Disassembly::isSelected(QList* buffer, int index) const { if(buffer->size() > 0 && index >= 0 && index < buffer->size()) { - if((dsint)buffer->at(index).rva >= mSelection.fromIndex && (dsint)buffer->at(index).rva <= mSelection.toIndex) + if(buffer->at(index).rva >= mSelection.fromIndex && buffer->at(index).rva <= mSelection.toIndex) return true; else return false; @@ -1691,33 +1708,33 @@ duint Disassembly::getSelectedVa() const Update/Reload/Refresh/Repaint ************************************************************************************/ -void Disassembly::prepareDataCount(const QList & wRVAs, QList* instBuffer) +void Disassembly::prepareDataCount(const QList & rvas, QList* instBuffer) { instBuffer->clear(); - Instruction_t wInst; - for(int wI = 0; wI < wRVAs.count(); wI++) + instBuffer->reserve(rvas.count()); + for(int i = 0; i < rvas.count(); i++) { - wInst = DisassembleAt(wRVAs.at(wI)); - instBuffer->append(wInst); + auto inst = DisassembleAt(rvas.at(i)); + instBuffer->append(inst); } } -void Disassembly::prepareDataRange(dsint startRva, dsint endRva, const std::function & disassembled) +void Disassembly::prepareDataRange(duint startRva, duint endRva, const std::function & disassembled) { - dsint wAddrPrev = startRva; - dsint wAddr = wAddrPrev; + auto addrPrev = startRva; + auto addr = addrPrev; int i = 0; while(true) { - if(wAddr > endRva) + if(addr > endRva) break; - wAddrPrev = wAddr; - auto wInst = DisassembleAt(wAddr); - wAddr = getNextInstructionRVA(wAddr, 1); - if(wAddr == wAddrPrev) + addrPrev = addr; + auto inst = DisassembleAt(addr); + addr = getNextInstructionRVA(addr, 1); + if(addr == addrPrev) break; - if(!disassembled(i++, wInst)) + if(!disassembled(i++, inst)) break; } } @@ -1803,33 +1820,36 @@ RichTextPainter::List Disassembly::getRichBytes(const Instruction_t & instr, boo void Disassembly::prepareData() { - dsint wViewableRowsCount = getViewableRowsCount(); + auto viewableRowsCount = getViewableRowsCount(); + mInstBuffer.clear(); - mInstBuffer.reserve(wViewableRowsCount); + mInstBuffer.reserve(viewableRowsCount); - dsint wAddrPrev = getTableOffset(); - dsint wAddr = wAddrPrev; - Instruction_t wInst; + dsint addrPrev = getTableOffset(); + dsint addr = addrPrev; - int wCount = 0; + mDisasm->UpdateArchitecture(); - for(int wI = 0; wI < wViewableRowsCount && getRowCount() > 0; wI++) + for(duint i = 0; i < viewableRowsCount && getRowCount() > 0; i++) { - wAddrPrev = wAddr; - wInst = DisassembleAt(wAddr); - wAddr = getNextInstructionRVA(wAddr, 1); - if(wAddr == wAddrPrev) + addrPrev = addr; + auto inst = DisassembleAt(addr); + if(inst.length == 0) break; - mInstBuffer.append(wInst); - wCount++; + addr = getNextInstructionRVA(addr, 1); + if(addr == addrPrev) + break; + mInstBuffer.append(inst); } - setNbrOfLineToPrint(wCount); + mSelectedInstruction = DisassembleAt(mSelection.fromIndex); + + setNbrOfLineToPrint(mInstBuffer.size()); mRichText.resize(getColumnCount()); for(size_t i = 0; i < mRichText.size(); i++) { - mRichText[i].resize(wViewableRowsCount); + mRichText[i].resize(viewableRowsCount); for(size_t j = 0; j < mRichText[i].size(); j++) { mRichText[i][j].alive = false; @@ -2011,7 +2031,7 @@ void Disassembly::paintEvent(QPaintEvent* event) /************************************************************************************ Public Methods ************************************************************************************/ -duint Disassembly::rvaToVa(dsint rva) const +duint Disassembly::rvaToVa(duint rva) const { return mMemPage->va(rva); } @@ -2028,15 +2048,15 @@ void Disassembly::gotoAddress(duint addr) GuiUpdateAllViews(); } -void Disassembly::disassembleAt(dsint parVA, bool history, dsint newTableOffset) +void Disassembly::disassembleAt(duint va, bool history, duint newTableOffset) { - duint wSize; - auto wBase = DbgMemFindBaseAddr(parVA, &wSize); + duint size = 0; + auto base = DbgMemFindBaseAddr(va, &size); - unsigned char test; - if(!wBase || !wSize || !DbgMemRead(parVA, &test, sizeof(test))) + unsigned char test = 0; + if(!base || !size || !DbgMemRead(va, &test, sizeof(test))) return; - dsint wRVA = parVA - wBase; + duint rva = va - base; HistoryData newHistory; @@ -2050,8 +2070,8 @@ void Disassembly::disassembleAt(dsint parVA, bool history, dsint newTableOffset) //NOTE: mCurrentVa always points to the last entry of the list //add the currently selected address to the history - dsint selectionVA = rvaToVa(getInitialSelection()); //currently selected VA - dsint selectionTableOffset = getTableOffset(); + duint selectionVA = rvaToVa(getInitialSelection()); //currently selected VA + duint selectionTableOffset = getTableOffset(); if(selectionVA && mVaHistory.size() && mVaHistory.last().va != selectionVA) //do not have 2x the same va in a row { mCurrentVa++; @@ -2062,62 +2082,62 @@ void Disassembly::disassembleAt(dsint parVA, bool history, dsint newTableOffset) } // Set base and size (Useful when memory page changed) - mMemPage->setAttributes(wBase, wSize); - mDisasm->getEncodeMap()->setMemoryRegion(wBase); + mMemPage->setAttributes(base, size); + mDisasm->getEncodeMap()->setMemoryRegion(base); if(mRvaDisplayEnabled && mMemPage->getBase() != mRvaDisplayPageBase) mRvaDisplayEnabled = false; - setRowCount(wSize); + setRowCount(size); - setSingleSelection(wRVA); // Selects disassembled instruction - dsint wInstrSize = getInstructionRVA(wRVA, 1) - wRVA - 1; - expandSelectionUpTo(wRVA + wInstrSize); + // Selects disassembled instruction + setSingleSelection(rva); + duint instrSize = getInstructionRVA(rva, 1) - rva - 1; + expandSelectionUpTo(rva + instrSize); if(newTableOffset == -1) //nothing specified { // Update table offset depending on the location of the instruction to disassemble - if(mInstBuffer.size() > 0 && wRVA >= (dsint)mInstBuffer.first().rva && wRVA < (dsint)mInstBuffer.last().rva) + if(mInstBuffer.size() > 0 && rva >= mInstBuffer.first().rva && rva < mInstBuffer.last().rva) { - int wI; - bool wIsAligned = false; + bool isAligned = false; // Check if the new RVA is aligned on an instruction from the cache (buffer) - for(wI = 0; wI < mInstBuffer.size(); wI++) + for(int i = 0; i < mInstBuffer.size(); i++) { - if(mInstBuffer.at(wI).rva == wRVA) + if(mInstBuffer.at(i).rva == rva) { - wIsAligned = true; + isAligned = true; break; } } - if(wIsAligned == true) + if(isAligned) { updateViewport(); } else { - setTableOffset(wRVA); + setTableOffset(rva); } } - else if(mInstBuffer.size() > 0 && wRVA == (dsint)mInstBuffer.last().rva) + else if(mInstBuffer.size() > 0 && rva == (dsint)mInstBuffer.last().rva) { setTableOffset(mInstBuffer.first().rva + mInstBuffer.first().length); } else { - setTableOffset(wRVA); + setTableOffset(rva); } if(history) { //new disassembled address - newHistory.va = parVA; + newHistory.va = va; newHistory.tableOffset = getTableOffset(); if(mVaHistory.size()) { - if(mVaHistory.last().va != parVA) //not 2x the same va in history + if(mVaHistory.last().va != va) //not 2x the same va in history { if(mVaHistory.size() >= 1024) //max 1024 in the history { @@ -2152,19 +2172,19 @@ QList* Disassembly::instructionsBuffer() return &mInstBuffer; } -void Disassembly::disassembleAtSlot(dsint parVA, dsint parCIP) +void Disassembly::disassembleAtSlot(duint va, duint cip) { - if(parCIP == 0) - parCIP = mCipVa; + if(cip == 0) + cip = mCipVa; if(mCodeFoldingManager) { - mCodeFoldingManager->expandFoldSegment(parVA); - mCodeFoldingManager->expandFoldSegment(parCIP); + mCodeFoldingManager->expandFoldSegment(va); + mCodeFoldingManager->expandFoldSegment(cip); } - mCipVa = parCIP; + mCipVa = cip; if(mIsMain || !mMemPage->getBase()) - disassembleAt(parVA, true, -1); + disassembleAt(va, true, -1); } void Disassembly::disassembleClear() @@ -2264,7 +2284,7 @@ bool Disassembly::historyHasNext() const return true; } -QString Disassembly::getAddrText(dsint cur_addr, char label[MAX_LABEL_SIZE], bool getLabel) +QString Disassembly::getAddrText(duint cur_addr, QString & label, bool getLabel) { QString addrText = ""; if(mRvaDisplayEnabled) //RVA display @@ -2272,27 +2292,24 @@ QString Disassembly::getAddrText(dsint cur_addr, char label[MAX_LABEL_SIZE], boo dsint rva = cur_addr - mRvaDisplayBase; if(rva == 0) { -#ifdef _WIN64 - addrText = "$ ==> "; -#else - addrText = "$ ==> "; -#endif //_WIN64 + if(mArchitecture->addr64()) + addrText = "$ ==> "; + else + addrText = "$ ==> "; } else if(rva > 0) { -#ifdef _WIN64 - addrText = "$+" + QString("%1").arg(rva, -15, 16, QChar(' ')).toUpper(); -#else - addrText = "$+" + QString("%1").arg(rva, -7, 16, QChar(' ')).toUpper(); -#endif //_WIN64 + if(mArchitecture->addr64()) + addrText = "$+" + QString("%1").arg(rva, -15, 16, QChar(' ')).toUpper(); + else + addrText = "$+" + QString("%1").arg(rva, -7, 16, QChar(' ')).toUpper(); } else if(rva < 0) { -#ifdef _WIN64 - addrText = "$-" + QString("%1").arg(-rva, -15, 16, QChar(' ')).toUpper(); -#else - addrText = "$-" + QString("%1").arg(-rva, -7, 16, QChar(' ')).toUpper(); -#endif //_WIN64 + if(mArchitecture->addr64()) + addrText = "$-" + QString("%1").arg(-rva, -15, 16, QChar(' ')).toUpper(); + else + addrText = "$-" + QString("%1").arg(-rva, -7, 16, QChar(' ')).toUpper(); } } addrText += ToPtrString(cur_addr); @@ -2307,8 +2324,7 @@ QString Disassembly::getAddrText(dsint cur_addr, char label[MAX_LABEL_SIZE], boo } else *label_ = 0; - if(label) - strcpy_s(label, MAX_LABEL_SIZE, label_); + label = label_; return addrText; } @@ -2326,7 +2342,7 @@ void Disassembly::setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager) * @brief Unfolds specified rva. * @param rva the address. */ -void Disassembly::unfold(dsint rva) +void Disassembly::unfold(duint rva) { if(mCodeFoldingManager) { diff --git a/src/gui/Src/BasicView/Disassembly.h b/src/gui/Src/BasicView/Disassembly.h index 547d9a3c..6783bee0 100644 --- a/src/gui/Src/BasicView/Disassembly.h +++ b/src/gui/Src/BasicView/Disassembly.h @@ -1,17 +1,19 @@ #pragma once #include "AbstractTableView.h" -#include "QBeaEngine.h" +#include "QZydis.h" #include +#include "Architecture.h" class CodeFoldingHelper; class MemoryPage; +class DisassemblyPopup; class Disassembly : public AbstractTableView { Q_OBJECT public: - Disassembly(QWidget* parent, bool isMain); + Disassembly(QWidget* parent, bool isMain, Architecture* architecture); ~Disassembly() override; // Configuration @@ -19,7 +21,7 @@ public: void updateFonts() override; // Reimplemented Functions - QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override; + QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override; // Mouse Management void mouseMoveEvent(QMouseEvent* event) override; @@ -31,25 +33,25 @@ public: void keyPressEvent(QKeyEvent* event) override; // ScrollBar Management - dsint sliderMovedHook(int type, dsint value, dsint delta) override; + duint sliderMovedHook(QScrollBar::SliderAction action, duint value, dsint delta) override; // Instructions Management - dsint getPreviousInstructionRVA(dsint rva, duint count); - dsint getNextInstructionRVA(dsint rva, duint count, bool isGlobal = false); - dsint getInstructionRVA(dsint index, dsint count); - Instruction_t DisassembleAt(dsint rva); - Instruction_t DisassembleAt(dsint rva, dsint count); + duint getPreviousInstructionRVA(duint rva, duint count); + duint getNextInstructionRVA(duint rva, duint count, bool isGlobal = false); + duint getInstructionRVA(duint index, dsint count); + Instruction_t DisassembleAt(duint rva); + Instruction_t DisassembleAt(duint rva, dsint count); // Selection Management - void expandSelectionUpTo(dsint to); - void setSingleSelection(dsint index); - dsint getInitialSelection() const; - dsint getSelectionSize() const; - dsint getSelectionStart() const; - dsint getSelectionEnd() const; + void expandSelectionUpTo(duint to); + void setSingleSelection(duint index); + duint getInitialSelection() const; + duint getSelectionSize() const; + duint getSelectionStart() const; + duint getSelectionEnd() const; void selectNext(bool expand); void selectPrevious(bool expand); - bool isSelected(dsint base, dsint offset); + bool isSelected(duint base, dsint offset); bool isSelected(QList* buffer, int index) const; duint getSelectedVa() const; @@ -60,7 +62,7 @@ public: void paintEvent(QPaintEvent* event) override; // Public Methods - duint rvaToVa(dsint rva) const; + duint rvaToVa(duint rva) const; void disassembleClear(); const duint getBase() const; duint getSize() const; @@ -75,32 +77,31 @@ public: //disassemble void gotoAddress(duint addr); - void disassembleAt(dsint parVA, bool history, dsint newTableOffset); + void disassembleAt(duint va, bool history, duint newTableOffset); QList* instructionsBuffer(); // ugly - const dsint baseAddress() const; + const duint baseAddress() const; - QString getAddrText(dsint cur_addr, char label[MAX_LABEL_SIZE], bool getLabel = true); - void prepareDataCount(const QList & wRVAs, QList* instBuffer); - void prepareDataRange(dsint startRva, dsint endRva, const std::function & disassembled); + QString getAddrText(duint cur_addr, QString & label, bool getLabel = true); + void prepareDataCount(const QList & rvas, QList* instBuffer); + void prepareDataRange(duint startRva, duint endRva, const std::function & disassembled); RichTextPainter::List getRichBytes(const Instruction_t & instr, bool isSelected) const; //misc void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager); - duint getDisassemblyPopupAddress(int mousex, int mousey) override; - void unfold(dsint rva); + void unfold(duint rva); bool hightlightToken(const ZydisTokenizer::SingleToken & token); bool isHighlightMode() const; signals: - void selectionChanged(dsint parVA); + void selectionChanged(duint va); void selectionExpanded(); void updateWindowTitle(QString title); public slots: - void disassembleAtSlot(dsint parVA, dsint parCIP); + void disassembleAtSlot(duint va, duint cip); void debugStateChangedSlot(DBGSTATE state); - void selectionChangedSlot(dsint parVA); + void selectionChangedSlot(duint va); void tokenizerConfigUpdatedSlot(); void updateConfigSlot(); @@ -127,30 +128,31 @@ private: { GJD_Nothing, GJD_Up, - GJD_Down + GJD_Down, + GJD_Out, }; struct SelectionData { - dsint firstSelectedIndex; - dsint fromIndex; - dsint toIndex; - }; - - SelectionData mSelection; + duint firstSelectedIndex = 0; + duint fromIndex = 0; + duint toIndex = 0; + } mSelection; + Architecture* mArchitecture = nullptr; bool mIsLastInstDisplayed; GuiState mGuiState; duint mCipVa = 0; + Instruction_t mSelectedInstruction; QList mInstBuffer; struct HistoryData { - dsint va; - dsint tableOffset; + duint va = 0; + duint tableOffset = 0; }; QList mVaHistory; @@ -165,9 +167,11 @@ private: ColMnemonicBrief, }; + DisassemblyPopup* mDisassemblyPopup = nullptr; + protected: // Jumps Graphic - int paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, bool isjmp); + int paintJumpsGraphic(QPainter* painter, int x, int y, const Instruction_t & instruction); // Function Graphic @@ -182,6 +186,9 @@ protected: }; int paintFunctionGraphic(QPainter* painter, int x, int y, Function_t funcType, bool loop); + + duint getAddressForPosition(int mousex, int mousey) override; + // Configuration QColor mInstructionHighlightColor; QColor mDisassemblyRelocationUnderlineColor; @@ -243,7 +250,7 @@ protected: dsint mRvaDisplayPageBase; bool mHighlightingMode; MemoryPage* mMemPage; - QBeaEngine* mDisasm; + QZydis* mDisasm; bool mShowMnemonicBrief; XREF_INFO mXrefInfo; CodeFoldingHelper* mCodeFoldingManager; diff --git a/src/gui/Src/BasicView/StdSearchListView.cpp b/src/gui/Src/BasicView/StdSearchListView.cpp index a3a306b6..a08b681c 100644 --- a/src/gui/Src/BasicView/StdSearchListView.cpp +++ b/src/gui/Src/BasicView/StdSearchListView.cpp @@ -85,12 +85,6 @@ void StdSearchListView::setSearchStartCol(int col) mSearchStartCol = col; } -bool StdSearchListView::setDisassemblyPopupEnabled(bool enabled) -{ - stdList()->setDisassemblyPopupEnabled(enabled); - return stdSearchList()->setDisassemblyPopupEnabled(enabled); -} - StdTable* StdSearchListView::stdList() { return mSearchListData->mList; diff --git a/src/gui/Src/BasicView/StdSearchListView.h b/src/gui/Src/BasicView/StdSearchListView.h index 9e1c86a5..e92b15e4 100644 --- a/src/gui/Src/BasicView/StdSearchListView.h +++ b/src/gui/Src/BasicView/StdSearchListView.h @@ -18,7 +18,6 @@ public: void enableMultiSelection(bool enabled); void setAddressColumn(int col, bool cipBase = false); void loadColumnFromConfig(const QString & viewName); - bool setDisassemblyPopupEnabled(bool enabled); public slots: virtual void setRowCount(dsint count); diff --git a/src/gui/Src/Bridge/Bridge.cpp b/src/gui/Src/Bridge/Bridge.cpp index 526b40b7..c396aa1c 100644 --- a/src/gui/Src/Bridge/Bridge.cpp +++ b/src/gui/Src/Bridge/Bridge.cpp @@ -1,6 +1,6 @@ #include "Bridge.h" #include -#include "QBeaEngine.h" +#include "QZydis.h" #include "main.h" #include "Exports.h" @@ -12,6 +12,19 @@ ************************************************************************************/ static Bridge* mBridge; +class BridgeArchitecture : public Architecture +{ + bool disasm64() const override + { + return ArchValue(false, true); + } + + bool addr64() const override + { + return ArchValue(false, true); + } +} mArch; + /************************************************************************************ Class Members ************************************************************************************/ @@ -72,6 +85,11 @@ void Bridge::initBridge() mBridge = new Bridge(); } +Architecture* Bridge::getArch() +{ + return &mArch; +} + /************************************************************************************ Helper Functions ************************************************************************************/ @@ -100,7 +118,7 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) { case GUI_DISASSEMBLE_AT: mLastCip = (duint)param2; - emit disassembleAt((dsint)param1, (dsint)param2); + emit disassembleAt((duint)param1, (duint)param2); break; case GUI_SET_DEBUG_STATE: @@ -361,7 +379,7 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) byte_t buffer[16]; if(!DbgMemRead(parVA, buffer, 16)) return 0; - QBeaEngine disasm(int(ConfigUint("Disassembler", "MaxModuleSize")), Bridge::getArch()); + QZydis disasm(int(ConfigUint("Disassembler", "MaxModuleSize")), Bridge::getArch()); Instruction_t instr = disasm.DisassembleAt(buffer, 16, 0, parVA); QString finalInstruction; for(const auto & curToken : instr.tokens.tokens) diff --git a/src/gui/Src/Bridge/Bridge.h b/src/gui/Src/Bridge/Bridge.h index 21efb3cc..e35acda0 100644 --- a/src/gui/Src/Bridge/Bridge.h +++ b/src/gui/Src/Bridge/Bridge.h @@ -7,6 +7,15 @@ #include #include "Imports.h" #include "BridgeResult.h" +#include "Architecture.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) +namespace Qt +{ + static QString::SplitBehavior KeepEmptyParts = QString::KeepEmptyParts; + static QString::SplitBehavior SkipEmptyParts = QString::SkipEmptyParts; +} +#endif // QT_VERSION class ReferenceManager; class SymbolView; @@ -23,6 +32,7 @@ public: static Bridge* getBridge(); static void initBridge(); + static Architecture* getArch(); // Message processing function void* processMessage(GUIMSG type, void* param1, void* param2); @@ -47,7 +57,7 @@ public: bool loggingEnabled = true; signals: - void disassembleAt(dsint va, dsint eip); + void disassembleAt(duint va, duint eip); void updateDisassembly(); void dbgStateChanged(DBGSTATE state); void addMsgToLog(QByteArray msg); @@ -57,11 +67,11 @@ signals: void saveLogToFile(QString file); void redirectLogStop(); void redirectLogToFile(QString filename); - void shutdown(); + void close(); void updateRegisters(); void updateBreakpoints(); void updateWindowTitle(QString filename); - void dumpAt(dsint va); + void dumpAt(duint va); void scriptAdd(int count, const char** lines); void scriptClear(); void scriptSetIp(int line); @@ -76,7 +86,7 @@ signals: void clearSymbolLog(); void setSymbolProgress(int progress); void referenceAddColumnAt(int width, QString title); - void referenceSetRowCount(dsint count); + void referenceSetRowCount(duint count); void referenceSetCellContent(int r, int c, QString s); void referenceAddCommand(QString title, QString command); void referenceReloadData(); diff --git a/src/gui/Src/Disassembler/Architecture.cpp b/src/gui/Src/Disassembler/Architecture.cpp new file mode 100644 index 00000000..0927da24 --- /dev/null +++ b/src/gui/Src/Disassembler/Architecture.cpp @@ -0,0 +1 @@ +#include "Architecture.h" diff --git a/src/gui/Src/Disassembler/Architecture.h b/src/gui/Src/Disassembler/Architecture.h new file mode 100644 index 00000000..cc6d1be0 --- /dev/null +++ b/src/gui/Src/Disassembler/Architecture.h @@ -0,0 +1,17 @@ +#pragma once + +/* +This should probably take some inspiration from Zydis: +- Address space min/max (64 vs 32 bit basically) +- Disassembly architecture (likely should return a reference to a disassembler) + +*/ +class Architecture +{ +public: + virtual ~Architecture() = default; + + // TODO: replace this with something about address space + virtual bool disasm64() const = 0; + virtual bool addr64() const = 0; +}; diff --git a/src/gui/Src/Disassembler/QBeaEngine.h b/src/gui/Src/Disassembler/QBeaEngine.h deleted file mode 100644 index 7f1ffaa0..00000000 --- a/src/gui/Src/Disassembler/QBeaEngine.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include -#include -#include "ZydisTokenizer.h" - -class EncodeMap; -class CodeFoldingHelper; - -struct Instruction_t -{ - enum BranchType - { - None, - Conditional, - Unconditional, - Call - }; - - Instruction_t() - : rva(0), - length(0), - branchDestination(0), - branchType(None) - { - } - - QString instStr; - QByteArray dump; - uint8_t prefixSize, opcodeSize, group1Size, group2Size, group3Size; - duint rva; - int length; - duint branchDestination; - BranchType branchType; - ZydisTokenizer::InstructionToken tokens; - std::vector> regsReferenced; - uint8_t vectorElementType[4]; -}; - -class QBeaEngine -{ -public: - explicit QBeaEngine(int maxModuleSize); - ~QBeaEngine(); - ulong DisassembleBack(const byte_t* data, duint base, duint size, duint ip, int n); - ulong DisassembleNext(const byte_t* data, duint base, duint size, duint ip, int n); - Instruction_t DisassembleAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr = true); - Instruction_t DecodeDataAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type); - void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager); - void UpdateConfig(); - - EncodeMap* getEncodeMap() - { - return mEncodeMap; - } - -private: - struct DataInstructionInfo - { - QString shortName; - QString longName; - QString cName; - }; - - void UpdateDataInstructionMap(); - ZydisTokenizer _tokenizer; - QHash dataInstMap; - bool _bLongDataInst; - EncodeMap* mEncodeMap; - CodeFoldingHelper* mCodeFoldingManager; - uint8_t reginfo[ZYDIS_REGISTER_MAX_VALUE + 1]; - uint8_t flaginfo[ZYDIS_CPUFLAG_MAX_VALUE + 1]; -}; - -void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector> & realBytes); diff --git a/src/gui/Src/Disassembler/QBeaEngine.cpp b/src/gui/Src/Disassembler/QZydis.cpp similarity index 55% rename from src/gui/Src/Disassembler/QBeaEngine.cpp rename to src/gui/Src/Disassembler/QZydis.cpp index 07121ec4..0343f494 100644 --- a/src/gui/Src/Disassembler/QBeaEngine.cpp +++ b/src/gui/Src/Disassembler/QZydis.cpp @@ -1,19 +1,24 @@ -#include "QBeaEngine.h" +#include "QZydis.h" #include "StringUtil.h" #include "EncodeMap.h" #include "CodeFolding.h" +#include "Bridge.h" -QBeaEngine::QBeaEngine(int maxModuleSize) - : _tokenizer(maxModuleSize), mCodeFoldingManager(nullptr), _bLongDataInst(false) +#ifndef _countof +#define _countof(array) (sizeof(array) / sizeof(array[0])) +#endif // _countof + +QZydis::QZydis(int maxModuleSize, Architecture* architecture) + : mTokenizer(maxModuleSize, architecture), mArchitecture(architecture) { ZydisTokenizer::UpdateColors(); UpdateDataInstructionMap(); - this->mEncodeMap = new EncodeMap(); + mEncodeMap = new EncodeMap(); } -QBeaEngine::~QBeaEngine() +QZydis::~QZydis() { - delete this->mEncodeMap; + delete mEncodeMap; } /** @@ -28,14 +33,14 @@ QBeaEngine::~QBeaEngine() * * @return Return the RVA (Relative to the data pointer) of the nth instruction before the instruction pointed by ip */ -ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, duint ip, int n) +ulong QZydis::DisassembleBack(const uint8_t* data, duint base, duint size, duint ip, int n) { int i; uint abuf[128], addr, back, cmdsize; const unsigned char* pdata; // Reset Disasm Structure - Zydis cp; + Zydis zydis(mArchitecture->disasm64()); // Check if the pointer is not null if(data == NULL) @@ -89,10 +94,10 @@ ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, du } else { - if(!cp.DisassembleSafe(addr + base, pdata, (int)size)) + if(!zydis.DisassembleSafe(addr + base, pdata, (int)size)) cmdsize = 2; //heuristic for better output (FF FE or FE FF are usually part of an instruction) else - cmdsize = cp.Size(); + cmdsize = zydis.Size(); cmdsize = mEncodeMap->getDataSize(base + addr, cmdsize); @@ -124,14 +129,14 @@ ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, du * * @return Return the RVA (Relative to the data pointer) of the nth instruction after the instruction pointed by ip */ -ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, duint ip, int n) +ulong QZydis::DisassembleNext(const uint8_t* data, duint base, duint size, duint ip, int n) { int i; uint cmdsize; const unsigned char* pdata; // Reset Disasm Structure - Zydis cp; + Zydis zydis(mArchitecture->disasm64()); if(data == NULL) return 0; @@ -154,10 +159,10 @@ ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, du } else { - if(!cp.DisassembleSafe(ip + base, pdata, (int)size)) + if(!zydis.DisassembleSafe(ip + base, pdata, (int)size)) cmdsize = 1; else - cmdsize = cp.Size(); + cmdsize = zydis.Size(); cmdsize = mEncodeMap->getDataSize(base + ip, cmdsize); @@ -181,7 +186,7 @@ ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, du * * @return Return the disassembled instruction */ -Instruction_t QBeaEngine::DisassembleAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr) +Instruction_t QZydis::DisassembleAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr) { if(datainstr) { @@ -189,147 +194,140 @@ Instruction_t QBeaEngine::DisassembleAt(const byte_t* data, duint size, duint or if(!mEncodeMap->isCode(type)) return DecodeDataAt(data, size, origBase, origInstRVA, type); } + //tokenize ZydisTokenizer::InstructionToken cap; - _tokenizer.Tokenize(origBase + origInstRVA, data, size, cap); - int len = _tokenizer.Size(); - - const auto & cp = _tokenizer.GetZydis(); - bool success = cp.Success(); + mTokenizer.Tokenize(origBase + origInstRVA, data, size, cap); + int len = mTokenizer.Size(); + const auto & zydis = mTokenizer.GetZydis(); + bool success = zydis.Success(); auto branchType = Instruction_t::None; - Instruction_t wInst; - if(success && cp.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTRet | Zydis::BTLoop | Zydis::BTXbegin)) + Instruction_t inst; + if(success && zydis.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTRet | Zydis::BTLoop | Zydis::BTXbegin)) { - wInst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA); - if(cp.IsBranchType(Zydis::BTUncondJmp)) + inst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA); + if(zydis.IsBranchType(Zydis::BTUncondJmp)) branchType = Instruction_t::Unconditional; - else if(cp.IsBranchType(Zydis::BTCall)) + else if(zydis.IsBranchType(Zydis::BTCall)) branchType = Instruction_t::Call; - else if(cp.IsBranchType(Zydis::BTCondJmp) || cp.IsBranchType(Zydis::BTLoop)) + else if(zydis.IsBranchType(Zydis::BTCondJmp) || zydis.IsBranchType(Zydis::BTLoop)) branchType = Instruction_t::Conditional; } else - wInst.branchDestination = 0; + inst.branchDestination = 0; - wInst.instStr = QString(cp.InstructionText().c_str()); - wInst.dump = QByteArray((const char*)data, len); - wInst.rva = origInstRVA; + inst.instStr = QString(zydis.InstructionText().c_str()); + inst.dump = QByteArray((const char*)data, len); + inst.rva = origInstRVA; if(mCodeFoldingManager && mCodeFoldingManager->isFolded(origInstRVA)) - wInst.length = mCodeFoldingManager->getFoldEnd(origInstRVA + origBase) - (origInstRVA + origBase) + 1; + inst.length = mCodeFoldingManager->getFoldEnd(origInstRVA + origBase) - (origInstRVA + origBase) + 1; else - wInst.length = len; - wInst.branchType = branchType; - wInst.tokens = cap; - cp.BytesGroup(&wInst.prefixSize, &wInst.opcodeSize, &wInst.group1Size, &wInst.group2Size, &wInst.group3Size); - for(uint8_t i = 0; i < _countof(wInst.vectorElementType); ++i) - wInst.vectorElementType[i] = cp.getVectorElementType(i); + inst.length = len; + inst.branchType = branchType; + inst.tokens = cap; + zydis.BytesGroup(&inst.prefixSize, &inst.opcodeSize, &inst.group1Size, &inst.group2Size, &inst.group3Size); + for(uint8_t i = 0; i < _countof(inst.vectorElementType); ++i) + inst.vectorElementType[i] = zydis.getVectorElementType(i); if(!success) - return wInst; + return inst; - auto instr = cp.GetInstr(); - cp.RegInfo(reginfo); + uint8_t regInfo[ZYDIS_REGISTER_MAX_VALUE + 1]; + uint8_t flagInfo[32]; + zydis.RegInfo(regInfo); + zydis.FlagInfo(flagInfo); - for(size_t i = 0; i < _countof(instr->accessedFlags); ++i) + regInfo[ZYDIS_REGISTER_RFLAGS] = Zydis::RAINone; + regInfo[ZYDIS_REGISTER_EFLAGS] = Zydis::RAINone; + regInfo[ZYDIS_REGISTER_FLAGS] = Zydis::RAINone; + regInfo[mArchitecture->disasm64() ? ZYDIS_REGISTER_RIP : ZYDIS_REGISTER_EIP] = Zydis::RAINone; + + inst.regsReferenced.reserve(ZYDIS_REGISTER_MAX_VALUE + 21); + for(int i = ZYDIS_REGISTER_NONE; i <= ZYDIS_REGISTER_MAX_VALUE; ++i) { - auto flagAction = instr->accessedFlags[i].action; - if(flagAction == ZYDIS_CPUFLAG_ACTION_NONE) - continue; - - Zydis::RegAccessInfo rai; - switch(flagAction) + if(regInfo[i] != Zydis::RAINone) { - case ZYDIS_CPUFLAG_ACTION_MODIFIED: - case ZYDIS_CPUFLAG_ACTION_SET_0: - case ZYDIS_CPUFLAG_ACTION_SET_1: - rai = Zydis::RAIWrite; - break; - case ZYDIS_CPUFLAG_ACTION_TESTED: - rai = Zydis::RAIRead; - break; - default: - rai = Zydis::RAINone; - break; + inst.regsReferenced.emplace_back(zydis.RegName(ZydisRegister(i)), regInfo[i]); + } + } + for(uint8_t i = 0; i < _countof(flagInfo); i++) + { + auto flag = 1u << i; + auto name = zydis.FlagName(flag); + auto rai = flagInfo[i]; + if(name != nullptr && rai != Zydis::RAINone) + { + inst.regsReferenced.emplace_back(name, rai); } - - reginfo[ZYDIS_REGISTER_RFLAGS] = Zydis::RAINone; - reginfo[ZYDIS_REGISTER_EFLAGS] = Zydis::RAINone; - reginfo[ZYDIS_REGISTER_FLAGS] = Zydis::RAINone; - - wInst.regsReferenced.emplace_back(cp.FlagName(ZydisCPUFlag(i)), rai); } - wInst.regsReferenced.reserve(ZYDIS_REGISTER_MAX_VALUE); - reginfo[ArchValue(ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_RIP)] = Zydis::RAINone; - for(int i = ZYDIS_REGISTER_NONE; i <= ZYDIS_REGISTER_MAX_VALUE; ++i) - if(reginfo[i]) - wInst.regsReferenced.emplace_back(cp.RegName(ZydisRegister(i)), reginfo[i]); - // Info about volatile and nonvolatile registers - if(cp.IsBranchType(Zydis::BranchType::BTCall)) + if(zydis.IsBranchType(Zydis::BranchType::BTCall)) { enum : uint8_t { Volatile = Zydis::RAIImplicit | Zydis::RAIWrite, Parameter = Volatile | Zydis::RAIRead, }; -#define info(reg, type) wInst.regsReferenced.emplace_back(#reg, type) +#define info(reg, type) inst.regsReferenced.emplace_back(#reg, type) -#ifdef _WIN64 - // https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions - info(rax, Volatile); - info(rcx, Parameter); - info(rdx, Parameter); - info(r8, Parameter); - info(r9, Parameter); - info(r10, Volatile); - info(r11, Volatile); - info(xmm0, Parameter); - info(ymm0, Parameter); - info(xmm1, Parameter); - info(ymm1, Parameter); - info(xmm2, Parameter); - info(ymm2, Parameter); - info(xmm3, Parameter); - info(ymm3, Parameter); - info(xmm4, Parameter); - info(ymm4, Parameter); - info(xmm5, Parameter); - info(ymm5, Parameter); - -#else - // https://en.wikipedia.org/wiki/X86_calling_conventions#Caller-saved_(volatile)_registers - info(eax, Volatile); - info(edx, Volatile); - info(ecx, Volatile); -#endif // _WIN64 + if(mArchitecture->disasm64()) + { + // https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions + info(rax, Volatile); + info(rcx, Parameter); + info(rdx, Parameter); + info(r8, Parameter); + info(r9, Parameter); + info(r10, Volatile); + info(r11, Volatile); + info(xmm0, Parameter); + info(ymm0, Parameter); + info(xmm1, Parameter); + info(ymm1, Parameter); + info(xmm2, Parameter); + info(ymm2, Parameter); + info(xmm3, Parameter); + info(ymm3, Parameter); + info(xmm4, Parameter); + info(ymm4, Parameter); + info(xmm5, Parameter); + info(ymm5, Parameter); + } + else + { + // https://en.wikipedia.org/wiki/X86_calling_conventions#Caller-saved_(volatile)_registers + info(eax, Volatile); + info(edx, Volatile); + info(ecx, Volatile); + } #undef info } - return wInst; + return inst; } -Instruction_t QBeaEngine::DecodeDataAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type) +Instruction_t QZydis::DecodeDataAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type) { //tokenize ZydisTokenizer::InstructionToken cap; - auto infoIter = dataInstMap.find(type); - if(infoIter == dataInstMap.end()) - infoIter = dataInstMap.find(enc_byte); + auto infoIter = mDataInstMap.find(type); + if(infoIter == mDataInstMap.end()) + infoIter = mDataInstMap.find(enc_byte); int len = mEncodeMap->getDataSize(origBase + origInstRVA, 1); - QString mnemonic = _bLongDataInst ? infoIter.value().longName : infoIter.value().shortName; + QString mnemonic = mLongDataInst ? infoIter.value().longName : infoIter.value().shortName; len = std::min(len, (int)size); QString datastr = GetDataTypeString(data, len, type); - _tokenizer.TokenizeData(mnemonic, datastr, cap); + mTokenizer.TokenizeData(mnemonic, datastr, cap); Instruction_t inst; inst.instStr = mnemonic + " " + datastr; @@ -352,35 +350,40 @@ Instruction_t QBeaEngine::DecodeDataAt(const byte_t* data, duint size, duint ori return inst; } -void QBeaEngine::UpdateDataInstructionMap() +void QZydis::UpdateDataInstructionMap() { - dataInstMap.clear(); - dataInstMap.insert(enc_byte, {"db", "byte", "int8"}); - dataInstMap.insert(enc_word, {"dw", "word", "short"}); - dataInstMap.insert(enc_dword, {"dd", "dword", "int"}); - dataInstMap.insert(enc_fword, {"df", "fword", "fword"}); - dataInstMap.insert(enc_qword, {"dq", "qword", "long"}); - dataInstMap.insert(enc_tbyte, {"tbyte", "tbyte", "tbyte"}); - dataInstMap.insert(enc_oword, {"oword", "oword", "oword"}); - dataInstMap.insert(enc_mmword, {"mmword", "mmword", "long long"}); - dataInstMap.insert(enc_xmmword, {"xmmword", "xmmword", "_m128"}); - dataInstMap.insert(enc_ymmword, {"ymmword", "ymmword", "_m256"}); - dataInstMap.insert(enc_real4, {"real4", "real4", "float"}); - dataInstMap.insert(enc_real8, {"real8", "real8", "double"}); - dataInstMap.insert(enc_real10, {"real10", "real10", "long double"}); - dataInstMap.insert(enc_ascii, {"ascii", "ascii", "string"}); - dataInstMap.insert(enc_unicode, {"unicode", "unicode", "wstring"}); + mDataInstMap.clear(); + mDataInstMap.insert(enc_byte, {"db", "byte", "int8"}); + mDataInstMap.insert(enc_word, {"dw", "word", "short"}); + mDataInstMap.insert(enc_dword, {"dd", "dword", "int"}); + mDataInstMap.insert(enc_fword, {"df", "fword", "fword"}); + mDataInstMap.insert(enc_qword, {"dq", "qword", "long"}); + mDataInstMap.insert(enc_tbyte, {"tbyte", "tbyte", "tbyte"}); + mDataInstMap.insert(enc_oword, {"oword", "oword", "oword"}); + mDataInstMap.insert(enc_mmword, {"mmword", "mmword", "long long"}); + mDataInstMap.insert(enc_xmmword, {"xmmword", "xmmword", "_m128"}); + mDataInstMap.insert(enc_ymmword, {"ymmword", "ymmword", "_m256"}); + mDataInstMap.insert(enc_real4, {"real4", "real4", "float"}); + mDataInstMap.insert(enc_real8, {"real8", "real8", "double"}); + mDataInstMap.insert(enc_real10, {"real10", "real10", "long double"}); + mDataInstMap.insert(enc_ascii, {"ascii", "ascii", "string"}); + mDataInstMap.insert(enc_unicode, {"unicode", "unicode", "wstring"}); } -void QBeaEngine::setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager) +void QZydis::setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager) { mCodeFoldingManager = CodeFoldingManager; } -void QBeaEngine::UpdateConfig() +void QZydis::UpdateConfig() { - _bLongDataInst = ConfigBool("Disassembler", "LongDataInstruction"); - _tokenizer.UpdateConfig(); + mLongDataInst = ConfigBool("Disassembler", "LongDataInstruction"); + mTokenizer.UpdateConfig(); +} + +void QZydis::UpdateArchitecture() +{ + mTokenizer.UpdateArchitecture(); } void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector> & realBytes) diff --git a/src/gui/Src/Disassembler/QZydis.h b/src/gui/Src/Disassembler/QZydis.h new file mode 100644 index 00000000..889edb95 --- /dev/null +++ b/src/gui/Src/Disassembler/QZydis.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include "ZydisTokenizer.h" + +class EncodeMap; +class CodeFoldingHelper; + +struct Instruction_t +{ + enum BranchType : uint8_t + { + None, + Conditional, + Unconditional, + Call + }; + + duint rva = 0; + duint branchDestination = 0; + int length = 0; + uint8_t vectorElementType[4]; + uint8_t prefixSize = 0; + uint8_t opcodeSize = 0; + uint8_t group1Size = 0; + uint8_t group2Size = 0; + uint8_t group3Size = 0; + BranchType branchType = None; + + QString instStr; + QByteArray dump; + std::vector> regsReferenced; + ZydisTokenizer::InstructionToken tokens; + + Instruction_t() + { + memset(vectorElementType, 0, sizeof(vectorElementType)); + } +}; + +class QZydis +{ +public: + QZydis(int maxModuleSize, Architecture* architecture); + ~QZydis(); + ulong DisassembleBack(const uint8_t* data, duint base, duint size, duint ip, int n); + ulong DisassembleNext(const uint8_t* data, duint base, duint size, duint ip, int n); + Instruction_t DisassembleAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr = true); + Instruction_t DecodeDataAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type); + void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager); + void UpdateConfig(); + void UpdateArchitecture(); + + EncodeMap* getEncodeMap() + { + return mEncodeMap; + } + +private: + struct DataInstructionInfo + { + QString shortName; + QString longName; + QString cName; + }; + + void UpdateDataInstructionMap(); + + Architecture* mArchitecture = nullptr; + ZydisTokenizer mTokenizer; + QHash mDataInstMap; + bool mLongDataInst = false; + EncodeMap* mEncodeMap = nullptr; + CodeFoldingHelper* mCodeFoldingManager = nullptr; +}; + +void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector> & realBytes); diff --git a/src/gui/Src/Disassembler/ZydisTokenizer.cpp b/src/gui/Src/Disassembler/ZydisTokenizer.cpp index b4c6f1b0..b6f6fcc3 100644 --- a/src/gui/Src/Disassembler/ZydisTokenizer.cpp +++ b/src/gui/Src/Disassembler/ZydisTokenizer.cpp @@ -2,19 +2,18 @@ #include "Configuration.h" #include "StringUtil.h" #include "CachedFontMetrics.h" +#include "Bridge.h" -ZydisTokenizer::ZydisTokenizer(int maxModuleLength) - : _maxModuleLength(maxModuleLength), - _success(false), - isNop(false), - _mnemonicType(TokenType::Uncategorized) +ZydisTokenizer::ZydisTokenizer(int maxModuleLength, Architecture* architecture) + : mMaxModuleLength(maxModuleLength), + mZydis(architecture->disasm64()), + mArchitecture(architecture) { - SetConfig(false, false, false, false, false, false, false, false, false); } static ZydisTokenizer::TokenColor colorNamesMap[size_t(ZydisTokenizer::TokenType::Last)]; -QHash ZydisTokenizer::stringPoolMap; -int ZydisTokenizer::poolId = 0; +QHash ZydisTokenizer::gStringPool; +int ZydisTokenizer::gPoolId = 0; void ZydisTokenizer::addColorName(TokenType type, QString color, QString backgroundColor) { @@ -28,10 +27,10 @@ ZydisTokenizer::TokenColor ZydisTokenizer::getTokenColor(TokenType type) void ZydisTokenizer::addStringsToPool(const QString & strings) { - QStringList stringList = strings.split(' ', QString::SkipEmptyParts); + QStringList stringList = strings.split(' ', Qt::SkipEmptyParts); for(const QString & string : stringList) - stringPoolMap.insert(string, poolId); - poolId++; + gStringPool.insert(string, gPoolId); + gPoolId++; } void ZydisTokenizer::UpdateColors() @@ -77,8 +76,8 @@ void ZydisTokenizer::UpdateColors() void ZydisTokenizer::UpdateStringPool() { - poolId = 0; - stringPoolMap.clear(); + gPoolId = 0; + gStringPool.clear(); // These registers must be in lower case. addStringsToPool("rax eax ax al ah"); addStringsToPool("rbx ebx bx bl bh"); @@ -116,75 +115,75 @@ void ZydisTokenizer::UpdateStringPool() bool ZydisTokenizer::Tokenize(duint addr, const unsigned char* data, int datasize, InstructionToken & instruction) { - _inst = InstructionToken(); + mInst = InstructionToken(); - _success = _cp.DisassembleSafe(addr, data, datasize); - if(_success) + mSuccess = mZydis.DisassembleSafe(addr, data, datasize); + if(mSuccess) { if(!tokenizePrefix()) return false; - isNop = _cp.IsNop(); + mIsNop = mZydis.IsNop(); if(!tokenizeMnemonic()) return false; - for(int i = 0; i < _cp.OpCount(); i++) + for(int i = 0; i < mZydis.OpCount(); i++) { - if(i == 1 && _cp[0].size >= 128 && _cp[1].type == ZYDIS_OPERAND_TYPE_REGISTER - && ZydisRegisterGetClass(_cp[1].reg.value) == ZYDIS_REGCLASS_MASK) + if(i == 1 && mZydis[0].size >= 128 && mZydis[1].type == ZYDIS_OPERAND_TYPE_REGISTER + && ZydisRegisterGetClass(mZydis[1].reg.value) == ZYDIS_REGCLASS_MASK) { - if(_bArgumentSpaces) + if(mArgumentSpaces) addToken(TokenType::ArgumentSpace, " "); addToken(TokenType::Comma, "{"); - if(!tokenizeOperand(_cp[i])) + if(!tokenizeOperand(mZydis[i])) return false; addToken(TokenType::Comma, "}"); } else if(i) { addToken(TokenType::Comma, ","); - if(_bArgumentSpaces) + if(mArgumentSpaces) addToken(TokenType::ArgumentSpace, " "); - if(!tokenizeOperand(_cp[i])) + if(!tokenizeOperand(mZydis[i])) return false; } else { - if(!tokenizeOperand(_cp[i])) + if(!tokenizeOperand(mZydis[i])) return false; } } } else { - isNop = false; + mIsNop = false; addToken(TokenType::MnemonicUnusual, "???"); } - if(_bNoHighlightOperands) + if(mNoHighlightOperands) { - while(_inst.tokens.size() && _inst.tokens[_inst.tokens.size() - 1].type == TokenType::Space) - _inst.tokens.pop_back(); - for(SingleToken & token : _inst.tokens) - token.type = _mnemonicType; + while(mInst.tokens.size() && mInst.tokens[mInst.tokens.size() - 1].type == TokenType::Space) + mInst.tokens.pop_back(); + for(SingleToken & token : mInst.tokens) + token.type = mMnemonicType; } - instruction = _inst; + instruction = mInst; return true; } bool ZydisTokenizer::TokenizeData(const QString & datatype, const QString & data, InstructionToken & instruction) { - _inst = InstructionToken(); - isNop = false; + mInst = InstructionToken(); + mIsNop = false; if(!tokenizeMnemonic(TokenType::MnemonicNormal, datatype)) return false; addToken(TokenType::Value, data); - instruction = _inst; + instruction = mInst; return true; } @@ -218,40 +217,45 @@ void ZydisTokenizer::TokenizeTraceMemory(duint address, duint oldValue, duint ne void ZydisTokenizer::UpdateConfig() { - SetConfig(ConfigBool("Disassembler", "Uppercase"), - ConfigBool("Disassembler", "TabbedMnemonic"), - ConfigBool("Disassembler", "ArgumentSpaces"), - ConfigBool("Disassembler", "HidePointerSizes"), - ConfigBool("Disassembler", "HideNormalSegments"), - ConfigBool("Disassembler", "MemorySpaces"), - ConfigBool("Disassembler", "NoHighlightOperands"), - ConfigBool("Disassembler", "NoCurrentModuleText"), - ConfigBool("Disassembler", "0xPrefixValues")); - _maxModuleLength = (int)ConfigUint("Disassembler", "MaxModuleSize"); + mUppercase = ConfigBool("Disassembler", "Uppercase"); + mTabbedMnemonic = ConfigBool("Disassembler", "TabbedMnemonic"); + mArgumentSpaces = ConfigBool("Disassembler", "ArgumentSpaces"); + mHidePointerSizes = ConfigBool("Disassembler", "HidePointerSizes"); + mHideNormalSegments = ConfigBool("Disassembler", "HideNormalSegments"); + mMemorySpaces = ConfigBool("Disassembler", "MemorySpaces"); + mNoHighlightOperands = ConfigBool("Disassembler", "NoHighlightOperands"); + mNoCurrentModuleText = ConfigBool("Disassembler", "NoCurrentModuleText"); + m0xPrefixValues = ConfigBool("Disassembler", "0xPrefixValues"); + mMaxModuleLength = (int)ConfigUint("Disassembler", "MaxModuleSize"); UpdateStringPool(); } +void ZydisTokenizer::UpdateArchitecture() +{ + mZydis.Reset(mArchitecture->disasm64()); +} + void ZydisTokenizer::SetConfig(bool bUppercase, bool bTabbedMnemonic, bool bArgumentSpaces, bool bHidePointerSizes, bool bHideNormalSegments, bool bMemorySpaces, bool bNoHighlightOperands, bool bNoCurrentModuleText, bool b0xPrefixValues) { - _bUppercase = bUppercase; - _bTabbedMnemonic = bTabbedMnemonic; - _bArgumentSpaces = bArgumentSpaces; - _bHidePointerSizes = bHidePointerSizes; - _bHideNormalSegments = bHideNormalSegments; - _bMemorySpaces = bMemorySpaces; - _bNoHighlightOperands = bNoHighlightOperands; - _bNoCurrentModuleText = bNoCurrentModuleText; - _b0xPrefixValues = b0xPrefixValues; + mUppercase = bUppercase; + mTabbedMnemonic = bTabbedMnemonic; + mArgumentSpaces = bArgumentSpaces; + mHidePointerSizes = bHidePointerSizes; + mHideNormalSegments = bHideNormalSegments; + mMemorySpaces = bMemorySpaces; + mNoHighlightOperands = bNoHighlightOperands; + mNoCurrentModuleText = bNoCurrentModuleText; + m0xPrefixValues = b0xPrefixValues; } int ZydisTokenizer::Size() const { - return _success ? _cp.Size() : 1; + return mSuccess ? mZydis.Size() : 1; } const Zydis & ZydisTokenizer::GetZydis() const { - return _cp; + return mZydis; } void ZydisTokenizer::TokenToRichText(const InstructionToken & instr, RichTextPainter::List & richTextList, const SingleToken* highlightToken) @@ -317,17 +321,18 @@ bool ZydisTokenizer::IsHighlightableToken(const SingleToken & token) case TokenType::MemoryOperator: return false; break; + default: + return true; } - return true; } bool ZydisTokenizer::tokenTextPoolEquals(const QString & a, const QString & b) { if(a.compare(b, Qt::CaseInsensitive) == 0) return true; - auto found1 = stringPoolMap.find(a.toLower()); - auto found2 = stringPoolMap.find(b.toLower()); - if(found1 == stringPoolMap.end() || found2 == stringPoolMap.end()) + auto found1 = gStringPool.find(a.toLower()); + auto found2 = gStringPool.find(b.toLower()); + if(found1 == gStringPool.end() || found2 == gStringPool.end()) return false; return found1.value() == found2.value(); } @@ -358,9 +363,9 @@ void ZydisTokenizer::addToken(TokenType type, QString text, const TokenValue & v text = text.trimmed(); break; } - if(_bUppercase && !value.size) + if(mUppercase && !value.size) text = text.toUpper(); - _inst.tokens.push_back(SingleToken(isNop ? TokenType::MnemonicNop : type, text, value)); + mInst.tokens.push_back(SingleToken(mIsNop ? TokenType::MnemonicNop : type, text, value)); } void ZydisTokenizer::addToken(TokenType type, const QString & text) @@ -370,39 +375,39 @@ void ZydisTokenizer::addToken(TokenType type, const QString & text) void ZydisTokenizer::addMemoryOperator(char operatorText) { - if(_bMemorySpaces) + if(mMemorySpaces) addToken(TokenType::MemoryOperatorSpace, " "); QString text; text += operatorText; addToken(TokenType::MemoryOperator, text); - if(_bMemorySpaces) + if(mMemorySpaces) addToken(TokenType::MemoryOperatorSpace, " "); } -QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule, int maxModuleLength) const +QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule) const { QString labelText; - char label_[MAX_LABEL_SIZE] = ""; - char module_[MAX_MODULE_SIZE] = ""; + char label[MAX_LABEL_SIZE] = ""; + char module[MAX_MODULE_SIZE] = ""; QString moduleText; duint addr = value.value; - bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, label_); - labelText = QString(label_); + bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, label); + labelText = QString(label); bool bHasModule; - if(_bNoCurrentModuleText) + if(mNoCurrentModuleText) { duint size, base; base = DbgMemFindBaseAddr(this->GetZydis().Address(), &size); if(addr >= base && addr < base + size) bHasModule = false; else - bHasModule = (expandModule && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&")); + bHasModule = (expandModule && DbgGetModuleAt(addr, module) && !QString(labelText).startsWith("JMP.&")); } else - bHasModule = (expandModule && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&")); - moduleText = QString(module_); - if(maxModuleLength != -1) - moduleText.truncate(maxModuleLength); + bHasModule = (expandModule && DbgGetModuleAt(addr, module) && !QString(labelText).startsWith("JMP.&")); + moduleText = QString(module); + if(mMaxModuleLength != -1) + moduleText.truncate(mMaxModuleLength); if(moduleText.length()) moduleText += "."; QString addrText = ToHexString(addr); @@ -413,7 +418,7 @@ QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule, finalText = QString("%1%2").arg(moduleText).arg(addrText); else if(bHasLabel) //