mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
1fd5fd5817
When run with the gdb-index or debug-names target boards, dup-psym.exp fails. This came up for me because my new DWARF scanner reuses this part of the existing index code, and so it registers as a regression. This is PR symtab/25834. Looking into this, I found that the DWARF index code here is fairly different from the psymtab code. I don't think there's a deep reason for this, and in fact, it seemed to me that the index code could simply mimic what the psymtab code already does. That is what this patch implements. The DW_AT_name and DW_AT_comp_dir are now stored in the quick file names table. This may require allocating a quick file names table even when DW_AT_stmt_list does not exist. Then, the functions that work with this data are changed to use find_source_or_rewrite, just as the psymbol code does. Finally, line_header::file_full_name is removed, as it is no longer needed. Currently, the index maintains a hash table of "quick file names". The hash table uses a deletion function to free the "real name" components when necessary. There's also a second such function to implement the forget_cached_source_info method. This bug fix patch will create a quick file name object even when there is no DW_AT_stmt_list, meaning that the object won't be entered in the hash table. So, this patch changes the memory management approach so that the entries are cleared when the per-BFD object is destroyed. (A dwarf2_per_cu_data destructor is not introduced, because we have been avoiding adding a vtable to that class.) Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25834
204 lines
6.6 KiB
C++
204 lines
6.6 KiB
C++
/* 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 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 */
|