[PATCH 1/6] Code cleanup: C++ify .gdb_index producer.

Jan Kratochvil
2017-05-26T18:25:50Z

gdb/ChangeLog
2017-05-26 Jan Kratochvil <jan.kratochvil@redhat.com>

Code cleanup: C++ify .gdb_index producer.
* common/common-defs.h <c++11> (std::make_unique): New.
* dwarf2read.c: Remove include common/gdb_unlinker.h. Add includes
unordered_set and unordered_map.
(MAYBE_SWAP): Cast it to offset_type.
(struct strtab_entry, hash_strtab_entry, eq_strtab_entry)
(create_strtab, add_string): Remove.
(file_write, file_write, DataBuf): New.
(struct symtab_index_entry): Use std::vector for cu_indices.
(struct mapped_symtab): Use std::vector for data.
(hash_symtab_entry, eq_symtab_entry, delete_symtab_entry)
(create_symbol_hash_table, create_mapped_symtab, cleanup_mapped_symtab):
Remove.
(find_slot): Change return type. Update it to the new data structures.
(hash_expand, add_index_entry): Update it to the new data structures.
(offset_type_compare): Remove.
(uniquify_cu_indices): Update it to the new data structures.
(CstrView, CstrViewHasher, VectorHasher): New.
(add_indices_to_cpool): Remove.
(write_hash_table): Update it to the new data structures.
(struct psymtab_cu_index_map, hash_psymtab_cu_index)
(eq_psymtab_cu_index): Remove.
(struct addrmap_index_data): Change addr_obstack pointer to DataBuf
reference and std::unordered_map for cu_index_htab.
(add_address_entry, add_address_entry_worker, write_address_map)
(write_psymbols): Update it to the new data structures.
(write_obstack): Remove.
(struct signatured_type_index_data): Change types_list to a DataBuf
reference and psyms_seen to a std::unordered_set reference.
(write_one_signatured_type, recursively_write_psymbols)
(write_psymtabs_to_index): Update it to the new data structures.
---
gdb/common/common-defs.h | 14 +
gdb/dwarf2read.c | 793 ++++++++++++++++++----------------------------
2 files changed, 328 insertions(+), 479 deletions(-)

diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h
index 439bce6..e624c5e 100644
--- a/gdb/common/common-defs.h
+++ b/gdb/common/common-defs.h
@@ -91,4 +91,18 @@
/* Pull in gdb::unique_xmalloc_ptr. */
#include "common/gdb_unique_ptr.h"

+// Provide C++14 std::make_unique<> for C++11 compilation mode.
+// A copy from: gcc/libstdc++-v3/include/bits/unique_ptr.h
+#if __cplusplus <= 201103L
+namespace std {
+ template<typename _Tp>
+ struct _MakeUniq
+ { typedef unique_ptr<_Tp> __single_object; };
+ template<typename _Tp, typename... _Args>
+ inline typename _MakeUniq<_Tp>::__single_object
+ make_unique(_Args&&... __args)
+ { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
+}
+#endif
+
#endif /* COMMON_DEFS_H */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index b58d0fc..12a194a 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -69,7 +69,6 @@
#include "filestuff.h"
#include "build-id.h"
#include "namespace.h"
-#include "common/gdb_unlinker.h"
#include "common/function-view.h"
#include "common/gdb_optional.h"
#include "common/underlying.h"
@@ -77,6 +76,8 @@
#include <fcntl.h>
#include <sys/types.h>
#include <algorithm>
+#include <unordered_set>
+#include <unordered_map>

typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
@@ -2146,7 +2147,7 @@ byte_swap (offset_type value)
#define MAYBE_SWAP(V) byte_swap (V)

#else
-#define MAYBE_SWAP(V) (V)
+#define MAYBE_SWAP(V) static_cast<offset_type> (V)
#endif /* WORDS_BIGENDIAN */

/* Read the given attribute value as an address, taking the attribute's
@@ -23193,69 +23194,76 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
\f
/* The "save gdb-index" command. */

-/* The contents of the hash table we create when building the string
- table. */
-struct strtab_entry
-{
- offset_type offset;
- const char *str;
-};
-
-/* Hash function for a strtab_entry.
-
- Function is used only during write_hash_table so no index format backward
- compatibility is needed. */
+// Write to FILE bytes starting at DATA of length SIZE with error checking.

-static hashval_t
-hash_strtab_entry (const void *e)
+static void
+file_write (FILE *file, const void *data, size_t size)
{
- const struct strtab_entry *entry = (const struct strtab_entry *) e;
- return mapped_index_string_hash (INT_MAX, entry->str);
+ if (fwrite (data, 1, size, file) != size)
+ error (_("couldn't data write to file"));
}

-/* Equality function for a strtab_entry. */
+// Write to FILE bytes of std::vector VEC with error checking.

-static int
-eq_strtab_entry (const void *a, const void *b)
+template<class Elem> static void
+file_write (FILE *file, const std::vector<Elem> &vec)
{
- const struct strtab_entry *ea = (const struct strtab_entry *) a;
- const struct strtab_entry *eb = (const struct strtab_entry *) b;
- return !strcmp (ea->str, eb->str);
+ file_write (file, vec.data (), vec.size() * sizeof (vec[0]));
}

-/* Create a strtab_entry hash table. */
-
-static htab_t
-create_strtab (void)
+// In-memory buffer to prepare data to be written later to a file.
+class DataBuf
{
- return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry,
- xfree, xcalloc, xfree);
-}
+private:
+ std::vector<gdb_byte> vec;
+public:

-/* Add a string to the constant pool. Return the string's offset in
- host order. */
+ // Append space of SIZE number of bytes to the end of buffer.
+ // Return pointer to its start.

-static offset_type
-add_string (htab_t table, struct obstack *cpool, const char *str)
-{
- void **slot;
- struct strtab_entry entry;
- struct strtab_entry *result;
+ gdb_byte *
+ append_space (size_t size)
+ {
+ vec.resize (vec.size () + size);
+ return &*vec.end () - size;
+ }

- entry.str = str;
- slot = htab_find_slot (table, &entry, INSERT);
- if (*slot)
- result = (struct strtab_entry *) *slot;
- else
- {
- result = XNEW (struct strtab_entry);
- result->offset = obstack_object_size (cpool);
- result->str = str;
- obstack_grow_str0 (cpool, str);
- *slot = result;
- }
- return result->offset;
-}
+ // Copy DATA to the end of buffer.
+
+ template<typename T> void
+ append_data (const T &data)
+ {
+ std::copy (reinterpret_cast<const gdb_byte *> (&data),
+ reinterpret_cast<const gdb_byte *> (&data + 1),
+ append_space (sizeof (data)));
+ }
+
+ // Copy CSTR zero-terminated string to the end of buffer including its
+ // terminating zero.
+
+ void
+ append_cstr0 (const char *cstr)
+ {
+ const size_t size (strlen (cstr) + 1);
+ std::copy (cstr, cstr + size, append_space (size));
+ }
+
+ // Return size of the buffer.
+
+ size_t
+ size () const
+ {
+ return vec.size ();
+ }
+
+ /* Write the buffer to FILE. */
+
+ void
+ file_write (FILE *file) const
+ {
+ ::file_write (file, vec);
+ }
+};

/* An entry in the symbol table. */
struct symtab_index_entry
@@ -23266,107 +23274,40 @@ struct symtab_index_entry
offset_type index_offset;
/* A sorted vector of the indices of all the CUs that hold an object
of this name. */
- VEC (offset_type) *cu_indices;
+ std::vector<offset_type> cu_indices;
};

/* The symbol table. This is a power-of-2-sized hash table. */
struct mapped_symtab
{
- offset_type n_elements;
- offset_type size;
- struct symtab_index_entry **data;
+public:
+ offset_type n_elements = 0;
+ std::vector<std::unique_ptr<symtab_index_entry>> data;
+ mapped_symtab ()
+ {
+ data.resize (1024);
+ }
};

-/* Hash function for a symtab_index_entry. */
-
-static hashval_t
-hash_symtab_entry (const void *e)
-{
- const struct symtab_index_entry *entry
- = (const struct symtab_index_entry *) e;
- return iterative_hash (VEC_address (offset_type, entry->cu_indices),
- sizeof (offset_type) * VEC_length (offset_type,
- entry->cu_indices),
- 0);
-}
-
-/* Equality function for a symtab_index_entry. */
-
-static int
-eq_symtab_entry (const void *a, const void *b)
-{
- const struct symtab_index_entry *ea = (const struct symtab_index_entry *) a;
- const struct symtab_index_entry *eb = (const struct symtab_index_entry *) b;
- int len = VEC_length (offset_type, ea->cu_indices);
- if (len != VEC_length (offset_type, eb->cu_indices))
- return 0;
- return !memcmp (VEC_address (offset_type, ea->cu_indices),
- VEC_address (offset_type, eb->cu_indices),
- sizeof (offset_type) * len);
-}
-
-/* Destroy a symtab_index_entry. */
-
-static void
-delete_symtab_entry (void *p)
-{
- struct symtab_index_entry *entry = (struct symtab_index_entry *) p;
- VEC_free (offset_type, entry->cu_indices);
- xfree (entry);
-}
-
-/* Create a hash table holding symtab_index_entry objects. */
-
-static htab_t
-create_symbol_hash_table (void)
-{
- return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry,
- delete_symtab_entry, xcalloc, xfree);
-}
-
-/* Create a new mapped symtab object. */
-
-static struct mapped_symtab *
-create_mapped_symtab (void)
-{
- struct mapped_symtab *symtab = XNEW (struct mapped_symtab);
- symtab->n_elements = 0;
- symtab->size = 1024;
- symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size);
- return symtab;
-}
-
-/* Destroy a mapped_symtab. */
-
-static void
-cleanup_mapped_symtab (void *p)
-{
- struct mapped_symtab *symtab = (struct mapped_symtab *) p;
- /* The contents of the array are freed when the other hash table is
- destroyed. */
- xfree (symtab->data);
- xfree (symtab);
-}
-
-/* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to
+/* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
the slot.

Function is used only during write_hash_table so no index format backward
compatibility is needed. */

