aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/index-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2/index-write.c')
-rw-r--r--gdb/dwarf2/index-write.c197
1 files changed, 105 insertions, 92 deletions
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 2a50e3b..0a3b9d0 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -1,6 +1,6 @@
/* DWARF index writing support for GDB.
- Copyright (C) 1994-2024 Free Software Foundation, Inc.
+ Copyright (C) 1994-2025 Free Software Foundation, Inc.
This file is part of GDB.
@@ -28,7 +28,6 @@
#include "gdbsupport/gdb_unlinker.h"
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/scoped_fd.h"
-#include "complaints.h"
#include "dwarf2/index-common.h"
#include "dwarf2/cooked-index.h"
#include "dwarf2.h"
@@ -39,16 +38,11 @@
#include "objfiles.h"
#include "ada-lang.h"
#include "dwarf2/tag.h"
-#include "gdbsupport/gdb_tilde_expand.h"
#include "dwarf2/read-debug-names.h"
+#include "extract-store-integer.h"
#include <algorithm>
-#include <cmath>
-#include <forward_list>
#include <map>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
/* Ensure only legit values are used. */
#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
@@ -134,6 +128,15 @@ public:
::store_unsigned_integer (grow (len), len, byte_order, val);
}
+ /* Accept a host-format integer in VAL and write it in the buffer at offset
+ OFFSET as a target-format integer which is LEN bytes long. */
+ void write_uint (size_t offset, size_t len, bfd_endian byte_order,
+ ULONGEST val)
+ {
+ gdb_assert (offset + len <= m_vec.size ());
+ ::store_unsigned_integer (&m_vec[offset], len, byte_order, val);
+ }
+
/* Copy VALUE to the end of the buffer, little-endian. */
void append_offset (offset_type value)
{
@@ -309,7 +312,8 @@ mapped_symtab::hash_expand ()
/* See mapped_symtab class declaration. */
-void mapped_symtab::sort ()
+void
+mapped_symtab::sort ()
{
/* Move contents out of this->data vector. */
std::vector<symtab_index_entry> original_data = std::move (m_data);
@@ -427,7 +431,7 @@ symtab_index_entry::minimize ()
this, we want to keep the entry from the first CU -- but this is
implicit due to the sort. This choice is done because it's
similar to what gdb historically did for partial symbols. */
- std::unordered_set<offset_type> seen;
+ gdb::unordered_set<offset_type> seen;
from = std::remove_if (cu_indices.begin (), cu_indices.end (),
[&] (offset_type val)
{
@@ -473,7 +477,7 @@ private:
const char *const m_cstr;
};
-/* A std::unordered_map::hasher for c_str_view that uses the right
+/* A gdb::unordered_map::hasher for c_str_view that uses the right
hash function for strings in a mapped index. */
class c_str_view_hasher
{
@@ -484,7 +488,7 @@ public:
}
};
-/* A std::unordered_map::hasher for std::vector<>. */
+/* A gdb::unordered_map::hasher for std::vector<>. */
template<typename T>
class vector_hasher
{
@@ -505,7 +509,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
{
/* Elements are sorted vectors of the indices of all the CUs that
hold an object of this name. */
- std::unordered_map<std::vector<offset_type>, offset_type,
+ gdb::unordered_map<std::vector<offset_type>, offset_type,
vector_hasher<offset_type>>
symbol_hash_table;
@@ -532,7 +536,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
}
/* Now write out the hash table. */
- std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
+ gdb::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
for (const auto &entry : *symtab)
{
offset_type str_off, vec_off;
@@ -558,8 +562,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
}
}
-using cu_index_map
- = std::unordered_map<const dwarf2_per_cu_data *, unsigned int>;
+using cu_index_map = gdb::unordered_map<const dwarf2_per_cu *, unsigned int>;
/* Helper struct for building the address table. */
struct addrmap_index_data
@@ -600,8 +603,7 @@ add_address_entry (data_buf &addr_vec,
int
addrmap_index_data::operator() (CORE_ADDR start_addr, const void *obj)
{
- const dwarf2_per_cu_data *per_cu
- = static_cast<const dwarf2_per_cu_data *> (obj);
+ const dwarf2_per_cu *per_cu = static_cast<const dwarf2_per_cu *> (obj);
if (previous_valid)
add_address_entry (addr_vec,
@@ -674,15 +676,11 @@ public:
/* Insert one symbol. */
void insert (const cooked_index_entry *entry)
{
- /* These entries are synthesized by the reader, and so should not
- be written. */
- if (entry->lang == language_ada && entry->tag == DW_TAG_namespace)
+ /* Synthesized entries should not be written. */
+ if ((entry->flags & IS_SYNTHESIZED) != 0)
return;
- const auto insertpair
- = m_name_to_value_set.try_emplace (c_str_view (entry->name));
- entry_list &elist = insertpair.first->second;
- elist.entries.push_back (entry);
+ m_name_to_value_set[entry->name].emplace_back (entry);
}
/* Build all the tables. All symbols must be already inserted.
@@ -696,25 +694,16 @@ public:
m_name_table_string_offs.reserve (name_count);
m_name_table_entry_offs.reserve (name_count);
- /* The name table is indexed from 1. The numbers are needed here
- so that parent entries can be handled correctly. */
- int next_name = 1;
- for (auto &item : m_name_to_value_set)
- item.second.index = next_name++;
-
/* The next available abbrev number. */
int next_abbrev = 1;
- for (auto &item : m_name_to_value_set)
+ for (auto &[name, these_entries] : m_name_to_value_set)
{
- const c_str_view &name = item.first;
- entry_list &these_entries = item.second;
-
/* Sort the items within each bucket. This ensures that the
generated index files will be the same no matter the order in
which symbols were added into the index. */
- std::sort (these_entries.entries.begin (),
- these_entries.entries.end (),
+ std::sort (these_entries.begin (),
+ these_entries.end (),
[] (const cooked_index_entry *a,
const cooked_index_entry *b)
{
@@ -734,16 +723,16 @@ public:
(m_debugstrlookup.lookup (name.c_str ())); /* ??? */
m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ());
- for (const cooked_index_entry *entry : these_entries.entries)
+ for (const cooked_index_entry *entry : these_entries)
{
unit_kind kind = (entry->per_cu->is_debug_types
? unit_kind::tu
: unit_kind::cu);
- /* Currently Ada parentage is synthesized by the
- reader and so must be ignored here. */
- const cooked_index_entry *parent = (entry->lang == language_ada
- ? nullptr
- : entry->get_parent ());
+ /* Some Ada parentage is synthesized by the reader and so
+ must be ignored here. */
+ const cooked_index_entry *parent = entry->get_parent ();
+ if (parent != nullptr && (parent->flags & IS_SYNTHESIZED) != 0)
+ parent = nullptr;
int &idx = m_indexkey_to_idx[index_key (entry->tag,
kind,
@@ -764,7 +753,8 @@ public:
m_abbrev_table.append_unsigned_leb128 (DW_FORM_ref_addr);
m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_language);
m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata);
- if ((entry->flags & IS_STATIC) != 0)
+ if (!tag_is_type (entry->tag)
+ && (entry->flags & IS_STATIC) != 0)
{
m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_internal);
m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present);
@@ -782,7 +772,7 @@ public:
if (parent != nullptr)
{
m_abbrev_table.append_unsigned_leb128 (DW_IDX_parent);
- m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata);
+ m_abbrev_table.append_unsigned_leb128 (DW_FORM_data4);
}
/* Terminate attributes list. */
@@ -790,6 +780,14 @@ public:
m_abbrev_table.append_unsigned_leb128 (0);
}
+ /* Record the offset in the pool at which this entry will
+ reside. */
+ const auto offset_inserted
+ = (m_entry_pool_offsets.emplace (entry, m_entry_pool.size ())
+ .second);
+ gdb_assert (offset_inserted);
+
+ /* Write the entry to the pool. */
m_entry_pool.append_unsigned_leb128 (idx);
const auto it = m_cu_index_htab.find (entry->per_cu);
@@ -804,11 +802,11 @@ public:
if (parent != nullptr)
{
- c_str_view par_name (parent->name);
- auto name_iter = m_name_to_value_set.find (par_name);
- gdb_assert (name_iter != m_name_to_value_set.end ());
- gdb_assert (name_iter->second.index != 0);
- m_entry_pool.append_unsigned_leb128 (name_iter->second.index);
+ m_offsets_to_patch.emplace_back (m_entry_pool.size (), parent);
+
+ /* Write a dummy number, this gets patched later. */
+ m_entry_pool.append_uint (4, m_dwarf5_byte_order,
+ 0xfafafafa);
}
}
@@ -818,6 +816,15 @@ public:
/* Terminate tags list. */
m_abbrev_table.append_unsigned_leb128 (0);
+
+ /* Write the parent offset values. */
+ for (const auto &[reloc_offset, parent] : m_offsets_to_patch)
+ {
+ const auto parent_offset_it = m_entry_pool_offsets.find (parent);
+ gdb_assert (parent_offset_it != m_entry_pool_offsets.cend ());
+ m_entry_pool.write_uint (reloc_offset, 4, m_dwarf5_byte_order,
+ parent_offset_it->second);
+ }
}
/* Return .debug_names names count. This must be called only after
@@ -865,7 +872,7 @@ public:
m_debugstrlookup.file_write (file_str);
}
- void add_cu (dwarf2_per_cu_data *per_cu, offset_type index)
+ void add_cu (dwarf2_per_cu *per_cu, offset_type index)
{
m_cu_index_htab.emplace (per_cu, index);
}
@@ -880,8 +887,7 @@ private:
/* Object constructor to be called for current DWARF2_PER_BFD. */
debug_str_lookup (dwarf2_per_bfd *per_bfd)
- : m_abfd (per_bfd->obfd),
- m_per_bfd (per_bfd)
+ : m_per_bfd (per_bfd)
{
}
@@ -914,8 +920,7 @@ private:
}
private:
- std::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table;
- bfd *const m_abfd;
+ gdb::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table;
dwarf2_per_bfd *m_per_bfd;
/* Data to add at the end of .debug_str for new needed symbol names. */
@@ -953,7 +958,7 @@ private:
const bool has_parent;
};
- /* Provide std::unordered_map::hasher for index_key. */
+ /* Provide gdb::unordered_map::hasher for index_key. */
class index_key_hasher
{
public:
@@ -1063,15 +1068,26 @@ private:
offset_vec_tmpl<OffsetSize> m_name_table_entry_offs;
};
- struct entry_list
- {
- unsigned index = 0;
- std::vector<const cooked_index_entry *> entries;
- };
+ /* Store the index entries for each name.
+
+ Note that we rely on the sorting behavior of map to make the output
+ stable. */
+ std::map<c_str_view, std::vector<const cooked_index_entry *>>
+ m_name_to_value_set;
+
+ /* Offset at which each entry is written in the entry pool. */
+ gdb::unordered_map<const cooked_index_entry *, offset_type>
+ m_entry_pool_offsets;
+
+ /* The locations where we need to patch offset to entries.
- /* Store value of each symbol. Note that we rely on the sorting
- behavior of map to make the output stable. */
- std::map<c_str_view, entry_list> m_name_to_value_set;
+ The first element of the pair is the offset into the pool that needs to
+ be patched.
+
+ The second element is the entry the offset to which needs to be
+ patched in. */
+ std::vector<std::pair<offset_type, const cooked_index_entry *>>
+ m_offsets_to_patch;
const bfd_endian m_dwarf5_byte_order;
dwarf_tmpl<uint32_t> m_dwarf32;
@@ -1082,7 +1098,7 @@ private:
/* Map each used .debug_names abbreviation tag parameter to its
index value. */
- std::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx;
+ gdb::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx;
/* .debug_names abbreviation table. */
data_buf m_abbrev_table;
@@ -1262,7 +1278,7 @@ write_shortcuts_table (cooked_index *table, data_buf &shortcuts,
if (dw_lang != 0)
{
auto_obstack obstack;
- const auto main_name = main_info->full_name (&obstack, true);
+ const auto main_name = main_info->full_name (&obstack, FOR_MAIN);
main_name_offset = cpool.size ();
cpool.append_cstr0 (main_name);
@@ -1286,10 +1302,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
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_data
- (which is what addrmap records) to its index (which is what is recorded
- in the index file). This will later be needed to write the address
- table. */
+ /* 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
+ index file). This will later be needed to write the address table. */
cu_index_map cu_index_htab;
cu_index_htab.reserve (per_bfd->all_units.size ());
@@ -1300,11 +1315,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
work here. */
int counter = 0;
- for (int i = 0; i < per_bfd->all_units.size (); ++i)
+ for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
{
- dwarf2_per_cu_data *per_cu = per_bfd->all_units[i].get ();
-
- const auto insertpair = cu_index_htab.emplace (per_cu, counter);
+ const auto insertpair = cu_index_htab.emplace (per_cu.get (), counter);
gdb_assert (insertpair.second);
/* See enhancement PR symtab/30838. */
@@ -1320,7 +1333,7 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
to_underlying (per_cu->sect_off));
if (per_cu->is_debug_types)
{
- signatured_type *sig_type = (signatured_type *) per_cu;
+ 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,
@@ -1337,7 +1350,8 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
/* Dump the address map. */
data_buf addr_vec;
for (auto map : table->get_addrmaps ())
- write_address_map (map, addr_vec, cu_index_htab);
+ if (map != nullptr)
+ write_address_map (map, addr_vec, cu_index_htab);
/* Ensure symbol hash is built domestically. */
symtab.sort ();
@@ -1382,14 +1396,12 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order);
int counter = 0;
int types_counter = 0;
- for (int i = 0; i < per_bfd->all_units.size (); ++i)
+ for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
{
- dwarf2_per_cu_data *per_cu = per_bfd->all_units[i].get ();
-
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, this_counter);
+ 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));
@@ -1410,7 +1422,7 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
const offset_type bytes_of_header
= ((dwarf5_is_dwarf64 ? 12 : 4)
+ 2 + 2 + 7 * 4
- + sizeof (dwarf5_augmentation));
+ + sizeof (dwarf5_augmentation_3));
size_t expected_bytes = 0;
expected_bytes += bytes_of_header;
expected_bytes += cu_list.size ();
@@ -1462,9 +1474,9 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
/* augmentation_string_size - The size in bytes of the augmentation
string. This value is rounded up to a multiple of 4. */
- static_assert (sizeof (dwarf5_augmentation) % 4 == 0);
- header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_augmentation));
- header.append_array (dwarf5_augmentation);
+ static_assert (sizeof (dwarf5_augmentation_3) % 4 == 0);
+ header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_augmentation_3));
+ header.append_array (dwarf5_augmentation_3);
gdb_assert (header.size () == bytes_of_header);
@@ -1551,6 +1563,9 @@ write_dwarf_index (dwarf2_per_bfd *per_bfd, const char *dir,
if (table == nullptr)
error (_("Cannot use an index to create the index"));
+ if (per_bfd->infos.size () > 1)
+ error (_("Cannot make an index when the file has multiple .debug_info"
+ " sections"));
if (per_bfd->types.size () > 1)
error (_("Cannot make an index when the file has multiple .debug_types sections"));
@@ -1621,8 +1636,8 @@ gdb_save_index_cmd_completer (struct cmd_list_element *ignore,
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp))
return;
- word = advance_to_filename_complete_word_point (tracker, text);
- filename_completer (ignore, tracker, text, word);
+ word = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
}
/* Implementation of the `save gdb-index' command.
@@ -1639,10 +1654,10 @@ save_gdb_index_command (const char *args, int from_tty)
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
- if (args == nullptr || *args == '\0')
+ std::string directory = extract_single_filename_arg (args);
+ if (directory.empty ())
error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
- std::string directory (gdb_tilde_expand (args));
dw_index_kind index_kind
= (opts.dwarf_5 ? dw_index_kind::DEBUG_NAMES : dw_index_kind::GDB_INDEX);
@@ -1659,7 +1674,7 @@ save_gdb_index_command (const char *args, int from_tty)
try
{
const char *basename = lbasename (objfile_name (objfile));
- const dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
+ const dwz_file *dwz = per_objfile->per_bfd->get_dwz_file ();
const char *dwz_basename = NULL;
if (dwz != NULL)
@@ -1753,9 +1768,7 @@ gdb_index ()
} /* selftests namespace. */
#endif
-void _initialize_dwarf_index_write ();
-void
-_initialize_dwarf_index_write ()
+INIT_GDB_FILE (dwarf_index_write)
{
#if GDB_SELF_TEST
selftests::register_test ("gdb_index", selftests::gdb_index);