mirror of
https://github.com/rizinorg/cutter
synced 2026-08-11 16:23:06 -04:00
Switch to widget on seek change (#3597)
* Seek to other widgets if the address type matches * Open the correct widget on undo or redo actions * Don't seek to the last on Unknown * Only switch to other widgets from Graph * Create getSectionAddressAt(RVA addr) * Remove on_core_seekChanged * Use virtual address in rz_bin_get_section_at * Move address == RVA_INVALID check to the correct place
This commit is contained in:
parent
1de599c11b
commit
a9e2a7909c
6 changed files with 122 additions and 7 deletions
|
|
@ -75,14 +75,14 @@ void CutterSeekable::seekToReference(RVA offset)
|
|||
// Try first call
|
||||
for (auto &ref : refs) {
|
||||
if (ref.to != RVA_INVALID && ref.type == "CALL") {
|
||||
seek(ref.to);
|
||||
Core()->seekAndShow(ref.to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Fallback to first valid, if any
|
||||
for (auto &ref : refs) {
|
||||
if (ref.to != RVA_INVALID) {
|
||||
seek(ref.to);
|
||||
Core()->seekAndShow(ref.to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1009,13 +1009,13 @@ void CutterCore::showMemoryWidget()
|
|||
void CutterCore::seekAndShow(ut64 offset)
|
||||
{
|
||||
seek(offset);
|
||||
showMemoryWidget();
|
||||
emit showAddressRequested(offset);
|
||||
}
|
||||
|
||||
void CutterCore::seekAndShow(QString offset)
|
||||
{
|
||||
seek(offset);
|
||||
showMemoryWidget();
|
||||
emit showAddressRequested(math(offset));
|
||||
}
|
||||
|
||||
void CutterCore::seek(QString thing)
|
||||
|
|
@ -1150,6 +1150,30 @@ void CutterCore::setConfig(const char *k, const QString &v)
|
|||
rz_config_set(core->config, k, v.toUtf8().constData());
|
||||
}
|
||||
|
||||
AddressTypeHint CutterCore::getAddressType(RVA addr)
|
||||
{
|
||||
CORE_LOCK();
|
||||
|
||||
if (functionIn(addr)) {
|
||||
return AddressTypeHint::Function;
|
||||
}
|
||||
|
||||
auto section = getSectionAtAddress(addr);
|
||||
if (section.name.isEmpty()) {
|
||||
return AddressTypeHint::Unknown;
|
||||
}
|
||||
|
||||
if (section.perm.contains('x', Qt::CaseInsensitive)) {
|
||||
return AddressTypeHint::Code;
|
||||
}
|
||||
if (section.perm.contains('r', Qt::CaseInsensitive)
|
||||
|| section.perm.contains('w', Qt::CaseInsensitive)) {
|
||||
return AddressTypeHint::Data;
|
||||
}
|
||||
|
||||
return AddressTypeHint::Unknown;
|
||||
}
|
||||
|
||||
void CutterCore::setConfig(const char *k, int v)
|
||||
{
|
||||
CORE_LOCK();
|
||||
|
|
@ -3507,6 +3531,42 @@ QList<FlagDescription> CutterCore::getAllFlags(QString flagspace)
|
|||
return flags;
|
||||
}
|
||||
|
||||
SectionDescription CutterCore::getSectionAtAddress(RVA addr)
|
||||
{
|
||||
CORE_LOCK();
|
||||
RzBinObject *o = rz_bin_cur_object(core->bin);
|
||||
if (!o) {
|
||||
return {};
|
||||
}
|
||||
RzBinSection *section = rz_bin_get_section_at(o, addr, true);
|
||||
if (!section) {
|
||||
return {};
|
||||
}
|
||||
RzList *hashnames = rz_list_newf(free);
|
||||
if (!hashnames) {
|
||||
return {};
|
||||
}
|
||||
SectionDescription desc;
|
||||
desc.vaddr = section->vaddr;
|
||||
desc.paddr = section->paddr;
|
||||
desc.size = section->size;
|
||||
desc.name = section->name;
|
||||
desc.vsize = section->vsize;
|
||||
desc.perm = rz_str_rwx_i(section->perm);
|
||||
if (desc.size > 0) {
|
||||
HtSS *digests = rz_core_bin_create_digests(core, desc.paddr, desc.size, hashnames);
|
||||
if (!digests) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const char *entropy = (const char *)ht_ss_find(digests, "entropy", NULL);
|
||||
desc.entropy = rz_str_get(entropy);
|
||||
ht_ss_free(digests);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
QList<SectionDescription> CutterCore::getAllSections()
|
||||
{
|
||||
CORE_LOCK();
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ enum class SearchKind {
|
|||
MagicSignature,
|
||||
};
|
||||
|
||||
enum class AddressTypeHint { Function, Code, Data, Unknown };
|
||||
|
||||
class CUTTER_EXPORT CutterCore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -236,6 +238,7 @@ public:
|
|||
RVA getFunctionEnd(RVA addr);
|
||||
RVA getLastFunctionInstruction(RVA addr);
|
||||
QString flagAt(RVA addr, bool getClosestFlag = true);
|
||||
AddressTypeHint getAddressType(RVA addr);
|
||||
void createFunctionAt(RVA addr);
|
||||
void createFunctionAt(RVA addr, QString name);
|
||||
QStringList getDisassemblyPreview(RVA address, int num_of_lines);
|
||||
|
|
@ -559,6 +562,12 @@ public:
|
|||
bool isBreakpoint(const QList<RVA> &breakpoints, RVA addr);
|
||||
QList<RVA> getBreakpointsAddresses();
|
||||
|
||||
/**
|
||||
* @brief Get the section at the given address
|
||||
* @param addr Address to get the section for
|
||||
* @return SectionDescription of the section at the given address
|
||||
*/
|
||||
SectionDescription getSectionAtAddress(RVA addr);
|
||||
/**
|
||||
* @brief Sets the RzRun profile directives by writing them to a file
|
||||
* If a profile path is already set in 'dbg.profile', this method overwrites that file
|
||||
|
|
@ -924,6 +933,7 @@ signals:
|
|||
void newDebugMessage(const QString &msg);
|
||||
|
||||
void showMemoryWidgetRequested();
|
||||
void showAddressRequested(RVA addr);
|
||||
|
||||
/**
|
||||
* @brief emitted when a specific type is requested to be shown in the Types Widget
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ void MainWindow::initUI()
|
|||
|
||||
connect(core, &CutterCore::showMemoryWidgetRequested, this,
|
||||
static_cast<void (MainWindow::*)()>(&MainWindow::showMemoryWidget));
|
||||
connect(core, &CutterCore::showAddressRequested, this, &MainWindow::showAddress);
|
||||
|
||||
connect(core, &CutterCore::showTypeRequested, typesDock, [this](const QString &typeName) {
|
||||
typesDock->toggleDockWidget(true);
|
||||
|
|
@ -1020,6 +1021,28 @@ void MainWindow::showMemoryWidget(MemoryWidgetType type)
|
|||
memoryDockWidget->raiseMemoryWidget();
|
||||
}
|
||||
|
||||
MemoryDockWidget *MainWindow::getOrCreateMemoryWidget(MemoryWidgetType type, RVA address,
|
||||
bool synchronized)
|
||||
{
|
||||
if (address == RVA_INVALID) {
|
||||
address = Core()->getOffset();
|
||||
}
|
||||
|
||||
for (auto &dock : dockWidgets) {
|
||||
if (auto memoryWidget = qobject_cast<MemoryDockWidget *>(dock)) {
|
||||
if (memoryWidget->getType() == type
|
||||
&& memoryWidget->getSeekable()->isSynchronized() == synchronized) {
|
||||
if (address != RVA_INVALID) {
|
||||
memoryWidget->getSeekable()->seek(address);
|
||||
}
|
||||
return memoryWidget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return addNewMemoryWidget(type, address, synchronized);
|
||||
}
|
||||
|
||||
QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address, AddressTypeHint addressType)
|
||||
{
|
||||
QMenu *menu = new QMenu(parent);
|
||||
|
|
@ -1084,6 +1107,26 @@ MemoryDockWidget *MainWindow::getLastMemoryWidget()
|
|||
return lastMemoryWidget;
|
||||
}
|
||||
|
||||
void MainWindow::showAddress(RVA addr)
|
||||
{
|
||||
if (lastMemoryWidget && lastMemoryWidget->getType() == MemoryWidgetType::Graph) {
|
||||
AddressTypeHint addressType = core->getAddressType(addr);
|
||||
|
||||
MemoryWidgetType targetType;
|
||||
if (addressType == AddressTypeHint::Data) {
|
||||
targetType = MemoryWidgetType::Hexdump;
|
||||
} else if (addressType == AddressTypeHint::Function) {
|
||||
targetType = MemoryWidgetType::Graph;
|
||||
} else {
|
||||
targetType = MemoryWidgetType::Disassembly;
|
||||
}
|
||||
|
||||
auto memoryWidget = getOrCreateMemoryWidget(targetType, addr, true);
|
||||
memoryWidget->tryRaiseMemoryWidget();
|
||||
setCurrentMemoryWidget(memoryWidget);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryDockWidget *MainWindow::addNewMemoryWidget(MemoryWidgetType type, RVA address,
|
||||
bool synchronized)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -116,11 +116,12 @@ public:
|
|||
QString getUniqueObjectName(const QString &widgetType) const;
|
||||
void showMemoryWidget();
|
||||
void showMemoryWidget(MemoryWidgetType type);
|
||||
enum class AddressTypeHint { Function, Data, Unknown };
|
||||
QMenu *createShowInMenu(QWidget *parent, RVA address,
|
||||
AddressTypeHint addressType = AddressTypeHint::Unknown);
|
||||
void setCurrentMemoryWidget(MemoryDockWidget *memoryWidget);
|
||||
MemoryDockWidget *getLastMemoryWidget();
|
||||
MemoryDockWidget *getOrCreateMemoryWidget(MemoryWidgetType type, RVA address = RVA_INVALID,
|
||||
bool synchronized = true);
|
||||
|
||||
/* Context menu plugins */
|
||||
enum class ContextMenuType { Disassembly, Addressable };
|
||||
|
|
@ -133,6 +134,7 @@ public:
|
|||
|
||||
public slots:
|
||||
void finalizeOpen();
|
||||
void showAddress(RVA addr);
|
||||
|
||||
void refreshAll();
|
||||
void seekToFunctionLastInstruction();
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ void DecompilerContextMenu::updateTargetMenuActions()
|
|||
if (annotationHere->type == RZ_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE
|
||||
|| annotationHere->type == RZ_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE) {
|
||||
menu = mainWindow->createShowInMenu(this, annotationHere->reference.offset,
|
||||
MainWindow::AddressTypeHint::Data);
|
||||
AddressTypeHint::Data);
|
||||
RVA var_addr = annotationHere->reference.offset;
|
||||
RzFlagItem *flagDetails = rz_flag_get_i(core->flags, var_addr);
|
||||
if (flagDetails) {
|
||||
|
|
@ -585,7 +585,7 @@ void DecompilerContextMenu::updateTargetMenuActions()
|
|||
}
|
||||
} else if (annotationHere->type == RZ_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||
menu = mainWindow->createShowInMenu(this, annotationHere->reference.offset,
|
||||
MainWindow::AddressTypeHint::Function);
|
||||
AddressTypeHint::Function);
|
||||
name = tr("%1 (%2)").arg(QString(annotationHere->reference.name),
|
||||
RzAddressString(annotationHere->reference.offset));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue