/* DWARF index writing support for GDB.
- Copyright (C) 1994-2018 Free Software Foundation, Inc.
+ Copyright (C) 1994-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "common/byte-vector.h"
#include "common/filestuff.h"
#include "common/gdb_unlinker.h"
+#include "common/pathstuff.h"
+#include "common/scoped_fd.h"
#include "complaints.h"
#include "dwarf-index-common.h"
#include "dwarf2.h"
#include <unordered_map>
#include <unordered_set>
-/* The suffix for an index file. */
-#define INDEX4_SUFFIX ".gdb-index"
-#define INDEX5_SUFFIX ".debug_names"
-#define DEBUG_STR_SUFFIX ".debug_str"
-
/* Ensure only legit values are used. */
#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
do { \
static void
file_write (FILE *file, const std::vector<Elem, Alloc> &vec)
{
- file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
+ if (!vec.empty ())
+ file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
}
/* In-memory buffer to prepare data to be written later to a file. */
gdb_byte *grow (size_t size)
{
m_vec.resize (m_vec.size () + size);
- return &*m_vec.end () - size;
+ return &*(m_vec.end () - size);
}
gdb::byte_vector m_vec;
add_address_entry (struct objfile *objfile, data_buf &addr_vec,
CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
{
- CORE_ADDR baseaddr;
-
- baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-
- addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, start - baseaddr);
- addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, end - baseaddr);
+ addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, start);
+ addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, end);
addr_vec.append_data (MAYBE_SWAP (cu_index));
}
addrmap_index_data.objfile = objfile;
addrmap_index_data.previous_valid = 0;
- addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
- &addrmap_index_data);
+ addrmap_foreach (objfile->partial_symtabs->psymtabs_addrmap,
+ add_address_entry_worker, &addrmap_index_data);
/* It's highly unlikely the last entry (end address = 0xff...ff)
is valid, but we should still handle it.
static gdb_index_symbol_kind
symbol_kind (struct partial_symbol *psym)
{
- domain_enum domain = PSYMBOL_DOMAIN (psym);
- enum address_class aclass = PSYMBOL_CLASS (psym);
+ domain_enum domain = psym->domain;
+ enum address_class aclass = psym->aclass;
switch (domain)
{
{
struct partial_symbol *psym = *psymp;
- if (SYMBOL_LANGUAGE (psym) == language_ada)
+ if (psym->ginfo.language == language_ada)
error (_("Ada is not currently supported by the index"));
/* Only add a given psymbol once. */
{
gdb_index_symbol_kind kind = symbol_kind (psym);
- add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
+ add_index_entry (symtab, symbol_search_name (&psym->ginfo),
is_static, kind, cu_index);
}
}
write_psymbols (info->symtab,
info->psyms_seen,
- &info->objfile->global_psymbols[psymtab->globals_offset],
+ (info->objfile->partial_symtabs->global_psymbols.data ()
+ + psymtab->globals_offset),
psymtab->n_global_syms, info->cu_index,
0);
write_psymbols (info->symtab,
info->psyms_seen,
- &info->objfile->static_psymbols[psymtab->statics_offset],
+ (info->objfile->partial_symtabs->static_psymbols.data ()
+ + psymtab->statics_offset),
psymtab->n_static_syms, info->cu_index,
1);
write_psymbols (symtab,
psyms_seen,
- &objfile->global_psymbols[psymtab->globals_offset],
+ (objfile->partial_symtabs->global_psymbols.data ()
+ + psymtab->globals_offset),
psymtab->n_global_syms, cu_index,
0);
write_psymbols (symtab,
psyms_seen,
- &objfile->static_psymbols[psymtab->statics_offset],
+ (objfile->partial_symtabs->static_psymbols.data ()
+ + psymtab->statics_offset),
psymtab->n_static_syms, cu_index,
1);
}
const int dwarf_tag = psymbol_tag (psym);
if (dwarf_tag == 0)
return;
- const char *const name = SYMBOL_SEARCH_NAME (psym);
+ const char *const name = symbol_search_name (&psym->ginfo);
const auto insertpair
= m_name_to_value_set.emplace (c_str_view (name),
std::set<symbol_value> ());
psyms_seen, cu_index);
write_psymbols (psyms_seen,
- &objfile->global_psymbols[psymtab->globals_offset],
+ (objfile->partial_symtabs->global_psymbols.data ()
+ + psymtab->globals_offset),
psymtab->n_global_syms, cu_index, false, unit_kind::cu);
write_psymbols (psyms_seen,
- &objfile->static_psymbols[psymtab->statics_offset],
+ (objfile->partial_symtabs->static_psymbols.data ()
+ + psymtab->statics_offset),
psymtab->n_static_syms, cu_index, true, unit_kind::cu);
}
= m_str_table.emplace (c_str_view (s),
data - dwarf2_per_objfile->str.buffer);
if (!insertpair.second)
- complaint (&symfile_complaints,
- _("Duplicate string \"%s\" in "
+ complaint (_("Duplicate string \"%s\" in "
".debug_str section [in module %s]"),
s, bfd_get_filename (m_abfd));
data += strlen (s) + 1;
GDB as a DWARF-5 index consumer. */
static int psymbol_tag (const struct partial_symbol *psym)
{
- domain_enum domain = PSYMBOL_DOMAIN (psym);
- enum address_class aclass = PSYMBOL_CLASS (psym);
+ domain_enum domain = psym->domain;
+ enum address_class aclass = psym->aclass;
switch (domain)
{
{
struct partial_symbol *psym = *psymp;
- if (SYMBOL_LANGUAGE (psym) == language_ada)
+ if (psym->ginfo.language == language_ada)
error (_("Ada is not currently supported by the index"));
/* Only add a given psymbol once. */
struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
write_psymbols (info->psyms_seen,
- &info->objfile->global_psymbols[psymtab->globals_offset],
+ (info->objfile->partial_symtabs->global_psymbols.data ()
+ + psymtab->globals_offset),
psymtab->n_global_syms, info->cu_index, false,
unit_kind::tu);
write_psymbols (info->psyms_seen,
- &info->objfile->static_psymbols[psymtab->statics_offset],
+ (info->objfile->partial_symtabs->static_psymbols.data ()
+ + psymtab->statics_offset),
psymtab->n_static_syms, info->cu_index, true,
unit_kind::tu);
static bool
check_dwarf64_offsets (struct dwarf2_per_objfile *dwarf2_per_objfile)
{
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
{
- const dwarf2_per_cu_data &per_cu = *dwarf2_per_objfile->all_comp_units[i];
-
- if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
+ if (to_underlying (per_cu->sect_off) >= (static_cast<uint64_t> (1) << 32))
return true;
}
- for (int i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ for (const signatured_type *sigtype : dwarf2_per_objfile->all_type_units)
{
- const signatured_type &sigtype = *dwarf2_per_objfile->all_type_units[i];
- const dwarf2_per_cu_data &per_cu = sigtype.per_cu;
+ const dwarf2_per_cu_data &per_cu = sigtype->per_cu;
if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
return true;
psyms_seen_size (struct dwarf2_per_objfile *dwarf2_per_objfile)
{
size_t psyms_count = 0;
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
{
- struct dwarf2_per_cu_data *per_cu
- = dwarf2_per_objfile->all_comp_units[i];
struct partial_symtab *psymtab = per_cu->v.psymtab;
if (psymtab != NULL && psymtab->user == NULL)
in the index file). This will later be needed to write the address
table. */
psym_index_map cu_index_htab;
- cu_index_htab.reserve (dwarf2_per_objfile->n_comp_units);
+ cu_index_htab.reserve (dwarf2_per_objfile->all_comp_units.size ());
/* 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
std::unordered_set<partial_symbol *> psyms_seen
(psyms_seen_size (dwarf2_per_objfile));
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (int i = 0; i < dwarf2_per_objfile->all_comp_units.size (); ++i)
{
struct dwarf2_per_cu_data *per_cu
= dwarf2_per_objfile->all_comp_units[i];
sig_data.objfile = objfile;
sig_data.symtab = &symtab;
- sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
+ sig_data.cu_index = dwarf2_per_objfile->all_comp_units.size ();
htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
write_one_signatured_type, &sig_data);
}
dwarf5_byte_order);
std::unordered_set<partial_symbol *>
psyms_seen (psyms_seen_size (dwarf2_per_objfile));
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ for (int i = 0; i < dwarf2_per_objfile->all_comp_units.size (); ++i)
{
const dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i];
partial_symtab *psymtab = per_cu->v.psymtab;
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, dwarf2_per_objfile->n_comp_units);
+ header.append_uint (4, dwarf5_byte_order,
+ dwarf2_per_objfile->all_comp_units.size ());
/* local_type_unit_count - The number of TUs in the local TU
list. */
- header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_type_units);
+ header.append_uint (4, dwarf5_byte_order,
+ dwarf2_per_objfile->all_type_units.size ());
/* foreign_type_unit_count - The number of TUs in the foreign TU
list. */
gdb_assert (file_size == expected_size);
}
-/* Create an index file for OBJFILE in the directory DIR. */
+/* See dwarf-index-write.h. */
-static void
+void
write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
- const char *dir,
+ const char *dir, const char *basename,
dw_index_kind index_kind)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
error (_("Cannot make an index when the file has multiple .debug_types sections"));
- if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
+ if (!objfile->partial_symtabs->psymtabs
+ || !objfile->partial_symtabs->psymtabs_addrmap)
return;
struct stat st;
if (stat (objfile_name (objfile), &st) < 0)
perror_with_name (objfile_name (objfile));
- std::string filename (std::string (dir) + SLASH_STRING
- + lbasename (objfile_name (objfile))
+ std::string filename (std::string (dir) + SLASH_STRING + basename
+ (index_kind == dw_index_kind::DEBUG_NAMES
? INDEX5_SUFFIX : INDEX4_SUFFIX));
+ gdb::char_vector filename_temp = make_temp_filename (filename);
- FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
- if (!out_file)
- error (_("Can't open `%s' for writing"), filename.c_str ());
+ /* Order matters here; we want FILE to be closed before
+ FILENAME_TEMP is unlinked, because on MS-Windows one cannot
+ delete a file that is still open. So, we wrap the unlinker in an
+ optional and emplace it once we know the file name. */
+ gdb::optional<gdb::unlinker> unlink_file;
+ scoped_fd out_file_fd (gdb_mkostemp_cloexec (filename_temp.data (),
+ O_BINARY));
+ if (out_file_fd.get () == -1)
+ perror_with_name (("mkstemp"));
- /* Order matters here; we want FILE to be closed before FILENAME is
- unlinked, because on MS-Windows one cannot delete a file that is
- still open. (Don't call anything here that might throw until
- file_closer is created.) */
- gdb::unlinker unlink_file (filename.c_str ());
- gdb_file_up close_out_file (out_file);
+ gdb_file_up out_file = out_file_fd.to_file ("wb");
+ if (out_file == nullptr)
+ error (_("Can't open `%s' for writing"), filename_temp.data ());
+
+ unlink_file.emplace (filename_temp.data ());
if (index_kind == dw_index_kind::DEBUG_NAMES)
{
std::string filename_str (std::string (dir) + SLASH_STRING
- + lbasename (objfile_name (objfile))
- + DEBUG_STR_SUFFIX);
- FILE *out_file_str
- = gdb_fopen_cloexec (filename_str.c_str (), "wb").release ();
- if (!out_file_str)
- error (_("Can't open `%s' for writing"), filename_str.c_str ());
- gdb::unlinker unlink_file_str (filename_str.c_str ());
- gdb_file_up close_out_file_str (out_file_str);
+ + basename + DEBUG_STR_SUFFIX);
+ gdb::char_vector filename_str_temp = make_temp_filename (filename_str);
+
+ /* As above, arrange to unlink the file only after the file
+ descriptor has been closed. */
+ gdb::optional<gdb::unlinker> unlink_file_str;
+ scoped_fd out_file_str_fd
+ (gdb_mkostemp_cloexec (filename_str_temp.data (), O_BINARY));
+ if (out_file_str_fd.get () == -1)
+ perror_with_name (("mkstemp"));
+
+ gdb_file_up out_file_str = out_file_str_fd.to_file ("wb");
+ if (out_file_str == nullptr)
+ error (_("Can't open `%s' for writing"), filename_str_temp.data ());
+
+ unlink_file_str.emplace (filename_str_temp.data ());
const size_t total_len
- = write_debug_names (dwarf2_per_objfile, out_file, out_file_str);
- assert_file_size (out_file, filename.c_str (), total_len);
+ = write_debug_names (dwarf2_per_objfile, out_file.get (),
+ out_file_str.get ());
+ assert_file_size (out_file.get (), filename_temp.data (), total_len);
/* We want to keep the file .debug_str file too. */
- unlink_file_str.keep ();
+ unlink_file_str->keep ();
+
+ /* Close and move the str file in place. */
+ out_file_str.reset ();
+ if (rename (filename_str_temp.data (), filename_str.c_str ()) != 0)
+ perror_with_name (("rename"));
}
else
{
const size_t total_len
- = write_gdbindex (dwarf2_per_objfile, out_file);
- assert_file_size (out_file, filename.c_str (), total_len);
+ = write_gdbindex (dwarf2_per_objfile, out_file.get ());
+ assert_file_size (out_file.get (), filename_temp.data (), total_len);
}
/* We want to keep the file. */
- unlink_file.keep ();
+ unlink_file->keep ();
+
+ /* Close and move the file in place. */
+ out_file.reset ();
+ if (rename (filename_temp.data (), filename.c_str ()) != 0)
+ perror_with_name (("rename"));
}
/* Implementation of the `save gdb-index' command.
static void
save_gdb_index_command (const char *arg, int from_tty)
{
- struct objfile *objfile;
const char dwarf5space[] = "-dwarf-5 ";
dw_index_kind index_kind = dw_index_kind::GDB_INDEX;
if (!*arg)
error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
- ALL_OBJFILES (objfile)
- {
- struct stat st;
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ struct stat st;
- /* If the objfile does not correspond to an actual file, skip it. */
- if (stat (objfile_name (objfile), &st) < 0)
- continue;
+ /* If the objfile does not correspond to an actual file, skip it. */
+ if (stat (objfile_name (objfile), &st) < 0)
+ continue;
- struct dwarf2_per_objfile *dwarf2_per_objfile
- = get_dwarf2_per_objfile (objfile);
+ struct dwarf2_per_objfile *dwarf2_per_objfile
+ = get_dwarf2_per_objfile (objfile);
- if (dwarf2_per_objfile != NULL)
- {
- TRY
- {
- write_psymtabs_to_index (dwarf2_per_objfile, arg, index_kind);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- exception_fprintf (gdb_stderr, except,
- _("Error while writing index for `%s': "),
- objfile_name (objfile));
- }
- END_CATCH
- }
+ if (dwarf2_per_objfile != NULL)
+ {
+ try
+ {
+ const char *basename = lbasename (objfile_name (objfile));
+ write_psymtabs_to_index (dwarf2_per_objfile, arg, basename,
+ index_kind);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ exception_fprintf (gdb_stderr, except,
+ _("Error while writing index for `%s': "),
+ objfile_name (objfile));
+ }
+ }
- }
+ }
}
void