/* 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. */
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));
}
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->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),
is_static, kind, cu_index);
}
}
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);
const auto insertpair
= m_name_to_value_set.emplace (c_str_view (name),
std::set<symbol_value> ());
= 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->language == language_ada)
error (_("Ada is not currently supported by the index"));
/* Only add a given psymbol once. */
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 (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);
+
+ /* 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"));
- FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
- if (!out_file)
- error (_("Can't open `%s' for writing"), filename.c_str ());
+ 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 ());
- /* 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);
+ 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.
{
TRY
{
- write_psymtabs_to_index (dwarf2_per_objfile, arg, index_kind);
+ const char *basename = lbasename (objfile_name (objfile));
+ write_psymtabs_to_index (dwarf2_per_objfile, arg, basename,
+ index_kind);
}
CATCH (except, RETURN_MASK_ERROR)
{