Home | History | Annotate | Line # | Download | only in dwarf2
line-header.h revision 1.1.1.4
      1 /* DWARF 2 debugging format support for GDB.
      2 
      3    Copyright (C) 1994-2024 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 GDB_DWARF2_LINE_HEADER_H
     21 #define GDB_DWARF2_LINE_HEADER_H
     22 
     23 #include "dwarf2/types.h"
     24 
     25 struct dwarf2_per_objfile;
     26 
     27 /* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and
     28    later.  */
     29 typedef int dir_index;
     30 
     31 /* file_name_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5
     32    and later.  */
     33 typedef int file_name_index;
     34 
     35 struct line_header;
     36 
     37 struct file_entry
     38 {
     39   file_entry () = default;
     40 
     41   file_entry (const char *name_, file_name_index index_, dir_index d_index_,
     42 	      unsigned int mod_time_, unsigned int length_)
     43     : name (name_),
     44       index (index_),
     45       d_index (d_index_),
     46       mod_time (mod_time_),
     47       length (length_)
     48   {}
     49 
     50   /* Return the include directory at D_INDEX stored in LH.  Returns
     51      NULL if D_INDEX is out of bounds.  */
     52   const char *include_dir (const line_header *lh) const;
     53 
     54   /* The file name.  Note this is an observing pointer.  The memory is
     55      owned by debug_line_buffer.  */
     56   const char *name {};
     57 
     58   /* The index of this file in the file table.  */
     59   file_name_index index {};
     60 
     61   /* The directory index (1-based).  */
     62   dir_index d_index {};
     63 
     64   unsigned int mod_time {};
     65 
     66   unsigned int length {};
     67 
     68   /* The associated symbol table, if any.  */
     69   struct symtab *symtab {};
     70 };
     71 
     72 /* The line number information for a compilation unit (found in the
     73    .debug_line section) begins with a "statement program header",
     74    which contains the following information.  */
     75 struct line_header
     76 {
     77   /* COMP_DIR is the value of the DW_AT_comp_dir attribute of the compilation
     78      unit in the context of which we are reading this line header, or nullptr
     79      if unknown or not applicable.  */
     80   explicit line_header (const char *comp_dir)
     81     : offset_in_dwz {}, m_comp_dir (comp_dir)
     82   {}
     83 
     84   /* This constructor should only be used to create line_header instances to do
     85      hash table lookups.  */
     86   line_header (sect_offset sect_off, bool offset_in_dwz)
     87     : sect_off (sect_off),
     88       offset_in_dwz (offset_in_dwz)
     89   {}
     90 
     91   /* Add an entry to the include directory table.  */
     92   void add_include_dir (const char *include_dir);
     93 
     94   /* Add an entry to the file name table.  */
     95   void add_file_name (const char *name, dir_index d_index,
     96 		      unsigned int mod_time, unsigned int length);
     97 
     98   /* Return the include dir at INDEX (0-based in DWARF 5 and 1-based before).
     99      Returns NULL if INDEX is out of bounds.  */
    100   const char *include_dir_at (dir_index index) const
    101   {
    102     int vec_index;
    103     if (version >= 5)
    104       vec_index = index;
    105     else
    106       vec_index = index - 1;
    107     if (vec_index < 0 || vec_index >= m_include_dirs.size ())
    108       return NULL;
    109     return m_include_dirs[vec_index];
    110   }
    111 
    112   bool is_valid_file_index (int file_index) const
    113   {
    114     if (version >= 5)
    115       return 0 <= file_index && file_index < file_names_size ();
    116     return 1 <= file_index && file_index <= file_names_size ();
    117   }
    118 
    119   /* Return the file name at INDEX (0-based in DWARF 5 and 1-based before).
    120      Returns NULL if INDEX is out of bounds.  */
    121   file_entry *file_name_at (file_name_index index)
    122   {
    123     int vec_index;
    124     if (version >= 5)
    125       vec_index = index;
    126     else
    127       vec_index = index - 1;
    128     if (vec_index < 0 || vec_index >= m_file_names.size ())
    129       return NULL;
    130     return &m_file_names[vec_index];
    131   }
    132 
    133   /* A const overload of the same.  */
    134   const file_entry *file_name_at (file_name_index index) const
    135   {
    136     line_header *lh = const_cast<line_header *> (this);
    137     return lh->file_name_at (index);
    138   }
    139 
    140   /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore,
    141      this method should only be used to iterate through all file entries in an
    142      index-agnostic manner.  */
    143   std::vector<file_entry> &file_names ()
    144   { return m_file_names; }
    145   /* A const overload of the same.  */
    146   const std::vector<file_entry> &file_names () const
    147   { return m_file_names; }
    148 
    149   /* Offset of line number information in .debug_line section.  */
    150   sect_offset sect_off {};
    151 
    152   /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile.  */
    153   unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class.  */
    154 
    155   unsigned short version {};
    156   unsigned char minimum_instruction_length {};
    157   unsigned char maximum_ops_per_instruction {};
    158   unsigned char default_is_stmt {};
    159   int line_base {};
    160   unsigned char line_range {};
    161   unsigned char opcode_base {};
    162 
    163   /* standard_opcode_lengths[i] is the number of operands for the
    164      standard opcode whose value is i.  This means that
    165      standard_opcode_lengths[0] is unused, and the last meaningful
    166      element is standard_opcode_lengths[opcode_base - 1].  */
    167   std::unique_ptr<unsigned char[]> standard_opcode_lengths;
    168 
    169   int file_names_size () const
    170   { return m_file_names.size(); }
    171 
    172   /* The start and end of the statement program following this
    173      header.  These point into dwarf2_per_objfile->line_buffer.  */
    174   const gdb_byte *statement_program_start {}, *statement_program_end {};
    175 
    176   /* Return the most "complete" file name for FILE possible.
    177 
    178      This means prepending the directory and compilation directory, as needed,
    179      until we get an absolute path.  */
    180   std::string file_file_name (const file_entry &fe) const;
    181 
    182   /* Return the compilation directory of the compilation unit in the context of
    183      which this line header is read.  Return nullptr if non applicable.  */
    184   const char *comp_dir () const
    185   { return m_comp_dir; }
    186 
    187  private:
    188   /* The include_directories table.  Note these are observing
    189      pointers.  The memory is owned by debug_line_buffer.  */
    190   std::vector<const char *> m_include_dirs;
    191 
    192   /* The file_names table. This is private because the meaning of indexes
    193      differs among DWARF versions (The first valid index is 1 in DWARF 4 and
    194      before, and is 0 in DWARF 5 and later).  So the client should use
    195      file_name_at method for access.  */
    196   std::vector<file_entry> m_file_names;
    197 
    198   /* Compilation directory of the compilation unit in the context of which this
    199      line header is read.  nullptr if unknown or not applicable.  */
    200   const char *m_comp_dir = nullptr;
    201 };
    202 
    203 typedef std::unique_ptr<line_header> line_header_up;
    204 
    205 inline const char *
    206 file_entry::include_dir (const line_header *lh) const
    207 {
    208   return lh->include_dir_at (d_index);
    209 }
    210 
    211 /* Read the statement program header starting at SECT_OFF in SECTION.
    212    Return line_header.  Returns nullptr if there is a problem reading
    213    the header, e.g., if it has a version we don't understand.
    214 
    215    NOTE: the strings in the include directory and file name tables of
    216    the returned object point into the dwarf line section buffer,
    217    and must not be freed.  */
    218 
    219 extern line_header_up dwarf_decode_line_header
    220   (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile,
    221    struct dwarf2_section_info *section, const struct comp_unit_head *cu_header,
    222    const char *comp_dir);
    223 
    224 #endif /* GDB_DWARF2_LINE_HEADER_H */
    225