aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/line-header.h
blob: ae06b3c195b4033ed7dc8d953d7349e5ff2f1110 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* 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 <http://www.gnu.org/licenses/>.  */

#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<line_header *> (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_entry> &file_names ()
  { return m_file_names; }
  /* A const overload of the same.  */
  const std::vector<file_entry> &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<unsigned char[]> 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 the full name of file number I in this object's file name
     table.  Use COMP_DIR as the name of the current directory of the
     compilation.  The result is allocated using xmalloc; the caller
     is responsible for freeing it.  */
  gdb::unique_xmalloc_ptr<char> file_full_name (int file,
						const char *comp_dir) const;

  /* 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<char> 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<const char *> 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<file_entry> m_file_names;
};

typedef std::unique_ptr<line_header> 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 */