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