/* DWARF 2 debugging format support for GDB. Copyright (C) 1994-2021 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DWARF2_LINE_HEADER_H #define DWARF2_LINE_HEADER_H #include "gdbtypes.h" /* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and later. */ typedef int dir_index; /* file_name_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and later. */ typedef int file_name_index; struct line_header; struct file_entry { file_entry () = default; file_entry (const char *name_, dir_index d_index_, unsigned int mod_time_, unsigned int length_) : name (name_), d_index (d_index_), mod_time (mod_time_), length (length_) {} /* Return the include directory at D_INDEX stored in LH. Returns NULL if D_INDEX is out of bounds. */ const char *include_dir (const line_header *lh) const; /* The file name. Note this is an observing pointer. The memory is owned by debug_line_buffer. */ const char *name {}; /* The directory index (1-based). */ dir_index d_index {}; unsigned int mod_time {}; unsigned int length {}; /* True if referenced by the Line Number Program. */ bool included_p {}; /* The associated symbol table, if any. */ struct symtab *symtab {}; }; /* The line number information for a compilation unit (found in the .debug_line section) begins with a "statement program header", which contains the following information. */ struct line_header { line_header () : offset_in_dwz {} {} /* Add an entry to the include directory table. */ void add_include_dir (const char *include_dir); /* Add an entry to the file name table. */ void add_file_name (const char *name, dir_index d_index, unsigned int mod_time, unsigned int length); /* Return the include dir at INDEX (0-based in DWARF 5 and 1-based before). Returns NULL if INDEX is out of bounds. */ const char *include_dir_at (dir_index index) const { int vec_index; if (version >= 5) vec_index = index; else vec_index = index - 1; if (vec_index < 0 || vec_index >= m_include_dirs.size ()) return NULL; return m_include_dirs[vec_index]; } bool is_valid_file_index (int file_index) const { if (version >= 5) return 0 <= file_index && file_index < file_names_size (); return 1 <= file_index && file_index <= file_names_size (); } /* Return the file name at INDEX (0-based in DWARF 5 and 1-based before). Returns NULL if INDEX is out of bounds. */ file_entry *file_name_at (file_name_index index) { int vec_index; if (version >= 5) vec_index = index; else vec_index = index - 1; if (vec_index < 0 || vec_index >= m_file_names.size ()) return NULL; return &m_file_names[vec_index]; } /* A const overload of the same. */ const file_entry *file_name_at (file_name_index index) const { line_header *lh = const_cast (this); return lh->file_name_at (index); } /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore, this method should only be used to iterate through all file entries in an index-agnostic manner. */ std::vector &file_names () { return m_file_names; } /* A const overload of the same. */ const std::vector &file_names () const { return m_file_names; } /* Offset of line number information in .debug_line section. */ sect_offset sect_off {}; /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */ unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class. */ unsigned int total_length {}; unsigned short version {}; unsigned int header_length {}; unsigned char minimum_instruction_length {}; unsigned char maximum_ops_per_instruction {}; unsigned char default_is_stmt {}; int line_base {}; unsigned char line_range {}; unsigned char opcode_base {}; /* standard_opcode_lengths[i] is the number of operands for the standard opcode whose value is i. This means that standard_opcode_lengths[0] is unused, and the last meaningful element is standard_opcode_lengths[opcode_base - 1]. */ std::unique_ptr standard_opcode_lengths; int file_names_size () const { return m_file_names.size(); } /* The start and end of the statement program following this header. These point into dwarf2_per_objfile->line_buffer. */ const gdb_byte *statement_program_start {}, *statement_program_end {}; /* Return file name relative to the compilation directory of file number I in this object's file name table. The result is allocated using xmalloc; the caller is responsible for freeing it. */ gdb::unique_xmalloc_ptr file_file_name (int file) const; private: /* The include_directories table. Note these are observing pointers. The memory is owned by debug_line_buffer. */ std::vector m_include_dirs; /* The file_names table. This is private because the meaning of indexes differs among DWARF versions (The first valid index is 1 in DWARF 4 and before, and is 0 in DWARF 5 and later). So the client should use file_name_at method for access. */ std::vector m_file_names; }; typedef std::unique_ptr line_header_up; inline const char * file_entry::include_dir (const line_header *lh) const { return lh->include_dir_at (d_index); } /* Read the statement program header starting at SECT_OFF in SECTION. Return line_header. Returns nullptr if there is a problem reading the header, e.g., if it has a version we don't understand. NOTE: the strings in the include directory and file name tables of the returned object point into the dwarf line section buffer, and must not be freed. */ extern line_header_up dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile, struct dwarf2_section_info *section, const struct comp_unit_head *cu_header); #endif /* DWARF2_LINE_HEADER_H */