]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Linux core prstatus support
authorAlan Modra <amodra@gmail.com>
Thu, 21 Jan 2016 09:24:32 +0000 (19:54 +1030)
committerPedro Alves <palves@redhat.com>
Thu, 21 Jan 2016 11:45:37 +0000 (11:45 +0000)
This and the next patch are the first steps towards making gcore
support writing NT_PRSTATUS on remote/cross targets.  I'm not going to
commit this one and I'm hoping someone from the gdb camp will run with
it as I'm going to be busy with other things in the near future.

bfd/elf-bfd.h
bfd/elf-linux-core.h
bfd/elf.c

index 6a04f044e78bcbf5975ca88987feb878865cbea5..b0f5026a5f39e39b6051263d30ece8441646acd7 100644 (file)
@@ -2435,6 +2435,35 @@ extern char *elfcore_write_linux_prpsinfo64
 extern char *elfcore_write_ppc_linux_prpsinfo32
   (bfd *, char *, int *, const struct elf_internal_linux_prpsinfo *);
 
+struct elf_internal_linux_prstatus
+{
+  struct elf_internal_siginfo
+  {
+    int si_signo;
+    int si_code;
+    int si_errno;
+  } pr_info;
+  int pr_cursig;
+  bfd_uint64_t pr_sigpend, pr_sighold;
+  int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+  struct elf_internal_timeval
+  {
+    long tv_sec;
+    long tv_usec;
+  } pr_utime, pr_stime, pr_cutime, pr_cstime;
+  void *pr_reg;
+  int pr_reg_size;
+  int pr_fpvalid;
+};
+
+/* Linux/most 32-bit archs.  */
+extern char *elfcore_write_linux_prstatus32
+  (bfd *, char *, int *, const struct elf_internal_linux_prstatus *);
+
+/* Linux/most 64-bit archs.  */
+extern char *elfcore_write_linux_prstatus64
+  (bfd *, char *, int *, const struct elf_internal_linux_prstatus *);
+
 extern bfd *_bfd_elf32_bfd_from_remote_memory
   (bfd *templ, bfd_vma ehdr_vma, bfd_size_type size, bfd_vma *loadbasep,
    int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type));