-static struct symtab_index_entry **
+static std::unique_ptr<symtab_index_entry> &
find_slot (struct mapped_symtab *symtab, const char *name)
{
offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);

- index = hash & (symtab->size - 1);
- step = ((hash * 17) & (symtab->size - 1)) | 1;
+ index = hash & (symtab->data.size () - 1);
+ step = ((hash * 17) & (symtab->data.size () - 1)) | 1;

for (;;)
{
if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name))
- return &symtab->data[index];
- index = (index + step) & (symtab->size - 1);
+ return symtab->data[index];
+ index = (index + step) & (symtab->data.size () - 1);
}
}

@@ -23375,24 +23316,17 @@ find_slot (struct mapped_symtab *symtab, const char *name)
static void
hash_expand (struct mapped_symtab *symtab)
{
- offset_type old_size = symtab->size;
- offset_type i;
- struct symtab_index_entry **old_entries = symtab->data;
-
- symtab->size *= 2;
- symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size);
+ auto old_entries (std::move (symtab->data));

- for (i = 0; i < old_size; ++i)
- {
- if (old_entries[i])
- {
- struct symtab_index_entry **slot = find_slot (symtab,
- old_entries[i]->name);
- *slot = old_entries[i];
- }
- }
+ symtab->data.clear ();
+ symtab->data.resize (old_entries.size () * 2);

- xfree (old_entries);
+ for (auto &it:old_entries)
+ if (it)
+ {
+ auto &ref (find_slot (symtab, it->name));
+ ref = std::move (it);
+ }
}

/* Add an entry to SYMTAB. NAME is the name of the symbol.
@@ -23404,20 +23338,18 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
int is_static, gdb_index_symbol_kind kind,
offset_type cu_index)
{
- struct symtab_index_entry **slot;
offset_type cu_index_and_attrs;

++symtab->n_elements;
- if (4 * symtab->n_elements / 3 >= symtab->size)
+ if (4 * symtab->n_elements / 3 >= symtab->data.size ())
hash_expand (symtab);

- slot = find_slot (symtab, name);
- if (!*slot)
+ std::unique_ptr<symtab_index_entry> &slot (find_slot (symtab, name));
+ if (!slot)
{
- *slot = XNEW (struct symtab_index_entry);
- (*slot)->name = name;
+ slot = std::make_unique<symtab_index_entry> ();
+ slot->name = name;
/* index_offset is set later. */
- (*slot)->cu_indices = NULL;
}

cu_index_and_attrs = 0;
@@ -23432,18 +23364,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
the last entry pushed), but a symbol could have multiple kinds in one CU.
To keep things simple we don't worry about the duplication here and
sort and uniqufy the list after we've processed all symbols. */
- VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index_and_attrs);
-}
-
-/* qsort helper routine for uniquify_cu_indices. */
-
-static int
-offset_type_compare (const void *ap, const void *bp)
-{
- offset_type a = *(offset_type *) ap;
- offset_type b = *(offset_type *) bp;
-
- return (a > b) - (b > a);
+ slot->cu_indices.push_back (cu_index_and_attrs);
}

/* Sort and remove duplicates of all symbols' cu_indices lists. */
@@ -23451,112 +23372,116 @@ offset_type_compare (const void *ap, const void *bp)
static void
uniquify_cu_indices (struct mapped_symtab *symtab)
{
- int i;
-
- for (i = 0; i < symtab->size; ++i)
+ for (const auto &entry:symtab->data)
{
- struct symtab_index_entry *entry = symtab->data[i];
-
- if (entry
- && entry->cu_indices != NULL)
+ if (entry && !entry->cu_indices.empty ())
{
unsigned int next_to_insert, next_to_check;
offset_type last_value;

- qsort (VEC_address (offset_type, entry->cu_indices),
- VEC_length (offset_type, entry->cu_indices),
- sizeof (offset_type), offset_type_compare);
+ std::sort (entry->cu_indices.begin (), entry->cu_indices.end ());

- last_value = VEC_index (offset_type, entry->cu_indices, 0);
+ last_value = entry->cu_indices[0];
next_to_insert = 1;
for (next_to_check = 1;
- next_to_check < VEC_length (offset_type, entry->cu_indices);
+ next_to_check < entry->cu_indices.size ();
++next_to_check)
- {
- if (VEC_index (offset_type, entry->cu_indices, next_to_check)
- != last_value)
- {
- last_value = VEC_index (offset_type, entry->cu_indices,
- next_to_check);
- VEC_replace (offset_type, entry->cu_indices, next_to_insert,
- last_value);
- ++next_to_insert;
- }
- }
- VEC_truncate (offset_type, entry->cu_indices, next_to_insert);
+ if (entry->cu_indices[next_to_check] != last_value)
+ {
+ last_value = entry->cu_indices[next_to_check];
+ entry->cu_indices[next_to_insert] = last_value;
+ ++next_to_insert;
+ }
+ entry->cu_indices.resize (next_to_insert);
}
}
}

