callstack.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <QStandardItemModel>
  5. #include "citra_qt/debugger/callstack.h"
  6. #include "common/common_types.h"
  7. #include "common/symbols.h"
  8. #include "core/arm/arm_interface.h"
  9. #include "core/arm/disassembler/arm_disasm.h"
  10. #include "core/core.h"
  11. #include "core/memory.h"
  12. CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) {
  13. ui.setupUi(this);
  14. callstack_model = new QStandardItemModel(this);
  15. callstack_model->setColumnCount(4);
  16. callstack_model->setHeaderData(0, Qt::Horizontal, "Stack Pointer");
  17. callstack_model->setHeaderData(2, Qt::Horizontal, "Return Address");
  18. callstack_model->setHeaderData(1, Qt::Horizontal, "Call Address");
  19. callstack_model->setHeaderData(3, Qt::Horizontal, "Function");
  20. ui.treeView->setModel(callstack_model);
  21. }
  22. void CallstackWidget::OnDebugModeEntered() {
  23. // Stack pointer
  24. const u32 sp = Core::AppCore().GetReg(13);
  25. Clear();
  26. int counter = 0;
  27. for (u32 addr = 0x10000000; addr >= sp; addr -= 4) {
  28. if (!Memory::IsValidVirtualAddress(addr))
  29. break;
  30. const u32 ret_addr = Memory::Read32(addr);
  31. const u32 call_addr = ret_addr - 4; // get call address???
  32. if (!Memory::IsValidVirtualAddress(call_addr))
  33. break;
  34. /* TODO (mattvail) clean me, move to debugger interface */
  35. u32 insn = Memory::Read32(call_addr);
  36. if (ARM_Disasm::Decode(insn) == OP_BL) {
  37. std::string name;
  38. // ripped from disasm
  39. u8 cond = (insn >> 28) & 0xf;
  40. u32 i_offset = insn & 0xffffff;
  41. // Sign-extend the 24-bit offset
  42. if ((i_offset >> 23) & 1)
  43. i_offset |= 0xff000000;
  44. // Pre-compute the left-shift and the prefetch offset
  45. i_offset <<= 2;
  46. i_offset += 8;
  47. const u32 func_addr = call_addr + i_offset;
  48. callstack_model->setItem(
  49. counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
  50. callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(
  51. ret_addr, 8, 16, QLatin1Char('0'))));
  52. callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(
  53. call_addr, 8, 16, QLatin1Char('0'))));
  54. name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
  55. callstack_model->setItem(
  56. counter, 3, new QStandardItem(
  57. QString("%1_%2")
  58. .arg(QString::fromStdString(name))
  59. .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
  60. counter++;
  61. }
  62. }
  63. }
  64. void CallstackWidget::OnDebugModeLeft() {}
  65. void CallstackWidget::Clear() {
  66. for (int row = 0; row < callstack_model->rowCount(); row++) {
  67. for (int column = 0; column < callstack_model->columnCount(); column++) {
  68. callstack_model->setItem(row, column, new QStandardItem());
  69. }
  70. }
  71. }