26#include "gdbsupport/byte-vector.h"
27#include "gdbsupport/filestuff.h"
28#include "gdbsupport/gdb_unlinker.h"
29#include "gdbsupport/pathstuff.h"
30#include "gdbsupport/scoped_fd.h"
36#include "gdb/gdb-index.h"
44#include <forward_list>
46#include <unordered_map>
47#include <unordered_set>
50#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
52 gdb_assert ((unsigned int) (value) <= 1); \
53 GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \
57#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
59 gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
60 && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
61 GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
65#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \
67 gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \
68 GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
79 if (fwrite (data, 1,
size, file) !=
size)
80 error (_(
"couldn't data write to file"));
85template<
typename Elem,
typename Alloc>
87file_write (FILE *file,
const std::vector<Elem, Alloc> &vec)
90 file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
100 std::copy (array.begin (), array.end (),
grow (array.size ()));
107 const size_t size = strlen (cstr) + 1;
116 gdb_byte output = input & 0x7f;
120 m_vec.push_back (output);
128 void append_uint (
size_t len, bfd_endian byte_order, ULONGEST val)
142 return m_vec.size ();
148 return m_vec.empty ();
201 std::vector<symtab_index_entry>
data;
218 index = hash & (
symtab->data.size () - 1);
219 step = ((hash * 17) & (
symtab->data.size () - 1)) | 1;
223 if (
symtab->data[index].name == NULL
224 || strcmp (
name,
symtab->data[index].name) == 0)
225 return symtab->data[index];
226 index = (index + step) & (
symtab->data.size () - 1);
235 auto old_entries = std::move (
symtab->data);
238 symtab->data.resize (old_entries.size () * 2);
240 for (
auto &it : old_entries)
244 ref = std::move (it);
254 int is_static, gdb_index_symbol_kind kind,
264 if (slot.
name == NULL)
270 cu_index_and_attrs = 0;
282 slot.
cu_indices.push_back (cu_index_and_attrs);
302 std::unordered_set<offset_type> seen;
306 gdb_index_symbol_kind kind = GDB_INDEX_SYMBOL_KIND_VALUE (val);
307 if (kind != GDB_INDEX_SYMBOL_KIND_TYPE)
310 val &= ~GDB_INDEX_CU_MASK;
311 return !seen.insert (val).second;
361 return iterative_hash (key.data (),
362 sizeof (key.front ()) * key.size (), 0);
375 std::unordered_map<std::vector<offset_type>,
offset_type,
383 if (entry.name == NULL)
385 gdb_assert (entry.index_offset == 0);
393 = symbol_hash_table.find (entry.cu_indices);
394 if (found != symbol_hash_table.end ())
396 entry.index_offset = found->second;
400 symbol_hash_table.emplace (entry.cu_indices, cpool.
size ());
401 entry.index_offset = cpool.
size ();
403 for (
const auto index : entry.cu_indices)
409 std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
410 for (
const auto &entry :
symtab->data)
414 if (entry.name != NULL)
416 const auto insertpair = str_table.emplace (entry.name, cpool.
size ());
417 if (insertpair.second)
419 str_off = insertpair.first->second;
420 vec_off = entry.index_offset;
436 = std::unordered_map<const dwarf2_per_cu_data *, unsigned int>;
449 int operator() (CORE_ADDR start_addr,
const void *obj);
465 CORE_ADDR start, CORE_ADDR end,
unsigned int cu_index)
467 addr_vec.
append_uint (8, BFD_ENDIAN_LITTLE, start);
527 bfd_endian dwarf5_byte_order)
542 return dwarf5_is_dwarf64 ? 8 : 4;
559 dwarf_tag tag = entry->tag;
561 tag = DW_TAG_structure_type;
562 else if (tag == DW_TAG_enumerator || tag == DW_TAG_constant)
563 tag = DW_TAG_variable;
565 int cu_index = it->second;
566 bool is_static = (entry->flags &
IS_STATIC) != 0;
567 unit_kind kind = (entry->per_cu->is_debug_types
580 const auto insertpair
582 std::set<symbol_value> ());
583 std::set<symbol_value> &value_set = insertpair.first->second;
584 value_set.emplace (
symbol_value (tag, cu_index, is_static, kind));
597 if (decoded[0] ==
'<')
599 decoded.c_str () + 1,
600 decoded.length () - 2);
606 const auto insertpair
608 std::set<symbol_value> ());
609 std::set<symbol_value> &value_set = insertpair.first->second;
610 value_set.emplace (
symbol_value (tag, cu_index, is_static, kind));
622 (std::pow (2, std::ceil (std::log2 (
name_count * 4 / 3))));
631 decltype (m_name_to_value_set)::const_iterator it;
633 std::vector<std::forward_list<hash_it_pair>> bucket_hash;
640 const char *
const name = it->first.c_str ();
642 hash_it_pair hashitpair;
643 hashitpair.hash = hash;
645 auto &slot = bucket_hash[hash % bucket_hash.size()];
646 slot.push_front (std::move (hashitpair));
648 for (
size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
650 const std::forward_list<hash_it_pair> &hashitlist
651 = bucket_hash[bucket_ix];
652 if (hashitlist.empty ())
659 for (
const hash_it_pair &hashitpair : hashitlist)
667 const std::set<symbol_value> &value_set = hashitpair.it->second;
671 gdb_assert (!value_set.empty ());
687 ? DW_IDX_GNU_internal
688 : DW_IDX_GNU_external);
746 size_t bytes ()
const
750 size_t expected_bytes = 0;
757 return expected_bytes;
763 void file_write (FILE *file_names, FILE *file_str)
const
798 for (
const gdb_byte *data = per_bfd->
str.
buffer;
802 const char *
const s =
reinterpret_cast<const char *
> (data);
803 const auto insertpair
806 if (!insertpair.second)
807 complaint (_(
"Duplicate string \"%s\" in "
808 ".debug_str section [in module %s]"),
809 s, bfd_get_filename (
m_abfd));
810 data += strlen (s) + 1;
817 size_t lookup (
const char *s)
836 std::unordered_map<c_str_view, size_t, c_str_view_hasher>
m_str_table;
885 symbol_value (
int dwarf_tag_,
int cu_index_,
bool is_static_,
919 explicit offset_vec (bfd_endian dwarf5_byte_order_)
924 virtual void reserve (
size_t nelem) = 0;
931 virtual size_t bytes ()
const = 0;
934 virtual void file_write (FILE *file)
const = 0;
938 template<
typename OffsetSize>
947 void reserve (
size_t nelem)
override
955 m_vec.push_back (elem);
957 gdb_assert (
m_vec.back () == elem);
963 size_t bytes ()
const override
975 std::vector<OffsetSize>
m_vec;
995 template<
typename OffsetSize>
999 explicit dwarf_tmpl (bfd_endian dwarf5_byte_order_)
1052 for (
const auto &per_cu : per_bfd->
all_units)
1054 if (to_underlying (per_cu->sect_off)
1055 >= (
static_cast<uint64_t
> (1) << 32))
1067 const auto file_size = ftell (file);
1068 if (file_size == -1)
1069 perror_with_name ((
"ftell"));
1070 gdb_assert (file_size == expected_size);
1086 uint64_t total_len = size_of_header;
1093 total_len += cu_list.
size ();
1097 total_len += types_cu_list.
size ();
1101 total_len += addr_vec.
size ();
1105 total_len += symtab_vec.
size ();
1109 total_len += constant_pool.
size ();
1111 gdb_assert (contents.
size () == size_of_header);
1117 if (total_len > max_size)
1118 error (_(
"gdb-index maximum file size of %zu exceeded"), max_size);
1120 if (out_file ==
nullptr)
1142 const auto it = cu_index_htab.find (entry->per_cu);
1143 gdb_assert (it != cu_index_htab.cend ());
1145 const char *
name = entry->full_name (&
symtab->m_string_obstack);
1153 name = obstack_strdup (&
symtab->m_string_obstack,
1172 gdb_index_symbol_kind kind;
1173 if (entry->tag == DW_TAG_subprogram)
1174 kind = GDB_INDEX_SYMBOL_KIND_FUNCTION;
1175 else if (entry->tag == DW_TAG_variable
1176 || entry->tag == DW_TAG_constant
1177 || entry->tag == DW_TAG_enumerator)
1178 kind = GDB_INDEX_SYMBOL_KIND_VARIABLE;
1179 else if (entry->tag == DW_TAG_module
1180 || entry->tag == DW_TAG_common_block)
1181 kind = GDB_INDEX_SYMBOL_KIND_OTHER;
1183 kind = GDB_INDEX_SYMBOL_KIND_TYPE;
1197 FILE *out_file, FILE *dwz_out_file)
1208 cu_index_htab.reserve (per_bfd->
all_units.size ());
1217 for (
int i = 0; i < per_bfd->
all_units.size (); ++i)
1221 const auto insertpair = cu_index_htab.emplace (per_cu, counter);
1222 gdb_assert (insertpair.second);
1232 : per_cu->
is_dwz ? dwz_cu_list : objfile_cu_list);
1260 data_buf symtab_vec, constant_pool;
1261 if (
symtab.n_elements == 0)
1267 symtab_vec, constant_pool);
1269 if (dwz_out_file != NULL)
1272 gdb_assert (dwz_cu_list.
empty ());
1284 FILE *out_file, FILE *out_file_str)
1287 const enum bfd_endian dwarf5_byte_order
1288 = bfd_big_endian (per_bfd->
obfd) ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
1295 debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order);
1297 int types_counter = 0;
1298 for (
int i = 0; i < per_bfd->
all_units.size (); ++i)
1302 int &this_counter = per_cu->
is_debug_types ? types_counter : counter;
1305 nametable.
add_cu (per_cu, this_counter);
1317 nametable.
insert (entry);
1324 = ((dwarf5_is_dwarf64 ? 12 : 4)
1327 size_t expected_bytes = 0;
1328 expected_bytes += bytes_of_header;
1329 expected_bytes += cu_list.
size ();
1330 expected_bytes += types_cu_list.
size ();
1331 expected_bytes += nametable.
bytes ();
1334 if (!dwarf5_is_dwarf64)
1336 const uint64_t size64 = expected_bytes - 4;
1337 gdb_assert (size64 < 0xfffffff0);
1338 header.
append_uint (4, dwarf5_byte_order, size64);
1342 header.
append_uint (4, dwarf5_byte_order, 0xffffffff);
1343 header.
append_uint (8, dwarf5_byte_order, expected_bytes - 12);
1353 header.
append_uint (4, dwarf5_byte_order, counter);
1357 header.
append_uint (4, dwarf5_byte_order, types_counter);
1380 gdb_assert (header.
size () == bytes_of_header);
1385 nametable.
file_write (out_file, out_file_str);
1403 filename = (std::string (dir) + SLASH_STRING + basename
1408 scoped_fd out_file_fd = gdb_mkostemp_cloexec (
filename_temp.data (),
1410 if (out_file_fd.get () == -1)
1411 perror_with_name ((
"mkstemp"));
1413 out_file = out_file_fd.to_file (
"wb");
1416 error (_(
"Can't open `%s' for writing"),
filename_temp.data ());
1429 perror_with_name ((
"rename"));
1448 const char *basename,
const char *dwz_basename,
1452 error (_(
"No debugging symbols"));
1455 if (per_bfd->
types.size () > 1)
1456 error (_(
"Cannot make an index when the file has multiple .debug_types sections"));
1462 gdb::optional<index_wip_file> dwz_index_wip;
1464 if (dwz_basename != NULL)
1465 dwz_index_wip.emplace (dir, dwz_basename, index_suffix);
1478 (dwz_index_wip.has_value ()
1479 ? dwz_index_wip->out_file.get () : NULL));
1483 if (dwz_index_wip.has_value ())
1484 dwz_index_wip->finalize ();
1496 const char dwarf5space[] =
"-dwarf-5 ";
1502 arg = skip_spaces (arg);
1503 if (strncmp (arg, dwarf5space, strlen (dwarf5space)) == 0)
1506 arg += strlen (dwarf5space);
1507 arg = skip_spaces (arg);
1511 error (_(
"usage: save gdb-index [-dwarf-5] DIRECTORY"));
1521 if (per_objfile != NULL)
1527 const char *dwz_basename = NULL;
1530 dwz_basename = lbasename (dwz->
filename ());
1533 dwz_basename, index_kind);
1535 catch (
const gdb_exception_error &except)
1538 _(
"Error while writing index for `%s': "),
1547#include "gdbsupport/selftest.h"
1551class pretend_data_buf :
public data_buf
1555 void set_pretend_size (
size_t s) {
1560 size_t size ()
const override {
1561 return m_pretend_size;
1565 size_t m_pretend_size = 0;
1571 pretend_data_buf cu_list;
1572 pretend_data_buf types_cu_list;
1573 pretend_data_buf addr_vec;
1574 pretend_data_buf symtab_vec;
1575 pretend_data_buf constant_pool;
1577 const size_t size_of_header = 6 *
sizeof (
offset_type);
1580 symtab_vec.set_pretend_size (~(
offset_type)0 - size_of_header);
1581 constant_pool.set_pretend_size (1);
1583 bool saw_exception =
false;
1587 symtab_vec, constant_pool);
1589 catch (
const gdb_exception_error &e)
1591 SELF_CHECK (e.reason == RETURN_ERROR);
1592 SELF_CHECK (e.error == GENERIC_ERROR);
1593 SELF_CHECK (e.message->find (_(
"gdb-index maximum file size of"))
1594 != std::string::npos);
1595 SELF_CHECK (e.message->find (_(
"exceeded")) != std::string::npos);
1596 saw_exception =
true;
1598 SELF_CHECK (saw_exception);
1601 constant_pool.set_pretend_size (0);
1603 saw_exception =
false;
1607 symtab_vec, constant_pool);
1609 catch (
const gdb_exception_error &e)
1611 saw_exception =
true;
1613 SELF_CHECK (!saw_exception);
1624 selftests::register_test (
"gdb_index", selftests::gdb_index);
1629Save a gdb-index file.\n\
1630Usage: save gdb-index [-dwarf-5] DIRECTORY\n\
1632No options create one file with .gdb-index extension for pre-DWARF-5\n\
1633compatible .gdb_index section. With -dwarf-5 creates two files with\n\
1634extension .debug_names and .debug_str for DWARF-5 .debug_names section."),
std::string ada_decode(const char *encoded, bool wrap, bool operators)
std::string ada_encode(const char *decoded, bool fold)
struct cmd_list_element * save_cmdlist
size_t operator()(const c_str_view &x) const
const char * c_str() const
bool operator==(const c_str_view &other) const
c_str_view(const char *cstr)
std::vector< const addrmap * > get_addrmaps() const
range all_entries() const
void file_write(FILE *file) const
void append_cstr0(const char *cstr)
virtual size_t size() const
void append_array(gdb::array_view< const gdb_byte > array)
void append_uint(size_t len, bfd_endian byte_order, ULONGEST val)
void append_unsigned_leb128(ULONGEST input)
gdb_byte * grow(size_t size)
void append_offset(offset_type value)
size_t lookup(const char *s)
std::unordered_map< c_str_view, size_t, c_str_view_hasher > m_str_table
debug_str_lookup(dwarf2_per_bfd *per_bfd)
dwarf2_per_bfd * m_per_bfd
void file_write(FILE *file) const
dwarf_tmpl(bfd_endian dwarf5_byte_order_)
offset_vec_tmpl< OffsetSize > m_name_table_string_offs
offset_vec_tmpl< OffsetSize > m_name_table_entry_offs
dwarf(offset_vec &name_table_string_offs_, offset_vec &name_table_entry_offs_)
offset_vec & name_table_string_offs
offset_vec & name_table_entry_offs
size_t operator()(const index_key &key) const
index_key(int dwarf_tag_, bool is_static_, unit_kind kind_)
bool operator==(const index_key &other) const
offset_vec_tmpl(bfd_endian dwarf5_byte_order_)
void file_write(FILE *file) const override
void push_back_reorder(size_t elem) override
void reserve(size_t nelem) override
size_t bytes() const override
std::vector< OffsetSize > m_vec
const bfd_endian dwarf5_byte_order
virtual void file_write(FILE *file) const =0
virtual size_t bytes() const =0
virtual void push_back_reorder(size_t elem)=0
virtual void reserve(size_t nelem)=0
offset_vec(bfd_endian dwarf5_byte_order_)
bool operator<(const symbol_value &other) const
symbol_value(int dwarf_tag_, int cu_index_, bool is_static_, unit_kind kind_)
std::vector< uint32_t > m_hash_table
int dwarf5_offset_size() const
void file_write(FILE *file_names, FILE *file_str) const
uint32_t abbrev_table_bytes() const
uint32_t name_count() const
offset_vec & m_name_table_entry_offs
dwarf_tmpl< uint64_t > m_dwarf64
void add_cu(dwarf2_per_cu_data *per_cu, offset_type index)
dwarf_tmpl< uint32_t > m_dwarf32
std::unordered_map< index_key, int, index_key_hasher > m_indexkey_to_idx
offset_vec & m_name_table_string_offs
void insert(const cooked_index_entry *entry)
cu_index_map m_cu_index_htab
std::unordered_map< c_str_view, std::set< symbol_value >, c_str_view_hasher > m_name_to_value_set
debug_str_lookup m_debugstrlookup
auto_obstack m_string_obstack
debug_names(dwarf2_per_bfd *per_bfd, bool is_dwarf64, bfd_endian dwarf5_byte_order)
std::vector< uint32_t > m_bucket_table
const bfd_endian m_dwarf5_byte_order
uint32_t bucket_count() const
size_t operator()(const std::vector< T > &key) const
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
void set_cmd_completer(struct cmd_list_element *cmd, completer_ftype *completer)
#define complaint(FMT,...)
void filename_completer(struct cmd_list_element *ignore, completion_tracker &tracker, const char *text, const char *word)
static void store_unsigned_integer(gdb_byte *addr, int len, enum bfd_endian byte_order, ULONGEST val)
struct dwz_file * dwarf2_get_dwz_file(dwarf2_per_bfd *per_bfd, bool require)
void exception_fprintf(struct ui_file *file, const struct gdb_exception &e, const char *prefix,...)
uint32_t dwarf5_djb_hash(const char *str_)
hashval_t mapped_index_string_hash(int index_version, const void *p)
static void write_gdbindex_1(FILE *out_file, const data_buf &cu_list, const data_buf &types_cu_list, const data_buf &addr_vec, const data_buf &symtab_vec, const data_buf &constant_pool)
#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value)
static void write_debug_names(dwarf2_per_bfd *per_bfd, cooked_index *table, FILE *out_file, FILE *out_file_str)
std::unordered_map< const dwarf2_per_cu_data *, unsigned int > cu_index_map
static void assert_file_size(FILE *file, size_t expected_size)
#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value)
static void write_address_map(const addrmap *addrmap, data_buf &addr_vec, cu_index_map &cu_index_htab)
void write_dwarf_index(dwarf2_per_bfd *per_bfd, const char *dir, const char *basename, const char *dwz_basename, dw_index_kind index_kind)
static symtab_index_entry & find_slot(struct mapped_symtab *symtab, const char *name)
#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value)
static void add_address_entry(data_buf &addr_vec, CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
void _initialize_dwarf_index_write()
static const gdb_byte dwarf5_gdb_augmentation[]
static void hash_expand(struct mapped_symtab *symtab)
static void write_cooked_index(cooked_index *table, const cu_index_map &cu_index_htab, struct mapped_symtab *symtab)
static void file_write(FILE *file, const void *data, size_t size)
static bool check_dwarf64_offsets(dwarf2_per_bfd *per_bfd)
static void save_gdb_index_command(const char *arg, int from_tty)
static void write_gdbindex(dwarf2_per_bfd *per_bfd, cooked_index *table, FILE *out_file, FILE *dwz_out_file)
static void add_index_entry(struct mapped_symtab *symtab, const char *name, int is_static, gdb_index_symbol_kind kind, offset_type cu_index)
static void write_hash_table(mapped_symtab *symtab, data_buf &output, data_buf &cpool)
const char * objfile_name(const struct objfile *objfile)
struct program_space * current_program_space
dwarf2_per_objfile * get_dwarf2_per_objfile(struct objfile *objfile)
cu_index_map & cu_index_htab
addrmap_index_data(data_buf &addr_vec_, cu_index_map &cu_index_htab_)
int operator()(CORE_ADDR start_addr, const void *obj)
CORE_ADDR previous_cu_start
unsigned int previous_cu_index
int foreach(addrmap_foreach_const_fn fn) const
gdb::array_view< dwarf2_per_cu_data_up > all_comp_units
std::unique_ptr< dwarf_scanner_base > index_table
gdb::array_view< dwarf2_per_cu_data_up > all_type_units
std::vector< dwarf2_section_info > types
std::vector< dwarf2_per_cu_data_up > all_units
unsigned int is_debug_types
unsigned int length() const
struct dwarf2_per_bfd * per_bfd
const char * filename() const
index_wip_file(const char *dir, const char *basename, const char *suffix)
gdb::optional< gdb::unlinker > unlink_file
gdb::char_vector filename_temp
std::vector< symtab_index_entry > data
auto_obstack m_string_obstack
objfiles_range objfiles()
cu_offset type_offset_in_tu
std::vector< offset_type > cu_indices
static bool tag_is_type(dwarf_tag tag)