/* Target-dependent code for GNU/Linux, architecture independent.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "cli/cli-utils.h"
#include "arch-utils.h"
#include "gdb_obstack.h"
-#include "observer.h"
+#include "observable.h"
#include "objfiles.h"
#include "infcall.h"
#include "gdbcmd.h"
static int use_coredump_filter = 1;
+/* Whether the value of smaps_vmflags->exclude_coredump should be
+ ignored, including mappings marked with the VM_DONTDUMP flag in
+ the dump. */
+static int dump_excluded_mappings = 0;
+
/* This enum represents the signals' numbers on a generic architecture
running the Linux kernel. The definition of "generic" comes from
the file <include/uapi/asm-generic/signal.h>, from the Linux kernel
{
CORE_ADDR dummy;
- return (target_auxv_search (¤t_target, AT_NULL, &dummy) > 0
- && target_auxv_search (¤t_target, AT_PAGESZ, &dummy) == 0);
+ return (target_auxv_search (current_top_target (), AT_NULL, &dummy) > 0
+ && target_auxv_search (current_top_target (), AT_PAGESZ, &dummy) == 0);
}
static int
{
static char buf[80];
- if (ptid_get_lwp (ptid) != 0)
+ if (ptid.lwp () != 0)
{
- snprintf (buf, sizeof (buf), "LWP %ld", ptid_get_lwp (ptid));
+ snprintf (buf, sizeof (buf), "LWP %ld", ptid.lwp ());
return buf;
}
return 0;
/* Check if we should exclude this mapping. */
- if (v->exclude_coredump)
+ if (!dump_excluded_mappings && v->exclude_coredump)
return 0;
/* Update our notion of whether this mapping is shared or
int status_f = (what == IP_STATUS || what == IP_ALL);
int stat_f = (what == IP_STAT || what == IP_ALL);
char filename[100];
- char *data;
int target_errno;
if (args && isdigit (args[0]))
if (cmdline_f)
{
xsnprintf (filename, sizeof filename, "/proc/%ld/cmdline", pid);
- gdb::unique_xmalloc_ptr<char> cmdline
- = target_fileio_read_stralloc (NULL, filename);
- if (cmdline)
- printf_filtered ("cmdline = '%s'\n", cmdline.get ());
+ gdb_byte *buffer;
+ ssize_t len = target_fileio_read_alloc (NULL, filename, &buffer);
+
+ if (len > 0)
+ {
+ gdb::unique_xmalloc_ptr<char> cmdline ((char *) buffer);
+ ssize_t pos;
+
+ for (pos = 0; pos < len - 1; pos++)
+ {
+ if (buffer[pos] == '\0')
+ buffer[pos] = ' ';
+ }
+ buffer[len - 1] = '\0';
+ printf_filtered ("cmdline = '%s'\n", buffer);
+ }
else
warning (_("unable to open /proc file '%s'"), filename);
}
if (cwd_f)
{
xsnprintf (filename, sizeof filename, "/proc/%ld/cwd", pid);
- data = target_fileio_readlink (NULL, filename, &target_errno);
- if (data)
- {
- struct cleanup *cleanup = make_cleanup (xfree, data);
- printf_filtered ("cwd = '%s'\n", data);
- do_cleanups (cleanup);
- }
+ gdb::optional<std::string> contents
+ = target_fileio_readlink (NULL, filename, &target_errno);
+ if (contents.has_value ())
+ printf_filtered ("cwd = '%s'\n", contents->c_str ());
else
warning (_("unable to read link '%s'"), filename);
}
if (exe_f)
{
xsnprintf (filename, sizeof filename, "/proc/%ld/exe", pid);
- data = target_fileio_readlink (NULL, filename, &target_errno);
- if (data)
- {
- struct cleanup *cleanup = make_cleanup (xfree, data);
- printf_filtered ("exe = '%s'\n", data);
- do_cleanups (cleanup);
- }
+ gdb::optional<std::string> contents
+ = target_fileio_readlink (NULL, filename, &target_errno);
+ if (contents.has_value ())
+ printf_filtered ("exe = '%s'\n", contents->c_str ());
else
warning (_("unable to read link '%s'"), filename);
}
line = strtok (NULL, "\n"))
{
ULONGEST addr, endaddr, offset, inode;
- const char *permissions, *device, *filename;
+ const char *permissions, *device, *mapping_filename;
size_t permissions_len, device_len;
read_mapping (line, &addr, &endaddr,
&permissions, &permissions_len,
&offset, &device, &device_len,
- &inode, &filename);
+ &inode, &mapping_filename);
if (gdbarch_addr_bit (gdbarch) == 32)
{
paddress (gdbarch, endaddr),
hex_string (endaddr - addr),
hex_string (offset),
- *filename? filename : "");
+ *mapping_filename ? mapping_filename : "");
}
else
{
paddress (gdbarch, endaddr),
hex_string (endaddr - addr),
hex_string (offset),
- *filename? filename : "");
+ *mapping_filename ? mapping_filename : "");
}
}
}
{
asection *section;
ULONGEST count, page_size;
- unsigned char *descdata, *filenames, *descend, *contents;
+ unsigned char *descdata, *filenames, *descend;
size_t note_size;
unsigned int addr_size_bits, addr_size;
- struct cleanup *cleanup;
struct gdbarch *core_gdbarch = gdbarch_from_bfd (core_bfd);
/* We assume this for reading 64-bit core files. */
gdb_static_assert (sizeof (ULONGEST) >= 8);
if (note_size < 2 * addr_size)
error (_("malformed core note - too short for header"));
- contents = (unsigned char *) xmalloc (note_size);
- cleanup = make_cleanup (xfree, contents);
- if (!bfd_get_section_contents (core_bfd, section, contents, 0, note_size))
+ gdb::def_vector<unsigned char> contents (note_size);
+ if (!bfd_get_section_contents (core_bfd, section, contents.data (),
+ 0, note_size))
error (_("could not get core note contents"));
- descdata = contents;
+ descdata = contents.data ();
descend = descdata + note_size;
if (descdata[note_size - 1] != '\0')
filenames += 1 + strlen ((char *) filenames);
}
-
- do_cleanups (cleanup);
}
/* Implement "info proc" for a corefile. */
find_signalled_thread (struct thread_info *info, void *data)
{
if (info->suspend.stop_signal != GDB_SIGNAL_0
- && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
+ && info->ptid.pid () == inferior_ptid.pid ())
return 1;
return 0;
};
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- gdb_byte *spu_ids;
- LONGEST i, j, size;
/* Determine list of SPU ids. */
- size = target_read_alloc (¤t_target, TARGET_OBJECT_SPU,
- NULL, &spu_ids);
+ gdb::optional<gdb::byte_vector>
+ spu_ids = target_read_alloc (current_top_target (),
+ TARGET_OBJECT_SPU, NULL);
+
+ if (!spu_ids)
+ return note_data;
/* Generate corefile notes for each SPU file. */
- for (i = 0; i < size; i += 4)
+ for (size_t i = 0; i < spu_ids->size (); i += 4)
{
- int fd = extract_unsigned_integer (spu_ids + i, 4, byte_order);
+ int fd = extract_unsigned_integer (spu_ids->data () + i, 4, byte_order);
- for (j = 0; j < sizeof (spu_files) / sizeof (spu_files[0]); j++)
+ for (size_t j = 0; j < sizeof (spu_files) / sizeof (spu_files[0]); j++)
{
char annex[32], note_name[32];
- gdb_byte *spu_data;
- LONGEST spu_len;
xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]);
- spu_len = target_read_alloc (¤t_target, TARGET_OBJECT_SPU,
- annex, &spu_data);
- if (spu_len > 0)
+ gdb::optional<gdb::byte_vector> spu_data
+ = target_read_alloc (current_top_target (), TARGET_OBJECT_SPU, annex);
+
+ if (spu_data && !spu_data->empty ())
{
xsnprintf (note_name, sizeof note_name, "SPU/%s", annex);
note_data = elfcore_write_note (obfd, note_data, note_size,
note_name, NT_SPU,
- spu_data, spu_len);
- xfree (spu_data);
+ spu_data->data (),
+ spu_data->size ());
if (!note_data)
- {
- xfree (spu_ids);
- return NULL;
- }
+ return nullptr;
}
}
}
- if (size > 0)
- xfree (spu_ids);
-
return note_data;
}
linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
char *note_data, int *note_size)
{
- struct cleanup *cleanup;
struct linux_make_mappings_data mapping_data;
struct type *long_type
= arch_integer_type (gdbarch, gdbarch_long_bit (gdbarch), 0, "long");
regset in the corefile note section. */
static void
-linux_collect_regset_section_cb (const char *sect_name, int size,
- const struct regset *regset,
+linux_collect_regset_section_cb (const char *sect_name, int supply_size,
+ int collect_size, const struct regset *regset,
const char *human_name, void *cb_data)
{
char *buf;
struct linux_collect_regset_section_cb_data *data
= (struct linux_collect_regset_section_cb_data *) cb_data;
+ bool variable_size_section = (regset != NULL
+ && regset->flags & REGSET_VARIABLE_SIZE);
+
+ if (!variable_size_section)
+ gdb_assert (supply_size == collect_size);
if (data->abort_iteration)
return;
gdb_assert (regset && regset->collect_regset);
- buf = (char *) xmalloc (size);
- regset->collect_regset (regset, data->regcache, -1, buf, size);
+ buf = (char *) xmalloc (collect_size);
+ regset->collect_regset (regset, data->regcache, -1, buf, collect_size);
/* PRSTATUS still needs to be treated specially. */
if (strcmp (sect_name, ".reg") == 0)
else
data->note_data = (char *) elfcore_write_register_note
(data->obfd, data->note_data, data->note_size,
- sect_name, buf, size);
+ sect_name, buf, collect_size);
xfree (buf);
if (data->note_data == NULL)
data.abort_iteration = 0;
/* For remote targets the LWP may not be available, so use the TID. */
- data.lwp = ptid_get_lwp (ptid);
+ data.lwp = ptid.lwp ();
if (!data.lwp)
- data.lwp = ptid_get_tid (ptid);
+ data.lwp = ptid.tid ();
gdbarch_iterate_over_regset_sections (gdbarch,
linux_collect_regset_section_cb,
}
/* Fetch the siginfo data for the specified thread, if it exists. If
- there is no data, or we could not read it, return NULL. Otherwise,
- return a newly malloc'd buffer holding the data and fill in *SIZE
- with the size of the data. The caller is responsible for freeing
- the data. */
-
-static gdb_byte *
-linux_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch,
- LONGEST *size)
+ there is no data, or we could not read it, return an empty
+ buffer. */
+
+static gdb::byte_vector
+linux_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch)
{
struct type *siginfo_type;
- gdb_byte *buf;
LONGEST bytes_read;
- struct cleanup *cleanups;
if (!gdbarch_get_siginfo_type_p (gdbarch))
- return NULL;
-
+ return gdb::byte_vector ();
+
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = thread->ptid;
siginfo_type = gdbarch_get_siginfo_type (gdbarch);
- buf = (gdb_byte *) xmalloc (TYPE_LENGTH (siginfo_type));
- cleanups = make_cleanup (xfree, buf);
+ gdb::byte_vector buf (TYPE_LENGTH (siginfo_type));
- bytes_read = target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
- buf, 0, TYPE_LENGTH (siginfo_type));
- if (bytes_read == TYPE_LENGTH (siginfo_type))
- {
- discard_cleanups (cleanups);
- *size = bytes_read;
- }
- else
- {
- do_cleanups (cleanups);
- buf = NULL;
- }
+ bytes_read = target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
+ buf.data (), 0, TYPE_LENGTH (siginfo_type));
+ if (bytes_read != TYPE_LENGTH (siginfo_type))
+ buf.clear ();
return buf;
}
linux_corefile_thread (struct thread_info *info,
struct linux_corefile_thread_data *args)
{
- struct cleanup *old_chain;
struct regcache *regcache;
- gdb_byte *siginfo_data;
- LONGEST siginfo_size = 0;
regcache = get_thread_arch_regcache (info->ptid, args->gdbarch);
target_fetch_registers (regcache, -1);
- siginfo_data = linux_get_siginfo_data (info, args->gdbarch, &siginfo_size);
-
- old_chain = make_cleanup (xfree, siginfo_data);
+ 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,
/* 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 != NULL)
+ if (!siginfo_data.empty ())
args->note_data = elfcore_write_note (args->obfd,
args->note_data,
args->note_size,
"CORE", NT_SIGINFO,
- siginfo_data, siginfo_size);
-
- do_cleanups (old_chain);
+ siginfo_data.data (),
+ siginfo_data.size ());
}
/* Fill the PRPSINFO structure with information about the process being
char filename[100];
/* The basename of the executable. */
const char *basename;
- char *infargs;
+ const char *infargs;
/* Temporary buffer. */
char *tmpstr;
/* The valid states of a process, according to the Linux kernel. */
gdb_assert (p != NULL);
/* Obtaining PID and filename. */
- pid = ptid_get_pid (inferior_ptid);
+ pid = inferior_ptid.pid ();
xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);
/* The full name of the program which generated the corefile. */
gdb::unique_xmalloc_ptr<char> fname
struct linux_corefile_thread_data thread_args;
struct elf_internal_linux_prpsinfo prpsinfo;
char *note_data = NULL;
- gdb_byte *auxv;
- int auxv_len;
struct thread_info *curr_thr, *signalled_thr, *thr;
if (! gdbarch_iterate_over_regset_sections_p (gdbarch))
{
if (thr == signalled_thr)
continue;
- if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid))
+ if (thr->ptid.pid () != inferior_ptid.pid ())
continue;
linux_corefile_thread (thr, &thread_args);
return NULL;
/* Auxillary vector. */
- auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV,
- NULL, &auxv);
- if (auxv_len > 0)
+ gdb::optional<gdb::byte_vector> auxv =
+ 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, auxv_len);
- xfree (auxv);
+ "CORE", NT_AUXV, auxv->data (),
+ auxv->size ());
if (!note_data)
return NULL;
char filename[100];
long pid;
- if (target_auxv_search (¤t_target, AT_SYSINFO_EHDR, &range->start) <= 0)
+ if (target_auxv_search (current_top_target (), AT_SYSINFO_EHDR, &range->start) <= 0)
return 0;
/* It doesn't make sense to access the host's /proc when debugging a
local-store address and is thus not usable as displaced stepping
location. The auxiliary vector gets us the PowerPC-side entry
point address instead. */
- if (target_auxv_search (¤t_target, AT_ENTRY, &addr) <= 0)
+ if (target_auxv_search (current_top_target (), AT_ENTRY, &addr) <= 0)
throw_error (NOT_SUPPORTED_ERROR,
_("Cannot find AT_ENTRY auxiliary vector entry."));
/* Make certain that the address points at real code, and not a
function descriptor. */
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
- ¤t_target);
+ current_top_target ());
/* Inferior calls also use the entry point as a breakpoint location.
We don't want displaced stepping to interfere with those
" corefiles is %s.\n"), value);
}
+/* Display whether the gcore command is dumping mappings marked with
+ the VM_DONTDUMP flag. */
+
+static void
+show_dump_excluded_mappings (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Dumping of mappings marked with the VM_DONTDUMP"
+ " flag is %s.\n"), value);
+}
+
/* To be called from the various GDB_OSABI_LINUX handlers for the
various GNU/Linux architectures and machine types. */
linux_inferior_data
= register_inferior_data_with_cleanup (NULL, linux_inferior_data_cleanup);
/* Observers used to invalidate the cache when needed. */
- observer_attach_inferior_exit (invalidate_linux_cache_inf);
- observer_attach_inferior_appeared (invalidate_linux_cache_inf);
+ gdb::observers::inferior_exit.attach (invalidate_linux_cache_inf);
+ gdb::observers::inferior_appeared.attach (invalidate_linux_cache_inf);
add_setshow_boolean_cmd ("use-coredump-filter", class_files,
&use_coredump_filter, _("\
about this file, refer to the manpage of core(5)."),
NULL, show_use_coredump_filter,
&setlist, &showlist);
+
+ add_setshow_boolean_cmd ("dump-excluded-mappings", class_files,
+ &dump_excluded_mappings, _("\
+Set whether gcore should dump mappings marked with the VM_DONTDUMP flag."),
+ _("\
+Show whether gcore should dump mappings marked with the VM_DONTDUMP flag."),
+ _("\
+Use this command to set whether gcore should dump mappings marked with the\n\
+VM_DONTDUMP flag (\"dd\" in /proc/PID/smaps) when generating the corefile. For\n\
+more information about this file, refer to the manpage of proc(5) and core(5)."),
+ NULL, show_dump_excluded_mappings,
+ &setlist, &showlist);
}