BacktraceModel.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "BacktraceModel.h"
  7. #include "Debugger.h"
  8. #include <LibDebug/StackFrameUtils.h>
  9. namespace HackStudio {
  10. NonnullRefPtr<BacktraceModel> BacktraceModel::create(Debug::ProcessInspector const& inspector, PtraceRegisters const& regs)
  11. {
  12. return adopt_ref(*new BacktraceModel(create_backtrace(inspector, regs)));
  13. }
  14. GUI::Variant BacktraceModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
  15. {
  16. if (role == GUI::ModelRole::Display) {
  17. auto& frame = m_frames.at(index.row());
  18. return frame.function_name;
  19. }
  20. return {};
  21. }
  22. GUI::ModelIndex BacktraceModel::index(int row, int column, const GUI::ModelIndex&) const
  23. {
  24. if (row < 0 || row >= static_cast<int>(m_frames.size()))
  25. return {};
  26. return create_index(row, column, &m_frames.at(row));
  27. }
  28. Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(Debug::ProcessInspector const& inspector, PtraceRegisters const& regs)
  29. {
  30. FlatPtr current_ebp = regs.bp();
  31. FlatPtr current_instruction = regs.ip();
  32. Vector<BacktraceModel::FrameInfo> frames;
  33. size_t frame_index = 0;
  34. do {
  35. auto lib = inspector.library_at(current_instruction);
  36. if (!lib)
  37. continue;
  38. // After the first frame, current_instruction holds the return address from the function call.
  39. // We need to go back to the 'call' instruction to get accurate source position information.
  40. if (frame_index > 0)
  41. --current_instruction;
  42. DeprecatedString name = lib->debug_info->elf().symbolicate(current_instruction - lib->base_address);
  43. if (name.is_empty()) {
  44. dbgln("BacktraceModel: couldn't find containing function for address: {:p} (library={})", current_instruction, lib->name);
  45. name = "<missing>";
  46. }
  47. auto source_position = lib->debug_info->get_source_position(current_instruction - lib->base_address);
  48. frames.append({ name, current_instruction, current_ebp, source_position });
  49. auto frame_info = Debug::StackFrameUtils::get_info(inspector, current_ebp);
  50. VERIFY(frame_info.has_value());
  51. current_instruction = frame_info.value().return_address;
  52. current_ebp = frame_info.value().next_ebp;
  53. ++frame_index;
  54. } while (current_ebp && current_instruction);
  55. return frames;
  56. }
  57. }