mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-24 05:45:27 +00:00
Heap widget wrapup (#2716)
This commit is contained in:
parent
e29585c672
commit
60343fa8b5
2
rizin
2
rizin
@ -1 +1 @@
|
|||||||
Subproject commit 381f22d7cc81bf2eb6663a690a715ff4f8f09373
|
Subproject commit 254c5119e3563d05d02665cabbcba003c921cee8
|
@ -146,6 +146,7 @@ set(SOURCES
|
|||||||
widgets/GlibcHeapWidget.cpp
|
widgets/GlibcHeapWidget.cpp
|
||||||
dialogs/GlibcHeapBinsDialog.cpp
|
dialogs/GlibcHeapBinsDialog.cpp
|
||||||
widgets/HeapBinsGraphView.cpp
|
widgets/HeapBinsGraphView.cpp
|
||||||
|
dialogs/ArenaInfoDialog.cpp
|
||||||
)
|
)
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
core/Cutter.h
|
core/Cutter.h
|
||||||
@ -304,6 +305,7 @@ set(HEADER_FILES
|
|||||||
widgets/GlibcHeapWidget.h
|
widgets/GlibcHeapWidget.h
|
||||||
dialogs/GlibcHeapBinsDialog.h
|
dialogs/GlibcHeapBinsDialog.h
|
||||||
widgets/HeapBinsGraphView.h
|
widgets/HeapBinsGraphView.h
|
||||||
|
dialogs/ArenaInfoDialog.h
|
||||||
)
|
)
|
||||||
set(UI_FILES
|
set(UI_FILES
|
||||||
dialogs/AboutDialog.ui
|
dialogs/AboutDialog.ui
|
||||||
@ -374,6 +376,7 @@ set(UI_FILES
|
|||||||
widgets/HeapDockWidget.ui
|
widgets/HeapDockWidget.ui
|
||||||
widgets/GlibcHeapWidget.ui
|
widgets/GlibcHeapWidget.ui
|
||||||
dialogs/GlibcHeapBinsDialog.ui
|
dialogs/GlibcHeapBinsDialog.ui
|
||||||
|
dialogs/ArenaInfoDialog.ui
|
||||||
)
|
)
|
||||||
set(QRC_FILES
|
set(QRC_FILES
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
@ -1592,6 +1592,12 @@ QVector<Chunk> CutterCore::getHeapChunks(RVA arena_addr)
|
|||||||
return chunks_vector;
|
return chunks_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CutterCore::getArchBits()
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
return core->dbg->bits;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<Arena> CutterCore::getArenas()
|
QVector<Arena> CutterCore::getArenas()
|
||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
@ -1606,6 +1612,12 @@ QVector<Arena> CutterCore::getArenas()
|
|||||||
Arena arena;
|
Arena arena;
|
||||||
arena.offset = data->addr;
|
arena.offset = data->addr;
|
||||||
arena.type = QString(data->type);
|
arena.type = QString(data->type);
|
||||||
|
arena.last_remainder = data->arena->last_remainder;
|
||||||
|
arena.top = data->arena->top;
|
||||||
|
arena.next = data->arena->next;
|
||||||
|
arena.next_free = data->arena->next_free;
|
||||||
|
arena.system_mem = data->arena->system_mem;
|
||||||
|
arena.max_system_mem = data->arena->max_system_mem;
|
||||||
arena_vector.append(arena);
|
arena_vector.append(arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1653,10 +1665,30 @@ QVector<RzHeapBin *> CutterCore::getHeapBins(ut64 arena_addr)
|
|||||||
}
|
}
|
||||||
bins_vector.append(bin);
|
bins_vector.append(bin);
|
||||||
}
|
}
|
||||||
|
// get tcache bins
|
||||||
|
RzList *tcache_bins = rz_heap_tcache_content(core, arena_addr);
|
||||||
|
RzListIter *iter;
|
||||||
|
RzHeapBin *bin;
|
||||||
|
CutterRListForeach(tcache_bins, iter, RzHeapBin, bin)
|
||||||
|
{
|
||||||
|
if (!bin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!rz_list_length(bin->chunks)) {
|
||||||
|
rz_heap_bin_free_64(bin);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bins_vector.append(bin);
|
||||||
|
}
|
||||||
return bins_vector;
|
return bins_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CutterCore::writeHeapChunk(RzHeapChunkSimple *chunk_simple)
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
return rz_heap_write_chunk(core, chunk_simple);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonDocument CutterCore::getChildProcesses(int pid)
|
QJsonDocument CutterCore::getChildProcesses(int pid)
|
||||||
{
|
{
|
||||||
// Return the currently debugged process and it's children
|
// Return the currently debugged process and it's children
|
||||||
|
@ -419,7 +419,20 @@ public:
|
|||||||
* @return RzHeapChunkSimple struct pointer for the heap chunk
|
* @return RzHeapChunkSimple struct pointer for the heap chunk
|
||||||
*/
|
*/
|
||||||
RzHeapChunkSimple *getHeapChunk(ut64 addr);
|
RzHeapChunkSimple *getHeapChunk(ut64 addr);
|
||||||
|
/**
|
||||||
|
* @brief Get heap bins of an arena with given base address
|
||||||
|
* (including large, small, fast, unsorted, tcache)
|
||||||
|
* @param arena_addr Base address of the arena
|
||||||
|
* @return QVector of non empty RzHeapBin pointers
|
||||||
|
*/
|
||||||
QVector<RzHeapBin *> getHeapBins(ut64 arena_addr);
|
QVector<RzHeapBin *> getHeapBins(ut64 arena_addr);
|
||||||
|
/**
|
||||||
|
* @brief Write the given chunk header to memory
|
||||||
|
* @param chunkSimple RzHeapChunkSimple pointer of the chunk to be written
|
||||||
|
* @return true if the write succeeded else false
|
||||||
|
*/
|
||||||
|
bool writeHeapChunk(RzHeapChunkSimple *chunkSimple);
|
||||||
|
int getArchBits();
|
||||||
void startDebug();
|
void startDebug();
|
||||||
void startEmulation();
|
void startEmulation();
|
||||||
/**
|
/**
|
||||||
|
@ -375,6 +375,12 @@ struct Arena
|
|||||||
{
|
{
|
||||||
RVA offset;
|
RVA offset;
|
||||||
QString type;
|
QString type;
|
||||||
|
ut64 top;
|
||||||
|
ut64 last_remainder;
|
||||||
|
ut64 next;
|
||||||
|
ut64 next_free;
|
||||||
|
ut64 system_mem;
|
||||||
|
ut64 max_system_mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
|
25
src/dialogs/ArenaInfoDialog.cpp
Normal file
25
src/dialogs/ArenaInfoDialog.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "ArenaInfoDialog.h"
|
||||||
|
#include "ui_ArenaInfoDialog.h"
|
||||||
|
|
||||||
|
ArenaInfoDialog::ArenaInfoDialog(Arena &arena, QWidget *parent)
|
||||||
|
: arena(arena), QDialog(parent), ui(new Ui::ArenaInfoDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowTitle("Arena @ " + RAddressString(arena.offset));
|
||||||
|
updateContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArenaInfoDialog::updateContents()
|
||||||
|
{
|
||||||
|
ui->lineEditTop->setText(RAddressString(arena.top));
|
||||||
|
ui->lineEditLastRem->setText(RAddressString(arena.last_remainder));
|
||||||
|
ui->lineEditNext->setText(RAddressString(arena.next));
|
||||||
|
ui->lineEditNextfree->setText(RAddressString(arena.next_free));
|
||||||
|
ui->lineEditSysMem->setText(RAddressString(arena.system_mem));
|
||||||
|
ui->lineEditMaxMem->setText(RAddressString(arena.max_system_mem));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArenaInfoDialog::~ArenaInfoDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
25
src/dialogs/ArenaInfoDialog.h
Normal file
25
src/dialogs/ArenaInfoDialog.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef ARENAINFODIALOG_H
|
||||||
|
#define ARENAINFODIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <CutterDescriptions.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ArenaInfoDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArenaInfoDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ArenaInfoDialog(Arena &arena, QWidget *parent = nullptr);
|
||||||
|
~ArenaInfoDialog();
|
||||||
|
void updateContents();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ArenaInfoDialog *ui;
|
||||||
|
Arena arena;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ARENAINFODIALOG_H
|
109
src/dialogs/ArenaInfoDialog.ui
Normal file
109
src/dialogs/ArenaInfoDialog.ui
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ArenaInfoDialog</class>
|
||||||
|
<widget class="QDialog" name="ArenaInfoDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>202</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Top</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Next</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Next free</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>System Memory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max Memory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditTop">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditNext">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditNextfree">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditSysMem">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditMaxMem">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Last Remainder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditLastRem">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -27,7 +27,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPlainTextEdit" name="chainInfoEdit"/>
|
<widget class="QPlainTextEdit" name="chainInfoEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout3">
|
<layout class="QHBoxLayout" name="horizontalLayout3">
|
||||||
|
@ -8,11 +8,6 @@ GlibcHeapInfoDialog::GlibcHeapInfoDialog(RVA offset, QString status, QWidget *pa
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// disable all the radio buttons for flag field so they are not user editable
|
|
||||||
this->ui->rbIM->setEnabled(false);
|
|
||||||
this->ui->rbNMA->setEnabled(false);
|
|
||||||
this->ui->rbPI->setEnabled(false);
|
|
||||||
|
|
||||||
// set window title
|
// set window title
|
||||||
QString windowTitle = tr("Chunk @ ") + RAddressString(offset);
|
QString windowTitle = tr("Chunk @ ") + RAddressString(offset);
|
||||||
if (!this->status.isEmpty()) {
|
if (!this->status.isEmpty()) {
|
||||||
@ -20,6 +15,8 @@ GlibcHeapInfoDialog::GlibcHeapInfoDialog(RVA offset, QString status, QWidget *pa
|
|||||||
}
|
}
|
||||||
this->setWindowTitle(windowTitle);
|
this->setWindowTitle(windowTitle);
|
||||||
|
|
||||||
|
connect(ui->saveButton, &QPushButton::clicked, this, &GlibcHeapInfoDialog::saveChunkInfo);
|
||||||
|
|
||||||
updateFields();
|
updateFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,13 +43,69 @@ void GlibcHeapInfoDialog::updateFields()
|
|||||||
this->ui->prevSizeEdit->setText(RHexString(chunk->prev_size));
|
this->ui->prevSizeEdit->setText(RHexString(chunk->prev_size));
|
||||||
if (chunk->is_mmapped) {
|
if (chunk->is_mmapped) {
|
||||||
this->ui->rbIM->setChecked(true);
|
this->ui->rbIM->setChecked(true);
|
||||||
|
} else {
|
||||||
|
this->ui->rbIM->setChecked(false);
|
||||||
}
|
}
|
||||||
if (chunk->prev_inuse) {
|
if (chunk->prev_inuse) {
|
||||||
this->ui->rbPI->setChecked(true);
|
this->ui->rbPI->setChecked(true);
|
||||||
|
} else {
|
||||||
|
this->ui->rbPI->setChecked(false);
|
||||||
}
|
}
|
||||||
if (chunk->non_main_arena) {
|
if (chunk->non_main_arena) {
|
||||||
this->ui->rbNMA->setChecked(true);
|
this->ui->rbNMA->setChecked(true);
|
||||||
|
} else {
|
||||||
|
this->ui->rbNMA->setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(chunk);
|
free(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlibcHeapInfoDialog::saveChunkInfo()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("Do you want to overwrite chunk metadata?");
|
||||||
|
msgBox.setInformativeText(
|
||||||
|
"Any field which cannot be converted to a valid integer will be saved as zero");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Save);
|
||||||
|
|
||||||
|
int ret = msgBox.exec();
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Save:
|
||||||
|
// Save was clicked
|
||||||
|
RzHeapChunkSimple chunkSimple;
|
||||||
|
chunkSimple.size = Core()->math(ui->sizeEdit->text());
|
||||||
|
chunkSimple.fd = Core()->math(ui->fdEdit->text());
|
||||||
|
chunkSimple.bk = Core()->math(ui->bkEdit->text());
|
||||||
|
chunkSimple.fd_nextsize = Core()->math(ui->fdnsEdit->text());
|
||||||
|
chunkSimple.bk_nextsize = Core()->math(ui->bknsEdit->text());
|
||||||
|
chunkSimple.addr = offset;
|
||||||
|
if (ui->rbIM->isChecked()) {
|
||||||
|
chunkSimple.is_mmapped = true;
|
||||||
|
} else {
|
||||||
|
chunkSimple.is_mmapped = false;
|
||||||
|
}
|
||||||
|
if (ui->rbNMA->isChecked()) {
|
||||||
|
chunkSimple.non_main_arena = true;
|
||||||
|
} else {
|
||||||
|
chunkSimple.non_main_arena = false;
|
||||||
|
}
|
||||||
|
if (ui->rbPI->isChecked()) {
|
||||||
|
chunkSimple.prev_inuse = true;
|
||||||
|
} else {
|
||||||
|
chunkSimple.prev_inuse = false;
|
||||||
|
}
|
||||||
|
if (Core()->writeHeapChunk(&chunkSimple)) {
|
||||||
|
updateFields();
|
||||||
|
QMessageBox::information(this, tr("Chunk saved"),
|
||||||
|
tr("Chunk header successfully overwritten"));
|
||||||
|
} else {
|
||||||
|
QMessageBox::information(this, tr("Chunk not saved"),
|
||||||
|
tr("Chunk header not successfully overwritten"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
// Cancel was clicked
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,9 @@ public:
|
|||||||
explicit GlibcHeapInfoDialog(RVA offset, QString status, QWidget *parent = nullptr);
|
explicit GlibcHeapInfoDialog(RVA offset, QString status, QWidget *parent = nullptr);
|
||||||
~GlibcHeapInfoDialog();
|
~GlibcHeapInfoDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void saveChunkInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::GlibcHeapInfoDialog *ui;
|
Ui::GlibcHeapInfoDialog *ui;
|
||||||
void updateFields();
|
void updateFields();
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<string>Size of the heap chunk including metadata</string>
|
<string>Size of the heap chunk including metadata</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<string>Link to next free chunk in bin's linked list</string>
|
<string>Link to next free chunk in bin's linked list</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -80,7 +80,7 @@
|
|||||||
<string>Link to previous free chunk in bin's linked list</string>
|
<string>Link to previous free chunk in bin's linked list</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
<string>Link to next larger free chunk (only for large chunks)</string>
|
<string>Link to next larger free chunk (only for large chunks)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -114,7 +114,7 @@
|
|||||||
<string>Link to next smaller free chunk (for large chunks)</string>
|
<string>Link to next smaller free chunk (for large chunks)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
<string>Size of previous chunk (if free)</string>
|
<string>Size of previous chunk (if free)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -189,6 +189,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="saveButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <dialogs/GlibcHeapBinsDialog.h>
|
#include <dialogs/GlibcHeapBinsDialog.h>
|
||||||
|
#include <dialogs/ArenaInfoDialog.h>
|
||||||
#include "GlibcHeapWidget.h"
|
#include "GlibcHeapWidget.h"
|
||||||
#include "ui_GlibcHeapWidget.h"
|
#include "ui_GlibcHeapWidget.h"
|
||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
@ -38,6 +39,7 @@ GlibcHeapWidget::GlibcHeapWidget(MainWindow *main, QWidget *parent)
|
|||||||
connect(chunkInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewChunkInfo);
|
connect(chunkInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewChunkInfo);
|
||||||
connect(binInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewBinInfo);
|
connect(binInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewBinInfo);
|
||||||
connect(ui->binsButton, &QPushButton::clicked, this, &GlibcHeapWidget::viewBinInfo);
|
connect(ui->binsButton, &QPushButton::clicked, this, &GlibcHeapWidget::viewBinInfo);
|
||||||
|
connect(ui->arenaButton, &QPushButton::clicked, this, &GlibcHeapWidget::viewArenaInfo);
|
||||||
|
|
||||||
addressableItemContextMenu.addAction(chunkInfoAction);
|
addressableItemContextMenu.addAction(chunkInfoAction);
|
||||||
addressableItemContextMenu.addAction(binInfoAction);
|
addressableItemContextMenu.addAction(binInfoAction);
|
||||||
@ -214,3 +216,18 @@ void GlibcHeapWidget::viewBinInfo()
|
|||||||
GlibcHeapBinsDialog heapBinsDialog(modelHeap->arena_addr, main, this);
|
GlibcHeapBinsDialog heapBinsDialog(modelHeap->arena_addr, main, this);
|
||||||
heapBinsDialog.exec();
|
heapBinsDialog.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlibcHeapWidget::viewArenaInfo()
|
||||||
|
{
|
||||||
|
// find the active arena
|
||||||
|
Arena currentArena;
|
||||||
|
for (auto &arena : arenas) {
|
||||||
|
if (arena.offset == modelHeap->arena_addr) {
|
||||||
|
currentArena = arena;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArenaInfoDialog arenaInfoDialog(currentArena, this);
|
||||||
|
arenaInfoDialog.exec();
|
||||||
|
}
|
@ -44,6 +44,7 @@ private slots:
|
|||||||
void onCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
void onCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void viewChunkInfo();
|
void viewChunkInfo();
|
||||||
void viewBinInfo();
|
void viewBinInfo();
|
||||||
|
void viewArenaInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateArenas();
|
void updateArenas();
|
||||||
|
@ -22,6 +22,19 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="arenaSelector"/>
|
<widget class="QComboBox" name="arenaSelector"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="arenaButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Arena</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="binsButton">
|
<widget class="QPushButton" name="binsButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -11,6 +11,8 @@ HeapBinsGraphView::HeapBinsGraphView(QWidget *parent, RzHeapBin *bin, MainWindow
|
|||||||
|
|
||||||
connect(chunkInfoAction, &QAction::triggered, this, &HeapBinsGraphView::viewChunkInfo);
|
connect(chunkInfoAction, &QAction::triggered, this, &HeapBinsGraphView::viewChunkInfo);
|
||||||
|
|
||||||
|
bits = Core()->getArchBits();
|
||||||
|
|
||||||
enableAddresses(true);
|
enableAddresses(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +32,8 @@ void HeapBinsGraphView::loadCurrentGraph()
|
|||||||
QVector<GraphHeapChunk> chunks;
|
QVector<GraphHeapChunk> chunks;
|
||||||
|
|
||||||
// if the bin is a fastbin or not
|
// if the bin is a fastbin or not
|
||||||
bool fast = QString(heapBin->type) == QString("Fast");
|
bool singleLinkedBin = QString(heapBin->type) == QString("Fast")
|
||||||
|
|| QString(heapBin->type) == QString("Tcache");
|
||||||
|
|
||||||
// store info about the chunks in a vector for easy access
|
// store info about the chunks in a vector for easy access
|
||||||
CutterRListForeach(heapBin->chunks, iter, RzHeapChunkListItem, item)
|
CutterRListForeach(heapBin->chunks, iter, RzHeapChunkListItem, item)
|
||||||
@ -45,7 +48,7 @@ void HeapBinsGraphView::loadCurrentGraph()
|
|||||||
+ RHexString(chunkInfo->size) + "\nFd: " + RAddressString(chunkInfo->fd);
|
+ RHexString(chunkInfo->size) + "\nFd: " + RAddressString(chunkInfo->fd);
|
||||||
|
|
||||||
// fastbins lack bk pointer
|
// fastbins lack bk pointer
|
||||||
if (!fast) {
|
if (!singleLinkedBin) {
|
||||||
content += "\nBk: " + RAddressString(chunkInfo->bk);
|
content += "\nBk: " + RAddressString(chunkInfo->bk);
|
||||||
}
|
}
|
||||||
graphHeapChunk.fd = chunkInfo->fd;
|
graphHeapChunk.fd = chunkInfo->fd;
|
||||||
@ -55,8 +58,8 @@ void HeapBinsGraphView::loadCurrentGraph()
|
|||||||
free(chunkInfo);
|
free(chunkInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fast bins have single linked list and other bins have double linked list
|
// fast and tcache bins have single linked list and other bins have double linked list
|
||||||
if (fast) {
|
if (singleLinkedBin) {
|
||||||
display_single_linked_list(chunks);
|
display_single_linked_list(chunks);
|
||||||
} else {
|
} else {
|
||||||
display_double_linked_list(chunks);
|
display_double_linked_list(chunks);
|
||||||
@ -68,19 +71,31 @@ void HeapBinsGraphView::loadCurrentGraph()
|
|||||||
|
|
||||||
void HeapBinsGraphView::display_single_linked_list(QVector<GraphHeapChunk> chunks)
|
void HeapBinsGraphView::display_single_linked_list(QVector<GraphHeapChunk> chunks)
|
||||||
{
|
{
|
||||||
|
bool tcache = QString(heapBin->type) == QString("Tcache");
|
||||||
|
int ptrSize = bits;
|
||||||
// add the graph block for the bin
|
// add the graph block for the bin
|
||||||
GraphLayout::GraphBlock gbBin;
|
GraphLayout::GraphBlock gbBin;
|
||||||
gbBin.entry = 1;
|
gbBin.entry = 1;
|
||||||
gbBin.edges.emplace_back(heapBin->fd);
|
gbBin.edges.emplace_back(heapBin->fd);
|
||||||
QString content = tr(heapBin->type) + tr("bin ") + QString::number(heapBin->bin_num);
|
QString content = tr(heapBin->type) + tr("bin ") + QString::number(heapBin->bin_num);
|
||||||
|
if (tcache) {
|
||||||
|
content += "\nEntry: " + RAddressString(heapBin->fd);
|
||||||
|
} else {
|
||||||
content += "\nFd: " + RAddressString(heapBin->fd);
|
content += "\nFd: " + RAddressString(heapBin->fd);
|
||||||
|
}
|
||||||
addBlock(gbBin, content);
|
addBlock(gbBin, content);
|
||||||
|
|
||||||
// add the graph blocks for the chunks
|
// add the graph blocks for the chunks
|
||||||
for (int i = 0; i < chunks.size(); i++) {
|
for (int i = 0; i < chunks.size(); i++) {
|
||||||
GraphLayout::GraphBlock gbChunk;
|
GraphLayout::GraphBlock gbChunk;
|
||||||
gbChunk.entry = chunks[i].addr;
|
gbChunk.entry = chunks[i].addr;
|
||||||
|
|
||||||
|
if (tcache && chunks[i].fd) {
|
||||||
|
// base_address = address - 2 * PTR_SIZE
|
||||||
|
gbChunk.edges.emplace_back(chunks[i].fd - 2 * ptrSize);
|
||||||
|
} else {
|
||||||
gbChunk.edges.emplace_back(chunks[i].fd);
|
gbChunk.edges.emplace_back(chunks[i].fd);
|
||||||
|
}
|
||||||
|
|
||||||
if (i == chunks.size() - 1 && heapBin->message) {
|
if (i == chunks.size() - 1 && heapBin->message) {
|
||||||
chunks[i].content += "\n" + QString(heapBin->message);
|
chunks[i].content += "\n" + QString(heapBin->message);
|
||||||
|
@ -33,6 +33,7 @@ private:
|
|||||||
void display_double_linked_list(QVector<GraphHeapChunk>);
|
void display_double_linked_list(QVector<GraphHeapChunk>);
|
||||||
QAction *chunkInfoAction;
|
QAction *chunkInfoAction;
|
||||||
RVA selectedBlock;
|
RVA selectedBlock;
|
||||||
|
int bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CUTTER_HEAPBINSGRAPHVIEW_H
|
#endif // CUTTER_HEAPBINSGRAPHVIEW_H
|
||||||
|
Loading…
Reference in New Issue
Block a user