-/* Add a vector of indices to the constant pool. */
+// Provide form of const char * suitable for container keys.
+// Only the pointer is being stored.
+// Comparison is done for the strings themselves - not for the pointer.
+class CstrView {
+private:
+ friend class CstrViewHasher;
+ const char *const cstr;
+public:
+ CstrView (const char *cstr_) : cstr (cstr_)
+ {
+ }
+ bool
+ operator == (const CstrView &other) const
+ {
+ return !strcmp (cstr, other.cstr);
+ }
+};

-static offset_type
-add_indices_to_cpool (htab_t symbol_hash_table, struct obstack *cpool,
- struct symtab_index_entry *entry)
+// Provide std::unordered_map::hasher for CstrView.
+class CstrViewHasher
{
- void **slot;
-
- slot = htab_find_slot (symbol_hash_table, entry, INSERT);
- if (!*slot)
- {
- offset_type len = VEC_length (offset_type, entry->cu_indices);
- offset_type val = MAYBE_SWAP (len);
- offset_type iter;
- int i;
-
- *slot = entry;
- entry->index_offset = obstack_object_size (cpool);
+public:
+ size_t
+ operator () (const CstrView &x) const
+ {
+ return mapped_index_string_hash (INT_MAX, x.cstr);
+ }
+};

- obstack_grow (cpool, &val, sizeof (val));
- for (i = 0;
- VEC_iterate (offset_type, entry->cu_indices, i, iter);
- ++i)
- {
- val = MAYBE_SWAP (iter);
- obstack_grow (cpool, &val, sizeof (val));
- }
- }
- else
- {
- struct symtab_index_entry *old_entry
- = (struct symtab_index_entry *) *slot;
- entry->index_offset = old_entry->index_offset;
- entry = old_entry;
- }
- return entry->index_offset;
-}
+// Provide std::unordered_map::hasher for std::vector<>.
+template<class T> class VectorHasher
+{
+public:
+ size_t
+ operator () (const std::vector<T> &key) const
+ {
+ // return boost::hash_value<std::vector<T>> (key);
+ return iterative_hash (key.data (),
+ sizeof (key.front ()) * key.size (), 0);
+ }
+};

/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with
constant pool entries going into the obstack CPOOL. */

