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