gdb: make gdbarch_make_corefile_notes return a unique ptr

This patch starts by making the gdbarch_make_corefile_notes function
return a gdb::unique_xmalloc_ptr<char> and takes care of the fallouts,
mostly in linux-tdep.c and fbsd-tdep.c.

The difficulty in these files is that they use the BFD API for writing
core files, where you pass in a pointer to a malloc-ed buffer (or NULL
in the beginning), it re-allocs it if needed, and returns you the
possibly updated pointer.  I therefore used this pattern everywhere:

  note_data.reset (elfcore_write_note (obfd, note_data.release (), ...)

This hands over the ownership of note_data to the BFD function for the
duration of the call, and then puts its back in note_data right after
the call.

gdb/ChangeLog:

	* gdbarch.sh (make_corefile_notes): Return unique pointer.
	* gdbarch.c: Re-generate.
	* gdbarch.h: Re-generate.
	* gcore.c (write_gcore_file_1): Adjust.
	* fbsd-tdep.c (struct fbsd_collect_regset_section_cb_data): Add
	constructor.
	<note_data>: Change type to unique pointer.
	<abort_iteration>: Change type to bool.
	(fbsd_collect_regset_section_cb): Adjust to unique pointer.
	(fbsd_collect_thread_registers): Return void, adjust.
	(struct fbsd_corefile_thread_data): Add construtor.
	<note_data>: Change type to unique pointer.
	(fbsd_corefile_thread): Adjust.
	(fbsd_make_corefile_notes): Return unique pointer, adjust.
	* linux-tdep.c (linux_make_mappings_corefile_notes): Change type
	to unique pointer, adjust.
	(struct linux_collect_regset_section_cb_data): Add constructor.
	<note_data>: Change type to unique pointer.
	<abort_iteration>: Change type to bool.
	(linux_collect_thread_registers): Return void, adjust.
	(struct linux_corefile_thread_data): Add constructor.
	<note_data>: Change type to unique pointer.
	(linux_corefile_thread): Adjust.
	(linux_make_corefile_notes): Return unique pointer, adjust.

Change-Id: I1e03476bb47b87c6acb3e12204d193f38cc4e02b
This commit is contained in:
Simon Marchi 2020-10-21 10:43:48 -04:00 committed by Simon Marchi
parent 4dbe16c811
commit c21f37a889
7 changed files with 184 additions and 121 deletions

View File

@ -1,3 +1,30 @@
2020-10-21 Simon Marchi <simon.marchi@polymtl.ca>
* gdbarch.sh (make_corefile_notes): Return unique pointer.
* gdbarch.c: Re-generate.
* gdbarch.h: Re-generate.
* gcore.c (write_gcore_file_1): Adjust.
* fbsd-tdep.c (struct fbsd_collect_regset_section_cb_data): Add
constructor.
<note_data>: Change type to unique pointer.
<abort_iteration>: Change type to bool.
(fbsd_collect_regset_section_cb): Adjust to unique pointer.
(fbsd_collect_thread_registers): Return void, adjust.
(struct fbsd_corefile_thread_data): Add construtor.
<note_data>: Change type to unique pointer.
(fbsd_corefile_thread): Adjust.
(fbsd_make_corefile_notes): Return unique pointer, adjust.
* linux-tdep.c (linux_make_mappings_corefile_notes): Change type
to unique pointer, adjust.
(struct linux_collect_regset_section_cb_data): Add constructor.
<note_data>: Change type to unique pointer.
<abort_iteration>: Change type to bool.
(linux_collect_thread_registers): Return void, adjust.
(struct linux_corefile_thread_data): Add constructor.
<note_data>: Change type to unique pointer.
(linux_corefile_thread): Adjust.
(linux_make_corefile_notes): Return unique pointer, adjust.
2020-10-20 Simon Marchi <simon.marchi@polymtl.ca>
* gdbarch.sh (displaced_step_hw_singlestep): Return bool.

View File

@ -589,13 +589,27 @@ find_signalled_thread (struct thread_info *info, void *data)
struct fbsd_collect_regset_section_cb_data
{
fbsd_collect_regset_section_cb_data (const struct regcache *regcache,
bfd *obfd,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size,
unsigned long lwp,
gdb_signal stop_signal)
: regcache (regcache),
obfd (obfd),
note_data (note_data),
note_size (note_size),
lwp (lwp),
stop_signal (stop_signal)
{}
const struct regcache *regcache;
bfd *obfd;
char *note_data;
gdb::unique_xmalloc_ptr<char> &note_data;
int *note_size;
unsigned long lwp;
enum gdb_signal stop_signal;
int abort_iteration;
bool abort_iteration = false;
};
static void
@ -617,50 +631,58 @@ fbsd_collect_regset_section_cb (const char *sect_name, int supply_size,
/* PRSTATUS still needs to be treated specially. */
if (strcmp (sect_name, ".reg") == 0)
data->note_data = (char *) elfcore_write_prstatus
(data->obfd, data->note_data, data->note_size, data->lwp,
gdb_signal_to_host (data->stop_signal), buf);
data->note_data.reset (elfcore_write_prstatus
(data->obfd, data->note_data.release (),
data->note_size, data->lwp,
gdb_signal_to_host (data->stop_signal),
buf));
else
data->note_data = (char *) elfcore_write_register_note
(data->obfd, data->note_data, data->note_size,
sect_name, buf, collect_size);
data->note_data.reset (elfcore_write_register_note
(data->obfd, data->note_data.release (),
data->note_size, sect_name, buf,
collect_size));
xfree (buf);
if (data->note_data == NULL)
data->abort_iteration = 1;
data->abort_iteration = true;
}
/* Records the thread's register state for the corefile note
section. */
static char *
static void
fbsd_collect_thread_registers (const struct regcache *regcache,
ptid_t ptid, bfd *obfd,
char *note_data, int *note_size,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size,
enum gdb_signal stop_signal)
{
struct gdbarch *gdbarch = regcache->arch ();
struct fbsd_collect_regset_section_cb_data data;
fbsd_collect_regset_section_cb_data data (regcache, obfd, note_data,
note_size, ptid.lwp (),
stop_signal);
data.regcache = regcache;
data.obfd = obfd;
data.note_data = note_data;
data.note_size = note_size;
data.stop_signal = stop_signal;
data.abort_iteration = 0;
data.lwp = ptid.lwp ();
gdbarch_iterate_over_regset_sections (gdbarch,
gdbarch_iterate_over_regset_sections (regcache->arch (),
fbsd_collect_regset_section_cb,
&data, regcache);
return data.note_data;
}
struct fbsd_corefile_thread_data
{
fbsd_corefile_thread_data (struct gdbarch *gdbarch,
bfd *obfd,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size,
gdb_signal stop_signal)
: gdbarch (gdbarch),
obfd (obfd),
note_data (note_data),
note_size (note_size),
stop_signal (stop_signal)
{}
struct gdbarch *gdbarch;
bfd *obfd;
char *note_data;
gdb::unique_xmalloc_ptr<char> &note_data;
int *note_size;
enum gdb_signal stop_signal;
};
@ -679,9 +701,9 @@ fbsd_corefile_thread (struct thread_info *info,
target_fetch_registers (regcache, -1);
args->note_data = fbsd_collect_thread_registers
(regcache, info->ptid, args->obfd, args->note_data,
args->note_size, args->stop_signal);
fbsd_collect_thread_registers (regcache, info->ptid, args->obfd,
args->note_data, args->note_size,
args->stop_signal);
}
/* Return a byte_vector containing the contents of a core dump note
@ -709,11 +731,10 @@ fbsd_make_note_desc (enum target_object object, uint32_t structsize)
/* Create appropriate note sections for a corefile, returning them in
allocated memory. */
static char *
static gdb::unique_xmalloc_ptr<char>
fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
{
struct fbsd_corefile_thread_data thread_args;
char *note_data = NULL;
gdb::unique_xmalloc_ptr<char> note_data;
Elf_Internal_Ehdr *i_ehdrp;
struct thread_info *curr_thr, *signalled_thr;
@ -732,8 +753,9 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
if (infargs != NULL)
psargs = psargs + " " + infargs;
note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
fname, psargs.c_str ());
note_data.reset (elfcore_write_prpsinfo (obfd, note_data.release (),
note_size, fname,
psargs.c_str ()));
}
/* Thread register information. */
@ -760,11 +782,8 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
signalled_thr = curr_thr;
}
thread_args.gdbarch = gdbarch;
thread_args.obfd = obfd;
thread_args.note_data = note_data;
thread_args.note_size = note_size;
thread_args.stop_signal = signalled_thr->suspend.stop_signal;
fbsd_corefile_thread_data thread_args (gdbarch, obfd, note_data, note_size,
signalled_thr->suspend.stop_signal);
fbsd_corefile_thread (signalled_thr, &thread_args);
for (thread_info *thr : current_inferior ()->non_exited_threads ())
@ -775,17 +794,17 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
fbsd_corefile_thread (thr, &thread_args);
}
note_data = thread_args.note_data;
/* Auxiliary vector. */
uint32_t structsize = gdbarch_ptr_bit (gdbarch) / 4; /* Elf_Auxinfo */
gdb::optional<gdb::byte_vector> note_desc =
fbsd_make_note_desc (TARGET_OBJECT_AUXV, structsize);
if (note_desc && !note_desc->empty ())
{
note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_AUXV,
note_desc->data (), note_desc->size ());
note_data.reset (elfcore_write_note (obfd, note_data.release (),
note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_AUXV,
note_desc->data (),
note_desc->size ()));
if (!note_data)
return NULL;
}
@ -794,9 +813,11 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
note_desc = fbsd_make_note_desc (TARGET_OBJECT_FREEBSD_VMMAP, 0);
if (note_desc && !note_desc->empty ())
{
note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_VMMAP,
note_desc->data (), note_desc->size ());
note_data.reset (elfcore_write_note (obfd, note_data.release (),
note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_VMMAP,
note_desc->data (),
note_desc->size ()));
if (!note_data)
return NULL;
}
@ -804,9 +825,11 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
note_desc = fbsd_make_note_desc (TARGET_OBJECT_FREEBSD_PS_STRINGS, 0);
if (note_desc && !note_desc->empty ())
{
note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_PSSTRINGS,
note_desc->data (), note_desc->size ());
note_data.reset (elfcore_write_note (obfd, note_data.release (),
note_size, "FreeBSD",
NT_FREEBSD_PROCSTAT_PSSTRINGS,
note_desc->data (),
note_desc->size ()));
if (!note_data)
return NULL;
}

