This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Fuchsia amd64 port


On 12/14/2016 11:33 AM, Doug Evans via gdb-patches wrote:
diff --git a/gdb/amd64-fuchsia-tdep.c b/gdb/amd64-fuchsia-tdep.c
new file mode 100644
index 0000000..d40852a
--- /dev/null
+++ b/gdb/amd64-fuchsia-tdep.c
@@ -0,0 +1,83 @@
+/* Target-dependent code for Fuchsia x86-64.
+
+   Copyright (C) 2001-2016 Free Software Foundation, Inc.

I suppose this is 2001-2016 because it is heavily based on existing amd64 code?

+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see
<http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "osabi.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "reggroups.h"
+#include "regset.h"
+#include "parser-defs.h"
+#include "user-regs.h"
+#include "amd64-fuchsia-tdep.h"
+#include "fuchsia-tdep.h"
+#include "amd64-tdep.h"
+
+static int
+amd64_fuchsia_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                 struct reggroup *group)
+{
+  return i386_register_reggroup_p (gdbarch, regnum, group);
+}
+
+static void
+amd64_fuchsia_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct target_desc *tdesc = info.target_desc;
+  struct tdesc_arch_data *tdesc_data
+    = (struct tdesc_arch_data *) info.tdep_info;
+
+  gdb_assert (tdesc_data);
+
+  amd64_init_abi (info, gdbarch);
+
+  fuchsia_init_abi (info, gdbarch);
+
+  tdep->register_reggroup_p = amd64_fuchsia_register_reggroup_p;
+
+  /* Displaced stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch,
+                    amd64_displaced_step_copy_insn);
+  set_gdbarch_displaced_step_fixup (gdbarch, amd64_displaced_step_fixup);
+  set_gdbarch_displaced_step_free_closure (gdbarch,
+                       simple_displaced_step_free_closure);
+  set_gdbarch_displaced_step_location (gdbarch,
+                       fuchsia_displaced_step_location);
+
+  // TODO:
+  // - set_gdbarch_handle_segmentation_fault
+  //   to display extra info for MPX boundary violations.
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern void _initialize_amd64_fuchsia_tdep (void);
+
+void
+_initialize_amd64_fuchsia_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
+                  fuchsia_osabi_sniffer);
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
+              GDB_OSABI_FUCHSIA, amd64_fuchsia_init_abi);
+}
diff --git a/gdb/amd64-fuchsia-tdep.h b/gdb/amd64-fuchsia-tdep.h
new file mode 100644
index 0000000..006d048
--- /dev/null
+++ b/gdb/amd64-fuchsia-tdep.h
@@ -0,0 +1,33 @@
+/* Target-dependent code for Fuchsia AMD64.
+
+   Copyright (C) 2006-2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see
<http://www.gnu.org/licenses/>.  */
+
+#ifndef AMD64_FUCHSIA_TDEP_H
+#define AMD64_FUCHSIA_TDEP_H
+
+/* Total number of registers for Fuchsia.  */
+#define AMD64_FUCHSIA_NUM_REGS (AMD64_ZMM31H_REGNUM + 1)
+
+/* Fuchsia target description.  */ // TODO
+extern struct target_desc *tdesc_amd64_fuchsia;
+extern struct target_desc *tdesc_amd64_avx_fuchsia;
+extern struct target_desc *tdesc_amd64_mpx_fuchsia;
+extern struct target_desc *tdesc_amd64_avx_mpx_fuchsia;
+extern struct target_desc *tdesc_amd64_avx512_fuchsia;
+
+#endif /* amd64-fuchsia-tdep.h */
diff --git a/gdb/auxv.c b/gdb/auxv.c
index de9205d..203b814 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -331,7 +331,7 @@ auxv_inferior_data_cleanup (struct inferior *inf,
void *arg)

 /* Invalidate INF's auxv cache.  */

-static void
+void
 invalidate_auxv_cache_inf (struct inferior *inf)
 {
   auxv_inferior_data_cleanup (inf, NULL);
diff --git a/gdb/auxv.h b/gdb/auxv.h
index 916f674..57099e9 100644
--- a/gdb/auxv.h
+++ b/gdb/auxv.h
@@ -46,6 +46,11 @@ extern int target_auxv_parse (struct target_ops *ops,
 extern int target_auxv_search (struct target_ops *ops,
                    CORE_ADDR match, CORE_ADDR *valp);

+/* Invalidate INF's auxv cache.  */
+
+struct inferior;
+extern void invalidate_auxv_cache_inf (struct inferior *inf);
+
 /* Print a description of a single AUXV entry on the specified file.  */
 enum auxv_format { AUXV_FORMAT_DEC, AUXV_FORMAT_HEX, AUXV_FORMAT_STR };

diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 3a1ea6f..502a46b 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -669,6 +669,11 @@ x86_64-*-dicos*)
 x86_64-*-elf*)
     gdb_target_obs="amd64-tdep.o i386-tdep.o i387-tdep.o"
     ;;
