callstack.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 "callstack.h"
  6. #include "core/core.h"
  7. #include "core/arm/arm_interface.h"
  8. #include "core/mem_map.h"
  9. #include "common/symbols.h"
  10. #include "core/arm/disassembler/arm_disasm.h"
  11. CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
  12. {
  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. {
  24. ARM_Interface* app_core = Core::g_app_core;
  25. u32 sp = app_core->GetReg(13); //stack pointer
  26. u32 ret_addr, call_addr, func_addr;
  27. Clear();
  28. int counter = 0;
  29. for (u32 addr = 0x10000000; addr >= sp; addr -= 4)
  30. {
  31. ret_addr = Memory::Read32(addr);
  32. call_addr = ret_addr - 4; //get call address???
  33. if (Memory::GetPointer(call_addr) == nullptr)
  34. break;
  35. /* TODO (mattvail) clean me, move to debugger interface */
  36. u32 insn = Memory::Read32(call_addr);
  37. if (ARM_Disasm::Decode(insn) == OP_BL)
  38. {
  39. std::string name;
  40. // ripped from disasm
  41. uint8_t cond = (insn >> 28) & 0xf;
  42. uint32_t i_offset = insn & 0xffffff;
  43. // Sign-extend the 24-bit offset
  44. if ((i_offset >> 23) & 1)
  45. i_offset |= 0xff000000;
  46. // Pre-compute the left-shift and the prefetch offset
  47. i_offset <<= 2;
  48. i_offset += 8;
  49. func_addr = call_addr + i_offset;
  50. callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
  51. callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0'))));
  52. callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0'))));
  53. name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
  54. callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name))
  55. .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
  56. counter++;
  57. }
  58. }
  59. }
  60. void CallstackWidget::OnDebugModeLeft()
  61. {
  62. }
  63. void CallstackWidget::Clear()
  64. {
  65. for (int row = 0; row < callstack_model->rowCount(); row++) {
  66. for (int column = 0; column < callstack_model->columnCount(); column++) {
  67. callstack_model->setItem(row, column, new QStandardItem());
  68. }
  69. }
  70. }