| Index: gdb/linux-tdep.c
|
| diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
|
| index 5209dc13592696f1d420debdca3085673a5c5d87..b6f2efbd45a439e70fd2fee430f556107716daae 100644
|
| --- a/gdb/linux-tdep.c
|
| +++ b/gdb/linux-tdep.c
|
| @@ -22,8 +22,16 @@
|
| #include "linux-tdep.h"
|
| #include "auxv.h"
|
| #include "target.h"
|
| +#include "gdbthread.h"
|
| +#include "gdbcore.h"
|
| +#include "regcache.h"
|
| +#include "regset.h"
|
| #include "elf/common.h"
|
| +#include "elf-bfd.h" /* for elfcore_write_* */
|
| #include "inferior.h"
|
| +#include "cli/cli-utils.h"
|
| +
|
| +#include <ctype.h>
|
|
|
| static struct gdbarch_data *linux_gdbarch_data_handle;
|
|
|
| @@ -165,8 +173,8 @@ linux_get_siginfo_type (struct gdbarch *gdbarch)
|
| return siginfo_type;
|
| }
|
|
|
| -int
|
| -linux_has_shared_address_space (void)
|
| +static int
|
| +linux_has_shared_address_space (struct gdbarch *gdbarch)
|
| {
|
| /* Determine whether we are running on uClinux or normal Linux
|
| kernel. */
|
| @@ -196,6 +204,651 @@ linux_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
|
| return normal_pid_to_str (ptid);
|
| }
|
|
|
| +/* Service function for corefiles and info proc. */
|
| +
|
| +static void
|
| +read_mapping (const char *line,
|
| + ULONGEST *addr, ULONGEST *endaddr,
|
| + const char **permissions, size_t *permissions_len,
|
| + ULONGEST *offset,
|
| + const char **device, size_t *device_len,
|
| + ULONGEST *inode,
|
| + const char **filename)
|
| +{
|
| + const char *p = line;
|
| +
|
| + *addr = strtoulst (p, &p, 16);
|
| + if (*p == '-')
|
| + p++;
|
| + *endaddr = strtoulst (p, &p, 16);
|
| +
|
| + while (*p && isspace (*p))
|
| + p++;
|
| + *permissions = p;
|
| + while (*p && !isspace (*p))
|
| + p++;
|
| + *permissions_len = p - *permissions;
|
| +
|
| + *offset = strtoulst (p, &p, 16);
|
| +
|
| + while (*p && isspace (*p))
|
| + p++;
|
| + *device = p;
|
| + while (*p && !isspace (*p))
|
| + p++;
|
| + *device_len = p - *device;
|
| +
|
| + *inode = strtoulst (p, &p, 10);
|
| +
|
| + while (*p && isspace (*p))
|
| + p++;
|
| + *filename = p;
|
| +}
|
| +
|
| +/* Implement the "info proc" command. */
|
| +
|
| +static void
|
| +linux_info_proc (struct gdbarch *gdbarch, char *args,
|
| + enum info_proc_what what)
|
| +{
|
| + /* A long is used for pid instead of an int to avoid a loss of precision
|
| + compiler warning from the output of strtoul. */
|
| + long pid;
|
| + int cmdline_f = (what == IP_MINIMAL || what == IP_CMDLINE || what == IP_ALL);
|
| + int cwd_f = (what == IP_MINIMAL || what == IP_CWD || what == IP_ALL);
|
| + int exe_f = (what == IP_MINIMAL || what == IP_EXE || what == IP_ALL);
|
| + int mappings_f = (what == IP_MAPPINGS || what == IP_ALL);
|
| + int status_f = (what == IP_STATUS || what == IP_ALL);
|
| + int stat_f = (what == IP_STAT || what == IP_ALL);
|
| + char filename[100];
|
| + gdb_byte *data;
|
| + int target_errno;
|
| +
|
| + if (args && isdigit (args[0]))
|
| + pid = strtoul (args, &args, 10);
|
| + else
|
| + {
|
| + if (!target_has_execution)
|
| + error (_("No current process: you must name one."));
|
| + if (current_inferior ()->fake_pid_p)
|
| + error (_("Can't determine the current process's PID: you must name one."));
|
| +
|
| + pid = current_inferior ()->pid;
|
| + }
|
| +
|
| + args = skip_spaces (args);
|
| + if (args && args[0])
|
| + error (_("Too many parameters: %s"), args);
|
| +
|
| + printf_filtered (_("process %ld\n"), pid);
|
| + if (cmdline_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/cmdline", pid);
|
| + data = target_fileio_read_stralloc (filename);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + printf_filtered ("cmdline = '%s'\n", data);
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to open /proc file '%s'"), filename);
|
| + }
|
| + if (cwd_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/cwd", pid);
|
| + data = target_fileio_readlink (filename, &target_errno);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + printf_filtered ("cwd = '%s'\n", data);
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to read link '%s'"), filename);
|
| + }
|
| + if (exe_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/exe", pid);
|
| + data = target_fileio_readlink (filename, &target_errno);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + printf_filtered ("exe = '%s'\n", data);
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to read link '%s'"), filename);
|
| + }
|
| + if (mappings_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/maps", pid);
|
| + data = target_fileio_read_stralloc (filename);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + char *line;
|
| +
|
| + printf_filtered (_("Mapped address spaces:\n\n"));
|
| + if (gdbarch_addr_bit (gdbarch) == 32)
|
| + {
|
| + printf_filtered ("\t%10s %10s %10s %10s %s\n",
|
| + "Start Addr",
|
| + " End Addr",
|
| + " Size", " Offset", "objfile");
|
| + }
|
| + else
|
| + {
|
| + printf_filtered (" %18s %18s %10s %10s %s\n",
|
| + "Start Addr",
|
| + " End Addr",
|
| + " Size", " Offset", "objfile");
|
| + }
|
| +
|
| + for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n"))
|
| + {
|
| + ULONGEST addr, endaddr, offset, inode;
|
| + const char *permissions, *device, *filename;
|
| + size_t permissions_len, device_len;
|
| +
|
| + read_mapping (line, &addr, &endaddr,
|
| + &permissions, &permissions_len,
|
| + &offset, &device, &device_len,
|
| + &inode, &filename);
|
| +
|
| + if (gdbarch_addr_bit (gdbarch) == 32)
|
| + {
|
| + printf_filtered ("\t%10s %10s %10s %10s %s\n",
|
| + paddress (gdbarch, addr),
|
| + paddress (gdbarch, endaddr),
|
| + hex_string (endaddr - addr),
|
| + hex_string (offset),
|
| + *filename? filename : "");
|
| + }
|
| + else
|
| + {
|
| + printf_filtered (" %18s %18s %10s %10s %s\n",
|
| + paddress (gdbarch, addr),
|
| + paddress (gdbarch, endaddr),
|
| + hex_string (endaddr - addr),
|
| + hex_string (offset),
|
| + *filename? filename : "");
|
| + }
|
| + }
|
| +
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to open /proc file '%s'"), filename);
|
| + }
|
| + if (status_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/status", pid);
|
| + data = target_fileio_read_stralloc (filename);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + puts_filtered (data);
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to open /proc file '%s'"), filename);
|
| + }
|
| + if (stat_f)
|
| + {
|
| + xsnprintf (filename, sizeof filename, "/proc/%ld/stat", pid);
|
| + data = target_fileio_read_stralloc (filename);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + const char *p = data;
|
| +
|
| + printf_filtered (_("Process: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| +
|
| + while (*p && isspace (*p))
|
| + p++;
|
| + if (*p == '(')
|
| + {
|
| + const char *ep = strchr (p, ')');
|
| + if (ep != NULL)
|
| + {
|
| + printf_filtered ("Exec file: %.*s\n",
|
| + (int) (ep - p - 1), p + 1);
|
| + p = ep + 1;
|
| + }
|
| + }
|
| +
|
| + while (*p && isspace (*p))
|
| + p++;
|
| + if (*p)
|
| + printf_filtered (_("State: %c\n"), *p++);
|
| +
|
| + if (*p)
|
| + printf_filtered (_("Parent process: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Process group: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Session id: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("TTY: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("TTY owner process group: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| +
|
| + if (*p)
|
| + printf_filtered (_("Flags: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Minor faults (no memory page): %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Minor faults, children: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Major faults (memory page faults): %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Major faults, children: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("utime: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("stime: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("utime, children: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("stime, children: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("jiffies remaining in current "
|
| + "time slice: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("'nice' value: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("jiffies until next timeout: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("jiffies until next SIGALRM: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("start time (jiffies since "
|
| + "system boot): %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Virtual memory size: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Resident set size: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("rlim: %s\n"),
|
| + pulongest (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Start of text: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("End of text: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Start of stack: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| +#if 0 /* Don't know how architecture-dependent the rest is...
|
| + Anyway the signal bitmap info is available from "status". */
|
| + if (*p)
|
| + printf_filtered (_("Kernel stack pointer: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Kernel instr pointer: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Pending signals bitmap: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Blocked signals bitmap: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Ignored signals bitmap: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("Catched signals bitmap: %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| + if (*p)
|
| + printf_filtered (_("wchan (system call): %s\n"),
|
| + hex_string (strtoulst (p, &p, 10)));
|
| +#endif
|
| + do_cleanups (cleanup);
|
| + }
|
| + else
|
| + warning (_("unable to open /proc file '%s'"), filename);
|
| + }
|
| +}
|
| +
|
| +/* List memory regions in the inferior for a corefile. */
|
| +
|
| +static int
|
| +linux_find_memory_regions (struct gdbarch *gdbarch,
|
| + find_memory_region_ftype func, void *obfd)
|
| +{
|
| + char filename[100];
|
| + gdb_byte *data;
|
| +
|
| + /* We need to know the real target PID to access /proc. */
|
| + if (current_inferior ()->fake_pid_p)
|
| + return 1;
|
| +
|
| + xsnprintf (filename, sizeof filename,
|
| + "/proc/%d/maps", current_inferior ()->pid);
|
| + data = target_fileio_read_stralloc (filename);
|
| + if (data)
|
| + {
|
| + struct cleanup *cleanup = make_cleanup (xfree, data);
|
| + char *line;
|
| +
|
| + for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n"))
|
| + {
|
| + ULONGEST addr, endaddr, offset, inode;
|
| + const char *permissions, *device, *filename;
|
| + size_t permissions_len, device_len;
|
| + int read, write, exec;
|
| +
|
| + read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
|
| + &offset, &device, &device_len, &inode, &filename);
|
| +
|
| + /* Decode permissions. */
|
| + read = (memchr (permissions, 'r', permissions_len) != 0);
|
| + write = (memchr (permissions, 'w', permissions_len) != 0);
|
| + exec = (memchr (permissions, 'x', permissions_len) != 0);
|
| +
|
| + /* Invoke the callback function to create the corefile segment. */
|
| + func (addr, endaddr - addr, read, write, exec, obfd);
|
| + }
|
| +
|
| + do_cleanups (cleanup);
|
| + return 0;
|
| + }
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +/* Determine which signal stopped execution. */
|
| +
|
| +static int
|
| +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))
|
| + return 1;
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +static enum gdb_signal
|
| +find_stop_signal (void)
|
| +{
|
| + struct thread_info *info =
|
| + iterate_over_threads (find_signalled_thread, NULL);
|
| +
|
| + if (info)
|
| + return info->suspend.stop_signal;
|
| + else
|
| + return GDB_SIGNAL_0;
|
| +}
|
| +
|
| +/* Generate corefile notes for SPU contexts. */
|
| +
|
| +static char *
|
| +linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
|
| +{
|
| + static const char *spu_files[] =
|
| + {
|
| + "object-id",
|
| + "mem",
|
| + "regs",
|
| + "fpcr",
|
| + "lslr",
|
| + "decr",
|
| + "decr_status",
|
| + "signal1",
|
| + "signal1_type",
|
| + "signal2",
|
| + "signal2_type",
|
| + "event_mask",
|
| + "event_status",
|
| + "mbox_info",
|
| + "ibox_info",
|
| + "wbox_info",
|
| + "dma_info",
|
| + "proxydma_info",
|
| + };
|
| +
|
| + 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);
|
| +
|
| + /* Generate corefile notes for each SPU file. */
|
| + for (i = 0; i < size; i += 4)
|
| + {
|
| + int fd = extract_unsigned_integer (spu_ids + i, 4, byte_order);
|
| +
|
| + for (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)
|
| + {
|
| + 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);
|
| +
|
| + if (!note_data)
|
| + {
|
| + xfree (spu_ids);
|
| + return NULL;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (size > 0)
|
| + xfree (spu_ids);
|
| +
|
| + return note_data;
|
| +}
|
| +
|
| +/* Records the thread's register state for the corefile note
|
| + section. */
|
| +
|
| +static char *
|
| +linux_collect_thread_registers (const struct regcache *regcache,
|
| + ptid_t ptid, bfd *obfd,
|
| + char *note_data, int *note_size,
|
| + enum gdb_signal stop_signal)
|
| +{
|
| + struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
| + struct core_regset_section *sect_list;
|
| + unsigned long lwp;
|
| +
|
| + sect_list = gdbarch_core_regset_sections (gdbarch);
|
| + gdb_assert (sect_list);
|
| +
|
| + /* For remote targets the LWP may not be available, so use the TID. */
|
| + lwp = ptid_get_lwp (ptid);
|
| + if (!lwp)
|
| + lwp = ptid_get_tid (ptid);
|
| +
|
| + while (sect_list->sect_name != NULL)
|
| + {
|
| + const struct regset *regset;
|
| + char *buf;
|
| +
|
| + regset = gdbarch_regset_from_core_section (gdbarch,
|
| + sect_list->sect_name,
|
| + sect_list->size);
|
| + gdb_assert (regset && regset->collect_regset);
|
| +
|
| + buf = xmalloc (sect_list->size);
|
| + regset->collect_regset (regset, regcache, -1, buf, sect_list->size);
|
| +
|
| + /* PRSTATUS still needs to be treated specially. */
|
| + if (strcmp (sect_list->sect_name, ".reg") == 0)
|
| + note_data = (char *) elfcore_write_prstatus
|
| + (obfd, note_data, note_size, lwp,
|
| + gdb_signal_to_host (stop_signal), buf);
|
| + else
|
| + note_data = (char *) elfcore_write_register_note
|
| + (obfd, note_data, note_size,
|
| + sect_list->sect_name, buf, sect_list->size);
|
| + xfree (buf);
|
| + sect_list++;
|
| +
|
| + if (!note_data)
|
| + return NULL;
|
| + }
|
| +
|
| + return note_data;
|
| +}
|
| +
|
| +struct linux_corefile_thread_data
|
| +{
|
| + struct gdbarch *gdbarch;
|
| + int pid;
|
| + bfd *obfd;
|
| + char *note_data;
|
| + int *note_size;
|
| + int num_notes;
|
| + enum gdb_signal stop_signal;
|
| + linux_collect_thread_registers_ftype collect;
|
| +};
|
| +
|
| +/* Called by gdbthread.c once per thread. Records the thread's
|
| + register state for the corefile note section. */
|
| +
|
| +static int
|
| +linux_corefile_thread_callback (struct thread_info *info, void *data)
|
| +{
|
| + struct linux_corefile_thread_data *args = data;
|
| +
|
| + if (ptid_get_pid (info->ptid) == args->pid)
|
| + {
|
| + struct cleanup *old_chain;
|
| + struct regcache *regcache;
|
| + regcache = get_thread_arch_regcache (info->ptid, args->gdbarch);
|
| +
|
| + old_chain = save_inferior_ptid ();
|
| + inferior_ptid = info->ptid;
|
| + target_fetch_registers (regcache, -1);
|
| + do_cleanups (old_chain);
|
| +
|
| + args->note_data = args->collect (regcache, info->ptid, args->obfd,
|
| + args->note_data, args->note_size,
|
| + args->stop_signal);
|
| + args->num_notes++;
|
| + }
|
| +
|
| + return !args->note_data;
|
| +}
|
| +
|
| +/* Fills the "to_make_corefile_note" target vector. Builds the note
|
| + section for a corefile, and returns it in a malloc buffer. */
|
| +
|
| +char *
|
| +linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
|
| + linux_collect_thread_registers_ftype collect)
|
| +{
|
| + struct linux_corefile_thread_data thread_args;
|
| + char *note_data = NULL;
|
| + gdb_byte *auxv;
|
| + int auxv_len;
|
| +
|
| + /* Process information. */
|
| + if (get_exec_file (0))
|
| + {
|
| + const char *fname = lbasename (get_exec_file (0));
|
| + char *psargs = xstrdup (fname);
|
| +
|
| + if (get_inferior_args ())
|
| + psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
|
| + (char *) NULL);
|
| +
|
| + note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
|
| + fname, psargs);
|
| + xfree (psargs);
|
| +
|
| + if (!note_data)
|
| + return NULL;
|
| + }
|
| +
|
| + /* Thread register information. */
|
| + thread_args.gdbarch = gdbarch;
|
| + thread_args.pid = ptid_get_pid (inferior_ptid);
|
| + thread_args.obfd = obfd;
|
| + thread_args.note_data = note_data;
|
| + thread_args.note_size = note_size;
|
| + thread_args.num_notes = 0;
|
| + thread_args.stop_signal = find_stop_signal ();
|
| + thread_args.collect = collect;
|
| + iterate_over_threads (linux_corefile_thread_callback, &thread_args);
|
| + note_data = thread_args.note_data;
|
| + if (!note_data)
|
| + return NULL;
|
| +
|
| + /* Auxillary vector. */
|
| + auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV,
|
| + NULL, &auxv);
|
| + if (auxv_len > 0)
|
| + {
|
| + note_data = elfcore_write_note (obfd, note_data, note_size,
|
| + "CORE", NT_AUXV, auxv, auxv_len);
|
| + xfree (auxv);
|
| +
|
| + if (!note_data)
|
| + return NULL;
|
| + }
|
| +
|
| + /* SPU information. */
|
| + note_data = linux_spu_make_corefile_notes (obfd, note_data, note_size);
|
| + if (!note_data)
|
| + return NULL;
|
| +
|
| + make_cleanup (xfree, note_data);
|
| + return note_data;
|
| +}
|
| +
|
| +static char *
|
| +linux_make_corefile_notes_1 (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
| +{
|
| + /* FIXME: uweigand/2011-10-06: Once all GNU/Linux architectures have been
|
| + converted to gdbarch_core_regset_sections, we no longer need to fall back
|
| + to the target method at this point. */
|
| +
|
| + if (!gdbarch_core_regset_sections (gdbarch))
|
| + return target_make_corefile_notes (obfd, note_size);
|
| + else
|
| + return linux_make_corefile_notes (gdbarch, obfd, note_size,
|
| + linux_collect_thread_registers);
|
| +}
|
| +
|
| /* To be called from the various GDB_OSABI_LINUX handlers for the
|
| various GNU/Linux architectures and machine types. */
|
|
|
| @@ -203,8 +856,16 @@ void
|
| linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
| {
|
| set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str);
|
| + set_gdbarch_info_proc (gdbarch, linux_info_proc);
|
| + set_gdbarch_find_memory_regions (gdbarch, linux_find_memory_regions);
|
| + set_gdbarch_make_corefile_notes (gdbarch, linux_make_corefile_notes_1);
|
| + set_gdbarch_has_shared_address_space (gdbarch,
|
| + linux_has_shared_address_space);
|
| }
|
|
|
| +/* Provide a prototype to silence -Wmissing-prototypes. */
|
| +extern initialize_file_ftype _initialize_linux_tdep;
|
| +
|
| void
|
| _initialize_linux_tdep (void)
|
| {
|
|
|