+x86_64-*-fuchsia*)
+    gdb_target_obs="amd64-tdep.o amd64-fuchsia-tdep.o \
+            i386-tdep.o i387-tdep.o \
+            solib-svr4.o symfile-mem.o fuchsia-tdep.o"
+    ;;
 x86_64-*-linux*)
     # Target: GNU/Linux x86-64
     gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o i386-tdep.o \
@@ -721,6 +726,7 @@ esac
 case "${targ}" in
 *-*-freebsd* | *-*-kfreebsd*-gnu)
         gdb_osabi=GDB_OSABI_FREEBSD_ELF ;;
+*-*-fuchsia*)    gdb_osabi=GDB_OSABI_FUCHSIA ;;
 *-*-linux* | *-*-uclinux*)
         gdb_osabi=GDB_OSABI_LINUX ;;
 *-*-nto*)    gdb_osabi=GDB_OSABI_QNXNTO ;;
diff --git a/gdb/defs.h b/gdb/defs.h
index 3d21f62..7dfccfd 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -593,6 +593,7 @@ enum gdb_osabi
   GDB_OSABI_LYNXOS178,
   GDB_OSABI_NEWLIB,
   GDB_OSABI_SDE,
+  GDB_OSABI_FUCHSIA,

   GDB_OSABI_INVALID        /* keep this last */
 };
