diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2e5cd0a687..e3d9f40d02 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,34 @@
+2018-09-07  John Baldwin  <jhb@FreeBSD.org>
+
+	* fbsd-tdep.c (KF_FLAGS, KF_OFFSET, KF_VNODE_TYPE, KF_SOCK_DOMAIN)
+	(KF_SOCK_TYPE, KF_SOCK_PROTOCOL, KF_SA_LOCAL, KF_SA_PEER)
+	(KINFO_FILE_TYPE_SOCKET, KINFO_FILE_TYPE_PIPE)
+	(KINFO_FILE_TYPE_FIFO, KINFO_FILE_TYPE_KQUEUE)
+	(KINFO_FILE_TYPE_CRYPTO, KINFO_FILE_TYPE_MQUEUE)
+	(KINFO_FILE_TYPE_SHM, KINFO_FILE_TYPE_SEM, KINFO_FILE_TYPE_PTS)
+	(KINFO_FILE_TYPE_PROCDESC, KINFO_FILE_FD_TYPE_ROOT)
+	(KINFO_FILE_FD_TYPE_JAIL, KINFO_FILE_FD_TYPE_TRACE)
+	(KINFO_FILE_FD_TYPE_CTTY, KINFO_FILE_FLAG_READ)
+	(KINFO_FILE_FLAG_WRITE, KINFO_FILE_FLAG_APPEND)
+	(KINFO_FILE_FLAG_ASYNC, KINFO_FILE_FLAG_FSYNC)
+	(KINFO_FILE_FLAG_NONBLOCK, KINFO_FILE_FLAG_DIRECT)
+	(KINFO_FILE_FLAG_HASLOCK, KINFO_FILE_FLAG_EXEC)
+	(KINFO_FILE_VTYPE_VREG, KINFO_FILE_VTYPE_VDIR)
+	(KINFO_FILE_VTYPE_VCHR, KINFO_FILE_VTYPE_VLNK)
+	(KINFO_FILE_VTYPE_VSOCK, KINFO_FILE_VTYPE_VFIFO, FBSD_AF_UNIX)
+	(FBSD_AF_INET, FBSD_AF_INET6, FBSD_SOCK_STREAM, FBSD_SOCK_DGRAM)
+	(FBSD_SOCK_SEQPACKET, FBSD_IPPROTO_ICMP, FBSD_IPPROTO_TCP)
+	(FBSD_IPPROTO_UDP, FBSD_IPPROTO_SCTP): New defines.
+	(struct fbsd_sockaddr_in, struct fbsd_sockaddr_in6)
+	(struct fbsd_sockaddr_un): New types.
+	(fbsd_file_fd, fbsd_file_type, fbsd_file_flags, fbsd_ipproto)
+	(fbsd_print_sockaddr_in, fbsd_print_sockaddr_in6)
+	(fbsd_print_socket, fbsd_core_info_proc_files): New functions.
+	(fbsd_core_info_proc): List open file descriptors for IP_FILES and
+	IP_ALL.
+	* fbsd-tdep.h (fbsd_file_fd, fbsd_file_type, fbsd_file_flags)
+	(fbsd_print_socket): New.
+
 2018-09-07  John Baldwin  <jhb@FreeBSD.org>
 
 	* defs.h (enum info_proc_what) [IP_FILES]: New value.
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 9e6d7276c4..a8b5b2f146 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -90,18 +90,115 @@
 #define	KF_STRUCTSIZE		0x0
 #define	KF_TYPE			0x4
 #define	KF_FD			0x8
+#define	KF_FLAGS		0x10
+#define	KF_OFFSET		0x18
+#define	KF_VNODE_TYPE		0x20
+#define	KF_SOCK_DOMAIN		0x24
+#define	KF_SOCK_TYPE		0x28
+#define	KF_SOCK_PROTOCOL	0x2c
+#define	KF_SA_LOCAL		0x30
+#define	KF_SA_PEER		0xb0
 #define	KF_PATH			0x170
 
 /* Constants for the 'kf_type' field in struct kinfo_file.  These
    match the KF_TYPE_* constants in <sys/user.h>.  */
 
 #define	KINFO_FILE_TYPE_VNODE	1
