Serenity Operating System
at master 125 lines 3.9 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 "CompilationUnit.h" 8#include <AK/ByteReader.h> 9#include <LibDebug/Dwarf/DIE.h> 10#include <LibDebug/Dwarf/DwarfInfo.h> 11#include <LibDebug/Dwarf/LineProgram.h> 12 13namespace Debug::Dwarf { 14 15CompilationUnit::CompilationUnit(DwarfInfo const& dwarf_info, u32 offset, CompilationUnitHeader const& header, NonnullOwnPtr<LineProgram>&& line_program) 16 : m_dwarf_info(dwarf_info) 17 , m_offset(offset) 18 , m_header(header) 19 , m_abbreviations(dwarf_info, header.abbrev_offset()) 20 , m_line_program(move(line_program)) 21{ 22 VERIFY(header.version() < 5 || header.unit_type() == CompilationUnitType::Full); 23} 24 25CompilationUnit::~CompilationUnit() = default; 26 27DIE CompilationUnit::root_die() const 28{ 29 return DIE(*this, m_offset + m_header.header_size()); 30} 31 32DIE CompilationUnit::get_die_at_offset(u32 die_offset) const 33{ 34 VERIFY(die_offset >= offset() && die_offset < offset() + size()); 35 return DIE(*this, die_offset); 36} 37 38LineProgram const& CompilationUnit::line_program() const 39{ 40 return *m_line_program; 41} 42 43ErrorOr<Optional<FlatPtr>> CompilationUnit::base_address() const 44{ 45 if (m_has_cached_base_address) 46 return m_cached_base_address; 47 48 auto die = root_die(); 49 auto res = TRY(die.get_attribute(Attribute::LowPc)); 50 if (res.has_value()) { 51 m_cached_base_address = TRY(res->as_addr()); 52 } 53 m_has_cached_base_address = true; 54 return m_cached_base_address; 55} 56 57ErrorOr<u64> CompilationUnit::address_table_base() const 58{ 59 if (m_has_cached_address_table_base) 60 return m_cached_address_table_base; 61 62 auto die = root_die(); 63 auto res = TRY(die.get_attribute(Attribute::AddrBase)); 64 if (res.has_value()) { 65 VERIFY(res->form() == AttributeDataForm::SecOffset); 66 m_cached_address_table_base = res->as_unsigned(); 67 } 68 m_has_cached_address_table_base = true; 69 return m_cached_address_table_base; 70} 71 72ErrorOr<u64> CompilationUnit::string_offsets_base() const 73{ 74 if (m_has_cached_string_offsets_base) 75 return m_cached_string_offsets_base; 76 77 auto die = root_die(); 78 auto res = TRY(die.get_attribute(Attribute::StrOffsetsBase)); 79 if (res.has_value()) { 80 VERIFY(res->form() == AttributeDataForm::SecOffset); 81 m_cached_string_offsets_base = res->as_unsigned(); 82 } 83 m_has_cached_string_offsets_base = true; 84 return m_cached_string_offsets_base; 85} 86 87ErrorOr<u64> CompilationUnit::range_lists_base() const 88{ 89 if (m_has_cached_range_lists_base) 90 return m_cached_range_lists_base; 91 92 auto die = root_die(); 93 auto res = TRY(die.get_attribute(Attribute::RngListsBase)); 94 if (res.has_value()) { 95 VERIFY(res->form() == AttributeDataForm::SecOffset); 96 m_cached_range_lists_base = res->as_unsigned(); 97 } 98 m_has_cached_range_lists_base = true; 99 return m_cached_range_lists_base; 100} 101 102ErrorOr<FlatPtr> CompilationUnit::get_address(size_t index) const 103{ 104 auto base = TRY(address_table_base()); 105 auto debug_addr_data = dwarf_info().debug_addr_data(); 106 VERIFY(base < debug_addr_data.size()); 107 auto addresses = debug_addr_data.slice(base); 108 VERIFY(index * sizeof(FlatPtr) < addresses.size()); 109 FlatPtr value { 0 }; 110 ByteReader::load<FlatPtr>(addresses.offset_pointer(index * sizeof(FlatPtr)), value); 111 return value; 112} 113 114ErrorOr<char const*> CompilationUnit::get_string(size_t index) const 115{ 116 auto base = TRY(string_offsets_base()); 117 auto debug_str_offsets_data = dwarf_info().debug_str_offsets_data(); 118 VERIFY(base < debug_str_offsets_data.size()); 119 // FIXME: This assumes DWARF32 120 auto offsets = debug_str_offsets_data.slice(base); 121 VERIFY(index * sizeof(u32) < offsets.size()); 122 auto offset = ByteReader::load32(offsets.offset_pointer(index * sizeof(u32))); 123 return bit_cast<char const*>(dwarf_info().debug_strings_data().offset(offset)); 124} 125}