2015-01-04 17:36:57 +00:00
|
|
|
// Copyright 2014 Citra Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2016-09-20 15:21:23 +00:00
|
|
|
#include <QStandardItemModel>
|
2016-09-21 06:52:38 +00:00
|
|
|
#include "citra_qt/debugger/callstack.h"
|
2015-08-11 21:32:39 +00:00
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "common/symbols.h"
|
2015-09-11 04:23:00 +00:00
|
|
|
#include "core/arm/arm_interface.h"
|
2014-04-18 22:30:53 +00:00
|
|
|
#include "core/arm/disassembler/arm_disasm.h"
|
2016-09-18 00:38:01 +00:00
|
|
|
#include "core/core.h"
|
|
|
|
#include "core/memory.h"
|
2014-04-18 22:30:53 +00:00
|
|
|
|
2016-09-18 00:38:01 +00:00
|
|
|
CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) {
|
2014-04-18 22:30:53 +00:00
|
|
|
ui.setupUi(this);
|
|
|
|
|
|
|
|
callstack_model = new QStandardItemModel(this);
|
|
|
|
callstack_model->setColumnCount(4);
|
2014-12-31 22:03:15 +00:00
|
|
|
callstack_model->setHeaderData(0, Qt::Horizontal, "Stack Pointer");
|
|
|
|
callstack_model->setHeaderData(2, Qt::Horizontal, "Return Address");
|
|
|
|
callstack_model->setHeaderData(1, Qt::Horizontal, "Call Address");
|
2014-04-18 22:30:53 +00:00
|
|
|
callstack_model->setHeaderData(3, Qt::Horizontal, "Function");
|
|
|
|
ui.treeView->setModel(callstack_model);
|
|
|
|
}
|
|
|
|
|
2016-09-18 00:38:01 +00:00
|
|
|
void CallstackWidget::OnDebugModeEntered() {
|
2015-12-29 23:03:08 +00:00
|
|
|
// Stack pointer
|
2016-12-22 05:00:01 +00:00
|
|
|
const u32 sp = Core::CPU().GetReg(13);
|
2014-11-19 08:49:13 +00:00
|
|
|
|
2015-01-11 06:39:00 +00:00
|
|
|
Clear();
|
|
|
|
|
2014-04-18 22:30:53 +00:00
|
|
|
int counter = 0;
|
2016-09-18 00:38:01 +00:00
|
|
|
for (u32 addr = 0x10000000; addr >= sp; addr -= 4) {
|
2016-04-16 08:48:46 +00:00
|
|
|
if (!Memory::IsValidVirtualAddress(addr))
|
|
|
|
break;
|
|
|
|
|
2015-12-29 23:03:08 +00:00
|
|
|
const u32 ret_addr = Memory::Read32(addr);
|
2016-09-18 00:38:01 +00:00
|
|
|
const u32 call_addr = ret_addr - 4; // get call address???
|
2015-05-25 18:34:09 +00:00
|
|
|
|
2016-04-16 08:48:46 +00:00
|
|
|
if (!Memory::IsValidVirtualAddress(call_addr))
|
2015-01-07 20:39:40 +00:00
|
|
|
break;
|
2014-04-18 22:30:53 +00:00
|
|
|
|
|
|
|
/* TODO (mattvail) clean me, move to debugger interface */
|
|
|
|
u32 insn = Memory::Read32(call_addr);
|
2016-09-18 00:38:01 +00:00
|
|
|
if (ARM_Disasm::Decode(insn) == OP_BL) {
|
2014-04-18 22:30:53 +00:00
|
|
|
std::string name;
|
|
|
|
// ripped from disasm
|
2015-08-11 21:32:39 +00:00
|
|
|
u32 i_offset = insn & 0xffffff;
|
2014-04-18 22:30:53 +00:00
|
|
|
// Sign-extend the 24-bit offset
|
|
|
|
if ((i_offset >> 23) & 1)
|
|
|
|
i_offset |= 0xff000000;
|
|
|
|
|
|
|
|
// Pre-compute the left-shift and the prefetch offset
|
|
|
|
i_offset <<= 2;
|
|
|
|
i_offset += 8;
|
2015-12-29 23:03:08 +00:00
|
|
|
const u32 func_addr = call_addr + i_offset;
|
2014-04-18 22:30:53 +00:00
|
|
|
|
2016-09-18 00:38:01 +00:00
|
|
|
callstack_model->setItem(
|
|
|
|
counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
|
|
|
|
callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(
|
|
|
|
ret_addr, 8, 16, QLatin1Char('0'))));
|
|
|
|
callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(
|
|
|
|
call_addr, 8, 16, QLatin1Char('0'))));
|
2014-11-19 08:49:13 +00:00
|
|
|
|
2014-04-18 22:30:53 +00:00
|
|
|
name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
|
2016-09-18 00:38:01 +00:00
|
|
|
callstack_model->setItem(
|
|
|
|
counter, 3, new QStandardItem(
|
|
|
|
QString("%1_%2")
|
|
|
|
.arg(QString::fromStdString(name))
|
|
|
|
.arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
|
2014-04-18 22:30:53 +00:00
|
|
|
|
|
|
|
counter++;
|
|
|
|
}
|
|
|
|
}
|
2014-11-19 08:49:13 +00:00
|
|
|
}
|
2015-01-07 11:14:23 +00:00
|
|
|
|
2016-09-19 01:01:46 +00:00
|
|
|
void CallstackWidget::OnDebugModeLeft() {}
|
2015-01-11 06:39:00 +00:00
|
|
|
|
2016-09-18 00:38:01 +00:00
|
|
|
void CallstackWidget::Clear() {
|
2015-01-11 06:39:00 +00:00
|
|
|
for (int row = 0; row < callstack_model->rowCount(); row++) {
|
|
|
|
for (int column = 0; column < callstack_model->columnCount(); column++) {
|
|
|
|
callstack_model->setItem(row, column, new QStandardItem());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|