+#define	KINFO_FILE_TYPE_SOCKET	2
+#define	KINFO_FILE_TYPE_PIPE	3
+#define	KINFO_FILE_TYPE_FIFO	4
+#define	KINFO_FILE_TYPE_KQUEUE	5
+#define	KINFO_FILE_TYPE_CRYPTO	6
+#define	KINFO_FILE_TYPE_MQUEUE	7
+#define	KINFO_FILE_TYPE_SHM	8
+#define	KINFO_FILE_TYPE_SEM	9
+#define	KINFO_FILE_TYPE_PTS	10
+#define	KINFO_FILE_TYPE_PROCDESC 11
 
 /* Special values for the 'kf_fd' field in struct kinfo_file.  These
    match the KF_FD_TYPE_* constants in <sys/user.h>.  */
 
 #define	KINFO_FILE_FD_TYPE_CWD	-1
+#define	KINFO_FILE_FD_TYPE_ROOT	-2
+#define	KINFO_FILE_FD_TYPE_JAIL	-3
+#define	KINFO_FILE_FD_TYPE_TRACE -4
 #define	KINFO_FILE_FD_TYPE_TEXT	-5
+#define	KINFO_FILE_FD_TYPE_CTTY	-6
+
+/* Flags in the 'kf_flags' field in struct kinfo_file.  These match
+   the KF_FLAG_* constants in <sys/user.h>.  */
+
+#define	KINFO_FILE_FLAG_READ		0x00000001
+#define	KINFO_FILE_FLAG_WRITE		0x00000002
+#define	KINFO_FILE_FLAG_APPEND		0x00000004
+#define	KINFO_FILE_FLAG_ASYNC		0x00000008
+#define	KINFO_FILE_FLAG_FSYNC		0x00000010
+#define	KINFO_FILE_FLAG_NONBLOCK	0x00000020
+#define	KINFO_FILE_FLAG_DIRECT		0x00000040
+#define	KINFO_FILE_FLAG_HASLOCK		0x00000080
+#define	KINFO_FILE_FLAG_EXEC		0x00004000
+
+/* Constants for the 'kf_vnode_type' field in struct kinfo_file.
+   These match the KF_VTYPE_* constants in <sys/user.h>.  */
+
+#define	KINFO_FILE_VTYPE_VREG	1
+#define	KINFO_FILE_VTYPE_VDIR	2
+#define	KINFO_FILE_VTYPE_VCHR	4
+#define	KINFO_FILE_VTYPE_VLNK	5
+#define	KINFO_FILE_VTYPE_VSOCK	6
+#define	KINFO_FILE_VTYPE_VFIFO	7
+
+/* Constants for socket address families.  These match AF_* constants
+   in <sys/socket.h>.  */
+
+#define	FBSD_AF_UNIX		1
+#define	FBSD_AF_INET		2
+#define	FBSD_AF_INET6		28
+
+/* Constats for socket types.  These match SOCK_* constants in
+   <sys/socket.h>.  */
+
+#define	FBSD_SOCK_STREAM	1
+#define	FBSD_SOCK_DGRAM		2
+#define	FBSD_SOCK_SEQPACKET	5
+
+/* Constants for IP protocols.  These match IPPROTO_* constants in
+   <netinet/in.h>.  */
+
+#define	FBSD_IPPROTO_ICMP	1
+#define	FBSD_IPPROTO_TCP	6
+#define	FBSD_IPPROTO_UDP	17
+#define	FBSD_IPPROTO_SCTP	132
+
+/* Socket address structures.  These have the same layout on all
+   FreeBSD architectures.  In addition, multibyte fields such as IP
+   addresses are always stored in network byte order.  */
+
+struct fbsd_sockaddr_in
+{
+  uint8_t sin_len;
+  uint8_t sin_family;
+  uint8_t sin_port[2];
+  uint8_t sin_addr[4];
+  char sin_zero[8];
+};
+
+struct fbsd_sockaddr_in6
+{
+  uint8_t sin6_len;
+  uint8_t sin6_family;
+  uint8_t sin6_port[2];
+  uint32_t sin6_flowinfo;
+  uint8_t sin6_addr[16];
+  uint32_t sin6_scope_id;
+};
+
+struct fbsd_sockaddr_un
+{
+  uint8_t sun_len;
+  uint8_t sun_family;
+  char sun_path[104];
+};
 
 /* Number of 32-bit words in a signal set.  This matches _SIG_WORDS in
    <sys/_sigset.h> and is the same value on all architectures.  */