diff --git a/gdb/fuchsia-tdep.c b/gdb/fuchsia-tdep.c
new file mode 100644
index 0000000..4dfd78b
--- /dev/null
+++ b/gdb/fuchsia-tdep.c
@@ -0,0 +1,744 @@
+/* Target-dependent code for Fuchsia, architecture independent.
+
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see
<http://www.gnu.org/licenses/>.  */
+
+/* TODO: This is taken from linux-tdep.c.
+   Converting it to fuchsia is a work-in-progress.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "fuchsia-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 "arch-utils.h"
+#include "gdb_obstack.h"
+#include "observer.h"
+#include "objfiles.h"
+#include "infcall.h"
+#include "gdbcmd.h"
+#include "gdb_regex.h"
+#include "solib.h"
+#include "solib-svr4.h"
+#include "solist.h"
+#include "common/enum-flags.h"
+
+#include <ctype.h>
+
+static struct target_so_ops fuchsia_so_ops;
+
+/* Signal numbers of the Fuchsia kernel.
+   TODO: Work-in-progress.  */
+
+enum
+  {
+    FUCHSIA_SIGHUP = 1,
+    FUCHSIA_SIGINT = 2,
+    FUCHSIA_SIGQUIT = 3,
+    FUCHSIA_SIGILL = 4,
+    FUCHSIA_SIGTRAP = 5,
+    FUCHSIA_SIGABRT = 6,
+    FUCHSIA_SIGIOT = 6,
+    FUCHSIA_SIGBUS = 7,
+    FUCHSIA_SIGFPE = 8,
+    FUCHSIA_SIGKILL = 9,
+    FUCHSIA_SIGUSR1 = 10,
+    FUCHSIA_SIGSEGV = 11,
+    FUCHSIA_SIGUSR2 = 12,
+    FUCHSIA_SIGPIPE = 13,
+    FUCHSIA_SIGALRM = 14,
+    FUCHSIA_SIGTERM = 15,
+    FUCHSIA_SIGSTKFLT = 16,
+    FUCHSIA_SIGCHLD = 17,
+    FUCHSIA_SIGCONT = 18,
+    FUCHSIA_SIGSTOP = 19,
+    FUCHSIA_SIGTSTP = 20,
+    FUCHSIA_SIGTTIN = 21,
+    FUCHSIA_SIGTTOU = 22,
+    FUCHSIA_SIGURG = 23,
+    FUCHSIA_SIGXCPU = 24,
+    FUCHSIA_SIGXFSZ = 25,
+    FUCHSIA_SIGVTALRM = 26,
+    FUCHSIA_SIGPROF = 27,
+    FUCHSIA_SIGWINCH = 28,
+    FUCHSIA_SIGIO = 29,
+    FUCHSIA_SIGPOLL = FUCHSIA_SIGIO,
+    FUCHSIA_SIGPWR = 30,
+    FUCHSIA_SIGSYS = 31,
+    FUCHSIA_SIGUNUSED = 31,
+
+    FUCHSIA_SIGRTMIN = 32,
+    FUCHSIA_SIGRTMAX = 64,
+  };
+
+static struct gdbarch_data *fuchsia_gdbarch_data_handle;
+
+struct fuchsia_gdbarch_data
+  {
+    struct type *siginfo_type;
+  };
+
+static void *
+init_fuchsia_gdbarch_data (struct gdbarch *gdbarch)
+{
+  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct fuchsia_gdbarch_data);
+}
+
+static struct fuchsia_gdbarch_data *
+get_fuchsia_gdbarch_data (struct gdbarch *gdbarch)
+{
+  return ((struct fuchsia_gdbarch_data *)
+      gdbarch_data (gdbarch, fuchsia_gdbarch_data_handle));
+}
+
+/* Per-inferior data key.  */
+static const struct inferior_data *fuchsia_inferior_data;
+
+/* Fuchsia-specific cached data.  This is used by GDB for caching
+   purposes for each inferior.  This helps reduce the overhead of
+   transfering data from a remote target to the local host.  */
+struct fuchsia_info
+{
+  // True if the exec displacement of this inferior has been calculated.
+  bool exec_displacement_known;
+
+  /* Cache of the inferior's vsyscall/vDSO mapping range.  Only valid
+     if VSYSCALL_RANGE_P is positive.  This is cached because getting
+     at this info requires an auxv lookup (which is itself cached),
+     and looking through the inferior's mappings (which change
+     throughout execution and therefore cannot be cached).  */
+  struct mem_range vsyscall_range;
+
+  /* Zero if we haven't tried looking up the vsyscall's range before
+     yet.  Positive if we tried looking it up, and found it.  Negative
+     if we tried looking it up but failed.  */
+  int vsyscall_range_p;
+};
+
+/* Frees whatever allocated space there is to be freed and sets INF's
+   fuchsia cache data pointer to NULL.  */
+
+static void
+invalidate_fuchsia_cache_inf (struct inferior *inf)
+{
+  struct fuchsia_info *info;
+
+  info = (struct fuchsia_info *) inferior_data (inf,
fuchsia_inferior_data);
+  if (info != NULL)
+    {
+      xfree (info);
+      set_inferior_data (inf, fuchsia_inferior_data, NULL);
+    }
+}
+
+/* Handles the cleanup of the fuchsia cache for inferior INF.  ARG is
+   ignored.  Callback for the inferior_appeared and inferior_exit
+   events.  */
+
+static void
+fuchsia_inferior_data_cleanup (struct inferior *inf, void *arg)
+{
+  invalidate_fuchsia_cache_inf (inf);
+}
+
+/* Fetch the fuchsia cache info for INF.  This function always returns a
+   valid INFO pointer.  */
+
+static struct fuchsia_info *
+get_fuchsia_inferior_data (void)
+{
+  struct fuchsia_info *info;
+  struct inferior *inf = current_inferior ();
+
+  info = (struct fuchsia_info *) inferior_data (inf,
fuchsia_inferior_data);
+  if (info == NULL)
+    {
+      info = XCNEW (struct fuchsia_info);
+      set_inferior_data (inf, fuchsia_inferior_data, info);
+    }
+
+  return info;
+}
+
+/* siginfo is still a work-in-progress for fuchsia.  */
+
+static struct type *
+fuchsia_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  struct fuchsia_gdbarch_data *fuchsia_gdbarch_data;
+  struct type *int_type;
+  struct type *siginfo_type;
+
+  fuchsia_gdbarch_data = get_fuchsia_gdbarch_data (gdbarch);
+  if (fuchsia_gdbarch_data->siginfo_type != NULL)
+    return fuchsia_gdbarch_data->siginfo_type;
+
+  int_type = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch),
+                 0, "int");
+
+  /* struct siginfo */
+  siginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (siginfo_type) = xstrdup ("siginfo");
+  append_composite_type_field (siginfo_type, "si_signo", int_type);
+  append_composite_type_field (siginfo_type, "si_errno", int_type);
+  append_composite_type_field (siginfo_type, "si_code", int_type);
+
+  fuchsia_gdbarch_data->siginfo_type = siginfo_type;
+
+  return siginfo_type;
+}
+
+/* Implementation of `gdbarch_gdb_signal_from_target', as defined in
+   gdbarch.h.  This function is not static because it is exported to
+   other -tdep files.  */
+
+enum gdb_signal
+fuchsia_gdb_signal_from_target (struct gdbarch *gdbarch, int signal)
+{
+  switch (signal)
+    {
+    case 0:
+      return GDB_SIGNAL_0;
+
+    case FUCHSIA_SIGHUP:
+      return GDB_SIGNAL_HUP;
+
+    case FUCHSIA_SIGINT:
+      return GDB_SIGNAL_INT;
+
+    case FUCHSIA_SIGQUIT:
+      return GDB_SIGNAL_QUIT;
+
+    case FUCHSIA_SIGILL:
+      return GDB_SIGNAL_ILL;
+
+    case FUCHSIA_SIGTRAP:
+      return GDB_SIGNAL_TRAP;
+
+    case FUCHSIA_SIGABRT:
+      return GDB_SIGNAL_ABRT;
+
+    case FUCHSIA_SIGBUS:
+      return GDB_SIGNAL_BUS;
+
+    case FUCHSIA_SIGFPE:
+      return GDB_SIGNAL_FPE;
+
+    case FUCHSIA_SIGKILL:
+      return GDB_SIGNAL_KILL;
+
+    case FUCHSIA_SIGUSR1:
+      return GDB_SIGNAL_USR1;
+
+    case FUCHSIA_SIGSEGV:
+      return GDB_SIGNAL_SEGV;
+
+    case FUCHSIA_SIGUSR2:
+      return GDB_SIGNAL_USR2;
+
+    case FUCHSIA_SIGPIPE:
+      return GDB_SIGNAL_PIPE;
+
+    case FUCHSIA_SIGALRM:
+      return GDB_SIGNAL_ALRM;
+
+    case FUCHSIA_SIGTERM:
+      return GDB_SIGNAL_TERM;
+
+    case FUCHSIA_SIGCHLD:
+      return GDB_SIGNAL_CHLD;
+
+    case FUCHSIA_SIGCONT:
+      return GDB_SIGNAL_CONT;
+
+    case FUCHSIA_SIGSTOP:
+      return GDB_SIGNAL_STOP;
+
+    case FUCHSIA_SIGTSTP:
+      return GDB_SIGNAL_TSTP;
+
+    case FUCHSIA_SIGTTIN:
+      return GDB_SIGNAL_TTIN;
+
+    case FUCHSIA_SIGTTOU:
+      return GDB_SIGNAL_TTOU;
+
+    case FUCHSIA_SIGURG:
+      return GDB_SIGNAL_URG;
+
+    case FUCHSIA_SIGXCPU:
+      return GDB_SIGNAL_XCPU;
+
+    case FUCHSIA_SIGXFSZ:
+      return GDB_SIGNAL_XFSZ;
+
+    case FUCHSIA_SIGVTALRM:
+      return GDB_SIGNAL_VTALRM;
+
+    case FUCHSIA_SIGPROF:
+      return GDB_SIGNAL_PROF;
+
+    case FUCHSIA_SIGWINCH:
+      return GDB_SIGNAL_WINCH;
+
+    /* No way to differentiate between SIGIO and SIGPOLL.
+       Therefore, we just handle the first one.  */
+    case FUCHSIA_SIGIO:
+      return GDB_SIGNAL_IO;
+
+    case FUCHSIA_SIGPWR:
+      return GDB_SIGNAL_PWR;
+
+    case FUCHSIA_SIGSYS:
+      return GDB_SIGNAL_SYS;
+
+    /* SIGRTMIN and SIGRTMAX are not continuous in <gdb/signals.def>,
+       therefore we have to handle them here.  */
+    case FUCHSIA_SIGRTMIN:
+      return GDB_SIGNAL_REALTIME_32;
+
+    case FUCHSIA_SIGRTMAX:
+      return GDB_SIGNAL_REALTIME_64;
+    }
+
+  if (signal >= FUCHSIA_SIGRTMIN + 1 && signal <= FUCHSIA_SIGRTMAX - 1)
+    {
+      int offset = signal - FUCHSIA_SIGRTMIN + 1;
+
+      return (enum gdb_signal) ((int) GDB_SIGNAL_REALTIME_33 + offset);
+    }
+
+  return GDB_SIGNAL_UNKNOWN;
+}
+
+/* Implementation of `gdbarch_gdb_signal_to_target', as defined in
+   gdbarch.h.  This function is not static because it is exported to
+   other -tdep files.  */
+
+int
+fuchsia_gdb_signal_to_target (struct gdbarch *gdbarch,
+                enum gdb_signal signal)
+{
+  switch (signal)
+    {
+    case GDB_SIGNAL_0:
+      return 0;
+
+    case GDB_SIGNAL_HUP:
+      return FUCHSIA_SIGHUP;
+
+    case GDB_SIGNAL_INT:
+      return FUCHSIA_SIGINT;
+
+    case GDB_SIGNAL_QUIT:
+      return FUCHSIA_SIGQUIT;
+
+    case GDB_SIGNAL_ILL:
+      return FUCHSIA_SIGILL;
+
+    case GDB_SIGNAL_TRAP:
+      return FUCHSIA_SIGTRAP;
+
+    case GDB_SIGNAL_ABRT:
+      return FUCHSIA_SIGABRT;
+
+    case GDB_SIGNAL_FPE:
+      return FUCHSIA_SIGFPE;
+
+    case GDB_SIGNAL_KILL:
+      return FUCHSIA_SIGKILL;
+
+    case GDB_SIGNAL_BUS:
+      return FUCHSIA_SIGBUS;
+
+    case GDB_SIGNAL_SEGV:
+      return FUCHSIA_SIGSEGV;
+
+    case GDB_SIGNAL_SYS:
+      return FUCHSIA_SIGSYS;
+
+    case GDB_SIGNAL_PIPE:
+      return FUCHSIA_SIGPIPE;
+
+    case GDB_SIGNAL_ALRM:
+      return FUCHSIA_SIGALRM;
+
+    case GDB_SIGNAL_TERM:
+      return FUCHSIA_SIGTERM;
+
+    case GDB_SIGNAL_URG:
+      return FUCHSIA_SIGURG;
+
+    case GDB_SIGNAL_STOP:
+      return FUCHSIA_SIGSTOP;
+
+    case GDB_SIGNAL_TSTP:
+      return FUCHSIA_SIGTSTP;
+
+    case GDB_SIGNAL_CONT:
+      return FUCHSIA_SIGCONT;
+
+    case GDB_SIGNAL_CHLD:
+      return FUCHSIA_SIGCHLD;
+
+    case GDB_SIGNAL_TTIN:
+      return FUCHSIA_SIGTTIN;
+
+    case GDB_SIGNAL_TTOU:
+      return FUCHSIA_SIGTTOU;
+
+    case GDB_SIGNAL_IO:
+      return FUCHSIA_SIGIO;
+
+    case GDB_SIGNAL_XCPU:
+      return FUCHSIA_SIGXCPU;
+
+    case GDB_SIGNAL_XFSZ:
+      return FUCHSIA_SIGXFSZ;
+
+    case GDB_SIGNAL_VTALRM:
+      return FUCHSIA_SIGVTALRM;
+
+    case GDB_SIGNAL_PROF:
+      return FUCHSIA_SIGPROF;
+
+    case GDB_SIGNAL_WINCH:
+      return FUCHSIA_SIGWINCH;
+
+    case GDB_SIGNAL_USR1:
+      return FUCHSIA_SIGUSR1;
+
+    case GDB_SIGNAL_USR2:
+      return FUCHSIA_SIGUSR2;
+
+    case GDB_SIGNAL_PWR:
+      return FUCHSIA_SIGPWR;
+
+    case GDB_SIGNAL_POLL:
+      return FUCHSIA_SIGPOLL;
+
+    /* GDB_SIGNAL_REALTIME_32 is not continuous in <gdb/signals.def>,
+       therefore we have to handle it here.  */
+    case GDB_SIGNAL_REALTIME_32:
+      return FUCHSIA_SIGRTMIN;
+
+    /* Same comment applies to _64.  */
+    case GDB_SIGNAL_REALTIME_64:
+      return FUCHSIA_SIGRTMAX;
+    }
+
+  /* GDB_SIGNAL_REALTIME_33 to _64 are continuous.  */
+  if (signal >= GDB_SIGNAL_REALTIME_33
+      && signal <= GDB_SIGNAL_REALTIME_63)
+    {
+      int offset = signal - GDB_SIGNAL_REALTIME_33;
+
+      return FUCHSIA_SIGRTMIN + 1 + offset;
+    }
+
+  return -1;
+}
+
+/* Helper for fuchsia_vsyscall_range that does the real work of finding
+   the vsyscall's address range.  */
+
+static int
+fuchsia_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range
*range)
+{
+  return 0; // TODO
+}
+
+/* Implementation of the "vsyscall_range" gdbarch hook.  Handles
+   caching, and defers the real work to fuchsia_vsyscall_range_raw.  */
+
+static int
+fuchsia_vsyscall_range (struct gdbarch *gdbarch, struct mem_range *range)
+{
+  struct fuchsia_info *info = get_fuchsia_inferior_data ();
+
+  if (info->vsyscall_range_p == 0)
+    {
+      if (fuchsia_vsyscall_range_raw (gdbarch, &info->vsyscall_range))
+    info->vsyscall_range_p = 1;
+      else
+    info->vsyscall_range_p = -1;
+    }
+
+  if (info->vsyscall_range_p < 0)
+    return 0;
+
+  *range = info->vsyscall_range;
+  return 1;
+}
+
+/* Symbols for fuchsia_infcall_mmap's ARG_FLAGS; their Fuchsia MAP_*
system
+   definitions would be dependent on compilation host.  */
+#define GDB_MMAP_MAP_PRIVATE   0x02 /* Changes are private.  */
+#define GDB_MMAP_MAP_ANONYMOUS 0x20 /* Don't use a file.  */
+
+/* See gdbarch.sh 'infcall_mmap'.  */
+
+static CORE_ADDR
+fuchsia_infcall_mmap (CORE_ADDR size, unsigned prot)
+{
+  struct objfile *objf;
+  /* Do there still exist any Fuchsia systems without "mmap64"?
+     "mmap" uses 64-bit off_t on x86_64 and 32-bit off_t on i386 and
x32.  */
+  struct value *mmap_val = find_function_in_inferior ("mmap64", &objf);
+  struct value *addr_val;
+  struct gdbarch *gdbarch = get_objfile_arch (objf);
+  CORE_ADDR retval;
+  enum
+    {
+      ARG_ADDR, ARG_LENGTH, ARG_PROT, ARG_FLAGS, ARG_FD, ARG_OFFSET,
ARG_LAST
+    };
+  struct value *arg[ARG_LAST];
+
+  arg[ARG_ADDR] = value_from_pointer (builtin_type
(gdbarch)->builtin_data_ptr,
+                      0);
+  /* Assuming sizeof (unsigned long) == sizeof (size_t).  */
+  arg[ARG_LENGTH] = value_from_ulongest
+            (builtin_type (gdbarch)->builtin_unsigned_long, size);
+  gdb_assert ((prot & ~(GDB_MMAP_PROT_READ | GDB_MMAP_PROT_WRITE
+            | GDB_MMAP_PROT_EXEC))
+          == 0);
+  arg[ARG_PROT] = value_from_longest (builtin_type
(gdbarch)->builtin_int, prot);
+  arg[ARG_FLAGS] = value_from_longest (builtin_type
(gdbarch)->builtin_int,
+                       GDB_MMAP_MAP_PRIVATE
+                       | GDB_MMAP_MAP_ANONYMOUS);
+  arg[ARG_FD] = value_from_longest (builtin_type
(gdbarch)->builtin_int, -1);
+  arg[ARG_OFFSET] = value_from_longest (builtin_type
(gdbarch)->builtin_int64,
+                    0);
+  addr_val = call_function_by_hand (mmap_val, ARG_LAST, arg);
+  retval = value_as_address (addr_val);
+  if (retval == (CORE_ADDR) -1)
+    error (_("Failed inferior mmap call for %s bytes, errno is changed."),
+       pulongest (size));
+  return retval;
+}
+
+/* See gdbarch.sh 'infcall_munmap'.  */
+
+static void
+fuchsia_infcall_munmap (CORE_ADDR addr, CORE_ADDR size)
+{
+  struct objfile *objf;
+  struct value *munmap_val = find_function_in_inferior ("munmap", &objf);
+  struct value *retval_val;
+  struct gdbarch *gdbarch = get_objfile_arch (objf);
+  LONGEST retval;
+  enum
+    {
+      ARG_ADDR, ARG_LENGTH, ARG_LAST
+    };
+  struct value *arg[ARG_LAST];
+
+  arg[ARG_ADDR] = value_from_pointer (builtin_type
(gdbarch)->builtin_data_ptr,
+                      addr);
+  /* Assuming sizeof (unsigned long) == sizeof (size_t).  */
+  arg[ARG_LENGTH] = value_from_ulongest
+            (builtin_type (gdbarch)->builtin_unsigned_long, size);
+  retval_val = call_function_by_hand (munmap_val, ARG_LAST, arg);
+  retval = value_as_long (retval_val);
+  if (retval != 0)
+    warning (_("Failed inferior munmap call at %s for %s bytes, "
+           "errno is changed."),
+         hex_string (addr), pulongest (size));
+}
+
+/* See fuchsia-tdep.h.  */
+
+CORE_ADDR
+fuchsia_displaced_step_location (struct gdbarch *gdbarch)
+{
+  CORE_ADDR addr;
+  int bp_len;
+
+  // TODO: We're assuming this is called after the first
+  // dynamic linker breakpoint has been hit (where we know the
+  // executable has been loaded). Could try to use the interpreter's
+  // entry point here.
+  /* Determine entry point from target auxiliary vector.  This avoids
+     the need for symbols.  */
+  if (target_auxv_search (&current_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,
+                         &current_target);
+
+  /* Inferior calls also use the entry point as a breakpoint location.
+     We don't want displaced stepping to interfere with those
+     breakpoints, so leave space.  */
+  gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len);
+  addr += bp_len * 2;
+
+  return addr;
+}
+
+/* For Fuchsia we can't relocate the main executable until after we get
+   to the shlib event breakpoint: The main executable is not loaded until
+   the dynamic linker loads it.  */
+
+static void
+fuchsia_handle_solib_event (void)
+{
+  struct fuchsia_info *info = get_fuchsia_inferior_data ();
+
+  if (!info->exec_displacement_known)
+    {
+      // Presumably this is the first time we've hit the dynamic linker
bkpt.
+      // It is now that the main executable has been loaded. To fetch the
+      // necessary info (e.g., AT_ENTRY) we need to flush the auxv
cache so
+      // gdb will refetch it.
+      invalidate_auxv_cache_inf (current_inferior ());
+      svr4_relocate_main_executable ();
+      info->exec_displacement_known = true;
+    }
+
+  extern void svr4_handle_solib_event (void);
+  svr4_handle_solib_event ();
+}
+
+/* To be called from the various GDB_OSABI_FUCHSIA handlers for the
+   various Fuchsia architectures and machine types.  */
+
+void
+fuchsia_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  set_gdbarch_gdb_signal_from_target (gdbarch,
+                      fuchsia_gdb_signal_from_target);
+  set_gdbarch_gdb_signal_to_target (gdbarch,
+                    fuchsia_gdb_signal_to_target);
+  set_gdbarch_vsyscall_range (gdbarch, fuchsia_vsyscall_range);
+  set_gdbarch_infcall_mmap (gdbarch, fuchsia_infcall_mmap);
+  set_gdbarch_infcall_munmap (gdbarch, fuchsia_infcall_munmap);
+  set_gdbarch_get_siginfo_type (gdbarch, fuchsia_get_siginfo_type);
+
+  /* Enable TLS support.  */
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+                         svr4_fetch_objfile_link_map);
+
+  /* Fuchsia uses SVR4-style shared libraries.  */
+  set_gdbarch_skip_trampoline_code (gdbarch,
find_solib_trampoline_target);
+
+  /* Fuchsia uses its own dynamic linker.  */
+  set_gdbarch_skip_solib_resolver (gdbarch, fuchsia_skip_solib_resolver);
+
+  /* Fuchsia uses SVR4-style shared libraries.
+     Note: This also calls set_solib_ops.  */
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+  /* But we need to use our own so_ops vtable to handle exec displacement
+     computation.
+     Initialize this lazily, to avoid an initialization order
+     dependency on solib-svr4.c's _initialize routine.  */
+  if (fuchsia_so_ops.handle_event == NULL)
+    {
+      fuchsia_so_ops = svr4_so_ops;
+      fuchsia_so_ops.handle_event = fuchsia_handle_solib_event;
+    }
+  set_solib_ops (gdbarch, &fuchsia_so_ops);
+}
+
+/* Calling functions in shared libraries.
+   See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
+   This function:
+   1) decides whether a PLT has sent us into the linker to resolve
+      a function reference, and
+   2) if so, tells us where to set a temporary breakpoint that will
+      trigger when the dynamic linker is done.  */
+
+CORE_ADDR
+fuchsia_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  // TODO: Update for fuchsia/musl.
+  /* The GNU dynamic linker is part of the GNU C library, and is used
+     by all GNU systems (GNU/Hurd, GNU/Linux).  An unresolved PLT
+     entry points to "_dl_runtime_resolve", which calls "fixup" to
+     patch the PLT, and then passes control to the function.
+
+     We look for the symbol `_dl_runtime_resolve', and find `fixup' in
+     the same objfile.  If we are at the entry point of `fixup', then
+     we set a breakpoint at the return address (at the top of the
+     stack), and continue.
+
+     It's kind of gross to do all these checks every time we're
+     called, since they don't change once the executable has gotten
+     started.  But this is only a temporary hack --- upcoming versions
+     of GNU/Linux will provide a portable, efficient interface for
+     debugging programs that use shared libraries.  */