index 48fd5aeb559af61836cc5926abc6321557f79624..3838ad16d708cbda5e5f12b8156da870630b2a7c 100644 (file)
@@ -1,4 +1,4 @@
-/* Definitions for PRPSINFO structures under ELF on GNU/Linux.
+/* Definitions for PRPSINFO and PRSTATUS structures under ELF on GNU/Linux.
    Copyright (C) 2013-2016 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -120,4 +120,116 @@ swap_linux_prpsinfo64_out (bfd *obfd,
   strncpy (to->pr_psargs, from->pr_psargs, sizeof (to->pr_psargs));
 }
 
+/* PRSTATUS structs.  */
+
+struct elf_external_linux_prstatus32
+{
+  char pr_info[12];
+  char pr_cursig[2];
+  char pad[2];
+  char pr_sigpend[4];
+  char pr_sighold[4];
+  char pr_pid[4];
+  char pr_ppid[4];
+  char pr_pgrp[4];
+  char pr_sid[4];
+  char pr_utime[8];
+  char pr_stime[8];
+  char pr_cutime[8];
+  char pr_cstime[8];
+  /* Variable size "char pr_reg[]" goes here.  */
+  char pr_fpvalid[4];
+};
+
+struct elf_external_linux_prstatus64
+{
+  char pr_info[12];
+  char pr_cursig[2];
+  char pad[2];
+  char pr_sigpend[8];
+  char pr_sighold[8];
+  char pr_pid[4];
+  char pr_ppid[4];
+  char pr_pgrp[4];
+  char pr_sid[4];
+  char pr_utime[16];
+  char pr_stime[16];
+  char pr_cutime[16];
+  char pr_cstime[16];
+  /* Variable size "char pr_reg[]" goes here.  */
+  char pr_fpvalid[4];
+  char pad2[4];
+};
+
+/* Helper function to copy an elf_internal_linux_prpstatus
+   to an elf_external_linux_prpsinfo32 in target endian.
+   FROM->pr_reg is already in target endian.  */
+
+static inline void
+swap_linux_prstatus32_out (bfd *obfd,
+                          const struct elf_internal_linux_prstatus *from,
+                          void *to)
+{
+  struct elf_external_linux_prstatus32 *dest;
+
+  dest = (struct elf_external_linux_prstatus32 *) to;
+  bfd_put_32 (obfd, from->pr_info.si_signo, dest->pr_info + 0);
+  bfd_put_32 (obfd, from->pr_info.si_code, dest->pr_info + 4);
+  bfd_put_32 (obfd, from->pr_info.si_errno, dest->pr_info + 8);
+  bfd_put_16 (obfd, from->pr_cursig, dest->pr_cursig);
+  memset (dest->pad, 0, sizeof (dest->pad));
+  bfd_put_32 (obfd, from->pr_sigpend, dest->pr_sigpend);
+  bfd_put_32 (obfd, from->pr_sighold, dest->pr_sighold);
+  bfd_put_32 (obfd, from->pr_pid, dest->pr_pid);
+  bfd_put_32 (obfd, from->pr_ppid, dest->pr_ppid);
+  bfd_put_32 (obfd, from->pr_pgrp, dest->pr_pgrp);
+  bfd_put_32 (obfd, from->pr_sid, dest->pr_sid);
+  bfd_put_32 (obfd, from->pr_utime.tv_sec, dest->pr_utime + 0);
+  bfd_put_32 (obfd, from->pr_utime.tv_usec, dest->pr_utime + 4);
+  bfd_put_32 (obfd, from->pr_stime.tv_sec, dest->pr_stime + 0);
+  bfd_put_32 (obfd, from->pr_stime.tv_usec, dest->pr_stime + 4);
+  bfd_put_32 (obfd, from->pr_cutime.tv_sec, dest->pr_cutime + 0);
+  bfd_put_32 (obfd, from->pr_cutime.tv_usec, dest->pr_cutime + 4);
+  bfd_put_32 (obfd, from->pr_cstime.tv_sec, dest->pr_cstime + 0);
+  bfd_put_32 (obfd, from->pr_cstime.tv_usec, dest->pr_cstime + 4);
+  memcpy (dest->pr_fpvalid, from->pr_reg, from->pr_reg_size);
+  bfd_put_32 (obfd, from->pr_fpvalid, dest->pr_fpvalid + from->pr_reg_size);
+}
+
+/* Helper function to copy an elf_internal_linux_prpstatus
+   to an elf_external_linux_prpsinfo64 in target endian.
+   FROM->pr_reg is already in target endian.  */
+
+static inline void
+swap_linux_prstatus64_out (bfd *obfd,
+                          const struct elf_internal_linux_prstatus *from,
+                          void *to)
+{
+  struct elf_external_linux_prstatus64 *dest;
+
+  dest = (struct elf_external_linux_prstatus64 *) to;
+  bfd_put_32 (obfd, from->pr_info.si_signo, dest->pr_info + 0);
+  bfd_put_32 (obfd, from->pr_info.si_code, dest->pr_info + 4);
+  bfd_put_32 (obfd, from->pr_info.si_errno, dest->pr_info + 8);
+  bfd_put_16 (obfd, from->pr_cursig, dest->pr_cursig);
+  memset (dest->pad, 0, sizeof (dest->pad));
+  bfd_put_64 (obfd, from->pr_sigpend, dest->pr_sigpend);
+  bfd_put_64 (obfd, from->pr_sighold, dest->pr_sighold);
+  bfd_put_32 (obfd, from->pr_pid, dest->pr_pid);
+  bfd_put_32 (obfd, from->pr_ppid, dest->pr_ppid);
+  bfd_put_32 (obfd, from->pr_pgrp, dest->pr_pgrp);
+  bfd_put_32 (obfd, from->pr_sid, dest->pr_sid);
+  bfd_put_64 (obfd, from->pr_utime.tv_sec, dest->pr_utime + 0);
+  bfd_put_64 (obfd, from->pr_utime.tv_usec, dest->pr_utime + 8);
+  bfd_put_64 (obfd, from->pr_stime.tv_sec, dest->pr_stime + 0);
+  bfd_put_64 (obfd, from->pr_stime.tv_usec, dest->pr_stime + 8);
+  bfd_put_64 (obfd, from->pr_cutime.tv_sec, dest->pr_cutime + 0);
+  bfd_put_64 (obfd, from->pr_cutime.tv_usec, dest->pr_cutime + 8);
+  bfd_put_64 (obfd, from->pr_cstime.tv_sec, dest->pr_cstime + 0);
+  bfd_put_64 (obfd, from->pr_cstime.tv_usec, dest->pr_cstime + 8);
+  memcpy (dest->pr_fpvalid, from->pr_reg, from->pr_reg_size);
+  bfd_put_32 (obfd, from->pr_fpvalid, dest->pr_fpvalid + from->pr_reg_size);
+  memset (dest->pad2 + from->pr_reg_size, 0, sizeof (dest->pad2));
+}
+
 #endif
index 74c2f2d33a46057fb1551a5f50190cf001ff1779..16d315df2ca2518da326fc2a67d17b7e3dd37122 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9808,6 +9808,40 @@ elfcore_write_linux_prpsinfo64
                             "CORE", NT_PRPSINFO, &data, sizeof (data));
 }
 
+char *
+elfcore_write_linux_prstatus32
+  (bfd *obfd,
+   char *buf,
+   int *bufsize,
+   const struct elf_internal_linux_prstatus *prstatus)
+{
+  size_t datasize = (prstatus->pr_reg_size
+                    + sizeof (struct elf_external_linux_prstatus32));
+  char data[1144];
+
+  BFD_ASSERT (sizeof (data) >= datasize);
+  swap_linux_prstatus32_out (obfd, prstatus, data);
+  return elfcore_write_note (obfd, buf, bufsize,
+                            "CORE", NT_PRSTATUS, data, datasize);
+}
+
+char *
+elfcore_write_linux_prstatus64
+  (bfd *obfd,
+   char *buf,
+   int *bufsize,
+   const struct elf_internal_linux_prstatus *prstatus)
+{
+  size_t datasize = (prstatus->pr_reg_size
+                    + sizeof (struct elf_external_linux_prstatus64));
+  char data[1144]; /* Size of ia64 prstatus.  */
+
+  BFD_ASSERT (sizeof (data) >= datasize);
+  swap_linux_prstatus64_out (obfd, prstatus, data);
+  return elfcore_write_note (obfd, buf, bufsize,
+                            "CORE", NT_PRSTATUS, data, datasize);
+}
+
 char *
 elfcore_write_prstatus (bfd *abfd,
                        char *buf,