--- /dev/null
+/* Unlinking class
+
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_UNLINKER_H
+#define GDB_UNLINKER_H
+
+namespace gdb
+{
+
+/* An object of this class holds a filename and, when the object goes
+ of scope, the file is removed using unlink.
+
+ A user of this class can request that the file be preserved using
+ the "keep" method. */
+class unlinker
+{
+ public:
+
+ unlinker (const char *filename) ATTRIBUTE_NONNULL (1)
+ : m_filename (filename)
+ {
+ gdb_assert (filename != NULL);
+ }
+
+ ~unlinker ()
+ {
+ if (m_filename != NULL)
+ unlink (m_filename);
+ }
+
+ /* Keep the file, rather than unlink it. */
+ void keep ()
+ {
+ m_filename = NULL;
+ }
+
+ private:
+
+ const char *m_filename;
+};
+
+}
+
+#endif /* GDB_UNLINKER_H */
#include "filestuff.h"
#include "build-id.h"
#include "namespace.h"
+#include "common/gdb_unlinker.h"
#include <fcntl.h>
#include <sys/types.h>
error (_("couldn't data write to file"));
}
-/* Unlink a file if the argument is not NULL. */
-
-static void
-unlink_if_set (void *p)
-{
- char **filename = (char **) p;
- if (*filename)
- unlink (*filename);
-}
-
/* A helper struct used when iterating over debug_types. */
struct signatured_type_index_data
{
write_psymtabs_to_index (struct objfile *objfile, const char *dir)
{
struct cleanup *cleanup;
- char *filename, *cleanup_filename;
+ char *filename;
struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
struct obstack cu_list, types_cu_list;
int i;
if (!out_file)
error (_("Can't open `%s' for writing"), filename);
- cleanup_filename = filename;
- make_cleanup (unlink_if_set, &cleanup_filename);
+ gdb::unlinker unlink_file (filename);
symtab = create_mapped_symtab ();
make_cleanup (cleanup_mapped_symtab, symtab);
fclose (out_file);
- /* We want to keep the file, so we set cleanup_filename to NULL
- here. See unlink_if_set. */
- cleanup_filename = NULL;
+ /* We want to keep the file. */
+ unlink_file.keep ();
do_cleanups (cleanup);
}
#include "gdb_bfd.h"
#include "readline/tilde.h"
#include <algorithm>
+#include "common/gdb_unlinker.h"
/* The largest amount of memory to read from the target at once. We
must throttle it to limit the amount of memory used by GDB during
throw_exception (except);
}
-static void
-do_bfd_delete_cleanup (void *arg)
-{
- bfd *obfd = (bfd *) arg;
- const char *filename = obfd->filename;
-
- gdb_bfd_unref ((bfd *) arg);
- unlink (filename);
-}
-
/* gcore_command -- implements the 'gcore' command.
Generate a core file from the inferior process. */
static void
gcore_command (char *args, int from_tty)
{
- struct cleanup *filename_chain;
- struct cleanup *bfd_chain;
- char *corefilename;
- bfd *obfd;
+ gdb::unique_xmalloc_ptr<char> corefilename;
/* No use generating a corefile without a target process. */
if (!target_has_execution)
noprocess ();
if (args && *args)
- corefilename = tilde_expand (args);
+ corefilename.reset (tilde_expand (args));
else
{
/* Default corefile name is "core.PID". */
- corefilename = xstrprintf ("core.%d", ptid_get_pid (inferior_ptid));
+ corefilename.reset (xstrprintf ("core.%d", ptid_get_pid (inferior_ptid)));
}
- filename_chain = make_cleanup (xfree, corefilename);
if (info_verbose)
fprintf_filtered (gdb_stdout,
- "Opening corefile '%s' for output.\n", corefilename);
+ "Opening corefile '%s' for output.\n",
+ corefilename.get ());
/* Open the output file. */
- obfd = create_gcore_bfd (corefilename).release ();
+ gdb_bfd_ref_ptr obfd (create_gcore_bfd (corefilename.get ()));
- /* Need a cleanup that will close and delete the file. */
- bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
+ /* Arrange to unlink the file on failure. */
+ gdb::unlinker unlink_file (corefilename.get ());
/* Call worker function. */
- write_gcore_file (obfd);
+ write_gcore_file (obfd.get ());
/* Succeeded. */
- discard_cleanups (bfd_chain);
- gdb_bfd_unref (obfd);
+ unlink_file.keep ();
- fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
- do_cleanups (filename_chain);
+ fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename.get ());
}
static unsigned long
#include "gdb_bfd.h"
#include "observer.h"
#include "infrun.h"
+#include "common/gdb_unlinker.h"
#include <signal.h>
record_full_open (args, from_tty);
}
-static void
-record_full_save_cleanups (void *data)
-{
- bfd *obfd = (bfd *) data;
- char *pathname = xstrdup (bfd_get_filename (obfd));
-
- gdb_bfd_unref (obfd);
- unlink (pathname);
- xfree (pathname);
-}
-
/* Save the execution log to a file. We use a modified elf corefile
format, with an extra section for our data. */
uint32_t magic;
struct regcache *regcache;
struct gdbarch *gdbarch;
- struct cleanup *old_cleanups;
struct cleanup *set_cleanups;
- bfd *obfd;
int save_size = 0;
asection *osec = NULL;
int bfd_offset = 0;
recfilename);
/* Open the output file. */
- obfd = create_gcore_bfd (recfilename).release ();
- old_cleanups = make_cleanup (record_full_save_cleanups, obfd);
+ gdb_bfd_ref_ptr obfd (create_gcore_bfd (recfilename));
+
+ /* Arrange to remove the output file on failure. */
+ gdb::unlinker unlink_file (recfilename);
/* Save the current record entry to "cur_record_full_list". */
cur_record_full_list = record_full_list;
}
/* Make the new bfd section. */
- osec = bfd_make_section_anyway_with_flags (obfd, "precord",
+ osec = bfd_make_section_anyway_with_flags (obfd.get (), "precord",
SEC_HAS_CONTENTS
| SEC_READONLY);
if (osec == NULL)
error (_("Failed to create 'precord' section for corefile %s: %s"),
recfilename,
bfd_errmsg (bfd_get_error ()));
- bfd_set_section_size (obfd, osec, save_size);
- bfd_set_section_vma (obfd, osec, 0);
- bfd_set_section_alignment (obfd, osec, 0);
- bfd_section_lma (obfd, osec) = 0;
+ bfd_set_section_size (obfd.get (), osec, save_size);
+ bfd_set_section_vma (obfd.get (), osec, 0);
+ bfd_set_section_alignment (obfd.get (), osec, 0);
+ bfd_section_lma (obfd.get (), osec) = 0;
/* Save corefile state. */
- write_gcore_file (obfd);
+ write_gcore_file (obfd.get ());
/* Write out the record log. */
/* Write the magic code. */
" Writing 4-byte magic cookie "
"RECORD_FULL_FILE_MAGIC (0x%s)\n",
phex_nz (magic, 4));
- bfdcore_write (obfd, osec, &magic, sizeof (magic), &bfd_offset);
+ bfdcore_write (obfd.get (), osec, &magic, sizeof (magic), &bfd_offset);
/* Save the entries to recfd and forward execute to the end of
record list. */
uint64_t addr;
type = record_full_list->type;
- bfdcore_write (obfd, osec, &type, sizeof (type), &bfd_offset);
+ bfdcore_write (obfd.get (), osec, &type, sizeof (type), &bfd_offset);
switch (record_full_list->type)
{
/* Write regnum. */
regnum = netorder32 (record_full_list->u.reg.num);
- bfdcore_write (obfd, osec, ®num,
+ bfdcore_write (obfd.get (), osec, ®num,
sizeof (regnum), &bfd_offset);
/* Write regval. */
- bfdcore_write (obfd, osec,
+ bfdcore_write (obfd.get (), osec,
record_full_get_loc (record_full_list),
record_full_list->u.reg.len, &bfd_offset);
break;
/* Write memlen. */
len = netorder32 (record_full_list->u.mem.len);
- bfdcore_write (obfd, osec, &len, sizeof (len), &bfd_offset);
+ bfdcore_write (obfd.get (), osec, &len, sizeof (len),
+ &bfd_offset);
/* Write memaddr. */
addr = netorder64 (record_full_list->u.mem.addr);
- bfdcore_write (obfd, osec, &addr,
+ bfdcore_write (obfd.get (), osec, &addr,
sizeof (addr), &bfd_offset);
/* Write memval. */
- bfdcore_write (obfd, osec,
+ bfdcore_write (obfd.get (), osec,
record_full_get_loc (record_full_list),
record_full_list->u.mem.len, &bfd_offset);
break;
(unsigned long) sizeof (count));
/* Write signal value. */
signal = netorder32 (record_full_list->u.end.sigval);
- bfdcore_write (obfd, osec, &signal,
+ bfdcore_write (obfd.get (), osec, &signal,
sizeof (signal), &bfd_offset);
/* Write insn count. */
count = netorder32 (record_full_list->u.end.insn_num);
- bfdcore_write (obfd, osec, &count,
+ bfdcore_write (obfd.get (), osec, &count,
sizeof (count), &bfd_offset);
break;
}
}
do_cleanups (set_cleanups);
- gdb_bfd_unref (obfd);
- discard_cleanups (old_cleanups);
+ unlink_file.keep ();
/* Succeeded. */
printf_filtered (_("Saved core file %s with execution log.\n"),