I suppose the above comment about getting an efficient interface is old and stale nowadays? :-)

Maybe just get rid of it in this instance.

+
+  struct bound_minimal_symbol resolver
+    = lookup_minimal_symbol_and_objfile ("_dl_runtime_resolve");
+
+  if (resolver.minsym)
+    {
+      /* The dynamic linker began using this name in early 2005.  */
+      struct bound_minimal_symbol fixup
+    = lookup_minimal_symbol ("_dl_fixup", NULL, resolver.objfile);
+
+      /* This is the name used in older versions.  */
+      if (! fixup.minsym)
+        fixup = lookup_minimal_symbol ("fixup", NULL, resolver.objfile);
+
+      if (fixup.minsym && BMSYMBOL_VALUE_ADDRESS (fixup) == pc)
+    return frame_unwind_caller_pc (get_current_frame ());
+    }
+
+  return 0;
+}
+
+/* Recognize Fuchsia object files.  */
+
+enum gdb_osabi
+fuchsia_osabi_sniffer (bfd *abfd)
+{
+  /* TODO: Until we have something like a fuchsia .note.ABI-tag, assume
the
+     absence of .note.ABI-tag means fuchsia.  */
+  if (bfd_get_section_by_name (abfd, ".note.ABI-tag") == NULL)
+    return GDB_OSABI_FUCHSIA;
+  return GDB_OSABI_UNKNOWN;
+}