static void
-write_hash_table (struct mapped_symtab *symtab,
- struct obstack *output, struct obstack *cpool)
+write_hash_table (struct mapped_symtab *symtab, DataBuf &output, DataBuf &cpool)
{
- offset_type i;
- htab_t symbol_hash_table;
- htab_t str_table;
-
- symbol_hash_table = create_symbol_hash_table ();
- str_table = create_strtab ();
-
- /* We add all the index vectors to the constant pool first, to
- ensure alignment is ok. */
- for (i = 0; i < symtab->size; ++i)
- {
- if (symtab->data[i])
- add_indices_to_cpool (symbol_hash_table, cpool, symtab->data[i]);
- }
+ {
+ /* 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,
+ VectorHasher<offset_type>> symbol_hash_table;
+
+ /* We add all the index vectors to the constant pool first, to
+ ensure alignment is ok. */
+ for (const std::unique_ptr<symtab_index_entry> &it:symtab->data)
+ {
+ if (!it)
+ continue;
+ gdb_assert (it->index_offset == 0);
+ const auto insertpair (symbol_hash_table.emplace (it->cu_indices,
+ cpool.size ()));
+ it->index_offset = insertpair.first->second;
+ if (!insertpair.second)
+ continue;
+ cpool.append_data (MAYBE_SWAP (it->cu_indices.size ()));
+ for (const auto iter:it->cu_indices)
+ cpool.append_data (MAYBE_SWAP (iter));
+ }
+ }

/* Now write out the hash table. */
- for (i = 0; i < symtab->size; ++i)
+ std::unordered_map<CstrView, offset_type, CstrViewHasher> str_table;
+ for (const auto &it:symtab->data)
{
offset_type str_off, vec_off;

- if (symtab->data[i])
+ if (it)
{
- str_off = add_string (str_table, cpool, symtab->data[i]->name);
- vec_off = symtab->data[i]->index_offset;
+ const auto insertpair (str_table.emplace (it->name, cpool.size ()));
+ if (insertpair.second)
+ cpool.append_cstr0 (it->name);
+ str_off = insertpair.first->second;
+ vec_off = it->index_offset;
}
else
{
@@ -23566,50 +23491,17 @@ write_hash_table (struct mapped_symtab *symtab,
vec_off = 0;
}

- str_off = MAYBE_SWAP (str_off);
- vec_off = MAYBE_SWAP (vec_off);
-
- obstack_grow (output, &str_off, sizeof (str_off));
- obstack_grow (output, &vec_off, sizeof (vec_off));
+ output.append_data (MAYBE_SWAP (str_off));
+ output.append_data (MAYBE_SWAP (vec_off));
}
-
- htab_delete (str_table);
- htab_delete (symbol_hash_table);
-}
-
-/* Struct to map psymtab to CU index in the index file. */
-struct psymtab_cu_index_map
-{
- struct partial_symtab *psymtab;
- unsigned int cu_index;
-};
-
-static hashval_t
-hash_psymtab_cu_index (const void *item)
-{
- const struct psymtab_cu_index_map *map
- = (const struct psymtab_cu_index_map *) item;
-
- return htab_hash_pointer (map->psymtab);
-}
-
-static int
-eq_psymtab_cu_index (const void *item_lhs, const void *item_rhs)
-{
- const struct psymtab_cu_index_map *lhs
- = (const struct psymtab_cu_index_map *) item_lhs;
- const struct psymtab_cu_index_map *rhs
- = (const struct psymtab_cu_index_map *) item_rhs;
-
- return lhs->psymtab == rhs->psymtab;
}

/* Helper struct for building the address table. */
struct addrmap_index_data
{
struct objfile *objfile;
- struct obstack *addr_obstack;
- htab_t cu_index_htab;
+ DataBuf &addr_vec;
+ std::unordered_map<struct partial_symtab *, unsigned int> &cu_index_htab;

/* Non-zero if the previous_* fields are valid.
We can't write an entry until we see the next entry (since it is only then
@@ -23619,26 +23511,28 @@ struct addrmap_index_data
unsigned int previous_cu_index;
/* Start address of the CU. */
CORE_ADDR previous_cu_start;
+
+ addrmap_index_data (DataBuf &addr_vec_,
+ std::unordered_map<struct partial_symtab *, unsigned int> &cu_index_htab_)
+ : addr_vec (addr_vec_), cu_index_htab (cu_index_htab_)
+ {}
};

/* Write an address entry to OBSTACK. */

static void
-add_address_entry (struct objfile *objfile, struct obstack *obstack,
+add_address_entry (struct objfile *objfile, DataBuf &addr_vec,
CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
{
- offset_type cu_index_to_write;
- gdb_byte addr[8];
CORE_ADDR baseaddr;

baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));

- store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, start - baseaddr);
- obstack_grow (obstack, addr, 8);
- store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, end - baseaddr);
- obstack_grow (obstack, addr, 8);
- cu_index_to_write = MAYBE_SWAP (cu_index);
- obstack_grow (obstack, &cu_index_to_write, sizeof (offset_type));
+ store_unsigned_integer (addr_vec.append_space (8), 8, BFD_ENDIAN_LITTLE,
+ start - baseaddr);
+ store_unsigned_integer (addr_vec.append_space (8), 8, BFD_ENDIAN_LITTLE,
+ end - baseaddr);
+ addr_vec.append_data (MAYBE_SWAP (cu_index));
}

/* Worker function for traversing an addrmap to build the address table. */
@@ -23650,19 +23544,16 @@ add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
struct partial_symtab *pst = (struct partial_symtab *) obj;