View File

@ -80,8 +80,8 @@ write_gcore_file_1 (bfd *obfd)
if (!gdbarch_make_corefile_notes_p (target_gdbarch ()))
note_data.reset (target_make_corefile_notes (obfd, &note_size));
else
note_data.reset (gdbarch_make_corefile_notes (target_gdbarch (), obfd,
&note_size));
note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd,
&note_size);
if (note_data == NULL || note_size == 0)
error (_("Target does not support core file generation."));

View File

@ -3700,7 +3700,7 @@ gdbarch_make_corefile_notes_p (struct gdbarch *gdbarch)
return gdbarch->make_corefile_notes != NULL;
}
char *
gdb::unique_xmalloc_ptr<char>
gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
{
gdb_assert (gdbarch != NULL);

View File

@ -912,8 +912,8 @@ extern void set_gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, g
extern bool gdbarch_make_corefile_notes_p (struct gdbarch *gdbarch);
typedef char * (gdbarch_make_corefile_notes_ftype) (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
extern char * gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
typedef gdb::unique_xmalloc_ptr<char> (gdbarch_make_corefile_notes_ftype) (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
extern gdb::unique_xmalloc_ptr<char> gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
extern void set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, gdbarch_make_corefile_notes_ftype *make_corefile_notes);
/* Find core file memory regions */

View File

@ -715,7 +715,7 @@ F;CORE_ADDR;fetch_pointer_argument;struct frame_info *frame, int argi, struct ty
M;void;iterate_over_regset_sections;iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache;cb, cb_data, regcache
# Create core file notes
M;char *;make_corefile_notes;bfd *obfd, int *note_size;obfd, note_size
M;gdb::unique_xmalloc_ptr<char>;make_corefile_notes;bfd *obfd, int *note_size;obfd, note_size
# Find core file memory regions
M;int;find_memory_regions;find_memory_region_ftype func, void *data;func, data

View File

@ -1548,12 +1548,12 @@ linux_make_mappings_callback (ULONGEST vaddr, ULONGEST size,
/* Write the file mapping data to the core file, if possible. OBFD is
the output BFD. NOTE_DATA is the current note data, and NOTE_SIZE
is a pointer to the note size. Returns the new NOTE_DATA and
updates NOTE_SIZE. */
is a pointer to the note size. Updates NOTE_DATA and NOTE_SIZE. */
static char *
static void
linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
char *note_data, int *note_size)
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size)
{
struct linux_make_mappings_data mapping_data;
struct type *long_type
@ -1590,13 +1590,12 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
obstack_grow (&data_obstack, obstack_base (&filename_obstack),
size);
note_data = elfcore_write_note (obfd, note_data, note_size,
"CORE", NT_FILE,
obstack_base (&data_obstack),
obstack_object_size (&data_obstack));
note_data.reset (elfcore_write_note
(obfd, note_data.release (),
note_size, "CORE", NT_FILE,
obstack_base (&data_obstack),
obstack_object_size (&data_obstack)));
}
return note_data;
}
/* Structure for passing information from
@ -1605,14 +1604,26 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
struct linux_collect_regset_section_cb_data
{
linux_collect_regset_section_cb_data (struct gdbarch *gdbarch,
const struct regcache *regcache,
bfd *obfd,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size,
unsigned long lwp,
gdb_signal stop_signal)
: gdbarch (gdbarch), regcache (regcache), obfd (obfd),
note_data (note_data), note_size (note_size), lwp (lwp),
stop_signal (stop_signal)
{}
struct gdbarch *gdbarch;
const struct regcache *regcache;
bfd *obfd;
char *note_data;
gdb::unique_xmalloc_ptr<char> &note_data;
int *note_size;
unsigned long lwp;
enum gdb_signal stop_signal;
int abort_iteration;
bool abort_iteration = false;
};
/* Callback for iterate_over_regset_sections that records a single
@ -1645,47 +1656,44 @@ linux_collect_regset_section_cb (const char *sect_name, int supply_size,
/* PRSTATUS still needs to be treated specially. */
if (strcmp (sect_name, ".reg") == 0)
data->note_data = (char *) elfcore_write_prstatus
(data->obfd, data->note_data, data->note_size, data->lwp,
gdb_signal_to_host (data->stop_signal), buf.data ());
data->note_data.reset (elfcore_write_prstatus
(data->obfd, data->note_data.release (),
data->note_size, data->lwp,
gdb_signal_to_host (data->stop_signal),
buf.data ()));
else
data->note_data = (char *) elfcore_write_register_note
(data->obfd, data->note_data, data->note_size,
sect_name, buf.data (), collect_size);
data->note_data.reset (elfcore_write_register_note
(data->obfd, data->note_data.release (),
data->note_size, sect_name, buf.data (),
collect_size));
if (data->note_data == NULL)
data->abort_iteration = 1;
data->abort_iteration = true;
}
/* Records the thread's register state for the corefile note
section. */
static char *
static void
linux_collect_thread_registers (const struct regcache *regcache,
ptid_t ptid, bfd *obfd,
char *note_data, int *note_size,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size,
enum gdb_signal stop_signal)
{
struct gdbarch *gdbarch = regcache->arch ();
struct linux_collect_regset_section_cb_data data;
data.gdbarch = gdbarch;
data.regcache = regcache;
data.obfd = obfd;
data.note_data = note_data;
data.note_size = note_size;
data.stop_signal = stop_signal;
data.abort_iteration = 0;
/* For remote targets the LWP may not be available, so use the TID. */
data.lwp = ptid.lwp ();
if (!data.lwp)
data.lwp = ptid.tid ();
long lwp = ptid.lwp ();
if (lwp == 0)
lwp = ptid.tid ();
linux_collect_regset_section_cb_data data (gdbarch, regcache, obfd, note_data,
note_size, lwp, stop_signal);
gdbarch_iterate_over_regset_sections (gdbarch,
linux_collect_regset_section_cb,
&data, regcache);
return data.note_data;
}
/* Fetch the siginfo data for the specified thread, if it exists. If
@ -1718,9 +1726,16 @@ linux_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch)
struct linux_corefile_thread_data
{
linux_corefile_thread_data (struct gdbarch *gdbarch, bfd *obfd,
gdb::unique_xmalloc_ptr<char> &note_data,
int *note_size, gdb_signal stop_signal)
: gdbarch (gdbarch), obfd (obfd), note_data (note_data),
note_size (note_size), stop_signal (stop_signal)
{}
struct gdbarch *gdbarch;
bfd *obfd;
char *note_data;
gdb::unique_xmalloc_ptr<char> &note_data;
int *note_size;
enum gdb_signal stop_signal;
};
@ -1740,20 +1755,22 @@ linux_corefile_thread (struct thread_info *info,
target_fetch_registers (regcache, -1);
gdb::byte_vector siginfo_data = linux_get_siginfo_data (info, args->gdbarch);
args->note_data = linux_collect_thread_registers
(regcache, info->ptid, args->obfd, args->note_data,
args->note_size, args->stop_signal);
linux_collect_thread_registers (regcache, info->ptid, args->obfd,
args->note_data, args->note_size,
args->stop_signal);
/* Don't return anything if we got no register information above,
such a core file is useless. */
if (args->note_data != NULL)
if (!siginfo_data.empty ())
args->note_data = elfcore_write_note (args->obfd,
args->note_data,
args->note_size,
"CORE", NT_SIGINFO,
siginfo_data.data (),
siginfo_data.size ());
{
if (!siginfo_data.empty ())
args->note_data.reset (elfcore_write_note (args->obfd,
args->note_data.release (),
args->note_size,
"CORE", NT_SIGINFO,
siginfo_data.data (),
siginfo_data.size ()));
}
}
/* Fill the PRPSINFO structure with information about the process being
@ -1971,12 +1988,11 @@ find_signalled_thread ()
/* Build the note section for a corefile, and return it in a malloc
buffer. */
static char *
static gdb::unique_xmalloc_ptr<char>
linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
{
struct linux_corefile_thread_data thread_args;
struct elf_internal_linux_prpsinfo prpsinfo;
char *note_data = NULL;
gdb::unique_xmalloc_ptr<char> note_data;
if (! gdbarch_iterate_over_regset_sections_p (gdbarch))
return NULL;
@ -1984,13 +2000,13 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
if (linux_fill_prpsinfo (&prpsinfo))
{
if (gdbarch_ptr_bit (gdbarch) == 64)
note_data = elfcore_write_linux_prpsinfo64 (obfd,
note_data, note_size,
&prpsinfo);
note_data.reset (elfcore_write_linux_prpsinfo64 (obfd,
note_data.release (),
note_size, &prpsinfo));
else
note_data = elfcore_write_linux_prpsinfo32 (obfd,
note_data, note_size,
&prpsinfo);
note_data.reset (elfcore_write_linux_prpsinfo32 (obfd,
note_data.release (),
note_size, &prpsinfo));
}
/* Thread register information. */
@ -2007,15 +2023,14 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
"First thread" is what tools use to infer the signalled
thread. */
thread_info *signalled_thr = find_signalled_thread ();
thread_args.gdbarch = gdbarch;
thread_args.obfd = obfd;
thread_args.note_data = note_data;
thread_args.note_size = note_size;
gdb_signal stop_signal;
if (signalled_thr != nullptr)
thread_args.stop_signal = signalled_thr->suspend.stop_signal;
stop_signal = signalled_thr->suspend.stop_signal;
else
thread_args.stop_signal = GDB_SIGNAL_0;
stop_signal = GDB_SIGNAL_0;
linux_corefile_thread_data thread_args (gdbarch, obfd, note_data, note_size,
stop_signal);
if (signalled_thr != nullptr)
linux_corefile_thread (signalled_thr, &thread_args);
@ -2027,7 +2042,6 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
linux_corefile_thread (thr, &thread_args);
}
note_data = thread_args.note_data;
if (!note_data)
return NULL;
@ -2036,17 +2050,16 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL);
if (auxv && !auxv->empty ())
{
note_data = elfcore_write_note (obfd, note_data, note_size,
"CORE", NT_AUXV, auxv->data (),
auxv->size ());
note_data.reset (elfcore_write_note (obfd, note_data.release (),
note_size, "CORE", NT_AUXV,
auxv->data (), auxv->size ()));
if (!note_data)
return NULL;
}
/* File mappings. */
note_data = linux_make_mappings_corefile_notes (gdbarch, obfd,
note_data, note_size);
linux_make_mappings_corefile_notes (gdbarch, obfd, note_data, note_size);
return note_data;
}