Should we enforce the presence of a .note.ABI-tag straight away to avoid future compatibility issues with old/new binaries? Or do we not have to worry, at this point, about being compatible and having a stable API/ABI?

+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_fuchsia_tdep;
+
+void
+_initialize_fuchsia_tdep (void)
+{
+  fuchsia_gdbarch_data_handle =
+    gdbarch_data_register_post_init (init_fuchsia_gdbarch_data);
+
+  /* Set a cache per-inferior.  */
+  fuchsia_inferior_data
+    = register_inferior_data_with_cleanup (NULL,
fuchsia_inferior_data_cleanup);
+  /* Observers used to invalidate the cache when needed.  */
+  observer_attach_inferior_exit (invalidate_fuchsia_cache_inf);
+  observer_attach_inferior_appeared (invalidate_fuchsia_cache_inf);
+}
diff --git a/gdb/fuchsia-tdep.h b/gdb/fuchsia-tdep.h
new file mode 100644
index 0000000..1f7af83
--- /dev/null
+++ b/gdb/fuchsia-tdep.h
@@ -0,0 +1,45 @@
+/* Target-dependent code for Fuchsia, architecture independent.
+
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see
<http://www.gnu.org/licenses/>.  */
+
+#ifndef FUCHSIA_TDEP_H
+#define FUCHSIA_TDEP_H
+
+#include "bfd.h"
+
+extern enum gdb_osabi fuchsia_osabi_sniffer (bfd *abfd);
+
+extern enum gdb_signal fuchsia_gdb_signal_from_target (struct gdbarch
*gdbarch,
+                               int signal);
+
+extern int fuchsia_gdb_signal_to_target (struct gdbarch *gdbarch,
+                     enum gdb_signal signal);
+
+/* Default Fuchsia implementation of `displaced_step_location', as
+   defined in gdbarch.h.  Determines the entry point from AT_ENTRY in
+   the target auxiliary vector.
+   TODO: This AT_ENTRY is for ld.so.  */
+extern CORE_ADDR fuchsia_displaced_step_location (struct gdbarch
*gdbarch);
+
+extern void fuchsia_init_abi (struct gdbarch_info info,
+                  struct gdbarch *gdbarch);
+
+extern CORE_ADDR fuchsia_skip_solib_resolver (struct gdbarch *gdbarch,
+                          CORE_ADDR);
+
+#endif /* fuchsia-tdep.h */
diff --git a/gdb/osabi.c b/gdb/osabi.c
index 8b44a85..5a5612e 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -83,6 +83,7 @@ static const struct osabi_names gdb_osabi_names[] =
   { "LynxOS178", NULL },
   { "Newlib", NULL },
   { "SDE", NULL },
