Serenity Operating System
at master 194 lines 5.3 kB view raw
1/* 2 * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/DeprecatedFlyString.h> 10#include <AK/Vector.h> 11#include <LibDebug/Dwarf/DwarfTypes.h> 12 13namespace Debug::Dwarf { 14 15class DwarfInfo; 16 17struct [[gnu::packed]] LineProgramUnitHeader32Common { 18 u32 length; 19 u16 version; 20}; 21 22struct [[gnu::packed]] LineProgramUnitHeader32V4Ext { 23 u32 header_length; 24 u8 min_instruction_length; 25 u8 max_instruction_length; 26 u8 default_is_stmt; 27 i8 line_base; 28 u8 line_range; 29 u8 opcode_base; 30}; 31 32struct [[gnu::packed]] LineProgramUnitHeader32V5Ext { 33 u8 address_size; 34 u8 segment_selector_size; 35 u32 header_length; 36 u8 min_instruction_length; 37 u8 max_instruction_length; 38 u8 default_is_stmt; 39 i8 line_base; 40 u8 line_range; 41 u8 opcode_base; 42}; 43 44struct [[gnu::packed]] LineProgramUnitHeader32 { 45 LineProgramUnitHeader32Common common; 46 47 union { 48 LineProgramUnitHeader32V4Ext v4; 49 LineProgramUnitHeader32V5Ext v5; 50 }; 51 52 u8 std_opcode_lengths[13]; 53 54 size_t header_size() const 55 { 56 return sizeof(common) + ((common.version <= 4) ? sizeof(v4) : sizeof(v5)) + (opcode_base() - 1) * sizeof(std_opcode_lengths[0]); 57 } 58 59 u32 length() const { return common.length; } 60 u16 version() const { return common.version; } 61 u32 header_length() const { return (common.version <= 4) ? v4.header_length : v5.header_length; } 62 u8 min_instruction_length() const { return (common.version <= 4) ? v4.min_instruction_length : v5.min_instruction_length; } 63 u8 default_is_stmt() const { return (common.version <= 4) ? v4.default_is_stmt : v5.default_is_stmt; } 64 i8 line_base() const { return (common.version <= 4) ? v4.line_base : v5.line_base; } 65 u8 line_range() const { return (common.version <= 4) ? v4.line_range : v5.line_range; } 66 u8 opcode_base() const { return (common.version <= 4) ? v4.opcode_base : v5.opcode_base; } 67 68 static ErrorOr<LineProgramUnitHeader32> read_from_stream(Stream& stream) 69 { 70 LineProgramUnitHeader32 header; 71 TRY(stream.read_until_filled(Bytes { &header.common, sizeof(header.common) })); 72 if (header.common.version <= 4) 73 TRY(stream.read_until_filled(Bytes { &header.v4, sizeof(header.v4) })); 74 else 75 TRY(stream.read_until_filled(Bytes { &header.v5, sizeof(header.v5) })); 76 TRY(stream.read_until_filled(Bytes { &header.std_opcode_lengths, min(sizeof(header.std_opcode_lengths), (header.opcode_base() - 1) * sizeof(header.std_opcode_lengths[0])) })); 77 return header; 78 } 79}; 80 81enum class ContentType { 82 Path = 1, 83 DirectoryIndex = 2, 84 Timestamp = 3, 85 Size = 4, 86 MD5 = 5, 87 LoUser = 0x2000, 88 HiUser = 0x3fff, 89}; 90 91struct PathEntryFormat { 92 ContentType type; 93 AttributeDataForm form; 94}; 95 96struct PathEntry { 97 DeprecatedString path; 98 size_t directory_index { 0 }; 99}; 100 101enum class PathListType { 102 Directories, 103 Filenames, 104}; 105 106class LineProgram { 107 AK_MAKE_NONCOPYABLE(LineProgram); 108 AK_MAKE_NONMOVABLE(LineProgram); 109 110public: 111 explicit LineProgram(DwarfInfo& dwarf_info, SeekableStream& stream); 112 113 struct LineInfo { 114 FlatPtr address { 0 }; 115 DeprecatedFlyString file; 116 size_t line { 0 }; 117 }; 118 119 Vector<LineInfo> const& lines() const { return m_lines; } 120 121 struct DirectoryAndFile { 122 DeprecatedFlyString directory; 123 DeprecatedFlyString filename; 124 }; 125 DirectoryAndFile get_directory_and_file(size_t file_index) const; 126 127 struct FileEntry { 128 DeprecatedFlyString name; 129 size_t directory_index { 0 }; 130 }; 131 Vector<FileEntry> const& source_files() const { return m_source_files; } 132 133 bool looks_like_embedded_resource() const; 134 135private: 136 ErrorOr<void> parse_unit_header(); 137 ErrorOr<void> parse_source_directories(); 138 ErrorOr<void> parse_source_files(); 139 ErrorOr<void> run_program(); 140 141 void append_to_line_info(); 142 void reset_registers(); 143 144 ErrorOr<void> handle_extended_opcode(); 145 ErrorOr<void> handle_standard_opcode(u8 opcode); 146 void handle_special_opcode(u8 opcode); 147 148 ErrorOr<void> parse_path_entries(Function<void(PathEntry& entry)> callback, PathListType list_type); 149 150 enum StandardOpcodes { 151 Copy = 1, 152 AdvancePc, 153 AdvanceLine, 154 SetFile, 155 SetColumn, 156 NegateStatement, 157 SetBasicBlock, 158 ConstAddPc, 159 FixAdvancePc, 160 SetPrologueEnd, 161 SetEpilogueBegin, 162 SetIsa 163 }; 164 165 enum ExtendedOpcodes { 166 EndSequence = 1, 167 SetAddress, 168 DefineFile, 169 SetDiscriminator, 170 }; 171 172 static constexpr u16 MIN_DWARF_VERSION = 3; 173 static constexpr u16 MAX_DWARF_VERSION = 5; 174 175 DwarfInfo& m_dwarf_info; 176 SeekableStream& m_stream; 177 178 size_t m_unit_offset { 0 }; 179 LineProgramUnitHeader32 m_unit_header {}; 180 Vector<DeprecatedString> m_source_directories; 181 Vector<FileEntry> m_source_files; 182 183 // The registers of the "line program" virtual machine 184 FlatPtr m_address { 0 }; 185 size_t m_line { 0 }; 186 size_t m_file_index { 0 }; 187 bool m_is_statement { false }; 188 bool m_basic_block { false }; 189 bool m_prologue_end { false }; 190 191 Vector<LineInfo> m_lines; 192}; 193 194}