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