+  { "Fuchsia", NULL },

   { "<invalid>", NULL }
 };
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 0e18292..4aa1318 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -48,7 +48,6 @@

 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
-static void svr4_relocate_main_executable (void);
 static void svr4_free_library_list (void *p_list);

 /* Link map info to include in an allocated so_list entry.  */
@@ -1911,7 +1910,9 @@ disable_probes_interface_cleanup (void *arg)
    probes-based linker interface.  Do nothing if using the
    standard interface.  */

-static void
+extern void svr4_handle_solib_event (void);
+
+void
 svr4_handle_solib_event (void)
 {
   struct svr4_info *info = get_svr4_info ();
@@ -2988,12 +2989,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
   return 1;
 }

-/* Relocate the main executable.  This function should be called upon
-   stopping the inferior process at the entry point to the program.
-   The entry point from BFD is compared to the AT_ENTRY of AUXV and if
they are
-   different, the main executable is relocated by the proper amount.  */
+/* See solib-svr4.h.  */

-static void
+void
 svr4_relocate_main_executable (void)
 {
   CORE_ADDR displacement;
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index d541136..46467a5 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -84,4 +84,10 @@ extern struct link_map_offsets
*svr4_lp64_fetch_link_map_offsets (void);
    SVR4 run time loader.  */
 int svr4_in_dynsym_resolve_code (CORE_ADDR pc);

+/* Relocate the main executable.  This function should be called upon
+   stopping the inferior process at the entry point to the program.
+   The entry point from BFD is compared to the AT_ENTRY of AUXV and if
they are
+   different, the main executable is relocated by the proper amount.  */
+void svr4_relocate_main_executable (void);
+
 #endif /* solib-svr4.h */


Overall it looks OK to me. I'd drop most of the TODO's or document limitations at the top of the file or somewhere else. Also, i'd remove or tweak comments that were copied from other files so they are more Fuchsia-specific.

I'm assuming this is still in early stages and target descriptions and other bits will be decided later on?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]