aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/MAINTAINERS6
-rw-r--r--gdb/cli/cli-cmds.c5
-rw-r--r--gdb/corelow.c5
-rw-r--r--gdb/dictionary.c26
-rw-r--r--gdb/dwarf2/cooked-indexer.c42
-rw-r--r--gdb/dwarf2/cooked-indexer.h4
-rw-r--r--gdb/dwarf2/cu.h5
-rw-r--r--gdb/dwarf2/index-write.c142
-rw-r--r--gdb/dwarf2/read-debug-names.c148
-rw-r--r--gdb/dwarf2/read-gdb-index.c38
-rw-r--r--gdb/dwarf2/read.c445
-rw-r--r--gdb/dwarf2/read.h54
-rw-r--r--gdb/dwarf2/section.h10
-rw-r--r--gdb/inflow.c23
-rw-r--r--gdb/mingw-hdep.c5
-rw-r--r--gdb/solib-frv.h2
-rw-r--r--gdb/solib-svr4.c15
-rw-r--r--gdb/solib.c5
-rw-r--r--gdb/svr4-tls-tdep.c2
-rw-r--r--gdb/symtab.c5
-rw-r--r--gdb/terminal.h15
-rw-r--r--gdb/testsuite/gdb.ada/operator_call.exp6
-rw-r--r--gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp81
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp109
-rw-r--r--gdb/testsuite/gdb.dwarf2/varval.exp2
-rw-r--r--gdb/testsuite/gdb.gdb/python-helper.exp20
-rw-r--r--gdb/testsuite/gdb.tui/main-2.exp2
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm.exp46
-rw-r--r--gdb/testsuite/lib/tuiterm.exp93
29 files changed, 843 insertions, 518 deletions
diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS
index 9284c46..f46afa7 100644
--- a/gdb/MAINTAINERS
+++ b/gdb/MAINTAINERS
@@ -234,7 +234,7 @@ Pedro Alves pedro@palves.net
John Baldwin jhb@freebsd.org
Kevin Buettner kevinb@redhat.com
Andrew Burgess aburgess@redhat.com
-Luis Machado luis.machado@arm.com
+Luis Machado luis.machado.foss@gmail.com
Simon Marchi simon.marchi@polymtl.ca
Tom Tromey tom@tromey.com
Tom de Vries tdevries@suse.de
@@ -320,7 +320,7 @@ the native maintainer when resolving ABI issues.
aarch64 --target=aarch64-elf
Alan Hayward alan.hayward@arm.com
- Luis Machado luis.machado@arm.com
+ Luis Machado luis.machado.foss@gmail.com
alpha --target=alpha-elf
@@ -332,7 +332,7 @@ the native maintainer when resolving ABI issues.
arm --target=arm-elf
Alan Hayward alan.hayward@arm.com
- Luis Machado luis.machado@arm.com
+ Luis Machado luis.machado.foss@gmail.com
avr --target=avr
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 5e887f5..a15a04a 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -51,6 +51,7 @@
#include "cli/cli-cmds.h"
#include "cli/cli-style.h"
#include "cli/cli-utils.h"
+#include "terminal.h"
#include "extension.h"
#include "gdbsupport/pathstuff.h"
@@ -949,6 +950,9 @@ shell_escape (const char *arg, int from_tty)
static void
shell_command (const char *arg, int from_tty)
{
+ scoped_gdb_ttystate save_restore_gdb_ttystate;
+ restore_initial_gdb_ttystate ();
+
shell_escape (arg, from_tty);
}
@@ -2898,6 +2902,7 @@ This can be changed using \"set listsize\", and the current value\n\
can be shown using \"show listsize\"."));
add_com_alias ("l", list_cmd, class_files, 1);
+ set_cmd_completer(list_cmd, location_completer);
c = add_com ("disassemble", class_vars, disassemble_command, _("\
Disassemble a specified section of memory.\n\
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 24b949b..a74cb05 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -451,11 +451,8 @@ core_target::build_file_mappings ()
const bfd_build_id *core_build_id
= build_id_bfd_get (current_program_space->core_bfd ());
- for (const auto &iter : mapped_files)
+ for (const auto &[filename, file_data] : mapped_files)
{
- const std::string &filename = iter.first;
- const mapped_file &file_data = iter.second;
-
/* If this mapped file has the same build-id as was discovered for
the core-file itself, then we assume this is the main
executable. Record the filename as we can use this later. */
diff --git a/gdb/dictionary.c b/gdb/dictionary.c
index 91dafd1..28e900d 100644
--- a/gdb/dictionary.c
+++ b/gdb/dictionary.c
@@ -952,14 +952,9 @@ mdict_create_hashed (struct obstack *obstack,
retval->n_allocated_dictionaries = nsyms.size ();
int idx = 0;
- for (const auto &pair : nsyms)
- {
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
-
- retval->dictionaries[idx++]
- = dict_create_hashed (obstack, language, symlist);
- }
+ for (const auto &[language, symlist] : nsyms)
+ retval->dictionaries[idx++] = dict_create_hashed (obstack, language,
+ symlist);
return retval;
}
@@ -997,14 +992,9 @@ mdict_create_linear (struct obstack *obstack,
retval->n_allocated_dictionaries = nsyms.size ();
int idx = 0;
- for (const auto &pair : nsyms)
- {
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
-
- retval->dictionaries[idx++]
- = dict_create_linear (obstack, language, symlist);
- }
+ for (const auto &[language, symlist] : nsyms)
+ retval->dictionaries[idx++] = dict_create_linear (obstack, language,
+ symlist);
return retval;
}
@@ -1135,10 +1125,8 @@ mdict_add_pending (struct multidictionary *mdict,
gdb::unordered_map<enum language, std::vector<symbol *>> nsyms
= collate_pending_symbols_by_language (symbol_list);
- for (const auto &pair : nsyms)
+ for (const auto &[language, symlist] : nsyms)
{
- enum language language = pair.first;
- std::vector<symbol *> symlist = pair.second;
struct dictionary *dict = find_language_dictionary (mdict, language);
if (dict == nullptr)
diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c
index c093984..d4557c45 100644
--- a/gdb/dwarf2/cooked-indexer.c
+++ b/gdb/dwarf2/cooked-indexer.c
@@ -83,19 +83,17 @@ tag_can_have_linkage_name (enum dwarf_tag tag)
cutu_reader *
cooked_indexer::ensure_cu_exists (cutu_reader *reader,
- sect_offset sect_off, bool is_dwz,
+ const section_and_offset &sect_off,
bool for_scanning)
{
/* Lookups for type unit references are always in the CU, and
cross-CU references will crash. */
- if (reader->cu ()->per_cu->is_dwz == is_dwz
- && reader->cu ()->header.offset_in_unit_p (sect_off))
+ if (reader->section () == sect_off.section
+ && reader->cu ()->header.offset_in_unit_p (sect_off.offset))
return reader;
dwarf2_per_objfile *per_objfile = reader->cu ()->per_objfile;
- dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
- per_objfile->per_bfd);
+ dwarf2_per_cu *per_cu = dwarf2_find_containing_unit (sect_off, per_objfile);
/* When scanning, we only want to visit a given CU a single time.
Doing this check here avoids self-imports as well. */
@@ -148,10 +146,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
bool *is_enum_class,
bool for_specification)
{
- bool origin_is_dwz = false;
bool is_declaration = false;
- sect_offset origin_offset {};
-
+ std::optional<section_and_offset> origin;
std::optional<unrelocated_addr> low_pc;
std::optional<unrelocated_addr> high_pc;
bool high_pc_relative = false;
@@ -221,8 +217,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
case DW_AT_specification:
case DW_AT_abstract_origin:
case DW_AT_extension:
- origin_offset = attr.get_ref_die_offset ();
- origin_is_dwz = attr.form_is_alt ();
+ origin = { &get_section_for_ref (attr, reader->cu ()),
+ attr.get_ref_die_offset () };
break;
case DW_AT_external:
@@ -311,19 +307,19 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
|| (*linkage_name == nullptr
&& tag_can_have_linkage_name (abbrev->tag))
|| (*parent_entry == nullptr && m_language != language_c))
- && origin_offset != sect_offset (0))
+ && origin.has_value ())
{
cutu_reader *new_reader
- = ensure_cu_exists (reader, origin_offset, origin_is_dwz, false);
+ = ensure_cu_exists (reader, *origin, false);
if (new_reader == nullptr)
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
- sect_offset_str (origin_offset),
+ sect_offset_str (origin->offset),
bfd_get_filename (reader->abfd ()));
const gdb_byte *new_info_ptr
- = (new_reader->buffer () + to_underlying (origin_offset));
+ = (new_reader->buffer () + to_underlying (origin->offset));
if (*parent_entry == nullptr)
{
@@ -347,7 +343,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
if (new_abbrev == nullptr)
error (_(DWARF_ERROR_PREFIX
"Unexpected null DIE at offset %s [in module %s]"),
- sect_offset_str (origin_offset),
+ sect_offset_str (origin->offset),
bfd_get_filename (new_reader->abfd ()));
new_info_ptr += bytes_read;
@@ -411,8 +407,7 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
const gdb_byte *info_ptr,
const abbrev_info *abbrev)
{
- sect_offset sect_off {};
- bool is_dwz = false;
+ std::optional<section_and_offset> target;
for (int i = 0; i < abbrev->num_attrs; ++i)
{
@@ -421,19 +416,16 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
info_ptr = reader->read_attribute (&attr, &abbrev->attrs[i], info_ptr);
if (attr.name == DW_AT_import)
- {
- sect_off = attr.get_ref_die_offset ();
- is_dwz = (attr.form_is_alt ()
- || reader->cu ()->per_cu->is_dwz);
- }
+ target = { &get_section_for_ref (attr, reader->cu ()),
+ attr.get_ref_die_offset () };
}
/* Did not find DW_AT_import. */
- if (sect_off == sect_offset (0))
+ if (!target.has_value ())
return info_ptr;
cutu_reader *new_reader
- = ensure_cu_exists (reader, sect_off, is_dwz, true);
+ = ensure_cu_exists (reader, *target, true);
if (new_reader != nullptr)
{
index_dies (new_reader, new_reader->info_ptr (), nullptr, false);
diff --git a/gdb/dwarf2/cooked-indexer.h b/gdb/dwarf2/cooked-indexer.h
index 904c55f..83cbf7f 100644
--- a/gdb/dwarf2/cooked-indexer.h
+++ b/gdb/dwarf2/cooked-indexer.h
@@ -30,6 +30,7 @@ struct cooked_index_worker_result;
struct cutu_reader;
struct dwarf2_per_cu;
struct dwarf2_per_objfile;
+struct section_and_offset;
/* An instance of this is created to index a CU. */
@@ -55,8 +56,7 @@ private:
the DIEs in the CU; when false, this use is assumed to be to look
up just a single DIE. */
cutu_reader *ensure_cu_exists (cutu_reader *reader,
- sect_offset sect_off,
- bool is_dwz,
+ const section_and_offset &sect_off,
bool for_scanning);
/* Index DIEs in the READER starting at INFO_PTR. PARENT is
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
index 69f396c..68010a0 100644
--- a/gdb/dwarf2/cu.h
+++ b/gdb/dwarf2/cu.h
@@ -54,6 +54,11 @@ struct dwarf2_cu
DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
+ /* The section the DIEs were effectively read from. This could be
+ .debug_info, .debug_types, or with split DWARF, their .dwo
+ variants. */
+ const dwarf2_section_info &section () const;
+
/* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
Create the set of symtabs used by this TU, or if this TU is sharing
symtabs with another TU and the symtabs have already been created
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 0a3b9d0..d5b198b 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -872,7 +872,7 @@ public:
m_debugstrlookup.file_write (file_str);
}
- void add_cu (dwarf2_per_cu *per_cu, offset_type index)
+ void add_cu (const dwarf2_per_cu *per_cu, offset_type index)
{
m_cu_index_htab.emplace (per_cu, index);
}
@@ -1289,6 +1289,40 @@ write_shortcuts_table (cooked_index *table, data_buf &shortcuts,
shortcuts.append_offset (main_name_offset);
}
+/* Get sorted (by section offset) lists of comp units and type units. */
+
+static std::pair<std::vector<const dwarf2_per_cu *>,
+ std::vector<const signatured_type *>>
+get_unit_lists (const dwarf2_per_bfd &per_bfd)
+{
+ std::vector<const dwarf2_per_cu *> comp_units;
+ std::vector<const signatured_type *> type_units;
+
+ for (const auto &unit : per_bfd.all_units)
+ if (unit->is_debug_types)
+ type_units.emplace_back (static_cast<const signatured_type *>
+ (unit.get ()));
+ else
+ comp_units.emplace_back (unit.get ());
+
+ auto by_sect_off = [] (const dwarf2_per_cu *lhs, const dwarf2_per_cu *rhs)
+ { return lhs->sect_off < rhs->sect_off; };
+
+ /* Sort both lists, even though it is technically not always required:
+
+ - while .gdb_index requires the CU list to be sorted, DWARF 5 doesn't
+ say anything about the order of CUs in .debug_names.
+ - .gdb_index doesn't require the TU list to be sorted, and DWARF 5
+ doesn't say anything about the order of TUs in .debug_names.
+
+ However, it helps make sure that GDB produce a stable and predictable
+ output, which is nice. */
+ std::sort (comp_units.begin (), comp_units.end (), by_sect_off);
+ std::sort (type_units.begin (), type_units.end (), by_sect_off);
+
+ return {std::move (comp_units), std::move (type_units)};
+}
+
/* Write contents of a .gdb_index section for OBJFILE into OUT_FILE.
If OBJFILE has an associated dwz file, write contents of a .gdb_index
section for that dwz file into DWZ_OUT_FILE. If OBJFILE does not have an
@@ -1299,8 +1333,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
FILE *out_file, FILE *dwz_out_file)
{
mapped_symtab symtab;
- data_buf objfile_cu_list;
- data_buf dwz_cu_list;
/* While we're scanning CU's create a table that maps a dwarf2_per_cu (which
is what addrmap records) to its index (which is what is recorded in the
@@ -1308,40 +1340,44 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
cu_index_map cu_index_htab;
cu_index_htab.reserve (per_bfd->all_units.size ());
- /* Store out the .debug_type CUs, if any. */
- data_buf types_cu_list;
+ auto [comp_units, type_units] = get_unit_lists (*per_bfd);
+ int counter = 0;
- /* The CU list is already sorted, so we don't need to do additional
- work here. */
+ /* Write comp units. */
+ data_buf objfile_cu_list;
+ data_buf dwz_cu_list;
- int counter = 0;
- for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
+ for (const dwarf2_per_cu *per_cu : comp_units)
{
- const auto insertpair = cu_index_htab.emplace (per_cu.get (), counter);
+ const auto insertpair = cu_index_htab.emplace (per_cu, counter);
gdb_assert (insertpair.second);
- /* See enhancement PR symtab/30838. */
- gdb_assert (!(per_cu->is_dwz && per_cu->is_debug_types));
-
/* The all_units list contains CUs read from the objfile as well as
from the eventual dwz file. We need to place the entry in the
corresponding index. */
- data_buf &cu_list = (per_cu->is_debug_types
- ? types_cu_list
- : per_cu->is_dwz ? dwz_cu_list : objfile_cu_list);
+ data_buf &cu_list = per_cu->is_dwz ? dwz_cu_list : objfile_cu_list;
cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
to_underlying (per_cu->sect_off));
- if (per_cu->is_debug_types)
- {
- signatured_type *sig_type = (signatured_type *) per_cu.get ();
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
- to_underlying (sig_type->type_offset_in_tu));
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
- sig_type->signature);
- }
- else
- cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ());
+ cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ());
+ ++counter;
+ }
+
+ /* Write type units. */
+ data_buf types_cu_list;
+
+ for (const signatured_type *sig_type : type_units)
+ {
+ const auto insertpair = cu_index_htab.emplace (sig_type, counter);
+ gdb_assert (insertpair.second);
+
+ /* See enhancement PR symtab/30838. */
+ gdb_assert (!sig_type->is_dwz);
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+ to_underlying (sig_type->sect_off));
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+ to_underlying (sig_type->type_offset_in_tu));
+ types_cu_list.append_uint (8, BFD_ENDIAN_LITTLE, sig_type->signature);
++counter;
}
@@ -1388,29 +1424,35 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
const enum bfd_endian dwarf5_byte_order
= bfd_big_endian (per_bfd->obfd) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- /* The CU list is already sorted, so we don't need to do additional
- work here. Also, the debug_types entries do not appear in
- all_units, but only in their own hash table. */
- data_buf cu_list;
- data_buf types_cu_list;
+ auto [comp_units, type_units] = get_unit_lists (*per_bfd);
debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order);
- int counter = 0;
- int types_counter = 0;
- for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
+ data_buf comp_unit_list;
+ int comp_unit_counter = 0;
+
+ for (const auto per_cu : comp_units)
+ {
+ nametable.add_cu (per_cu, comp_unit_counter);
+ comp_unit_list.append_uint (nametable.dwarf5_offset_size (),
+ dwarf5_byte_order,
+ to_underlying (per_cu->sect_off));
+ comp_unit_counter++;
+ }
+
+ data_buf type_unit_list;
+ int type_unit_counter = 0;
+
+ for (const auto per_cu : type_units)
{
- int &this_counter = per_cu->is_debug_types ? types_counter : counter;
- data_buf &this_list = per_cu->is_debug_types ? types_cu_list : cu_list;
-
- nametable.add_cu (per_cu.get (), this_counter);
- this_list.append_uint (nametable.dwarf5_offset_size (),
- dwarf5_byte_order,
- to_underlying (per_cu->sect_off));
- ++this_counter;
+ nametable.add_cu (per_cu, type_unit_counter);
+ type_unit_list.append_uint (nametable.dwarf5_offset_size (),
+ dwarf5_byte_order,
+ to_underlying (per_cu->sect_off));
+ type_unit_counter++;
}
/* Verify that all units are represented. */
- gdb_assert (counter == per_bfd->all_comp_units.size ());
- gdb_assert (types_counter == per_bfd->all_type_units.size ());
+ gdb_assert (comp_unit_counter == per_bfd->num_comp_units);
+ gdb_assert (type_unit_counter == per_bfd->num_type_units);
for (const cooked_index_entry *entry : table->all_entries ())
nametable.insert (entry);
@@ -1425,8 +1467,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
+ sizeof (dwarf5_augmentation_3));
size_t expected_bytes = 0;
expected_bytes += bytes_of_header;
- expected_bytes += cu_list.size ();
- expected_bytes += types_cu_list.size ();
+ expected_bytes += comp_unit_list.size ();
+ expected_bytes += type_unit_list.size ();
expected_bytes += nametable.bytes ();
data_buf header;
@@ -1449,11 +1491,11 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
header.append_uint (2, dwarf5_byte_order, 0);
/* comp_unit_count - The number of CUs in the CU list. */
- header.append_uint (4, dwarf5_byte_order, counter);
+ header.append_uint (4, dwarf5_byte_order, comp_unit_counter);
/* local_type_unit_count - The number of TUs in the local TU
list. */
- header.append_uint (4, dwarf5_byte_order, types_counter);
+ header.append_uint (4, dwarf5_byte_order, type_unit_counter);
/* foreign_type_unit_count - The number of TUs in the foreign TU
list. */
@@ -1481,8 +1523,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
gdb_assert (header.size () == bytes_of_header);
header.file_write (out_file);
- cu_list.file_write (out_file);
- types_cu_list.file_write (out_file);
+ comp_unit_list.file_write (out_file);
+ type_unit_list.file_write (out_file);
nametable.file_write (out_file, out_file_str);
assert_file_size (out_file, expected_bytes);
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 4b3f385..97677c0 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -114,6 +114,14 @@ struct mapped_debug_names_reader
gdb::unordered_map<ULONGEST, index_val> abbrev_map;
+ /* List of CUs in the same order as found in the index header (DWARF 5 section
+ 6.1.1.4.2). */
+ std::vector<dwarf2_per_cu *> comp_units;
+
+ /* List of local TUs in the same order as found in the index (DWARF 5 section
+ 6.1.1.4.3). */
+ std::vector<dwarf2_per_cu *> type_units;
+
/* Even though the scanning of .debug_names and creation of the
cooked index entries is done serially, we create multiple shards
so that the finalization step can be parallelized. The shards
@@ -232,7 +240,7 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
case DW_IDX_compile_unit:
{
/* Don't crash on bad data. */
- if (ull >= per_objfile->per_bfd->all_comp_units.size ())
+ if (ull >= this->comp_units.size ())
{
complaint (_(".debug_names entry has bad CU index %s"
" [in module %s]"),
@@ -240,30 +248,31 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
bfd_get_filename (abfd));
continue;
}
+
+ per_cu = this->comp_units[ull];
+ break;
}
- per_cu = per_objfile->per_bfd->get_unit (ull);
- break;
case DW_IDX_type_unit:
- /* Don't crash on bad data. */
- if (ull >= per_objfile->per_bfd->all_type_units.size ())
- {
- complaint (_(".debug_names entry has bad TU index %s"
- " [in module %s]"),
- pulongest (ull),
- bfd_get_filename (abfd));
- continue;
- }
{
- int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
- per_cu = per_objfile->per_bfd->get_unit (nr_cus + ull);
+ /* Don't crash on bad data. */
+ if (ull >= this->type_units.size ())
+ {
+ complaint (_(".debug_names entry has bad TU index %s"
+ " [in module %s]"),
+ pulongest (ull),
+ bfd_get_filename (abfd));
+ continue;
+ }
+
+ per_cu = this->type_units[ull];
+ break;
}
- break;
case DW_IDX_die_offset:
die_offset = sect_offset (ull);
/* In a per-CU index (as opposed to a per-module index), index
entries without CU attribute implicitly refer to the single CU. */
- if (per_cu == NULL)
- per_cu = per_objfile->per_bfd->get_unit (0);
+ if (per_cu == nullptr)
+ per_cu = this->comp_units[0];
break;
case DW_IDX_parent:
parent = ull;
@@ -440,45 +449,45 @@ cooked_index_worker_debug_names::do_reading ()
bfd_thread_cleanup ();
}
-/* Check the signatured type hash table from .debug_names. */
+/* Build the list of TUs (mapped_debug_names_reader::type_units) from the index
+ header and verify that it matches the list of TUs read from the DIEs in
+ `.debug_info`.
+
+ Return true if they match, false otherwise. */
static bool
-check_signatured_type_table_from_debug_names
- (dwarf2_per_objfile *per_objfile,
- const mapped_debug_names_reader &map,
- struct dwarf2_section_info *section)
+build_and_check_tu_list_from_debug_names (dwarf2_per_objfile *per_objfile,
+ mapped_debug_names_reader &map,
+ dwarf2_section_info *section)
{
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- int nr_cus = per_bfd->all_comp_units.size ();
- int nr_cus_tus = per_bfd->all_units.size ();
section->read (objfile);
- uint32_t j = nr_cus;
for (uint32_t i = 0; i < map.tu_count; ++i)
{
+ /* Read one entry from the TU list. */
sect_offset sect_off
= (sect_offset) (extract_unsigned_integer
(map.tu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
- bool found = false;
- for (; j < nr_cus_tus; j++)
- if (per_bfd->get_unit (j)->sect_off == sect_off)
- {
- found = true;
- break;
- }
- if (!found)
+ /* Find the matching dwarf2_per_cu. */
+ dwarf2_per_cu *per_cu = dwarf2_find_unit ({ section, sect_off },
+ per_bfd);
+
+ if (per_cu == nullptr || !per_cu->is_debug_types)
{
warning (_("Section .debug_names has incorrect entry in TU table,"
" ignoring .debug_names."));
return false;
}
- per_bfd->all_comp_units_index_tus.push_back (per_bfd->get_unit (j));
+
+ map.type_units.emplace_back (per_cu);
}
+
return true;
}
@@ -700,40 +709,11 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
list. */
static bool
-check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names_reader &map,
- dwarf2_section_info &section,
- bool is_dwz)
+build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd,
+ mapped_debug_names_reader &map,
+ dwarf2_section_info &section)
{
- int nr_cus = per_bfd->all_comp_units.size ();
-
- if (!map.augmentation_is_gdb)
- {
- uint32_t j = 0;
- for (uint32_t i = 0; i < map.cu_count; ++i)
- {
- sect_offset sect_off
- = (sect_offset) (extract_unsigned_integer
- (map.cu_table_reordered + i * map.offset_size,
- map.offset_size,
- map.dwarf5_byte_order));
- bool found = false;
- for (; j < nr_cus; j++)
- if (per_bfd->get_unit (j)->sect_off == sect_off)
- {
- found = true;
- break;
- }
- if (!found)
- {
- warning (_("Section .debug_names has incorrect entry in CU table,"
- " ignoring .debug_names."));
- return false;
- }
- per_bfd->all_comp_units_index_cus.push_back (per_bfd->get_unit (j));
- }
- return true;
- }
+ int nr_cus = per_bfd->num_comp_units;
if (map.cu_count != nr_cus)
{
@@ -749,35 +729,43 @@ check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
(map.cu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
- if (sect_off != per_bfd->get_unit (i)->sect_off)
+
+ /* Find the matching dwarf2_per_cu. */
+ dwarf2_per_cu *per_cu = dwarf2_find_unit ({ &section, sect_off }, per_bfd);
+
+ if (per_cu == nullptr || per_cu->is_debug_types)
{
warning (_("Section .debug_names has incorrect entry in CU table,"
" ignoring .debug_names."));
return false;
}
+
+ map.comp_units.emplace_back (per_cu);
}
return true;
}
-/* Read the CU list from the mapped index, and use it to create all
- the CU objects for this dwarf2_per_objfile. */
+/* Build the list of CUs (mapped_debug_names_reader::compile_units) from the
+ index header and verify that it matches the list of CUs read from the DIEs in
+ `.debug_info`.
+
+ Return true if they match, false otherwise. */
static bool
-check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names_reader &map,
- const mapped_debug_names_reader &dwz_map)
+build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd,
+ mapped_debug_names_reader &map,
+ mapped_debug_names_reader &dwz_map)
{
- if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->infos[0],
- false /* is_dwz */))
+ if (!build_and_check_cu_list_from_debug_names (per_bfd, map,
+ per_bfd->infos[0]))
return false;
if (dwz_map.cu_count == 0)
return true;
dwz_file *dwz = per_bfd->get_dwz_file ();
- return check_cus_from_debug_names_list (per_bfd, dwz_map, dwz->info,
- true /* is_dwz */);
+ return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info);
}
/* This does all the work for dwarf2_read_debug_names, but putting it
@@ -815,7 +803,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
}
create_all_units (per_objfile);
- if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
+ if (!build_and_check_cu_lists_from_debug_names (per_bfd, map, dwz_map))
return false;
if (map.tu_count != 0)
@@ -831,8 +819,8 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
? &per_bfd->types[0]
: &per_bfd->infos[0]);
- if (!check_signatured_type_table_from_debug_names (per_objfile,
- map, section))
+ if (!build_and_check_tu_list_from_debug_names (per_objfile, map,
+ section))
return false;
}
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index 464fbdd..76317fe 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -117,6 +117,10 @@ struct mapped_gdb_index : public dwarf_scanner_base
/* Index data format version. */
int version = 0;
+ /* Compile units followed by type units, in the order as found in the
+ index. Indices found in index entries can index directly into this. */
+ std::vector<dwarf2_per_cu *> units;
+
/* The address table data. */
gdb::array_view<const gdb_byte> address_table;
@@ -1106,14 +1110,14 @@ dw2_expand_marked_cus (dwarf2_per_objfile *per_objfile, offset_type idx,
}
/* Don't crash on bad data. */
- if (cu_index >= per_objfile->per_bfd->all_units.size ())
+ if (cu_index >= index.units.size ())
{
complaint (_(".gdb_index entry has bad CU index"
" [in module %s]"), objfile_name (per_objfile->objfile));
continue;
}
- dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_unit (cu_index);
+ dwarf2_per_cu *per_cu = index.units[cu_index];
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
expansion_notify, lang_matcher))
@@ -1313,7 +1317,7 @@ static void
create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type n_elements,
struct dwarf2_section_info *section,
- int is_dwz)
+ int is_dwz, std::vector<dwarf2_per_cu *> &units)
{
for (offset_type i = 0; i < n_elements; i += 2)
{
@@ -1324,10 +1328,10 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
cu_list += 2 * 8;
- per_bfd->all_units.emplace_back (per_bfd->allocate_per_cu (section,
- sect_off,
- length,
- is_dwz));
+ dwarf2_per_cu_up per_cu = per_bfd->allocate_per_cu (section, sect_off,
+ length, is_dwz);
+ units.emplace_back (per_cu.get ());
+ per_bfd->all_units.emplace_back (std::move (per_cu));
}
}
@@ -1337,20 +1341,21 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
static void
create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type cu_list_elements,
+ std::vector<dwarf2_per_cu *> &units,
const gdb_byte *dwz_list, offset_type dwz_elements)
{
gdb_assert (per_bfd->all_units.empty ());
per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
- &per_bfd->infos[0], 0);
+ &per_bfd->infos[0], 0, units);
if (dwz_elements == 0)
return;
dwz_file *dwz = per_bfd->get_dwz_file ();
create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements,
- &dwz->info, 1);
+ &dwz->info, 1, units);
}
/* Create the signatured type hash table from the index. */
@@ -1358,7 +1363,8 @@ create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
static void
create_signatured_type_table_from_gdb_index
(dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
- const gdb_byte *bytes, offset_type elements)
+ const gdb_byte *bytes, offset_type elements,
+ std::vector<dwarf2_per_cu *> &units)
{
signatured_type_set sig_types_hash;
@@ -1382,6 +1388,7 @@ create_signatured_type_table_from_gdb_index
sig_type->type_offset_in_tu = type_offset_in_tu;
sig_types_hash.emplace (sig_type.get ());
+ units.emplace_back (sig_type.get ());
per_bfd->all_units.emplace_back (sig_type.release ());
}
@@ -1419,14 +1426,14 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
continue;
}
- if (cu_index >= per_bfd->all_units.size ())
+ if (cu_index >= index->units.size ())
{
complaint (_(".gdb_index address table has invalid CU number %u"),
(unsigned) cu_index);
continue;
}
- mutable_map.set_empty (lo, hi - 1, per_bfd->get_unit (cu_index));
+ mutable_map.set_empty (lo, hi - 1, index->units[cu_index]);
}
index->index_addrmap
@@ -1528,8 +1535,8 @@ dwarf2_read_gdb_index
}
}
- create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list,
- dwz_list_elements);
+ create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, map->units,
+ dwz_list, dwz_list_elements);
if (types_list_elements)
{
@@ -1548,7 +1555,8 @@ dwarf2_read_gdb_index
: &per_bfd->infos[0]);
create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
- types_list_elements);
+ types_list_elements,
+ map->units);
}
finalize_all_units (per_bfd);
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 5e18e45..ec8d376 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1690,6 +1690,7 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section,
dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off,
length, is_dwz));
result->index = all_units.size ();
+ this->num_comp_units++;
return result;
}
@@ -1706,7 +1707,7 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
= std::make_unique<signatured_type> (this, section, sect_off, length,
is_dwz, signature);
result->index = all_units.size ();
- tu_stats.nr_tus++;
+ this->num_type_units++;
return result;
}
@@ -2370,6 +2371,24 @@ get_abbrev_section_for_cu (dwarf2_per_cu *this_cu)
return abbrev;
}
+/* "less than" function used to both sort and bisect units in the
+ `dwarf2_per_bfd::all_units` vector. Return true if the LHS CU comes before
+ (is "less" than) the section and offset in RHS.
+
+ For simplicity, sort sections by their pointer. This is not ideal, because
+ it can cause the behavior to change across runs, making some bugs harder to
+ investigate. An improvement would be for sections to be sorted by their
+ properties. */
+
+static bool
+all_units_less_than (const dwarf2_per_cu &lhs, const section_and_offset &rhs)
+{
+ if (lhs.section != rhs.section)
+ return lhs.section < rhs.section;
+
+ return lhs.sect_off < rhs.offset;
+}
+
/* Fetch the abbreviation table offset from a comp or type unit header. */
static sect_offset
@@ -2413,7 +2432,17 @@ add_type_unit (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section,
false /* is_dwz */, sig);
signatured_type *sig_type = sig_type_holder.get ();
- per_bfd->all_units.emplace_back (sig_type_holder.release ());
+ /* Preserve the ordering of per_bfd->all_units. */
+ auto insert_it
+ = std::lower_bound (per_bfd->all_units.begin (), per_bfd->all_units.end (),
+ sig_type,
+ [] (const dwarf2_per_cu_up &lhs,
+ const signatured_type *rhs) {
+ return all_units_less_than (*lhs, { rhs->section,
+ rhs->sect_off });
+ });
+
+ per_bfd->all_units.emplace (insert_it, sig_type_holder.release ());
auto emplace_ret = per_bfd->signatured_types.emplace (sig_type);
/* Assert that an insertion took place - that there wasn't a type unit with
@@ -3212,10 +3241,11 @@ private:
void print_tu_stats (dwarf2_per_objfile *per_objfile)
{
- struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ tu_stats *tu_stats = &per_bfd->tu_stats;
dwarf_read_debug_printf ("Type unit statistics:");
- dwarf_read_debug_printf (" %d TUs", tu_stats->nr_tus);
+ dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units);
dwarf_read_debug_printf (" %d uniq abbrev tables",
tu_stats->nr_uniq_abbrev_tables);
dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
@@ -3365,7 +3395,7 @@ cooked_index_worker_debug_info::process_type_units
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
- if (per_objfile->per_bfd->all_type_units.size () == 0)
+ if (per_objfile->per_bfd->num_type_units == 0)
return;
/* TUs typically share abbrev tables, and there can be way more TUs than
@@ -3392,7 +3422,7 @@ cooked_index_worker_debug_info::process_type_units
/* Sort in a separate table to maintain the order of all_units
for .gdb_index: TU indices directly index all_type_units. */
std::vector<tu_abbrev_offset> sorted_by_abbrev;
- sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ());
+ sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units);
for (const auto &cu : per_objfile->per_bfd->all_units)
if (cu->is_debug_types)
@@ -3644,16 +3674,18 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
}
}
-/* Initialize the views on all_units. */
+/* See read.h. */
void
finalize_all_units (dwarf2_per_bfd *per_bfd)
{
- size_t nr_tus = per_bfd->tu_stats.nr_tus;
- size_t nr_cus = per_bfd->all_units.size () - nr_tus;
- gdb::array_view<dwarf2_per_cu_up> tmp = per_bfd->all_units;
- per_bfd->all_comp_units = tmp.slice (0, nr_cus);
- per_bfd->all_type_units = tmp.slice (nr_cus, nr_tus);
+ /* Ensure that the all_units vector is in the expected order for
+ dwarf2_find_containing_unit to be able to perform a binary search. */
+ std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
+ [] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b)
+ {
+ return all_units_less_than (*a, { b->section, b->sect_off });
+ });
}
/* See read.h. */
@@ -4909,6 +4941,21 @@ process_full_type_unit (dwarf2_cu *cu)
cu->reset_builder ();
}
+/* See read.h. */
+
+const dwarf2_section_info &
+get_section_for_ref (const attribute &attr, dwarf2_cu *cu)
+{
+ gdb_assert (attr.form_is_ref ());
+
+ if (attr.form_is_alt ())
+ return cu->per_cu->per_bfd->get_dwz_file (true)->info;
+
+ /* If the source is already in the supplementary (dwz) file, then CU->SECTION
+ already represents the section in the supplementary file. */
+ return cu->section ();
+}
+
/* Process an imported unit DIE. */
static void
@@ -4928,12 +4975,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_import, cu);
if (attr != NULL)
{
+ const dwarf2_section_info &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
- bool is_dwz = attr->form_is_alt () || cu->per_cu->is_dwz;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
/* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
into another compilation unit, at root level. Regard this as a hint,
@@ -6054,6 +6100,20 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
}
}
+/* See cu.h.
+
+ This function is defined in this file (instead of cu.c) because it needs
+ to see the definition of struct dwo_unit. */
+
+const dwarf2_section_info &
+dwarf2_cu::section () const
+{
+ if (this->dwo_unit != nullptr)
+ return *this->dwo_unit->section;
+ else
+ return *this->per_cu->section;
+}
+
void
dwarf2_cu::setup_type_unit_groups (struct die_info *die)
{
@@ -9918,33 +9978,37 @@ static void
handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
struct field *field)
{
- struct attribute *attr;
+ const auto data_member_location_attr
+ = dwarf2_attr (die, DW_AT_data_member_location, cu);
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr != NULL)
+ if (data_member_location_attr != nullptr)
{
bool has_bit_offset = false;
LONGEST bit_offset = 0;
LONGEST anonymous_size = 0;
+ const auto bit_offset_attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- attribute *attr2 = dwarf2_attr (die, DW_AT_bit_offset, cu);
- if (attr2 != nullptr && attr2->form_is_constant ())
+ if (bit_offset_attr != nullptr && bit_offset_attr->form_is_constant ())
{
has_bit_offset = true;
- bit_offset = attr2->confused_constant ().value_or (0);
- attr2 = dwarf2_attr (die, DW_AT_byte_size, cu);
- if (attr2 != nullptr && attr2->form_is_constant ())
+ bit_offset = bit_offset_attr->confused_constant ().value_or (0);
+
+ const auto byte_size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+
+ if (byte_size_attr != nullptr && byte_size_attr->form_is_constant ())
{
/* The size of the anonymous object containing
the bit field is explicit, so use the
indicated size (in bytes). */
- anonymous_size = attr2->unsigned_constant ().value_or (0);
+ anonymous_size
+ = byte_size_attr->unsigned_constant ().value_or (0);
}
}
- if (attr->form_is_constant ())
+ if (data_member_location_attr->form_is_constant ())
{
- LONGEST offset = attr->confused_constant ().value_or (0);
+ LONGEST offset
+ = data_member_location_attr->confused_constant ().value_or (0);
/* Work around this GCC 11 bug, where it would erroneously use -1
data member locations, instead of 0:
@@ -9962,11 +10026,17 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
if (has_bit_offset)
apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
}
- else if (attr->form_is_block ())
+ else if (data_member_location_attr->form_is_block ())
{
CORE_ADDR offset;
- if (decode_locdesc (attr->as_block (), cu, &offset))
- field->set_loc_bitpos (offset * bits_per_byte);
+ if (decode_locdesc (data_member_location_attr->as_block (), cu,
+ &offset))
+ {
+ field->set_loc_bitpos (offset * bits_per_byte);
+
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
+ }
else
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
@@ -9985,8 +10055,8 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
else
dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_locexpr_baton);
- dlbaton->data = attr->as_block ()->data;
- dlbaton->size = attr->as_block ()->size;
+ dlbaton->data = data_member_location_attr->as_block ()->data;
+ dlbaton->size = data_member_location_attr->as_block ()->size;
/* When using this baton, we want to compute the address
of the field, not the value. This is why
is_reference is set to false here. */
@@ -9999,16 +10069,19 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
}
else
complaint (_("Unsupported form %s for DW_AT_data_member_location"),
- dwarf_form_name (attr->form));
+ dwarf_form_name (data_member_location_attr->form));
}
else
{
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- if (attr != nullptr)
+ const auto data_bit_offset_attr
+ = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+
+ if (data_bit_offset_attr != nullptr)
{
- if (attr->form_is_constant ())
- field->set_loc_bitpos (attr->unsigned_constant ().value_or (0));
- else if (attr->form_is_block ())
+ if (data_bit_offset_attr->form_is_constant ())
+ field->set_loc_bitpos (data_bit_offset_attr->unsigned_constant ()
+ .value_or (0));
+ else if (data_bit_offset_attr->form_is_block ())
{
/* This is a DWARF extension. See
https://dwarfstd.org/issues/250501.1.html. */
@@ -10016,8 +10089,8 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
dwarf2_locexpr_baton *dlbaton
= OBSTACK_ZALLOC (&per_objfile->objfile->objfile_obstack,
dwarf2_locexpr_baton);
- dlbaton->data = attr->as_block ()->data;
- dlbaton->size = attr->as_block ()->size;
+ dlbaton->data = data_bit_offset_attr->as_block ()->data;
+ dlbaton->size = data_bit_offset_attr->as_block ()->size;
dlbaton->per_objfile = per_objfile;
dlbaton->per_cu = cu->per_cu;
@@ -10025,7 +10098,7 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
}
else
complaint (_("Unsupported form %s for DW_AT_data_bit_offset"),
- dwarf_form_name (attr->form));
+ dwarf_form_name (data_bit_offset_attr->form));
}
}
}
@@ -17459,9 +17532,10 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
if (attr->form_is_alt ())
{
+ const auto &section = get_section_for_ref (*attr, cu);
sect_offset sect_off = attr->get_ref_die_offset ();
dwarf2_per_cu *per_cu
- = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile->per_bfd);
+ = dwarf2_find_containing_unit ({ &section, sect_off }, per_objfile);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
@@ -18162,14 +18236,13 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
return die;
}
-/* Follow reference OFFSET.
- On entry *REF_CU is the CU of the source die referencing OFFSET.
+/* Follow reference TARGET.
+ On entry *REF_CU is the CU of the source die referencing TARGET.
On exit *REF_CU is the CU of the result.
- Returns NULL if OFFSET is invalid. */
+ Returns nullptr if TARGET is invalid. */
-static struct die_info *
-follow_die_offset (sect_offset sect_off, int offset_in_dwz,
- struct dwarf2_cu **ref_cu)
+static die_info *
+follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
{
dwarf2_cu *source_cu = *ref_cu;
dwarf2_cu *target_cu = source_cu;
@@ -18181,23 +18254,23 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
"source CU contains target offset: %d",
sect_offset_str (source_cu->per_cu->sect_off),
- sect_offset_str (sect_off),
- source_cu->header.offset_in_unit_p (sect_off));
+ sect_offset_str (target.offset),
+ (target.section == &source_cu->section ()
+ && source_cu->header.offset_in_unit_p (target.offset)));
if (source_cu->per_cu->is_debug_types)
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
DW_FORM_ref_sig8. */
- if (!source_cu->header.offset_in_unit_p (sect_off))
+ if (!source_cu->header.offset_in_unit_p (target.offset))
return NULL;
}
- else if (offset_in_dwz != source_cu->per_cu->is_dwz
- || !source_cu->header.offset_in_unit_p (sect_off))
+ else if (target.section != &source_cu->section ()
+ || !source_cu->header.offset_in_unit_p (target.offset))
{
dwarf2_per_cu *target_per_cu
- = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
- per_objfile->per_bfd);
+ = dwarf2_find_containing_unit (target, per_objfile);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
@@ -18219,13 +18292,13 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
- sect_offset_str (sect_off),
+ sect_offset_str (target.offset),
objfile_name (per_objfile->objfile));
}
*ref_cu = target_cu;
- return target_cu->find_die (sect_off);
+ return target_cu->find_die (target.offset);
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -18237,8 +18310,7 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
sect_offset sect_off = attr->get_ref_die_offset ();
- struct dwarf2_cu *cu = *ref_cu;
- struct die_info *die;
+ struct dwarf2_cu *src_cu = *ref_cu;
if (!attr->form_is_alt () && src_die->sect_off == sect_off)
{
@@ -18246,14 +18318,13 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
return src_die;
}
- die = follow_die_offset (sect_off,
- attr->form_is_alt () || cu->per_cu->is_dwz,
- ref_cu);
- if (!die)
+ const dwarf2_section_info &section = get_section_for_ref (*attr, src_cu);
+ die_info *die = follow_die_offset ({ &section, sect_off }, ref_cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced from DIE at %s [in module %s]"),
sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
- objfile_name (cu->per_objfile->objfile));
+ objfile_name (src_cu->per_objfile->objfile));
return die;
}
@@ -18266,7 +18337,6 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
gdb::function_view<CORE_ADDR ()> get_frame_pc,
bool resolve_abstract_p)
{
- struct die_info *die;
struct attribute *attr;
struct dwarf2_locexpr_baton retval;
struct objfile *objfile = per_objfile->objfile;
@@ -18284,8 +18354,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
- if (!die)
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
+ if (die == nullptr)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
@@ -18301,8 +18371,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
: per_objfile->per_bfd->abstract_to_concrete[die->sect_off])
{
struct dwarf2_cu *cand_cu = cu;
- struct die_info *cand
- = follow_die_offset (cand_off, per_cu->is_dwz, &cand_cu);
+ die_info *cand
+ = follow_die_offset ({ &cu->section (), cand_off }, &cand_cu);
if (!cand
|| !cand->parent
|| cand->parent->tag != DW_TAG_subprogram)
@@ -18404,7 +18474,6 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
obstack *obstack,
LONGEST *len)
{
- struct die_info *die;
struct attribute *attr;
const gdb_byte *result = NULL;
struct type *type;
@@ -18425,7 +18494,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
sect_offset_str (sect_off), objfile_name (objfile));
}
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
@@ -18515,8 +18584,6 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
const char **var_name)
{
- struct die_info *die;
-
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
if (cu == nullptr)
cu = load_cu (per_cu, per_objfile, false);
@@ -18524,7 +18591,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
if (cu == nullptr)
return nullptr;
- die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+ die_info *die = follow_die_offset ({ &cu->section (), sect_off }, &cu);
if (!die)
return NULL;
@@ -19274,69 +19341,115 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile)
true, language_minimal, nullptr);
}
-/* A helper function for dwarf2_find_containing_comp_unit that returns
- the index of the result, and that searches a vector. It will
- return a result even if the offset in question does not actually
- occur in any CU. This is separate so that it can be unit
- tested. */
+/* Return the unit from ALL_UNITS that potentially contains TARGET.
-static int
-dwarf2_find_containing_comp_unit
- (sect_offset sect_off,
- unsigned int offset_in_dwz,
- const std::vector<dwarf2_per_cu_up> &all_units)
+ Since the unit lengths may not be known yet, this function doesn't check that
+ TARGET.OFFSET actually falls within the range of the returned unit. The
+ caller is responsible for this.
+
+ If no units possibly match TARGET, return nullptr. */
+
+static dwarf2_per_cu *
+dwarf2_find_containing_unit (const section_and_offset &target,
+ const std::vector<dwarf2_per_cu_up> &all_units)
{
- int low, high;
+ auto it = std::lower_bound (all_units.begin (), all_units.end (), target,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
- low = 0;
- high = all_units.size () - 1;
- while (high > low)
+ if (it == all_units.begin ())
{
- int mid = low + (high - low) / 2;
- dwarf2_per_cu *mid_cu = all_units[mid].get ();
-
- if (mid_cu->is_dwz > offset_in_dwz
- || (mid_cu->is_dwz == offset_in_dwz
- && mid_cu->sect_off + mid_cu->length () > sect_off))
- high = mid;
+ /* TARGET falls before the first unit of the first section, or is an
+ exact match with the first. */
+ if ((*it)->section == target.section && (*it)->sect_off == target.offset)
+ return it->get ();
else
- low = mid + 1;
+ return nullptr;
}
- gdb_assert (low == high);
- return low;
+
+ if (it != all_units.end ()
+ && (*it)->section == target.section
+ && (*it)->sect_off == target.offset)
+ {
+ /* TARGET is an exact match with the start of *IT, so *IT is what we're
+ looking for. */
+ return it->get ();
+ }
+
+ /* Otherwise, the match is the one just before, as long as it matches the
+ section we're looking for. */
+ --it;
+
+ if ((*it)->section == target.section)
+ return it->get ();
+
+ return nullptr;
}
/* See read.h. */
dwarf2_per_cu *
-dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int offset_in_dwz,
- dwarf2_per_bfd *per_bfd)
+dwarf2_find_containing_unit (const section_and_offset &target,
+ dwarf2_per_objfile *per_objfile)
{
- int low = dwarf2_find_containing_comp_unit
- (sect_off, offset_in_dwz, per_bfd->all_units);
- dwarf2_per_cu *this_cu = per_bfd->all_units[low].get ();
-
- if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ dwarf2_per_cu *per_cu
+ = dwarf2_find_containing_unit (target, per_bfd->all_units);
+ auto error_out = [&target, per_bfd] ()
{
- if (low == 0 || this_cu->is_dwz != offset_in_dwz)
- error (_(DWARF_ERROR_PREFIX
- "could not find CU containing offset %s [in module %s]"),
- sect_offset_str (sect_off),
- per_bfd->filename ());
+ error (_(DWARF_ERROR_PREFIX
+ "could not find unit containing offset %s [in module %s]"),
+ sect_offset_str (target.offset), per_bfd->filename ());
+ };
- gdb_assert (per_bfd->all_units[low-1]->sect_off
- <= sect_off);
- return per_bfd->all_units[low - 1].get ();
- }
- else
- {
- if (low == per_bfd->all_units.size () - 1
- && sect_off >= this_cu->sect_off + this_cu->length ())
- error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
- gdb_assert (sect_off < this_cu->sect_off + this_cu->length ());
- return this_cu;
- }
+ if (per_cu == nullptr)
+ error_out ();
+
+ gdb_assert (per_cu->section == target.section);
+
+ /* Some producers of dwarf2_per_cu objects (thinking of the .gdb_index reader)
+ do not set the length ahead of time. The length is needed to check if
+ the target is truly within PER_CU's range, so compute it now. Constructing
+ the cutu_reader object has the side-effect of setting PER_CU's length.
+ Even though it should happen too often, it could be replaced with
+ something more lightweight that has the same effect. */
+ if (!per_cu->length_is_set ())
+ cutu_reader (*per_cu, *per_objfile, nullptr, nullptr, false,
+ language_minimal);
+
+ /* Now we can check if the target section offset is within PER_CU's range. */
+ if (target.offset < per_cu->sect_off
+ || target.offset >= per_cu->sect_off + per_cu->length ())
+ error_out ();
+
+ return per_cu;
+}
+
+/* See read.h. */
+
+dwarf2_per_cu *
+dwarf2_find_unit (const section_and_offset &start, dwarf2_per_bfd *per_bfd)
+{
+ auto it = std::lower_bound (per_bfd->all_units.begin (),
+ per_bfd->all_units.end (), start,
+ [] (const dwarf2_per_cu_up &per_cu,
+ const section_and_offset &key)
+ {
+ return all_units_less_than (*per_cu, key);
+ });
+
+ if (it == per_bfd->all_units.end ())
+ return nullptr;
+
+ dwarf2_per_cu *per_cu = it->get ();
+
+ if (per_cu->section != start.section || per_cu->sect_off != start.offset)
+ return nullptr;
+
+ return per_cu;
}
#if GDB_SELF_TEST
@@ -19347,59 +19460,55 @@ namespace find_containing_comp_unit {
static void
run_test ()
{
- char dummy_per_bfd;
- char dummy_section;
-
- const auto create_dummy_per_cu = [&] (sect_offset sect_off,
- unsigned int length,
- bool is_dwz)
- {
- auto per_bfd = reinterpret_cast<dwarf2_per_bfd *> (&dummy_per_bfd);
- auto section = reinterpret_cast<dwarf2_section_info *> (&dummy_section);
+ auto dummy_per_bfd = reinterpret_cast<dwarf2_per_bfd *> (0x3000);
+ auto &main_section = *reinterpret_cast<dwarf2_section_info *> (0x4000);
+ auto &dwz_section = *reinterpret_cast<dwarf2_section_info *> (0x5000);
+ std::vector<dwarf2_per_cu_up> units;
- return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, section, sect_off,
- length, is_dwz));
+ /* Create one dummy unit, append it to UNITS, return a non-owning
+ reference. */
+ auto create_dummy_per_unit = [&] (dwarf2_section_info &section,
+ unsigned int sect_off, bool is_dwz)
+ -> dwarf2_per_cu &
+ {
+ /* Omit the length, because dwarf2_find_containing_unit does not consider
+ it. */
+ return *units.emplace_back (new dwarf2_per_cu (dummy_per_bfd, &section,
+ sect_offset (sect_off),
+ 0, is_dwz));
};
- /* Units in the main file. */
- dwarf2_per_cu_up one = create_dummy_per_cu (sect_offset (0), 5, false);
- dwarf2_per_cu *one_ptr = one.get ();
- dwarf2_per_cu_up two
- = create_dummy_per_cu (sect_offset (one->length ()), 7, false);
- dwarf2_per_cu *two_ptr = two.get ();
-
- /* Units in the supplementary (dwz) file. */
- dwarf2_per_cu_up three = create_dummy_per_cu (sect_offset (0), 5, true);
- dwarf2_per_cu *three_ptr = three.get ();
- dwarf2_per_cu_up four
- = create_dummy_per_cu (sect_offset (three->length ()), 7, true);
- dwarf2_per_cu *four_ptr = four.get ();
-
- std::vector<dwarf2_per_cu_up> units;
- units.push_back (std::move (one));
- units.push_back (std::move (two));
- units.push_back (std::move (three));
- units.push_back (std::move (four));
-
- int result;
+ /* Create 2 units in the main file and 2 units in the supplementary (dwz)
+ file. */
+ auto &main1 = create_dummy_per_unit (main_section, 10, false);
+ auto &main2 = create_dummy_per_unit (main_section, 20, false);
+ auto &dwz1 = create_dummy_per_unit (dwz_section, 10, false);
+ auto &dwz2 = create_dummy_per_unit (dwz_section, 20, false);
+
+ /* Check that looking up a unit at all offsets in the range [START,END[ in
+ section SECTION finds EXPECTED. */
+ auto check_range = [&units] (dwarf2_section_info &section, unsigned int start,
+ unsigned int end, dwarf2_per_cu *expected)
+ {
+ for (unsigned int sect_off = start; sect_off < end; ++sect_off)
+ {
+ section_and_offset target { &section, sect_offset (sect_off) };
+ dwarf2_per_cu *result = dwarf2_find_containing_unit (target, units);
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
- SELF_CHECK (units[result].get () == one_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
- SELF_CHECK (units[result].get () == two_ptr);
+ SELF_CHECK (result == expected);
+ }
+ };
- result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
- SELF_CHECK (units[result].get () == three_ptr);
- result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
- SELF_CHECK (units[result].get () == four_ptr);
-}
+ check_range (main_section, 0, 10, nullptr);
+ check_range (main_section, 10, 20, &main1);
+ check_range (main_section, 20, 30, &main2);
+ check_range (dwz_section, 0, 10, nullptr);
+ check_range (dwz_section, 10, 20, &dwz1);
+ check_range (dwz_section, 20, 30, &dwz2);
}
-}
+} /* namespace find_containing_comp_unit */
+} /* namespace selftests */
#endif /* GDB_SELF_TEST */
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index a5cfb31..4e3f8d7 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -47,7 +47,6 @@ struct tu_stats
int nr_symtab_sharers = 0;
int nr_stmt_less_type_units = 0;
int nr_all_type_units_reallocs = 0;
- int nr_tus = 0;
};
struct abbrev_table_cache;
@@ -296,6 +295,10 @@ public:
return m_length;
}
+ /* Return true if the length of this CU has been set. */
+ bool length_is_set () const
+ { return m_length != 0; }
+
void set_length (unsigned int length, bool strict_p = true)
{
if (m_length == 0)
@@ -521,20 +524,6 @@ struct dwarf2_per_bfd
return this->all_units[index].get ();
}
- /* Return the CU given its index in the CU table in the index. */
- dwarf2_per_cu *get_index_cu (int index) const
- {
- if (this->all_comp_units_index_cus.empty ())
- return get_unit (index);
-
- return this->all_comp_units_index_cus[index];
- }
-
- dwarf2_per_cu *get_index_tu (int index) const
- {
- return this->all_comp_units_index_tus[index];
- }
-
/* Return the separate '.dwz' debug file. If there is no
.gnu_debugaltlink or .debug_sup section in the file, then the
result depends on REQUIRE: if REQUIRE is true, error out; if
@@ -619,13 +608,9 @@ public:
the target compilation unit of a particular reference. */
std::vector<dwarf2_per_cu_up> all_units;
- /* The all_units vector contains both CUs and TUs. Provide views on the
- vector that are limited to either the CU part or the TU part. */
- gdb::array_view<dwarf2_per_cu_up> all_comp_units;
- gdb::array_view<dwarf2_per_cu_up> all_type_units;
-
- std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
- std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
+ /* Number of compilation and type units in the ALL_UNITS vector. */
+ unsigned int num_comp_units = 0;
+ unsigned int num_type_units = 0;
/* Set of signatured_types, used to look up by signature. */
signatured_type_set signatured_types;
@@ -1232,7 +1217,7 @@ extern void dw_expand_symtabs_matching_file_matcher
extern const char *read_indirect_string_at_offset
(dwarf2_per_objfile *per_objfile, LONGEST str_offset);
-/* Initialize the views on all_units. */
+/* Finalize the all_units vector. */
extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
@@ -1277,14 +1262,17 @@ extern pc_bounds_kind dwarf2_get_pc_bounds (die_info *die,
dwarf2_cu *cu, addrmap_mutable *map,
void *datum);
-/* Locate the .debug_info compilation unit from CU's objfile which contains
- the DIE at OFFSET. Raises an error on failure. */
+/* Locate the unit in PER_OBJFILE which contains the DIE at TARGET. Raises an
+ error on failure. */
+
+extern dwarf2_per_cu *dwarf2_find_containing_unit
+ (const section_and_offset &target, dwarf2_per_objfile *per_objfile);
+
+/* Locate the unit starting at START in PER_BFD. Return nullptr if not
+ found. */
-extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int
- offset_in_dwz,
- dwarf2_per_bfd
- *per_bfd);
+extern dwarf2_per_cu *dwarf2_find_unit (const section_and_offset &start,
+ dwarf2_per_bfd *per_bfd);
/* Decode simple location descriptions.
@@ -1327,4 +1315,10 @@ extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return,
extern file_and_directory &find_file_and_directory (die_info *die,
dwarf2_cu *cu);
+
+/* Return the section that ATTR, an attribute with ref form, references. */
+
+extern const dwarf2_section_info &get_section_for_ref
+ (const attribute &attr, dwarf2_cu *cu);
+
#endif /* GDB_DWARF2_READ_H */
diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h
index fd6e34d..fbdb025 100644
--- a/gdb/dwarf2/section.h
+++ b/gdb/dwarf2/section.h
@@ -43,6 +43,8 @@
the real section this "virtual" section is contained in, and BUFFER,SIZE
describe the virtual section. */
+#include "dwarf2/types.h"
+
struct dwarf2_section_info
{
/* Return the name of this section. */
@@ -114,4 +116,12 @@ struct dwarf2_section_info
using dwarf2_section_info_up = std::unique_ptr<dwarf2_section_info>;
+/* A pair-like structure to represent an offset into a section. */
+
+struct section_and_offset
+{
+ const dwarf2_section_info *section;
+ sect_offset offset;
+};
+
#endif /* GDB_DWARF2_SECTION_H */
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 31e1565..4f1c8ef 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -55,6 +55,20 @@ static void child_terminal_ours_1 (target_terminal_state);
static struct serial *stdin_serial;
+/* See terminal.h. */
+
+scoped_gdb_ttystate::scoped_gdb_ttystate ()
+{
+ m_ttystate = serial_get_tty_state (stdin_serial);
+}
+
+/* See terminal.h. */
+
+scoped_gdb_ttystate::~scoped_gdb_ttystate ()
+{
+ serial_set_tty_state (stdin_serial, m_ttystate);
+}
+
/* Terminal related info we need to keep track of. Each inferior
holds an instance of this structure --- we save it whenever the
corresponding inferior stops, and restore it to the terminal when
@@ -163,6 +177,15 @@ set_initial_gdb_ttystate (void)
}
}
+/* See terminal.h. */
+
+void
+restore_initial_gdb_ttystate ()
+{
+ if (initial_gdb_ttystate != nullptr)
+ serial_set_tty_state (stdin_serial, initial_gdb_ttystate);
+}
+
/* Does GDB have a terminal (on stdin)? */
static int
diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c
index 481bd41..a4e9cf5 100644
--- a/gdb/mingw-hdep.c
+++ b/gdb/mingw-hdep.c
@@ -493,10 +493,7 @@ show_maint_console_translation_mode (struct ui_file *file, int from_tty,
console_translation_mode.c_str ());
}
-extern void _initialize_mingw_hdep ();
-
-void
-_initialize_mingw_hdep ()
+INIT_GDB_FILE (mingw_hdep)
{
add_setshow_string_cmd ("console-translation-mode",
class_maintenance,
diff --git a/gdb/solib-frv.h b/gdb/solib-frv.h
index 710a424..a2f3558 100644
--- a/gdb/solib-frv.h
+++ b/gdb/solib-frv.h
@@ -1,5 +1,5 @@
/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
- Copyright (C) 2024 Free Software Foundation, Inc.
+ Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of GDB.
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index c72d9ad..af08b75 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -3591,16 +3591,11 @@ find_debug_base_for_solib (const solib *solib)
auto *lm_info
= gdb::checked_static_cast<const lm_info_svr4 *> (solib->lm_info.get ());
- for (const auto &tuple : info->solib_lists)
- {
- CORE_ADDR debug_base = tuple.first;
- const std::vector<svr4_so> &sos = tuple.second;
-
- for (const svr4_so &so : sos)
- if (svr4_same (solib->original_name.c_str (), so.name.c_str (),
- *lm_info, *so.lm_info))
- return debug_base;
- }
+ for (const auto &[debug_base, sos] : info->solib_lists)
+ for (const svr4_so &so : sos)
+ if (svr4_same (solib->original_name.c_str (), so.name.c_str (), *lm_info,
+ *so.lm_info))
+ return debug_base;
return 0;
}
diff --git a/gdb/solib.c b/gdb/solib.c
index bd9f3cb..3ec2032 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1210,14 +1210,13 @@ info_linker_namespace_command (const char *pattern, int from_tty)
bool ns_separator = false;
- for (auto &solibs_pair : all_solibs_to_print)
+ for (const auto &[ns, solibs_to_print] : all_solibs_to_print)
{
if (ns_separator)
uiout->message ("\n\n");
else
ns_separator = true;
- int ns = solibs_pair.first;
- std::vector<const solib *> solibs_to_print = solibs_pair.second;
+
if (solibs_to_print.size () == 0)
{
uiout->message (_("Linker namespace [[%d]] is not active.\n"), ns);
diff --git a/gdb/svr4-tls-tdep.c b/gdb/svr4-tls-tdep.c
index 75d06a4..1f36d57 100644
--- a/gdb/svr4-tls-tdep.c
+++ b/gdb/svr4-tls-tdep.c
@@ -1,6 +1,6 @@
/* Target-dependent code for GNU/Linux, architecture independent.
- Copyright (C) 2009-2024 Free Software Foundation, Inc.
+ Copyright (C) 2009-2025 Free Software Foundation, Inc.
This file is part of GDB.
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 160a465..302f4eb 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -6986,11 +6986,8 @@ info_module_subcommand (bool quiet, const char *module_regexp,
const char *last_filename = "";
const symbol *last_module_symbol = nullptr;
- for (const module_symbol_search &ms : module_symbols)
+ for (const auto &[p, q] : module_symbols)
{
- const symbol_search &p = ms.first;
- const symbol_search &q = ms.second;
-
gdb_assert (q.symbol != nullptr);
if (last_module_symbol != p.symbol)
diff --git a/gdb/terminal.h b/gdb/terminal.h
index 54e5e98..720fd4a 100644
--- a/gdb/terminal.h
+++ b/gdb/terminal.h
@@ -19,6 +19,8 @@
#ifndef GDB_TERMINAL_H
#define GDB_TERMINAL_H
+#include "serial.h"
+
struct inferior;
extern void new_tty_prefork (std::string ttyname);
@@ -43,4 +45,17 @@ extern void gdb_save_tty_state (void);
have had a chance to alter it. */
extern void set_initial_gdb_ttystate (void);
+/* Restore initial tty state. */
+extern void restore_initial_gdb_ttystate (void);
+
+/* An RAII-based object that saves the tty state, and then restores it again
+ when this object is destroyed. */
+class scoped_gdb_ttystate
+{
+public:
+ scoped_gdb_ttystate ();
+ ~scoped_gdb_ttystate ();
+private:
+ serial_ttystate m_ttystate;
+};
#endif /* GDB_TERMINAL_H */
diff --git a/gdb/testsuite/gdb.ada/operator_call.exp b/gdb/testsuite/gdb.ada/operator_call.exp
index e96107b..dc7f679 100644
--- a/gdb/testsuite/gdb.ada/operator_call.exp
+++ b/gdb/testsuite/gdb.ada/operator_call.exp
@@ -71,6 +71,12 @@ proc test_with_menu {command result} {
fail $command
}
}
+ "Argument to arithmetic operation not a number or boolean." {
+ fail $command
+ }
+ -re "No definition of \".*\" in current context." {
+ fail $command
+ }
timeout {
fail "$command (timeout)"
}
diff --git a/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp b/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp
deleted file mode 100644
index d86b5c4..0000000
--- a/gdb/testsuite/gdb.dwarf2/debug-names-non-ascending-cu.exp
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2022-2025 Free Software Foundation, Inc.
-
-# 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/>.
-
-load_lib dwarf.exp
-
-# This test can only be run on targets which support DWARF-2 and use gas.
-require dwarf2_support
-
-standard_testfile _start.c debug-names.S
-
-set func_info_vars \
- [get_func_info _start [list debug additional_flags=-nostartfiles]]
-
-# Create the DWARF.
-set asm_file [standard_output_file $srcfile2]
-Dwarf::assemble {
- filename $asm_file
- add_dummy_cus 0
-} {
- global func_info_vars
- foreach var $func_info_vars {
- global $var
- }
-
- cu { label cu_label } {
- compile_unit {{language @DW_LANG_C}} {
- subprogram {
- {DW_AT_name _start}
- {DW_AT_low_pc $_start_start DW_FORM_addr}
- {DW_AT_high_pc $_start_end DW_FORM_addr}
- }
- }
- }
-
- cu { label cu_label_2 } {
- compile_unit {{language @DW_LANG_C}} {
- base_type {
- {name int}
- {byte_size 4 sdata}
- {encoding @DW_ATE_signed}
- }
- }
- }
-
- debug_names {} {
- cu cu_label_2
- cu cu_label
- name _start subprogram cu_label 0xEDDB6232
- name int base_type cu_label 0xB888030
- }
-}
-
-if [prepare_for_testing "failed to prepare" $testfile "${asm_file} ${srcfile}" \
- [list additional_flags=-nostartfiles]] {
- return -1
-}
-
-# Check for warning.
-set re \
- [list \
- "warning:" \
- "Section .debug_names has incorrect entry in CU table," \
- "ignoring .debug_names."]
-set re [join $re]
-gdb_assert {[regexp $re $gdb_file_cmd_msg]} "warning"
-
-# Verify that .debug_names section is ignored.
-set index [have_index $binfile]
-gdb_assert { [string equal $index ""] } ".debug_names not used"
diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp b/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp
new file mode 100644
index 0000000..6253629
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp
@@ -0,0 +1,109 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+# This is a reproducer for PR 29518:
+#
+# https://sourceware.org/bugzilla/show_bug.cgi?id=29518
+#
+# The root cause for the problem was that function
+# dwarf2_find_containing_comp_unit was searching the whole "all_units" vector,
+# containing both compile units and type units, causing it to sometimes
+# erroneously return a type unit. It should have been restricted to searching
+# compile units.
+#
+# To get dwarf2_find_containing_comp_unit to be called and reproduce the
+# original bug, we need a value with form DW_FORM_ref_addr pointing to a
+# different compile unit. This is produced by `%$int_type` below.
+
+load_lib dwarf.exp
+require dwarf2_support
+standard_testfile main.c .S
+
+set asm_file [standard_output_file $srcfile2]
+
+Dwarf::assemble $asm_file {
+ global srcfile
+ declare_labels int_type
+
+ # The source CU.
+ cu {version 4} {
+ compile_unit {
+ } {
+ subprogram {
+ {MACRO_AT_func {main}}
+ {type %$int_type}
+ }
+ }
+ }
+
+ # Create a bunch of empty / dummy CUs, to make the offset of int_type a bit
+ # higher.
+ for {set i 1} {$i < 10} {incr i} {
+ cu {version 4} {
+ compile_unit {} {}
+ }
+ }
+
+ # The target CU.
+ cu {version 4} {
+ compile_unit {
+ } {
+ int_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name int}
+ }
+ }
+ }
+
+ # Create many TUs.
+ #
+ # We need enough type units in the "all_units" vector in order to steer the
+ # binary search in dwarf2_find_containing_comp_unit towards the type units
+ # region of the array.
+ for {set i 1} {$i < 20} {incr i} {
+ tu {version 4} $i the_type_i {
+ type_unit {} {
+ declare_labels dummy_int_type
+
+ the_type_i: structure_type {
+ {name s}
+ {byte_size 4 sdata}
+ } {
+ member {
+ {name i}
+ {type :$dummy_int_type}
+ }
+ }
+
+ dummy_int_type: base_type {
+ {name int}
+ {encoding @DW_ATE_signed}
+ {byte_size 4 sdata}
+ }
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+# Without the corresponding fix, we get an internal error:
+#
+# gdb/dwarf2/read.c:3940: internal-error: load_full_comp_unit: Assertion `! this_cu->is_debug_types' failed.
+gdb_test "p main" " = {int \\(void\\)} $hex <main>"
diff --git a/gdb/testsuite/gdb.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp
index 0693f43..6846ecb 100644
--- a/gdb/testsuite/gdb.dwarf2/varval.exp
+++ b/gdb/testsuite/gdb.dwarf2/varval.exp
@@ -348,6 +348,6 @@ if ![runto_main] {
}
gdb_test "print badval" "value has been optimized out"
gdb_test "print bad_die_val1" \
- "invalid dwarf2 offset 0xabcdef11"
+ {DWARF Error: could not find unit containing offset 0xabcdef11 \[in module .*/varval\]}
gdb_test "print bad_die_val2" \
"Bad DW_OP_GNU_variable_value DIE\\."
diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp
index 4b9adb0..8126740 100644
--- a/gdb/testsuite/gdb.gdb/python-helper.exp
+++ b/gdb/testsuite/gdb.gdb/python-helper.exp
@@ -264,10 +264,28 @@ proc test_python_helper {} {
gdb_test -prompt $outer_prompt_re "print varobj_table" \
"htab_t with ${::decimal} elements"
+ set inferior_list_supported 1
+ set inferior_list_unsupported_re "type = intrusive_list"
+ gdb_test_multiple "what inferior_list" "" -prompt $outer_prompt_re {
+ -re -wrap $inferior_list_unsupported_re {
+ set inferior_list_supported 0
+ pass $gdb_test_name
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+ }
+
# Test the intrusive_list pretty-printer. A bug occurred in the
# pretty-printer for lists with more than one element. Verify that
# we see both elements of the inferior_list list being printed.
- gdb_test -prompt $outer_prompt_re "print inferior_list" "intrusive list of inferior = {.*, num = 1,.*, num = 2,.*}"
+ set test "print inferior_list"
+ if { $inferior_list_supported } {
+ gdb_test -prompt $outer_prompt_re $test \
+ "intrusive list of inferior = {.*, num = 1,.*, num = 2,.*}"
+ } else {
+ unsupported $test
+ }
return 0
}
diff --git a/gdb/testsuite/gdb.tui/main-2.exp b/gdb/testsuite/gdb.tui/main-2.exp
index 2b0fb6b..71ad03b 100644
--- a/gdb/testsuite/gdb.tui/main-2.exp
+++ b/gdb/testsuite/gdb.tui/main-2.exp
@@ -41,7 +41,7 @@ if {![Term::enter_tui]} {
set line " return 0;"
set nr [gdb_get_line_number $line]
-set screen_line [Term::get_line_with_attrs 6]
+set screen_line [Term::get_string_with_attrs 6 1 79]
verbose -log "screen line 6: '$screen_line'"
gdb_assert { [regexp "$nr <reverse:1>$line<reverse:0>" $screen_line] } \
"highlighted line in middle of source window"
diff --git a/gdb/testsuite/gdb.tui/tuiterm.exp b/gdb/testsuite/gdb.tui/tuiterm.exp
index 9dc2402..6cd65f3 100644
--- a/gdb/testsuite/gdb.tui/tuiterm.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm.exp
@@ -102,7 +102,7 @@ proc test_backspace {} {
Term::_move_cursor 1 2
- Term::_ctl_0x08
+ Term::_ctl_0x08 0
check "backspace one" {
"abcdefgh"
"ijklmnop"
@@ -111,13 +111,22 @@ proc test_backspace {} {
} 0 2
# Cursor should not move if it is already at column 0.
- Term::_ctl_0x08
+ Term::_ctl_0x08 0
check "backspace 2" {
"abcdefgh"
"ijklmnop"
"qrstuvwx"
"yz01234 "
} 0 2
+
+ # Cursor should wrap to previous line.
+ Term::_ctl_0x08 1
+ check "backspace 3" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 1
}
proc test_linefeed { } {
@@ -435,6 +444,30 @@ proc test_horizontal_absolute { } {
"qrstuvwx"
"yz01234 "
} 3 2
+
+ Term::_csi_G 8
+ check "cursor horizontal absolute 3" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 2
+
+ Term::_csi_G 9
+ check "cursor horizontal absolute 4" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 7 2
+
+ Term::_csi_`
+ check "horizontal position absolute 1" {
+ "abcdefgh"
+ "ijklmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 0 2
}
proc test_cursor_position { } {
@@ -750,6 +783,15 @@ proc test_attrs {} {
set line [Term::get_line_with_attrs 0]
gdb_assert { [regexp $re $line] } "attribute: $attr"
}
+
+ # Regression test: Check that _csi_m works without arguments.
+ setup_terminal 4 1
+ Term::_csi_m 7
+ Term::_insert "a"
+ Term::_csi_m
+ Term::_insert "a"
+ set line [Term::get_line_with_attrs 0]
+ gdb_assert { [string equal $line "<reverse:1>a<reverse:0>a "] }
}
# Run proc TEST_PROC_NAME with a "small" terminal.
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index a0cd199..b83b8af 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -45,9 +45,16 @@ namespace eval Term {
set orig_cur_row $_cur_row
set orig_cur_col $_cur_col
- uplevel $body
+ set code [catch {uplevel $body} result]
_log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+
+ if { $code == 1 } {
+ global errorInfo errorCode
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+ } else {
+ return -code $code $result
+ }
}
# If ARG is empty, return DEF: otherwise ARG. This is useful for
@@ -83,14 +90,40 @@ namespace eval Term {
proc _ctl_0x07 {} {
}
+ # Return 1 if tuiterm has the bw/auto_left_margin enabled.
+ proc _have_bw {} {
+ return [string equal $Term::_TERM "ansiw"]
+ }
+
# Backspace.
- proc _ctl_0x08 {} {
- _log_cur "Backspace" {
+ proc _ctl_0x08 { {bw -1} } {
+ if { $bw == -1 } {
+ set bw [_have_bw]
+ }
+ _log_cur "Backspace, bw == $bw" {
variable _cur_col
+ variable _cur_row
+ variable _cols
- if {$_cur_col > 0} {
+ if { $_cur_col > 0 } {
+ # No wrapping needed.
incr _cur_col -1
+ return
+ }
+
+ if { ! $bw } {
+ # Wrapping not enabled.
+ return
}
+
+ if { $_cur_row == 0 } {
+ # Can't wrap.
+ return
+ }
+
+ # Wrap to previous line.
+ set _cur_col [expr $_cols - 1]
+ incr _cur_row -1
}
}
@@ -155,6 +188,14 @@ namespace eval Term {
}
}
+ # Horizontal Position Absolute.
+ #
+ # https://vt100.net/docs/vt510-rm/HPA.html
+ proc _csi_` {args} {
+ # Same as Cursor Horizontal Absolute.
+ return [Term::_csi_G {*}$args]
+ }
+
# Cursor Up.
#
# https://vt100.net/docs/vt510-rm/CUU.html
@@ -251,7 +292,7 @@ namespace eval Term {
variable _cur_col
variable _cols
- set _cur_col [expr {min ($arg - 1, $_cols)}]
+ set _cur_col [expr {min ($arg, $_cols)} - 1]
}
}
@@ -597,6 +638,11 @@ namespace eval Term {
#
# https://vt100.net/docs/vt510-rm/SGR.html
proc _csi_m {args} {
+ if { [llength $args] == 0 } {
+ # Apply default.
+ set args [list 0]
+ }
+
_log_cur "Select Graphic Rendition ([join $args {, }])" {
variable _attrs
@@ -740,7 +786,7 @@ namespace eval Term {
_log "wait_for: unsupported escape"
error "unsupported escape"
}
- -re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@\])" {
+ -re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@`\])" {
set cmd $expect_out(2,string)
set params [split $expect_out(1,string) ";"]
_log "wait_for: _csi_$cmd <<<$expect_out(1,string)>>>"
@@ -844,8 +890,16 @@ namespace eval Term {
# BODY.
proc with_tuiterm {rows cols body} {
global env stty_init
+ variable _TERM
save_vars {env(TERM) env(NO_COLOR) stty_init} {
- setenv TERM ansi
+ if { [ishost *-*-*bsd*] } {
+ setenv TERM ansiw
+ } else {
+ setenv TERM ansi
+ }
+ # Save active TERM variable.
+ set Term::_TERM $env(TERM)
+
setenv NO_COLOR ""
_setup $rows $cols
@@ -955,10 +1009,10 @@ namespace eval Term {
return $res
}
- # Return the text of screen line N. Lines are 0-based. If C is given,
- # stop before column C. Columns are also zero-based. If ATTRS, annotate
- # with attributes.
- proc get_line_1 {n c attrs} {
+ # Return the text of screen line N. Lines are 0-based. Start at column
+ # X. If C is non-empty, stop before column C. Columns are also
+ # zero-based. If ATTRS, annotate with attributes.
+ proc get_string {n x c {attrs 0}} {
variable _rows
# This can happen during resizing, if the cursor seems to
# temporarily be off-screen.
@@ -970,7 +1024,6 @@ namespace eval Term {
variable _cols
variable _chars
set c [_default $c $_cols]
- set x 0
if { $attrs } {
_reset_attrs line_attrs
}
@@ -990,6 +1043,20 @@ namespace eval Term {
return $result
}
+ # Return the text of screen line N. Lines are 0-based. Start at column
+ # X. If C is non-empty, stop before column C. Columns are also
+ # zero-based. Annotate with attributes.
+ proc get_string_with_attrs { n x c } {
+ return [get_string $n $x $c 1]
+ }
+
+ # Return the text of screen line N. Lines are 0-based. If C is
+ # non-empty, stop before column C. Columns are also zero-based. If
+ # ATTRS, annotate with attributes.
+ proc get_line_1 {n c attrs} {
+ return [get_string $n 0 $c $attrs]
+ }
+
# Return the text of screen line N, without attributes. Lines are
# 0-based. If C is given, stop before column C. Columns are also
# zero-based.
@@ -1224,7 +1291,7 @@ namespace eval Term {
for {set y 0} {$y < $_rows} {incr y} {
set fmt [format %5d $y]
- verbose -log "$fmt [get_line_1 $y "" $attrs]"
+ verbose -log "$fmt [get_line_1 $y {} $attrs]"
}
}