mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 19:06:10 +00:00
Decompiler Documentation + Clean up (#2374)
This commit is contained in:
parent
1c86f54c95
commit
b7d1059a1b
@ -17,11 +17,11 @@
|
||||
|
||||
DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWindow)
|
||||
: QMenu(parent),
|
||||
mainWindow(mainWindow),
|
||||
curHighlightedWord(QString()),
|
||||
offset(0),
|
||||
decompiledFunctionAddress(RVA_INVALID),
|
||||
isTogglingBreakpoints(false),
|
||||
mainWindow(mainWindow),
|
||||
annotationHere(nullptr),
|
||||
actionCopy(tr("Copy"), this),
|
||||
actionCopyInstructionAddress(tr("Copy instruction address (<address>)"), this),
|
||||
@ -48,11 +48,11 @@ DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWi
|
||||
setActionAddComment();
|
||||
setActionDeleteComment();
|
||||
|
||||
setActionXRefs();
|
||||
|
||||
setActionRenameThingHere();
|
||||
setActionDeleteName();
|
||||
|
||||
setActionXRefs();
|
||||
|
||||
setActionEditFunctionVariables();
|
||||
|
||||
addSeparator();
|
||||
@ -73,34 +73,37 @@ DecompilerContextMenu::~DecompilerContextMenu()
|
||||
|
||||
void DecompilerContextMenu::setAnnotationHere(RCodeAnnotation *annotation)
|
||||
{
|
||||
this->annotationHere = annotation;
|
||||
annotationHere = annotation;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setCurHighlightedWord(QString word)
|
||||
{
|
||||
this->curHighlightedWord = word;
|
||||
curHighlightedWord = word;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setOffset(RVA offset)
|
||||
void DecompilerContextMenu::setOffset(RVA newOffset)
|
||||
{
|
||||
this->offset = offset;
|
||||
|
||||
// this->actionSetFunctionVarTypes.setVisible(true);
|
||||
offset = newOffset;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setDecompiledFunctionAddress(RVA functionAddr)
|
||||
{
|
||||
this->decompiledFunctionAddress = functionAddr;
|
||||
decompiledFunctionAddress = functionAddr;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setFirstOffsetInLine(RVA firstOffset)
|
||||
{
|
||||
this->firstOffsetInLine = firstOffset;
|
||||
firstOffsetInLine = firstOffset;
|
||||
}
|
||||
|
||||
RVA DecompilerContextMenu::getFirstOffsetInLine()
|
||||
{
|
||||
return firstOffsetInLine;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setAvailableBreakpoints(QVector<RVA> offsetList)
|
||||
{
|
||||
this->availableBreakpoints = offsetList;
|
||||
availableBreakpoints = offsetList;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setupBreakpointsInLineMenu()
|
||||
@ -130,12 +133,12 @@ void DecompilerContextMenu::setShortcutContextInActions(QMenu *menu)
|
||||
|
||||
void DecompilerContextMenu::setIsTogglingBreakpoints(bool isToggling)
|
||||
{
|
||||
this->isTogglingBreakpoints = isToggling;
|
||||
isTogglingBreakpoints = isToggling;
|
||||
}
|
||||
|
||||
bool DecompilerContextMenu::getIsTogglingBreakpoints()
|
||||
{
|
||||
return this->isTogglingBreakpoints;
|
||||
return isTogglingBreakpoints;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::aboutToHideSlot()
|
||||
@ -169,7 +172,6 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
actionDeleteComment.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
setupBreakpointsInLineMenu();
|
||||
|
||||
// Only show debug options if we are currently debugging
|
||||
@ -184,7 +186,6 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
} else {
|
||||
actionToggleBreakpoint.setText(tr("Remove all breakpoints in line"));
|
||||
}
|
||||
|
||||
if (numberOfBreakpoints > 1) {
|
||||
actionAdvancedBreakpoint.setMenu(breakpointsInLineMenu);
|
||||
} else {
|
||||
@ -198,7 +199,7 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
|
||||
if (!annotationHere
|
||||
|| annotationHere->type ==
|
||||
R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) { // To be considered as invalid
|
||||
R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) { // If constant, don't show rename and targeted show-in
|
||||
actionRenameThingHere.setVisible(false);
|
||||
copySeparator->setVisible(false);
|
||||
} else {
|
||||
@ -219,7 +220,7 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
}
|
||||
actionCopyInstructionAddress.setText(tr("Copy instruction address (%1)").arg(RAddressString(
|
||||
offset)));
|
||||
if (annotationHere && r_annotation_is_reference(annotationHere)) {
|
||||
if (isReference()) {
|
||||
actionCopyReferenceAddress.setVisible(true);
|
||||
RVA referenceAddr = annotationHere->reference.offset;
|
||||
RFlagItem *flagDetails = r_flag_get_i(Core()->core()->flags, referenceAddr);
|
||||
@ -258,7 +259,6 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
|
||||
// Set up actions
|
||||
|
||||
|
||||
void DecompilerContextMenu::setActionCopy() // Set all three copy actions
|
||||
{
|
||||
connect(&actionCopy, &QAction::triggered, this, &DecompilerContextMenu::actionCopyTriggered);
|
||||
@ -386,7 +386,7 @@ void DecompilerContextMenu::actionDeleteCommentTriggered()
|
||||
|
||||
void DecompilerContextMenu::actionRenameThingHereTriggered()
|
||||
{
|
||||
if (!annotationHere) {
|
||||
if (!annotationHere || annotationHere->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) {
|
||||
return;
|
||||
}
|
||||
RCoreLocked core = Core()->core();
|
||||
@ -410,7 +410,6 @@ void DecompilerContextMenu::actionRenameThingHereTriggered()
|
||||
Core()->renameFunction(func_addr, newName);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE) {
|
||||
RVA var_addr = annotationHere->reference.offset;
|
||||
RFlagItem *flagDetails = r_flag_get_i(core->flags, var_addr);
|
||||
@ -467,7 +466,7 @@ void DecompilerContextMenu::actionEditFunctionVariablesTriggered()
|
||||
|
||||
void DecompilerContextMenu::actionXRefsTriggered()
|
||||
{
|
||||
if (!annotationHere || !r_annotation_is_reference(annotationHere)) {
|
||||
if (!isReference()) {
|
||||
return;
|
||||
}
|
||||
XrefsDialog dialog(mainWindow, nullptr);
|
||||
@ -551,9 +550,7 @@ void DecompilerContextMenu::updateTargetMenuActions()
|
||||
}
|
||||
showTargetMenuActions.clear();
|
||||
RCoreLocked core = Core()->core();
|
||||
if (annotationHere && (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE
|
||||
|| annotationHere->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME)) {
|
||||
if (isReference()) {
|
||||
QString name;
|
||||
QMenu *menu;
|
||||
if (annotationHere->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||
@ -580,6 +577,11 @@ void DecompilerContextMenu::updateTargetMenuActions()
|
||||
}
|
||||
}
|
||||
|
||||
bool DecompilerContextMenu::isReference()
|
||||
{
|
||||
return (annotationHere && r_annotation_is_reference(annotationHere));
|
||||
}
|
||||
|
||||
bool DecompilerContextMenu::isFunctionVariable()
|
||||
{
|
||||
return (annotationHere && r_annotation_is_variable(annotationHere));
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <r_util/r_annotated_code.h>
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class DecompilerContextMenu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -17,18 +19,18 @@ public:
|
||||
|
||||
bool getIsTogglingBreakpoints();
|
||||
void setAnnotationHere(RCodeAnnotation *annotation);
|
||||
RVA getFirstOffsetInLine();
|
||||
|
||||
signals:
|
||||
void copy();
|
||||
|
||||
public slots:
|
||||
void setCurHighlightedWord(QString word);
|
||||
void setOffset(RVA offset);
|
||||
void setOffset(RVA newOffset);
|
||||
void setDecompiledFunctionAddress(RVA functionAddr);
|
||||
void setFirstOffsetInLine(RVA firstOffset);
|
||||
void setAvailableBreakpoints(QVector<RVA> offsetList);
|
||||
|
||||
|
||||
private slots:
|
||||
void aboutToShowSlot();
|
||||
void aboutToHideSlot();
|
||||
@ -55,16 +57,30 @@ private slots:
|
||||
|
||||
private:
|
||||
// Private variables
|
||||
MainWindow *mainWindow;
|
||||
QString curHighlightedWord;
|
||||
RVA offset;
|
||||
RVA decompiledFunctionAddress;
|
||||
/**
|
||||
* Lowest offset among all offsets present in the line under cursor in the decompiler widget.
|
||||
*/
|
||||
RVA firstOffsetInLine;
|
||||
/**
|
||||
* When the actionToggleBreakpoint has been triggered, and it hasn't finished executing,
|
||||
* the value of this variable will be true, otherwise false
|
||||
*/
|
||||
bool isTogglingBreakpoints;
|
||||
/**
|
||||
* List of the offsets of all the breakpoints (enabled and disabled) that are present in the line under cursor.
|
||||
*/
|
||||
QVector<RVA> availableBreakpoints;
|
||||
MainWindow *mainWindow;
|
||||
|
||||
/**
|
||||
* Context-related annotation for the data under cursor in the decompiler widget.
|
||||
* If such an annotation doesn't exist, its value is nullptr.
|
||||
*/
|
||||
RCodeAnnotation *annotationHere;
|
||||
|
||||
// Actions and menus in the context menu
|
||||
QAction actionCopy;
|
||||
QAction actionCopyInstructionAddress;
|
||||
QAction actionCopyReferenceAddress;
|
||||
@ -94,6 +110,12 @@ private:
|
||||
QAction actionSetPC;
|
||||
|
||||
// Private Functions
|
||||
/**
|
||||
* @brief Sets the shortcut context in all the actions contained
|
||||
* in the specified QMenu to Qt::WidgetWithChildrenShortcut.
|
||||
*
|
||||
* @param menu - QMenu specified
|
||||
*/
|
||||
void setShortcutContextInActions(QMenu *menu);
|
||||
void setupBreakpointsInLineMenu();
|
||||
void setIsTogglingBreakpoints(bool isToggling);
|
||||
@ -123,9 +145,35 @@ private:
|
||||
void addBreakpointMenu();
|
||||
void addDebugMenu();
|
||||
|
||||
/**
|
||||
* @brief Updates targeted "Show in" menu.
|
||||
*
|
||||
* Removes all actions from the existing targeted "show in" menu. If annotationHere
|
||||
* represents an item that has an address assigned to it, insert actions compatible with the
|
||||
* type of this item in the targeted "Show in" menu.
|
||||
*/
|
||||
void updateTargetMenuActions();
|
||||
|
||||
/**
|
||||
* @brief Check if annotationHere is a reference (function name,
|
||||
* global variable, constant variable with an address).
|
||||
*
|
||||
* @return True if annotationHere is a reference, otherwise false.
|
||||
*/
|
||||
bool isReference();
|
||||
/**
|
||||
* @brief Check if annotationHere is a function variable
|
||||
* (local variable or function parameter).
|
||||
*
|
||||
* @return True if annotationHere is a function variable, otherwise false.
|
||||
*/
|
||||
bool isFunctionVariable();
|
||||
/**
|
||||
* @brief Check if the function variable annotated by annotationHere is
|
||||
* present in radare2.
|
||||
*
|
||||
* @return True if the variable is present, otherwise false
|
||||
*/
|
||||
bool variablePresentInR2();
|
||||
};
|
||||
|
||||
|
@ -31,10 +31,8 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
||||
&r_annotated_code_free)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
syntaxHighlighter = Config()->createSyntaxHighlighter(ui->textEdit->document());
|
||||
|
||||
// Event filter to intercept double clicks in the textbox
|
||||
// Event filter to intercept double click and right click in the textbox
|
||||
ui->textEdit->viewport()->installEventFilter(this);
|
||||
|
||||
setupFonts();
|
||||
@ -48,11 +46,9 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
||||
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
|
||||
doRefresh();
|
||||
});
|
||||
|
||||
refreshDeferrer = createRefreshDeferrer([this]() {
|
||||
doRefresh();
|
||||
});
|
||||
|
||||
autoRefreshEnabled = Config()->getDecompilerAutoRefreshEnabled();
|
||||
ui->autoRefreshCheckBox->setChecked(autoRefreshEnabled);
|
||||
setAutoRefresh(autoRefreshEnabled);
|
||||
@ -75,10 +71,8 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
||||
}
|
||||
connect(dec, &Decompiler::finished, this, &DecompilerWidget::decompilationFinished);
|
||||
}
|
||||
|
||||
decompilerSelectionEnabled = decompilers.size() > 1;
|
||||
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
||||
|
||||
if (decompilers.isEmpty()) {
|
||||
ui->textEdit->setPlainText(tr("No Decompiler available."));
|
||||
}
|
||||
@ -90,7 +84,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
||||
connect(Core(), &CutterCore::seekChanged, this, &DecompilerWidget::seekChanged);
|
||||
ui->textEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->textEdit, &QWidget::customContextMenuRequested,
|
||||
this, &DecompilerWidget::showDisasContextMenu);
|
||||
this, &DecompilerWidget::showDecompilerContextMenu);
|
||||
|
||||
connect(Core(), &CutterCore::breakpointsChanged, this, &DecompilerWidget::updateBreakpoints);
|
||||
addActions(mCtxMenu->actions());
|
||||
@ -147,13 +141,13 @@ void DecompilerWidget::updateRefreshButton()
|
||||
}
|
||||
}
|
||||
|
||||
static ut64 offsetForPosition(RAnnotatedCode &codeDecompiled, size_t pos)
|
||||
ut64 DecompilerWidget::offsetForPosition(size_t pos)
|
||||
{
|
||||
size_t closestPos = SIZE_MAX;
|
||||
ut64 closestOffset = UT64_MAX;
|
||||
void *annotationi;
|
||||
r_vector_foreach(&codeDecompiled.annotations, annotationi) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)annotationi;
|
||||
ut64 closestOffset = mCtxMenu->getFirstOffsetInLine();
|
||||
void *iter;
|
||||
r_vector_foreach(&code->annotations, iter) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)iter;
|
||||
if (annotation->type != R_CODE_ANNOTATION_TYPE_OFFSET || annotation->start > pos
|
||||
|| annotation->end <= pos) {
|
||||
continue;
|
||||
@ -167,13 +161,13 @@ static ut64 offsetForPosition(RAnnotatedCode &codeDecompiled, size_t pos)
|
||||
return closestOffset;
|
||||
}
|
||||
|
||||
static size_t positionForOffset(RAnnotatedCode &codeDecompiled, ut64 offset)
|
||||
size_t DecompilerWidget::positionForOffset(ut64 offset)
|
||||
{
|
||||
size_t closestPos = SIZE_MAX;
|
||||
ut64 closestOffset = UT64_MAX;
|
||||
void *annotationi;
|
||||
r_vector_foreach(&codeDecompiled.annotations, annotationi) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)annotationi;
|
||||
void *iter;
|
||||
r_vector_foreach(&code->annotations, iter) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)iter;
|
||||
if (annotation->type != R_CODE_ANNOTATION_TYPE_OFFSET || annotation->offset.offset > offset) {
|
||||
continue;
|
||||
}
|
||||
@ -216,13 +210,13 @@ void DecompilerWidget::gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size
|
||||
size_t endPos)
|
||||
{
|
||||
RVA firstOffset = RVA_MAX;
|
||||
void *annotationi;
|
||||
r_vector_foreach(&codeDecompiled.annotations, annotationi) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)annotationi;
|
||||
void *iter;
|
||||
r_vector_foreach(&codeDecompiled.annotations, iter) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)iter;
|
||||
if (annotation->type != R_CODE_ANNOTATION_TYPE_OFFSET) {
|
||||
continue;
|
||||
}
|
||||
if ((startPos <= annotation->start && annotation->start < endPos) || (startPos <= annotation->end
|
||||
if ((startPos <= annotation->start && annotation->start < endPos) || (startPos < annotation->end
|
||||
&& annotation->end < endPos)) {
|
||||
firstOffset = (annotation->offset.offset < firstOffset) ? annotation->offset.offset : firstOffset;
|
||||
}
|
||||
@ -231,7 +225,7 @@ void DecompilerWidget::gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size
|
||||
QList<RVA> functionBreakpoints = Core()->getBreakpointsInFunction(decompiledFunctionAddr);
|
||||
QVector<RVA> offsetList;
|
||||
for (auto bpOffset : functionBreakpoints) {
|
||||
size_t pos = positionForOffset(*code, bpOffset);
|
||||
size_t pos = positionForOffset(bpOffset);
|
||||
if (startPos <= pos && pos <= endPos) {
|
||||
offsetList.push_back(bpOffset);
|
||||
}
|
||||
@ -245,26 +239,21 @@ void DecompilerWidget::doRefresh(RVA addr)
|
||||
if (!refreshDeferrer->attemptRefresh(nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ui->decompilerComboBox->currentIndex() < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Decompiler *dec = getCurrentDecompiler();
|
||||
if (!dec) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dec->isRunning()) {
|
||||
decompilerWasBusy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr == RVA_INVALID) {
|
||||
ui->textEdit->setPlainText(tr("Click Refresh to generate Decompiler from current offset."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all selections since we just refreshed
|
||||
ui->textEdit->setExtraSelections({});
|
||||
previousFunctionAddr = decompiledFunctionAddr;
|
||||
@ -287,11 +276,10 @@ void DecompilerWidget::refreshDecompiler()
|
||||
|
||||
QTextCursor DecompilerWidget::getCursorForAddress(RVA addr)
|
||||
{
|
||||
size_t pos = positionForOffset(*code, addr);
|
||||
size_t pos = positionForOffset(addr);
|
||||
if (pos == SIZE_MAX || pos == 0) {
|
||||
return QTextCursor();
|
||||
}
|
||||
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
cursor.setPosition(pos);
|
||||
return cursor;
|
||||
@ -339,9 +327,9 @@ void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled)
|
||||
void DecompilerWidget::setAnnotationsAtCursor(size_t pos)
|
||||
{
|
||||
RCodeAnnotation *annotationAtPos = nullptr;
|
||||
void *annotationi;
|
||||
r_vector_foreach(&this->code->annotations, annotationi) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)annotationi;
|
||||
void *iter;
|
||||
r_vector_foreach(&this->code->annotations, iter) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)iter;
|
||||
if (annotation->type == R_CODE_ANNOTATION_TYPE_OFFSET ||
|
||||
annotation->type == R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT ||
|
||||
annotation->start > pos || annotation->end <= pos) {
|
||||
@ -381,10 +369,9 @@ void DecompilerWidget::cursorPositionChanged()
|
||||
|
||||
size_t pos = ui->textEdit->textCursor().position();
|
||||
setAnnotationsAtCursor(pos);
|
||||
|
||||
setInfoForBreakpoints();
|
||||
|
||||
RVA offset = offsetForPosition(*code, pos);
|
||||
RVA offset = offsetForPosition(pos);
|
||||
if (offset != RVA_INVALID && offset != Core()->getOffset()) {
|
||||
seekFromCursor = true;
|
||||
Core()->seek(offset);
|
||||
@ -399,7 +386,6 @@ void DecompilerWidget::seekChanged()
|
||||
if (seekFromCursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoRefreshEnabled) {
|
||||
auto fcnAddr = Core()->getFunctionStart(Core()->getOffset());
|
||||
if (fcnAddr == RVA_INVALID || fcnAddr != decompiledFunctionAddr) {
|
||||
@ -407,14 +393,13 @@ void DecompilerWidget::seekChanged()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateCursorPosition();
|
||||
}
|
||||
|
||||
void DecompilerWidget::updateCursorPosition()
|
||||
{
|
||||
RVA offset = Core()->getOffset();
|
||||
size_t pos = positionForOffset(*code, offset);
|
||||
size_t pos = positionForOffset(offset);
|
||||
if (pos == SIZE_MAX) {
|
||||
return;
|
||||
}
|
||||
@ -465,7 +450,7 @@ void DecompilerWidget::colorsUpdatedSlot()
|
||||
{
|
||||
}
|
||||
|
||||
void DecompilerWidget::showDisasContextMenu(const QPoint &pt)
|
||||
void DecompilerWidget::showDecompilerContextMenu(const QPoint &pt)
|
||||
{
|
||||
mCtxMenu->exec(ui->textEdit->mapToGlobal(pt));
|
||||
}
|
||||
@ -473,7 +458,7 @@ void DecompilerWidget::showDisasContextMenu(const QPoint &pt)
|
||||
void DecompilerWidget::seekToReference()
|
||||
{
|
||||
size_t pos = ui->textEdit->textCursor().position();
|
||||
RVA offset = offsetForPosition(*code, pos);
|
||||
RVA offset = offsetForPosition(pos);
|
||||
seekable->seekToReference(offset);
|
||||
}
|
||||
|
||||
@ -520,7 +505,6 @@ void DecompilerWidget::highlightBreakpoints()
|
||||
if (bp == RVA_INVALID) {
|
||||
continue;;
|
||||
}
|
||||
|
||||
cursor = getCursorForAddress(bp);
|
||||
if (!cursor.isNull()) {
|
||||
// Use a Block formatting since these lines are not updated frequently as selections and PC
|
||||
|
@ -28,16 +28,30 @@ public:
|
||||
explicit DecompilerWidget(MainWindow *main);
|
||||
~DecompilerWidget();
|
||||
public slots:
|
||||
void showDisasContextMenu(const QPoint &pt);
|
||||
void showDecompilerContextMenu(const QPoint &pt);
|
||||
|
||||
void highlightPC();
|
||||
private slots:
|
||||
/**
|
||||
* @brief Copy to clipboard what's needed depending on the state of text widget.
|
||||
*
|
||||
* @note If something is selected in the text widget, copy selection.
|
||||
* If something is highlighted, copy highlighted word.
|
||||
* Otherwise, copy the line under cursor.
|
||||
*/
|
||||
void copy();
|
||||
void fontsUpdatedSlot();
|
||||
void colorsUpdatedSlot();
|
||||
void refreshDecompiler();
|
||||
void decompilerSelected();
|
||||
void cursorPositionChanged();
|
||||
/**
|
||||
* @brief When the synced seek is changed, this refreshes the decompiler widget if needed.
|
||||
*
|
||||
* Decompiler widget is not refreshed in the following two cases
|
||||
* - Seek changed to an offset contained in the decompiled function.
|
||||
* - Auto-refresh is disabled.
|
||||
*/
|
||||
void seekChanged();
|
||||
void decompilationFinished(RAnnotatedCode *code);
|
||||
|
||||
@ -51,7 +65,7 @@ private:
|
||||
bool autoRefreshEnabled;
|
||||
|
||||
/**
|
||||
* True if doRefresh() was called, but the decompiler was still running
|
||||
* True if doRefresh() was called, but the decompiler was still running.
|
||||
* This means, after the decompiler has finished, it should be refreshed immediately.
|
||||
*/
|
||||
bool decompilerWasBusy;
|
||||
@ -65,16 +79,71 @@ private:
|
||||
|
||||
Decompiler *getCurrentDecompiler();
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable auto refresh as per the specified boolean value
|
||||
*
|
||||
* @param enabled
|
||||
*/
|
||||
void setAutoRefresh(bool enabled);
|
||||
/**
|
||||
* @brief Calls the function doRefresh() if auto-refresh is enabled.
|
||||
*/
|
||||
void doAutoRefresh();
|
||||
/**
|
||||
* @brief Refreshes the decompiler.
|
||||
*
|
||||
* - This does the following if the specified offset is valid
|
||||
* - Decompile function that contains the specified offset.
|
||||
* - Clears all selections stored for highlighting purposes.
|
||||
* - Reset previousFunctionAddr with the current function's address
|
||||
* and decompiledFunctionAddr with the address of the function that
|
||||
* was decompiled.
|
||||
* - If the offset is invalid, error message is shown in the text widget.
|
||||
*
|
||||
* @param addr Specified offset/offset in sync.
|
||||
*/
|
||||
void doRefresh(RVA addr = Core()->getOffset());
|
||||
void updateRefreshButton();
|
||||
/**
|
||||
* @brief Update fonts
|
||||
*/
|
||||
void setupFonts();
|
||||
/**
|
||||
* @brief Update highlights in the text widget.
|
||||
*
|
||||
* These include respective highlights for:
|
||||
* - Line under cursor
|
||||
* - Word under cursor
|
||||
* - Program Counter(PC) while debugging
|
||||
*/
|
||||
void updateSelection();
|
||||
/**
|
||||
* @brief Connect/Disconnect SIGNAL-SLOT connection that deals with changes in cursor position.
|
||||
*
|
||||
* If the argument is true, then disconnect the SIGNAL-SLOT connection
|
||||
* that changes the view as cursor position gets changed in the text widget.
|
||||
* Otherwise, connect the corresponding signal with slot.
|
||||
*
|
||||
* @param disconnect
|
||||
*/
|
||||
void connectCursorPositionChanged(bool disconnect);
|
||||
/**
|
||||
* @brief Find the current global offset in sync and update cursor
|
||||
* to the position specified by this offset (found using positionForOffset() )
|
||||
*/
|
||||
void updateCursorPosition();
|
||||
|
||||
QString getWindowTitle() const override;
|
||||
|
||||
/**
|
||||
* @brief Event filter that intercept the following events:
|
||||
* 1. Double click
|
||||
* 2. Right click
|
||||
*
|
||||
* @param obj
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
/**
|
||||
@ -104,21 +173,49 @@ private:
|
||||
void highlightBreakpoints();
|
||||
/**
|
||||
* @brief Finds the earliest offset and breakpoints within the specified range [startPos, endPos]
|
||||
* in the specified RAnnotatedCode
|
||||
* in the specified RAnnotatedCode.
|
||||
*
|
||||
* This function is supposed to be used for finding the earliest offset and breakpoints within the specified range
|
||||
* [startPos, endPos]. This will set the value of the variables 'RVA firstOffsetInLine' and 'QVector<RVA> availableBreakpoints' in
|
||||
* this->mCtxMenu.
|
||||
* the context menu.
|
||||
*
|
||||
* @param codeDecompiled - A reference to the RAnnotatedCode for the function that is decompiled.
|
||||
* @param startPos - Position of the start of the range(inclusive).
|
||||
* @param endPos - Position of the end of the range(inclusive).
|
||||
*/
|
||||
void gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size_t startPos, size_t endPos);
|
||||
|
||||
/**
|
||||
* @brief Finds the offset that's closest to the specified position in the decompiled code.
|
||||
*
|
||||
* @note If no annotations that covers the specified position is found, the first offset in the line
|
||||
* containing specified position will be returned
|
||||
*
|
||||
* @param pos - Position of the decompiled code.
|
||||
* @return Offset for the specified position/first offset in line.
|
||||
*/
|
||||
ut64 offsetForPosition(size_t pos);
|
||||
/**
|
||||
* @brief Find the start position of the annotation with the offset that's closest to
|
||||
* the specified offset
|
||||
*
|
||||
* @param offset
|
||||
* @return Position found or SIZE_MAX
|
||||
*/
|
||||
size_t positionForOffset(ut64 offset);
|
||||
/**
|
||||
* @brief Updates the view when breakpoints are changed
|
||||
*/
|
||||
void updateBreakpoints();
|
||||
/**
|
||||
* @brief Set information about the breakpoints on the line in the context menu
|
||||
*/
|
||||
void setInfoForBreakpoints();
|
||||
|
||||
/**
|
||||
* @brief Find the context-related annotation covering the specified position.
|
||||
* If found, set the variable annotationHere in the decompiler context menu.
|
||||
*
|
||||
* @param pos Position of cursor in the decompiled code.
|
||||
*/
|
||||
void setAnnotationsAtCursor(size_t pos);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user