| 1 | /* DWARF 2 debugging format support for GDB. |
| 2 | |
| 3 | Copyright (C) 1994-2020 Free Software Foundation, Inc. |
| 4 | |
| 5 | This file is part of GDB. |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 3 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 19 | |
| 20 | #ifndef DWARF2_LINE_HEADER_H |
| 21 | #define DWARF2_LINE_HEADER_H |
| 22 | |
| 23 | #include "gdbtypes.h" |
| 24 | |
| 25 | /* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and |
| 26 | later. */ |
| 27 | typedef int dir_index; |
| 28 | |
| 29 | /* file_name_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 |
| 30 | and later. */ |
| 31 | typedef int file_name_index; |
| 32 | |
| 33 | struct line_header; |
| 34 | |
| 35 | struct file_entry |
| 36 | { |
| 37 | file_entry () = default; |
| 38 | |
| 39 | file_entry (const char *name_, dir_index d_index_, |
| 40 | unsigned int mod_time_, unsigned int length_) |
| 41 | : name (name_), |
| 42 | d_index (d_index_), |
| 43 | mod_time (mod_time_), |
| 44 | length (length_) |
| 45 | {} |
| 46 | |
| 47 | /* Return the include directory at D_INDEX stored in LH. Returns |
| 48 | NULL if D_INDEX is out of bounds. */ |
| 49 | const char *include_dir (const line_header *lh) const; |
| 50 | |
| 51 | /* The file name. Note this is an observing pointer. The memory is |
| 52 | owned by debug_line_buffer. */ |
| 53 | const char *name {}; |
| 54 | |
| 55 | /* The directory index (1-based). */ |
| 56 | dir_index d_index {}; |
| 57 | |
| 58 | unsigned int mod_time {}; |
| 59 | |
| 60 | unsigned int length {}; |
| 61 | |
| 62 | /* True if referenced by the Line Number Program. */ |
| 63 | bool included_p {}; |
| 64 | |
| 65 | /* The associated symbol table, if any. */ |
| 66 | struct symtab *symtab {}; |
| 67 | }; |
| 68 | |
| 69 | /* The line number information for a compilation unit (found in the |
| 70 | .debug_line section) begins with a "statement program header", |
| 71 | which contains the following information. */ |
| 72 | struct line_header |
| 73 | { |
| 74 | line_header () |
| 75 | : offset_in_dwz {} |
| 76 | {} |
| 77 | |
| 78 | /* Add an entry to the include directory table. */ |
| 79 | void add_include_dir (const char *include_dir); |
| 80 | |
| 81 | /* Add an entry to the file name table. */ |
| 82 | void add_file_name (const char *name, dir_index d_index, |
| 83 | unsigned int mod_time, unsigned int length); |
| 84 | |
| 85 | /* Return the include dir at INDEX (0-based in DWARF 5 and 1-based before). |
| 86 | Returns NULL if INDEX is out of bounds. */ |
| 87 | const char *include_dir_at (dir_index index) const |
| 88 | { |
| 89 | int vec_index; |
| 90 | if (version >= 5) |
| 91 | vec_index = index; |
| 92 | else |
| 93 | vec_index = index - 1; |
| 94 | if (vec_index < 0 || vec_index >= m_include_dirs.size ()) |
| 95 | return NULL; |
| 96 | return m_include_dirs[vec_index]; |
| 97 | } |
| 98 | |
| 99 | bool is_valid_file_index (int file_index) const |
| 100 | { |
| 101 | if (version >= 5) |
| 102 | return 0 <= file_index && file_index < file_names_size (); |
| 103 | return 1 <= file_index && file_index <= file_names_size (); |
| 104 | } |
| 105 | |
| 106 | /* Return the file name at INDEX (0-based in DWARF 5 and 1-based before). |
| 107 | Returns NULL if INDEX is out of bounds. */ |
| 108 | file_entry *file_name_at (file_name_index index) |
| 109 | { |
| 110 | int vec_index; |
| 111 | if (version >= 5) |
| 112 | vec_index = index; |
| 113 | else |
| 114 | vec_index = index - 1; |
| 115 | if (vec_index < 0 || vec_index >= m_file_names.size ()) |
| 116 | return NULL; |
| 117 | return &m_file_names[vec_index]; |
| 118 | } |
| 119 | |
| 120 | /* A const overload of the same. */ |
| 121 | const file_entry *file_name_at (file_name_index index) const |
| 122 | { |
| 123 | line_header *lh = const_cast<line_header *> (this); |
| 124 | return lh->file_name_at (index); |
| 125 | } |
| 126 | |
| 127 | /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore, |
| 128 | this method should only be used to iterate through all file entries in an |
| 129 | index-agnostic manner. */ |
| 130 | std::vector<file_entry> &file_names () |
| 131 | { return m_file_names; } |
| 132 | /* A const overload of the same. */ |
| 133 | const std::vector<file_entry> &file_names () const |
| 134 | { return m_file_names; } |
| 135 | |
| 136 | /* Offset of line number information in .debug_line section. */ |
| 137 | sect_offset sect_off {}; |
| 138 | |
| 139 | /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */ |
| 140 | unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class. */ |
| 141 | |
| 142 | unsigned int total_length {}; |
| 143 | unsigned short version {}; |
| 144 | unsigned int header_length {}; |
| 145 | unsigned char minimum_instruction_length {}; |
| 146 | unsigned char maximum_ops_per_instruction {}; |
| 147 | unsigned char default_is_stmt {}; |
| 148 | int line_base {}; |
| 149 | unsigned char line_range {}; |
| 150 | unsigned char opcode_base {}; |
| 151 | |
| 152 | /* standard_opcode_lengths[i] is the number of operands for the |
| 153 | standard opcode whose value is i. This means that |
| 154 | standard_opcode_lengths[0] is unused, and the last meaningful |
| 155 | element is standard_opcode_lengths[opcode_base - 1]. */ |
| 156 | std::unique_ptr<unsigned char[]> standard_opcode_lengths; |
| 157 | |
| 158 | int file_names_size () const |
| 159 | { return m_file_names.size(); } |
| 160 | |
| 161 | /* The start and end of the statement program following this |
| 162 | header. These point into dwarf2_per_objfile->line_buffer. */ |
| 163 | const gdb_byte *statement_program_start {}, *statement_program_end {}; |
| 164 | |
| 165 | /* Return the full name of file number I in this object's file name |
| 166 | table. Use COMP_DIR as the name of the current directory of the |
| 167 | compilation. The result is allocated using xmalloc; the caller |
| 168 | is responsible for freeing it. */ |
| 169 | gdb::unique_xmalloc_ptr<char> file_full_name (int file, |
| 170 | const char *comp_dir) const; |
| 171 | |
| 172 | /* Return file name relative to the compilation directory of file |
| 173 | number I in this object's file name table. The result is |
| 174 | allocated using xmalloc; the caller is responsible for freeing |
| 175 | it. */ |
| 176 | gdb::unique_xmalloc_ptr<char> file_file_name (int file) const; |
| 177 | |
| 178 | private: |
| 179 | /* The include_directories table. Note these are observing |
| 180 | pointers. The memory is owned by debug_line_buffer. */ |
| 181 | std::vector<const char *> m_include_dirs; |
| 182 | |
| 183 | /* The file_names table. This is private because the meaning of indexes |
| 184 | differs among DWARF versions (The first valid index is 1 in DWARF 4 and |
| 185 | before, and is 0 in DWARF 5 and later). So the client should use |
| 186 | file_name_at method for access. */ |
| 187 | std::vector<file_entry> m_file_names; |
| 188 | }; |
| 189 | |
| 190 | typedef std::unique_ptr<line_header> line_header_up; |
| 191 | |
| 192 | inline const char * |
| 193 | file_entry::include_dir (const line_header *lh) const |
| 194 | { |
| 195 | return lh->include_dir_at (d_index); |
| 196 | } |
| 197 | |
| 198 | /* Read the statement program header starting at SECT_OFF in SECTION. |
| 199 | Return line_header. Returns nullptr if there is a problem reading |
| 200 | the header, e.g., if it has a version we don't understand. |
| 201 | |
| 202 | NOTE: the strings in the include directory and file name tables of |
| 203 | the returned object point into the dwarf line section buffer, |
| 204 | and must not be freed. */ |
| 205 | |
| 206 | extern line_header_up dwarf_decode_line_header |
| 207 | (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile, |
| 208 | struct dwarf2_section_info *section, const struct comp_unit_head *cu_header); |
| 209 | |
| 210 | #endif /* DWARF2_LINE_HEADER_H */ |