if (data->previous_valid)
- add_address_entry (data->objfile, data->addr_obstack,
+ add_address_entry (data->objfile, data->addr_vec,
data->previous_cu_start, start_addr,
data->previous_cu_index);

data->previous_cu_start = start_addr;
if (pst != NULL)
{
- struct psymtab_cu_index_map find_map, *map;
- find_map.psymtab = pst;
- map = ((struct psymtab_cu_index_map *)
- htab_find (data->cu_index_htab, &find_map));
- gdb_assert (map != NULL);
- data->previous_cu_index = map->cu_index;
+ const auto it (data->cu_index_htab.find (pst));
+ gdb_assert (it != data->cu_index_htab.cend ());
+ data->previous_cu_index = it->second;
data->previous_valid = 1;
}
else
@@ -23676,18 +23567,16 @@ add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
in the index file. */

static void
-write_address_map (struct objfile *objfile, struct obstack *obstack,
- htab_t cu_index_htab)
+write_address_map (struct objfile *objfile, DataBuf &addr_vec,
+ std::unordered_map<struct partial_symtab *, unsigned int> &cu_index_htab)
{
- struct addrmap_index_data addrmap_index_data;
+ struct addrmap_index_data addrmap_index_data (addr_vec, cu_index_htab);

/* When writing the address table, we have to cope with the fact that
the addrmap iterator only provides the start of a region; we have to
wait until the next invocation to get the start of the next region. */

addrmap_index_data.objfile = objfile;
- addrmap_index_data.addr_obstack = obstack;
- addrmap_index_data.cu_index_htab = cu_index_htab;
addrmap_index_data.previous_valid = 0;

addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
@@ -23699,7 +23588,7 @@ write_address_map (struct objfile *objfile, struct obstack *obstack,
doesn't work here. To cope we pass 0xff...ff, this is a rare situation
anyway. */
if (addrmap_index_data.previous_valid)
- add_address_entry (objfile, obstack,
+ add_address_entry (objfile, addr_vec,
addrmap_index_data.previous_cu_start, (CORE_ADDR) -1,
addrmap_index_data.previous_cu_index);
}
@@ -23746,7 +23635,7 @@ symbol_kind (struct partial_symbol *psym)

static void
write_psymbols (struct mapped_symtab *symtab,
- htab_t psyms_seen,
+ std::unordered_set<partial_symbol *> &psyms_seen,
struct partial_symbol **psymp,
int count,
offset_type cu_index,
@@ -23755,44 +23644,34 @@ write_psymbols (struct mapped_symtab *symtab,
for (; count-- > 0; ++psymp)
{
struct partial_symbol *psym = *psymp;
- void **slot;

if (SYMBOL_LANGUAGE (psym) == language_ada)
error (_("Ada is not currently supported by the index"));

/* Only add a given psymbol once. */
- slot = htab_find_slot (psyms_seen, psym, INSERT);
- if (!*slot)
+ if (psyms_seen.insert (psym).second)
{
gdb_index_symbol_kind kind = symbol_kind (psym);

- *slot = psym;
add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
is_static, kind, cu_index);
}
}
}

-/* Write the contents of an ("unfinished") obstack to FILE. Throw an
- exception if there is an error. */
-
-static void
-write_obstack (FILE *file, struct obstack *obstack)
-{
- if (fwrite (obstack_base (obstack), 1, obstack_object_size (obstack),
- file)
- != obstack_object_size (obstack))
- error (_("couldn't data write to file"));
-}
-
/* A helper struct used when iterating over debug_types. */
struct signatured_type_index_data
{
struct objfile *objfile;
struct mapped_symtab *symtab;
- struct obstack *types_list;
- htab_t psyms_seen;
+ DataBuf &types_list;
+ std::unordered_set<partial_symbol *> &psyms_seen;
int cu_index;
+
+ signatured_type_index_data (DataBuf &types_list_,
+ std::unordered_set<partial_symbol *> &psyms_seen_)
+ :types_list (types_list_), psyms_seen (psyms_seen_)
+ {}
};

/* A helper function that writes a single signatured_type to an
@@ -23805,7 +23684,6 @@ write_one_signatured_type (void **slot, void *d)
= (struct signatured_type_index_data *) d;
struct signatured_type *entry = (struct signatured_type *) *slot;
struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
- gdb_byte val[8];

write_psymbols (info->symtab,
info->psyms_seen,
@@ -23820,14 +23698,14 @@ write_one_signatured_type (void **slot, void *d)
psymtab->n_static_syms, info->cu_index,
1);

- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
+ store_unsigned_integer (info->types_list.append_space (8), 8,
+ BFD_ENDIAN_LITTLE,
to_underlying (entry->per_cu.sect_off));
- obstack_grow (info->types_list, val, 8);
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
+ store_unsigned_integer (info->types_list.append_space (8), 8,
+ BFD_ENDIAN_LITTLE,
to_underlying (entry->type_offset_in_tu));
- obstack_grow (info->types_list, val, 8);
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
- obstack_grow (info->types_list, val, 8);
+ store_unsigned_integer (info->types_list.append_space (8), 8,
+ BFD_ENDIAN_LITTLE, entry->signature);

++info->cu_index;

@@ -23841,7 +23719,7 @@ static void
recursively_write_psymbols (struct objfile *objfile,
struct partial_symtab *psymtab,
struct mapped_symtab *symtab,
- htab_t psyms_seen,
+ std::unordered_set<partial_symbol *> &psyms_seen,
offset_type cu_index)
{
int i;
@@ -23868,17 +23746,6 @@ recursively_write_psymbols (struct objfile *objfile,
static void
write_psymtabs_to_index (struct objfile *objfile, const char *dir)
{
- struct cleanup *cleanup;
- char *filename;
- struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
- struct obstack cu_list, types_cu_list;
- int i;
- FILE *out_file;
- struct mapped_symtab *symtab;
- offset_type val, size_of_contents, total_len;
- struct stat st;
- struct psymtab_cu_index_map *psymtab_cu_index_map;
-
if (dwarf2_per_objfile->using_index)
error (_("Cannot use an index to create the index"));

@@ -23888,160 +23755,128 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
return;

+ struct stat st;
if (stat (objfile_name (objfile), &st) < 0)
perror_with_name (objfile_name (objfile));

- filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)),
- INDEX_SUFFIX, (char *) NULL);
- cleanup = make_cleanup (xfree, filename);
+ std::string filename (std::string (dir) + SLASH_STRING
+ + lbasename (objfile_name (objfile)) + INDEX_SUFFIX);

- out_file = gdb_fopen_cloexec (filename, "wb");
+ FILE *out_file (gdb_fopen_cloexec (filename.c_str (), "wb"));
if (!out_file)
- error (_("Can't open `%s' for writing"), filename);
+ error (_("Can't open `%s' for writing"), filename.c_str ());

- gdb::unlinker unlink_file (filename);
+ TRY
+ {
+ mapped_symtab symtab;
+ DataBuf cu_list;
+ std::unordered_set<partial_symbol *> psyms_seen;
+
+ /* While we're scanning CU's create a table that maps a psymtab pointer
+ (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. */
+ std::unordered_map<struct partial_symtab *, unsigned int> cu_index_htab;
+ cu_index_htab.reserve (dwarf2_per_objfile->n_comp_units);
+
+ /* 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_comp_units, but only in their own hash table. */
+ for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *per_cu
+ = dwarf2_per_objfile->all_comp_units[i];
+ struct partial_symtab *psymtab = per_cu->v.psymtab;
+
+ /* CU of a shared file from 'dwz -m' may be unused by this main file.
+ It may be referenced from a local scope but in such case it does
+ not need to be present in .gdb_index. */
+ if (psymtab == NULL)
+ continue;

- symtab = create_mapped_symtab ();
- make_cleanup (cleanup_mapped_symtab, symtab);
+ if (psymtab->user == NULL)
+ recursively_write_psymbols (objfile, psymtab, &symtab, psyms_seen,
+ i);

- obstack_init (&addr_obstack);
- make_cleanup_obstack_free (&addr_obstack);
+ const auto insertpair (cu_index_htab.emplace (psymtab, i));
+ gdb_assert (insertpair.second);

- obstack_init (&cu_list);
- make_cleanup_obstack_free (&cu_list);
+ store_unsigned_integer (cu_list.append_space (8), 8,
+ BFD_ENDIAN_LITTLE,
+ to_underlying (per_cu->sect_off));
+ store_unsigned_integer (cu_list.append_space (8), 8,
+ BFD_ENDIAN_LITTLE, per_cu->length);
+ }

- obstack_init (&types_cu_list);
- make_cleanup_obstack_free (&types_cu_list);
+ /* Dump the address map. */
+ DataBuf addr_vec;
+ write_address_map (objfile, addr_vec, cu_index_htab);

- htab_up psyms_seen (htab_create_alloc (100, htab_hash_pointer,
- htab_eq_pointer,
- NULL, xcalloc, xfree));
+ /* Write out the .debug_type entries, if any. */
+ DataBuf types_cu_list;
+ if (dwarf2_per_objfile->signatured_types)
+ {
+ struct signatured_type_index_data sig_data (types_cu_list,
+ psyms_seen);
+
+ sig_data.objfile = objfile;
+ sig_data.symtab = &symtab;
+ sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
+ htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+ write_one_signatured_type, &sig_data);
+ }

- /* While we're scanning CU's create a table that maps a psymtab pointer
- (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. */
- htab_up cu_index_htab (htab_create_alloc (100,
- hash_psymtab_cu_index,
- eq_psymtab_cu_index,
- NULL, xcalloc, xfree));
- psymtab_cu_index_map = XNEWVEC (struct psymtab_cu_index_map,
- dwarf2_per_objfile->n_comp_units);
- make_cleanup (xfree, psymtab_cu_index_map);
+ /* Now that we've processed all symbols we can shrink their cu_indices
+ lists. */
+ uniquify_cu_indices (&symtab);

- /* 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_comp_units, but only in their own hash table. */
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
- {
- struct dwarf2_per_cu_data *per_cu
- = dwarf2_per_objfile->all_comp_units[i];
- struct partial_symtab *psymtab = per_cu->v.psymtab;
- gdb_byte val[8];
- struct psymtab_cu_index_map *map;
- void **slot;
+ DataBuf symtab_vec, constant_pool;
+ write_hash_table (&symtab, symtab_vec, constant_pool);

- /* CU of a shared file from 'dwz -m' may be unused by this main file.
- It may be referenced from a local scope but in such case it does not
- need to be present in .gdb_index. */
- if (psymtab == NULL)
- continue;
+ DataBuf contents;
+ const offset_type size_of_contents (6 * sizeof (offset_type));
+ offset_type total_len (size_of_contents);

- if (psymtab->user == NULL)
- recursively_write_psymbols (objfile, psymtab, symtab,
- psyms_seen.get (), i);
+ /* The version number. */
+ contents.append_data (MAYBE_SWAP (8));

- map = &psymtab_cu_index_map[i];
- map->psymtab = psymtab;
- map->cu_index = i;
- slot = htab_find_slot (cu_index_htab.get (), map, INSERT);
- gdb_assert (slot != NULL);
- gdb_assert (*slot == NULL);
- *slot = map;
-
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
- to_underlying (per_cu->sect_off));
- obstack_grow (&cu_list, val, 8);
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->length);
- obstack_grow (&cu_list, val, 8);
- }
-
- /* Dump the address map. */
- write_address_map (objfile, &addr_obstack, cu_index_htab.get ());
-
- /* Write out the .debug_type entries, if any. */
- if (dwarf2_per_objfile->signatured_types)
- {
- struct signatured_type_index_data sig_data;
-
- sig_data.objfile = objfile;
- sig_data.symtab = symtab;
- sig_data.types_list = &types_cu_list;
- sig_data.psyms_seen = psyms_seen.get ();
- sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
- htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
- write_one_signatured_type, &sig_data);
- }
-
- /* Now that we've processed all symbols we can shrink their cu_indices
- lists. */
- uniquify_cu_indices (symtab);
-
- obstack_init (&constant_pool);
- make_cleanup_obstack_free (&constant_pool);
- obstack_init (&symtab_obstack);
- make_cleanup_obstack_free (&symtab_obstack);
- write_hash_table (symtab, &symtab_obstack, &constant_pool);
-
- obstack_init (&contents);
- make_cleanup_obstack_free (&contents);
- size_of_contents = 6 * sizeof (offset_type);
- total_len = size_of_contents;
-
- /* The version number. */
- val = MAYBE_SWAP (8);
- obstack_grow (&contents, &val, sizeof (val));
-
- /* The offset of the CU list from the start of the file. */
- val = MAYBE_SWAP (total_len);
- obstack_grow (&contents, &val, sizeof (val));
- total_len += obstack_object_size (&cu_list);
-
- /* The offset of the types CU list from the start of the file. */
- val = MAYBE_SWAP (total_len);
- obstack_grow (&contents, &val, sizeof (val));
- total_len += obstack_object_size (&types_cu_list);
-
- /* The offset of the address table from the start of the file. */
- val = MAYBE_SWAP (total_len);
- obstack_grow (&contents, &val, sizeof (val));
- total_len += obstack_object_size (&addr_obstack);
-
- /* The offset of the symbol table from the start of the file. */
- val = MAYBE_SWAP (total_len);
- obstack_grow (&contents, &val, sizeof (val));
- total_len += obstack_object_size (&symtab_obstack);
-
- /* The offset of the constant pool from the start of the file. */
- val = MAYBE_SWAP (total_len);
- obstack_grow (&contents, &val, sizeof (val));
- total_len += obstack_object_size (&constant_pool);
-
- gdb_assert (obstack_object_size (&contents) == size_of_contents);
-
- write_obstack (out_file, &contents);
- write_obstack (out_file, &cu_list);
- write_obstack (out_file, &types_cu_list);
- write_obstack (out_file, &addr_obstack);
- write_obstack (out_file, &symtab_obstack);
- write_obstack (out_file, &constant_pool);
+ /* The offset of the CU list from the start of the file. */
+ contents.append_data (MAYBE_SWAP (total_len));
+ total_len += cu_list.size ();

- fclose (out_file);
+ /* The offset of the types CU list from the start of the file. */
+ contents.append_data (MAYBE_SWAP (total_len));
+ total_len += types_cu_list.size ();

- /* We want to keep the file. */
- unlink_file.keep ();
+ /* The offset of the address table from the start of the file. */
+ contents.append_data (MAYBE_SWAP (total_len));
+ total_len += addr_vec.size ();

- do_cleanups (cleanup);
+ /* The offset of the symbol table from the start of the file. */
+ contents.append_data (MAYBE_SWAP (total_len));
+ total_len += symtab_vec.size ();
+
+ /* The offset of the constant pool from the start of the file. */
+ contents.append_data (MAYBE_SWAP (total_len));
+ total_len += constant_pool.size ();
+
+ gdb_assert (contents.size () == size_of_contents);
+
+ contents.file_write (out_file);
+ cu_list.file_write (out_file);
+ types_cu_list.file_write (out_file);
+ addr_vec.file_write (out_file);
+ symtab_vec.file_write (out_file);
+ constant_pool.file_write (out_file);
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ fclose (out_file);
+ unlink (filename.c_str ());
+ throw_exception (except);
+ }
+ END_CATCH
+ fclose (out_file);
}

/* Implementation of the `save gdb-index' command.