mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 10:56:11 +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
|
||||
dialogs/GlibcHeapBinsDialog.cpp
|
||||
widgets/HeapBinsGraphView.cpp
|
||||
dialogs/ArenaInfoDialog.cpp
|
||||
)
|
||||
set(HEADER_FILES
|
||||
core/Cutter.h
|
||||
@ -304,6 +305,7 @@ set(HEADER_FILES
|
||||
widgets/GlibcHeapWidget.h
|
||||
dialogs/GlibcHeapBinsDialog.h
|
||||
widgets/HeapBinsGraphView.h
|
||||
dialogs/ArenaInfoDialog.h
|
||||
)
|
||||
set(UI_FILES
|
||||
dialogs/AboutDialog.ui
|
||||
@ -374,6 +376,7 @@ set(UI_FILES
|
||||
widgets/HeapDockWidget.ui
|
||||
widgets/GlibcHeapWidget.ui
|
||||
dialogs/GlibcHeapBinsDialog.ui
|
||||
dialogs/ArenaInfoDialog.ui
|
||||
)
|
||||
set(QRC_FILES
|
||||
resources.qrc
|
||||
|
@ -1592,6 +1592,12 @@ QVector<Chunk> CutterCore::getHeapChunks(RVA arena_addr)
|
||||
return chunks_vector;
|
||||
}
|
||||
|
||||
int CutterCore::getArchBits()
|
||||
{
|
||||
CORE_LOCK();
|
||||
return core->dbg->bits;
|
||||
}
|
||||
|
||||
QVector<Arena> CutterCore::getArenas()
|
||||
{
|
||||
CORE_LOCK();
|
||||
@ -1606,6 +1612,12 @@ QVector<Arena> CutterCore::getArenas()
|
||||
Arena arena;
|
||||
arena.offset = data->addr;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1653,10 +1665,30 @@ QVector<RzHeapBin *> CutterCore::getHeapBins(ut64 arena_addr)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
bool CutterCore::writeHeapChunk(RzHeapChunkSimple *chunk_simple)
|
||||
{
|
||||
CORE_LOCK();
|
||||
return rz_heap_write_chunk(core, chunk_simple);
|
||||
}
|
||||
|
||||
QJsonDocument CutterCore::getChildProcesses(int pid)
|
||||
{
|
||||
// Return the currently debugged process and it's children
|
||||
|
@ -419,7 +419,20 @@ public:
|
||||
* @return RzHeapChunkSimple struct pointer for the heap chunk
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* @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 startEmulation();
|
||||
/**
|
||||
|
@ -375,6 +375,12 @@ struct Arena
|
||||
{
|
||||
RVA offset;
|
||||
QString type;
|
||||
ut64 top;
|
||||
ut64 last_remainder;
|
||||
ut64 next;
|
||||
ut64 next_free;
|
||||
ut64 system_mem;
|
||||
ut64 max_system_mem;
|
||||
};
|
||||
|
||||
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>
|
@ -4,10 +4,10 @@
|
||||
<widget class="QDialog" name="GlibcHeapBinsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>544</height>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>544</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -27,7 +27,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="chainInfoEdit"/>
|
||||
<widget class="QPlainTextEdit" name="chainInfoEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout3">
|
||||
|
@ -8,11 +8,6 @@ GlibcHeapInfoDialog::GlibcHeapInfoDialog(RVA offset, QString status, QWidget *pa
|
||||
{
|
||||
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
|
||||
QString windowTitle = tr("Chunk @ ") + RAddressString(offset);
|
||||
if (!this->status.isEmpty()) {
|
||||
@ -20,6 +15,8 @@ GlibcHeapInfoDialog::GlibcHeapInfoDialog(RVA offset, QString status, QWidget *pa
|
||||
}
|
||||
this->setWindowTitle(windowTitle);
|
||||
|
||||
connect(ui->saveButton, &QPushButton::clicked, this, &GlibcHeapInfoDialog::saveChunkInfo);
|
||||
|
||||
updateFields();
|
||||
}
|
||||
|
||||
@ -46,13 +43,69 @@ void GlibcHeapInfoDialog::updateFields()
|
||||
this->ui->prevSizeEdit->setText(RHexString(chunk->prev_size));
|
||||
if (chunk->is_mmapped) {
|
||||
this->ui->rbIM->setChecked(true);
|
||||
} else {
|
||||
this->ui->rbIM->setChecked(false);
|
||||
}
|
||||
if (chunk->prev_inuse) {
|
||||
this->ui->rbPI->setChecked(true);
|
||||
} else {
|
||||
this->ui->rbPI->setChecked(false);
|
||||
}
|
||||
if (chunk->non_main_arena) {
|
||||
this->ui->rbNMA->setChecked(true);
|
||||
} else {
|
||||
this->ui->rbNMA->setChecked(false);
|
||||
}
|
||||
|
||||
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);
|
||||
~GlibcHeapInfoDialog();
|
||||
|
||||
private slots:
|
||||
void saveChunkInfo();
|
||||
|
||||
private:
|
||||
Ui::GlibcHeapInfoDialog *ui;
|
||||
void updateFields();
|
||||
|
@ -46,7 +46,7 @@
|
||||
<string>Size of the heap chunk including metadata</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -63,7 +63,7 @@
|
||||
<string>Link to next free chunk in bin's linked list</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -80,7 +80,7 @@
|
||||
<string>Link to previous free chunk in bin's linked list</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -90,7 +90,7 @@
|
||||
<string>Link to next larger free chunk (only for large chunks)</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -114,7 +114,7 @@
|
||||
<string>Link to next smaller free chunk (for large chunks)</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -124,7 +124,7 @@
|
||||
<string>Size of previous chunk (if free)</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -189,6 +189,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="saveButton">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <dialogs/GlibcHeapBinsDialog.h>
|
||||
#include <dialogs/ArenaInfoDialog.h>
|
||||
#include "GlibcHeapWidget.h"
|
||||
#include "ui_GlibcHeapWidget.h"
|
||||
#include "core/MainWindow.h"
|
||||
@ -38,6 +39,7 @@ GlibcHeapWidget::GlibcHeapWidget(MainWindow *main, QWidget *parent)
|
||||
connect(chunkInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewChunkInfo);
|
||||
connect(binInfoAction, &QAction::triggered, this, &GlibcHeapWidget::viewBinInfo);
|
||||
connect(ui->binsButton, &QPushButton::clicked, this, &GlibcHeapWidget::viewBinInfo);
|
||||
connect(ui->arenaButton, &QPushButton::clicked, this, &GlibcHeapWidget::viewArenaInfo);
|
||||
|
||||
addressableItemContextMenu.addAction(chunkInfoAction);
|
||||
addressableItemContextMenu.addAction(binInfoAction);
|
||||
@ -214,3 +216,18 @@ void GlibcHeapWidget::viewBinInfo()
|
||||
GlibcHeapBinsDialog heapBinsDialog(modelHeap->arena_addr, main, this);
|
||||
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 viewChunkInfo();
|
||||
void viewBinInfo();
|
||||
void viewArenaInfo();
|
||||
|
||||
private:
|
||||
void updateArenas();
|
||||
|
@ -19,25 +19,38 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="arenaSelector"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="binsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>View bins info for an arena</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="arenaSelector"/>
|
||||
</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>
|
||||
<widget class="QPushButton" name="binsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>View bins info for an arena</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -11,6 +11,8 @@ HeapBinsGraphView::HeapBinsGraphView(QWidget *parent, RzHeapBin *bin, MainWindow
|
||||
|
||||
connect(chunkInfoAction, &QAction::triggered, this, &HeapBinsGraphView::viewChunkInfo);
|
||||
|
||||
bits = Core()->getArchBits();
|
||||
|
||||
enableAddresses(true);
|
||||
}
|
||||
|
||||
@ -30,7 +32,8 @@ void HeapBinsGraphView::loadCurrentGraph()
|
||||
QVector<GraphHeapChunk> chunks;
|
||||
|
||||
// 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
|
||||
CutterRListForeach(heapBin->chunks, iter, RzHeapChunkListItem, item)
|
||||
@ -45,7 +48,7 @@ void HeapBinsGraphView::loadCurrentGraph()
|
||||
+ RHexString(chunkInfo->size) + "\nFd: " + RAddressString(chunkInfo->fd);
|
||||
|
||||
// fastbins lack bk pointer
|
||||
if (!fast) {
|
||||
if (!singleLinkedBin) {
|
||||
content += "\nBk: " + RAddressString(chunkInfo->bk);
|
||||
}
|
||||
graphHeapChunk.fd = chunkInfo->fd;
|
||||
@ -55,8 +58,8 @@ void HeapBinsGraphView::loadCurrentGraph()
|
||||
free(chunkInfo);
|
||||
}
|
||||
|
||||
// fast bins have single linked list and other bins have double linked list
|
||||
if (fast) {
|
||||
// fast and tcache bins have single linked list and other bins have double linked list
|
||||
if (singleLinkedBin) {
|
||||
display_single_linked_list(chunks);
|
||||
} else {
|
||||
display_double_linked_list(chunks);
|
||||
@ -68,19 +71,31 @@ void HeapBinsGraphView::loadCurrentGraph()
|
||||
|
||||
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
|
||||
GraphLayout::GraphBlock gbBin;
|
||||
gbBin.entry = 1;
|
||||
gbBin.edges.emplace_back(heapBin->fd);
|
||||
QString content = tr(heapBin->type) + tr("bin ") + QString::number(heapBin->bin_num);
|
||||
content += "\nFd: " + RAddressString(heapBin->fd);
|
||||
if (tcache) {
|
||||
content += "\nEntry: " + RAddressString(heapBin->fd);
|
||||
} else {
|
||||
content += "\nFd: " + RAddressString(heapBin->fd);
|
||||
}
|
||||
addBlock(gbBin, content);
|
||||
|
||||
// add the graph blocks for the chunks
|
||||
for (int i = 0; i < chunks.size(); i++) {
|
||||
GraphLayout::GraphBlock gbChunk;
|
||||
gbChunk.entry = chunks[i].addr;
|
||||
gbChunk.edges.emplace_back(chunks[i].fd);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (i == chunks.size() - 1 && heapBin->message) {
|
||||
chunks[i].content += "\n" + QString(heapBin->message);
|
||||
|
@ -33,6 +33,7 @@ private:
|
||||
void display_double_linked_list(QVector<GraphHeapChunk>);
|
||||
QAction *chunkInfoAction;
|
||||
RVA selectedBlock;
|
||||
int bits;
|
||||
};
|
||||
|
||||
#endif // CUTTER_HEAPBINSGRAPHVIEW_H
|
||||
|
Loading…
Reference in New Issue
Block a user