@@ -645,6 +742,341 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
   return note_data;
 }
 
+/* Helper function to generate the file descriptor description for a
+   single open file in 'info proc files'.  */
+
+const char *
+fbsd_file_fd (int kf_fd)
+{
+  switch (kf_fd)
+    {
+    case KINFO_FILE_FD_TYPE_CWD:
+      return "cwd";
+    case KINFO_FILE_FD_TYPE_ROOT:
+      return "root";
+    case KINFO_FILE_FD_TYPE_JAIL:
+      return "jail";
+    case KINFO_FILE_FD_TYPE_TRACE:
+      return "trace";
+    case KINFO_FILE_FD_TYPE_TEXT:
+      return "text";
+    case KINFO_FILE_FD_TYPE_CTTY:
+      return "ctty";
+    default:
+      return int_string (kf_fd, 10, 1, 0, 0);
+    }
+}
+
+/* Helper function to generate the file type for a single open file in
+   'info proc files'.  */
+
+const char *
+fbsd_file_type (int kf_type, int kf_vnode_type)
+{
+  switch (kf_type)
+    {
+    case KINFO_FILE_TYPE_VNODE:
+      switch (kf_vnode_type)
+	{
+	case KINFO_FILE_VTYPE_VREG:
+	  return "file";
+	case KINFO_FILE_VTYPE_VDIR:
+	  return "dir";
+	case KINFO_FILE_VTYPE_VCHR:
+	  return "chr";
+	case KINFO_FILE_VTYPE_VLNK:
+	  return "link";
+	case KINFO_FILE_VTYPE_VSOCK:
+	  return "socket";
+	case KINFO_FILE_VTYPE_VFIFO:
+	  return "fifo";
+	default:
+	  {
+	    char *str = get_print_cell ();
+
+	    xsnprintf (str, PRINT_CELL_SIZE, "vn:%d", kf_vnode_type);
+	    return str;
+	  }
+	}
+    case KINFO_FILE_TYPE_SOCKET:
+      return "socket";
+    case KINFO_FILE_TYPE_PIPE:
+      return "pipe";
+    case KINFO_FILE_TYPE_FIFO:
+      return "fifo";
+    case KINFO_FILE_TYPE_KQUEUE:
+      return "kqueue";
+    case KINFO_FILE_TYPE_CRYPTO:
+      return "crypto";
+    case KINFO_FILE_TYPE_MQUEUE:
+      return "mqueue";
+    case KINFO_FILE_TYPE_SHM:
+      return "shm";
+    case KINFO_FILE_TYPE_SEM:
+      return "sem";
+    case KINFO_FILE_TYPE_PTS:
+      return "pts";
+    case KINFO_FILE_TYPE_PROCDESC:
+      return "proc";
+    default:
+      return int_string (kf_type, 10, 1, 0, 0);
+    }
+}
+
+/* Helper function to generate the file flags for a single open file in
+   'info proc files'.  */
+
+const char *
+fbsd_file_flags (int kf_flags)
+{
+  static char file_flags[10];
+
+  file_flags[0] = (kf_flags & KINFO_FILE_FLAG_READ) ? 'r' : '-';
+  file_flags[1] = (kf_flags & KINFO_FILE_FLAG_WRITE) ? 'w' : '-';
+  file_flags[2] = (kf_flags & KINFO_FILE_FLAG_EXEC) ? 'x' : '-';
+  file_flags[3] = (kf_flags & KINFO_FILE_FLAG_APPEND) ? 'a' : '-';
+  file_flags[4] = (kf_flags & KINFO_FILE_FLAG_ASYNC) ? 's' : '-';
+  file_flags[5] = (kf_flags & KINFO_FILE_FLAG_FSYNC) ? 'f' : '-';
+  file_flags[6] = (kf_flags & KINFO_FILE_FLAG_NONBLOCK) ? 'n' : '-';
+  file_flags[7] = (kf_flags & KINFO_FILE_FLAG_DIRECT) ? 'd' : '-';
+  file_flags[8] = (kf_flags & KINFO_FILE_FLAG_HASLOCK) ? 'l' : '-';
+  file_flags[9] = '\0';
+
+  return file_flags;
+}
+
+/* Helper function to generate the name of an IP protocol.  */
+
+static const char *
+fbsd_ipproto (int protocol)
+{
+  switch (protocol)
+    {
+    case FBSD_IPPROTO_ICMP:
+      return "icmp";
+    case FBSD_IPPROTO_TCP:
+      return "tcp";
+    case FBSD_IPPROTO_UDP:
+      return "udp";
+    case FBSD_IPPROTO_SCTP:
+      return "sctp";
+    default:
+      {
+	char *str = get_print_cell ();
+
+	xsnprintf (str, PRINT_CELL_SIZE, "ip<%d>", protocol);
+	return str;
+      }
+    }
+}
+
+/* Helper function to print out an IPv4 socket address.  The address
+   is formatted similar to inet_ntoa.  */
+
+static void
+fbsd_print_sockaddr_in (void *sockaddr)
+{
+  struct fbsd_sockaddr_in *sin =
+    reinterpret_cast<struct fbsd_sockaddr_in *>(sockaddr);
+
+  printf_filtered ("%u.%u.%u.%u:%u", sin->sin_addr[0], sin->sin_addr[1],
+		   sin->sin_addr[2], sin->sin_addr[3],
+		   (sin->sin_port[0] << 8) | sin->sin_port[1]);
+}
+
+/* Helper function to print out an IPv6 socket address.  The address
+   is formatted similar to inet_ntop.  */
+
+static void
+fbsd_print_sockaddr_in6 (void *sockaddr)
+{
+  struct fbsd_sockaddr_in6 *sin6 =
+    reinterpret_cast<struct fbsd_sockaddr_in6 *>(sockaddr);
+  uint16_t words[ARRAY_SIZE(sin6->sin6_addr) / 2];
+
+  /* Populate the array of 16-bit words from network-order bytes.  */
+  for (int i = 0; i < ARRAY_SIZE(words); i++)
+    words[i] = (sin6->sin6_addr[i * 2] << 8) | sin6->sin6_addr[i * 2 + 1];
+
+  /* Find the longest run of zero words.  */
+  int best, bestlen, current, len;
+
+  best = -1;
+  bestlen = 0;
+  current = -1;
+  len = 0;
+  for (int i = 0; i < ARRAY_SIZE(words); i++)
+    {
+      if (words[i] == 0)
+	{
+	  if (current >= 0)
+	    len++;
+	  else
+	    {
+	      current = i;
+	      len = 1;
+	    }
+	}
+      else
+	{
+	  if (current >= 0 && len > bestlen)
+	    {
+	      best = current;
+	      bestlen = len;
+	    }
+	  current = -1;
+	  len = 0;
+	}
+    }
+  if (current >= 0 && len > bestlen)
+    {
+      best = current;
+      bestlen = len;
+    }
+  if (bestlen < 2)
+    best = -1;
+
+  for (int i = 0; i < ARRAY_SIZE(words); i++)
+    {
+      if (best >= 0 && i >= best && i < best + bestlen)
+	{
+	  if (i == best || i == ARRAY_SIZE(words) - 1)
+	    printf_filtered (":");
+	}
+      else
+	{
+	  if (i != 0)
+	    printf_filtered (":");
+	  printf_filtered ("%x", words[i]);
+	}
+    }
+  printf_filtered (".%u", (sin6->sin6_port[0] << 8) | sin6->sin6_port[1]);
+}
+
+/* Helper function to print out a description of a socket for 'info
+   proc files'.  */
+
+void
+fbsd_print_socket (int kf_sock_domain, int kf_sock_type, int kf_sock_protocol,
+		   void *kf_sa_local, void *kf_sa_peer)
+{
+  switch (kf_sock_domain)
+    {
+    case FBSD_AF_UNIX:
+      {
+	switch (kf_sock_type)
+	  {
+	  case FBSD_SOCK_STREAM:
+	    printf_filtered ("unix stream:");
+	    break;
+	  case FBSD_SOCK_DGRAM:
+	    printf_filtered ("unix dgram:");
+	    break;
+	  case FBSD_SOCK_SEQPACKET:
+	    printf_filtered ("unix seqpacket:");
+	    break;
+	  default:
+	    printf_filtered ("unix <%d>:", kf_sock_type);
+	    break;
+	  }
+
+	/* For local sockets, print out the first non-nul path rather
+	   than both paths.  */
+	struct fbsd_sockaddr_un *sun =
+	  reinterpret_cast<struct fbsd_sockaddr_un *>(kf_sa_local);
+	if (sun->sun_path[0] == 0)
+	  sun = reinterpret_cast<struct fbsd_sockaddr_un *>(kf_sa_peer);
+	printf_filtered ("%s", sun->sun_path);
+	break;
+      }
+    case FBSD_AF_INET:
+      printf_filtered ("%s4 ", fbsd_ipproto (kf_sock_protocol));
+      fbsd_print_sockaddr_in (kf_sa_local);
+      printf_filtered (" -> ");
+      fbsd_print_sockaddr_in (kf_sa_peer);
+      break;
+    case FBSD_AF_INET6:
+      printf_filtered ("%s6 ", fbsd_ipproto (kf_sock_protocol));
+      fbsd_print_sockaddr_in6 (kf_sa_local);
+      printf_filtered (" -> ");
+      fbsd_print_sockaddr_in6 (kf_sa_peer);
+      break;
+    }
+}
+
+/* Implement "info proc files" for a corefile.  */
+
+static void
+fbsd_core_info_proc_files (struct gdbarch *gdbarch)
+{
+  asection *section;
+  unsigned char *descdata, *descend;
+  size_t note_size;
+
+  section = bfd_get_section_by_name (core_bfd, ".note.freebsdcore.files");
+  if (section == NULL)
+    {
+      warning (_("unable to find open files in core file"));
+      return;
+    }
+
+  note_size = bfd_get_section_size (section);
+  if (note_size < 4)
+    error (_("malformed core note - too short for header"));
+
+  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.data ();
+  descend = descdata + note_size;
+
+  /* Skip over the structure size.  */
+  descdata += 4;
+
+  printf_filtered (_("Open files:\n\n"));
+  printf_filtered ("  %6s %6s %10s %9s %s\n",
+		   "FD", "Type", "Offset", "Flags  ", "Name");
+
+  while (descdata + KF_PATH < descend)
+    {
+      LONGEST fd, flags, offset, type, vnode_type;
+      ULONGEST structsize;
+
+      structsize = bfd_get_32 (core_bfd, descdata + KF_STRUCTSIZE);
+      if (structsize < KF_PATH)
+	error (_("malformed core note - vmmap entry too small"));
+
+      type = bfd_get_signed_32 (core_bfd, descdata + KF_TYPE);
+      fd = bfd_get_signed_32 (core_bfd, descdata + KF_FD);
+      flags = bfd_get_signed_32 (core_bfd, descdata + KF_FLAGS);
+      offset = bfd_get_signed_64 (core_bfd, descdata + KF_OFFSET);
+      vnode_type = bfd_get_signed_32 (core_bfd, descdata + KF_VNODE_TYPE);
+      printf_filtered ("  %6s %6s %10s %8s ",
+		       fbsd_file_fd (fd),
+		       fbsd_file_type (type, vnode_type),
+		       offset > -1 ? hex_string (offset) : "-",
+		       fbsd_file_flags (flags));
+      if (type == KINFO_FILE_TYPE_SOCKET)
+	{
+	  LONGEST sock_domain, sock_type, sock_protocol;
+
+	  sock_domain = bfd_get_signed_32 (core_bfd, descdata + KF_SOCK_DOMAIN);
+	  sock_type = bfd_get_signed_32 (core_bfd, descdata + KF_SOCK_TYPE);
+	  sock_protocol = bfd_get_signed_32 (core_bfd,
+					     descdata + KF_SOCK_PROTOCOL);
+	  fbsd_print_socket (sock_domain, sock_type, sock_protocol,
+			     descdata + KF_SA_LOCAL, descdata + KF_SA_PEER);
+	}
+      else
+	printf_filtered ("%s", descdata + KF_PATH);
+      printf_filtered ("\n");
+
+      descdata += structsize;
+    }
+}
+
 /* Helper function to generate mappings flags for a single VM map
    entry in 'info proc mappings'.  */
 
@@ -995,6 +1427,7 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
   bool do_cmdline = false;
   bool do_cwd = false;
   bool do_exe = false;
+  bool do_files = false;
   bool do_mappings = false;
   bool do_status = false;
   int pid;
@@ -1022,10 +1455,14 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
     case IP_CWD:
       do_cwd = true;
       break;
+    case IP_FILES:
+      do_files = true;
+      break;
     case IP_ALL:
       do_cmdline = true;
       do_cwd = true;
       do_exe = true;
+      do_files = true;
       do_mappings = true;
       do_status = true;
       break;
@@ -1065,6 +1502,8 @@ fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
       else
 	warning (_("unable to read executable path name"));
     }
+  if (do_files)
+    fbsd_core_info_proc_files (gdbarch);
   if (do_mappings)
     fbsd_core_info_proc_mappings (gdbarch);
   if (do_status)
diff --git a/gdb/fbsd-tdep.h b/gdb/fbsd-tdep.h
index 0b293e5a25..0e0ba57be8 100644
--- a/gdb/fbsd-tdep.h
+++ b/gdb/fbsd-tdep.h
@@ -22,6 +22,37 @@
 
 extern void fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
 
+/* Helper function to generate the file descriptor description for a
+   single open file in 'info proc files'.  The KF_FD parameter should
+   contain the value of the 'kf_fd' field from a 'struct
+   kinfo_file'.  */
+
+extern const char *fbsd_file_fd (int kf_fd);
+
+/* Helper function to generate the file type for a single open file in
+   'info proc files'.  The KF_TYPE and KF_VNODE_TYPE parameters should
+   contain the values of the corresponding fields in a 'struct
+   kinfo_file'.  */
+
+extern const char *fbsd_file_type (int kf_type, int kf_vnode_type);
+
+/* Helper function to generate the file flags for a single open file
+   in 'info proc files'.  The KF_FLAGS parameter should contain the
+   value of the 'kf_flags' field from a 'struct kinfo_file'.  */
+
+extern const char *fbsd_file_flags (int kf_flags);
+
+/* Helper function to print out a description of a socket for 'info
+   proc files'.  The KF_SOCK_DOMAIN, KF_SOCK_TYPE, and
+   KF_SOCK_PROTOCOL, parameters should contain the value of the
+   corresponding fields in a 'struct kinfo_file'.  The KF_SA_LOCAL and
+   KF_SA_PEER should contain pointers to the corresponding fields in a
+   'struct kinfo_file'.  */
+
+extern void fbsd_print_socket (int kf_sock_domain, int kf_sock_type,
+			       int kf_sock_protocol, void *kf_sa_local,
+			       void *kf_sa_peer);
+
 /* Helper function to generate mappings flags for a single VM map
    entry in 'info proc mappings'.  The KVE_FLAGS and KVE_PROTECTION
    parameters should contain the values of the corresponding fields in
