[PATCH] Add OSE operating system support [5/5] gdbarch support

Hui Zhu hui_zhu@mentor.com
Fri Mar 8 13:30:00 GMT 2013


On 03/05/13 18:02, Hui Zhu wrote:
> This is the patch add new gdbarch to GDB to make it support OSE.
>
> Thanks,
> Hui
>
> 2013-03-05  Luis Machado  <lgustavo@codesourcery.com>
>
>      * configure.tgt: Add powerpc-*-ose.
>      * defs.h (gdb_osabi): Add GDB_OSABI_OSE.
>      * osabi.c (gdb_osabi_name): Add "OSE".
>      * ose-tdep.c: New.
2013-03-08  Pedro Alves  <pedro@codesourcery.com>
	    Luis Machado  <lgustavo@codesourcery.com>

	* configure.tgt: Add powerpc-*-ose.
	* defs.h (gdb_osabi): Add GDB_OSABI_OSE.
	* osabi.c (gdb_osabi_name): Add "OSE".
	* ose-tdep.c: New.
-------------- next part --------------
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -437,6 +437,12 @@ powerpc-*-lynx*178)
 			xcoffread.o monitor.o dsrec.o ppc-sysv-tdep.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o"
 	;;
+powerpc-*-ose)
+	# Target: PowerPC running ENEA's OSE
+	gdb_target_obs="rs6000-tdep.o ravenscar-thread.o \
+			ppc-ravenscar-thread.o ppc-sysv-tdep.o \
+			ose-tdep.o"
+	;;
 powerpc*-*-*)
 	# Target: PowerPC running eabi
 	gdb_target_obs="rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o \
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -596,6 +596,7 @@ enum gdb_osabi
   GDB_OSABI_OPENVMS,
   GDB_OSABI_LYNXOS178,
   GDB_OSABI_NEWLIB,
+  GDB_OSABI_OSE,
 
   GDB_OSABI_INVALID		/* keep this last */
 };
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -75,6 +75,7 @@ static const char * const gdb_osabi_name
   "OpenVMS",
   "LynxOS178",
   "Newlib",
+  "OSE",
 
   "<invalid>"
 };
--- /dev/null
+++ b/gdb/ose-tdep.c
@@ -0,0 +1,462 @@
+/* Target-dependent code for Enea OSE.
+
+   Copyright (C) 2010, 2011 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/>.  */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "gdb_assert.h"
+#include "osabi.h"
+#include "regset.h"
+#include "regcache.h"
+#include "ppc-tdep.h"
+#include "exec.h"
+#include "gdbtypes.h"
+#include "language.h"
+
+/*
+
+  RMM definitions.
+
+typedef struct MonitorEventTimestamp
+{
+  uint32_t tick;
+  uint32_t ntick;
+  uint32_t sec;
+  uint32_t sectick;
+} MonitorEventTimestamp;
+
+The signal structure used for both MONITOR_RECEIVE_INTERCEPT_NOTIFY
+and MONITOR_SEND_INTERCEPT_NOTIFY:
+
+typedef struct MonitorSendReceiveInfo
+{
+  uint32_t sigNo;
+  uint32_t reference;
+  MonitorEventTimestamp time;
+  uint32_t signalNumber;
+  uint32_t signalSender;
+  uint32_t signalAddressee;
+  uint32_t signalSize;
+  uint32_t signalAddress;
+  uint32_t signalId;
+  uint32_t lineNumber;
+  uint32_t fileNameOffset;
+  uint32_t signalDataOffset;
+  uint32_t signalDataCount;
+  uint16_t euId;
+  uint16_t reserved0;
+  uint32_t reserved1;
+  uint8_t data[1];
+} MonitorSendReceiveInfo;
+
+*/
+
+/* Synthesize MonitorSendReceiveInfo.  This RMM signal contains all we
+   need to know about the sent/received signal, so we expose it to the
+   user.  */
+
+static struct type *
+ose_get_siginfo_type (struct gdbarch *gdbarch)
+{
+  struct type *monitor_send_receive_info_type;
+  struct type *monitor_event_time_stamp_type;
+  struct type *uint8_type, *uint16_type, *uint32_type;
+  struct type *index_type, *range_type, *uint8_array_1_type;
+  struct type *type;
+
+  uint8_type = builtin_type (gdbarch)->builtin_uint8;
+  uint16_type = builtin_type (gdbarch)->builtin_uint16;
+  uint32_type = builtin_type (gdbarch)->builtin_uint32;
+
+  index_type = builtin_type (gdbarch)->builtin_int;
+  range_type = create_range_type (NULL, index_type, 0, 0);
+  uint8_array_1_type = create_array_type (NULL, uint8_type, range_type);
+
+  /* MonitorEventTimeStamp */
+  type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "tick", uint32_type);
+  append_composite_type_field (type, "ntick", uint32_type);
+  append_composite_type_field (type, "sec", uint32_type);
+  append_composite_type_field (type, "sectick", uint32_type);
+  monitor_event_time_stamp_type = type;
+
+  type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (type, "sigNo", uint32_type);
+  append_composite_type_field (type, "reference", uint32_type);
+  append_composite_type_field (type, "time", monitor_event_time_stamp_type);
+  append_composite_type_field (type, "signalNumber", uint32_type);
+  append_composite_type_field (type, "signalSender", uint32_type);
+  append_composite_type_field (type, "signalAddressee", uint32_type);
+  append_composite_type_field (type, "signalSize", uint32_type);
+  append_composite_type_field (type, "signalAddress", uint32_type);
+  append_composite_type_field (type, "signalId", uint32_type);
+  append_composite_type_field (type, "lineNumber", uint32_type);
+  append_composite_type_field (type, "fileNameOffset", uint32_type);
+  append_composite_type_field (type, "signalDataOffset", uint32_type);
+  append_composite_type_field (type, "signalDataCount", uint32_type);
+  append_composite_type_field (type, "euId", uint16_type);
+  append_composite_type_field (type, "reserved0", uint16_type);
+  append_composite_type_field (type, "reserved1", uint32_type);
+  append_composite_type_field (type, "data", uint8_array_1_type);
+  monitor_send_receive_info_type = type;
+
+  return monitor_send_receive_info_type;
+}
+
+/* Supported register note sections.  */
+static struct core_regset_section powerpc_ose_regset_sections[] =
+{
+  { ".reg", 68, "general-purpose" },
+  { NULL, 0 }
+};
+
+typedef uint32_t MonitorStatus;
+typedef uint32_t MonitorRegisterId;
+typedef uint32_t SIGSELECT;
+typedef uint32_t PmStatus;
+typedef uint32_t U32;
+typedef uint32_t OSADDRESS;
+
+#define PM_STRING_LENGTH             32
+
+#define PM_SECTION_NAME_LENGTH       PM_STRING_LENGTH
+
+#define PM_SECTION_LOAD 1
+
+struct PmLoadModuleSectionInfo
+{
+  OSADDRESS   section_base;
+  U32         section_size;
+  U32         section_attr;
+  U32         section_options;
+  char        section_name[PM_SECTION_NAME_LENGTH];
+};
+
+#define PM_INSTALL_HANDLE_LENGTH     PM_STRING_LENGTH
+
+struct PmLoadModuleSectionInfoReply
+{
+  SIGSELECT            sigNo;
+  PmStatus             status;
+  char                 install_handle[PM_INSTALL_HANDLE_LENGTH];
+  U32                  section_interval_start;
+  U32                  section_interval_end;
+  struct PmLoadModuleSectionInfo sections[1];
+};
+
+#define MONITOR_REGISTER_INVALID 0x80000000
+
+#define MONITOR_REGISTER_IS_INVALID(MONITOR_REGISTER) \
+   (((MONITOR_REGISTER) & MONITOR_REGISTER_INVALID) >> 31)
+
+typedef struct MonitorRegister
+{
+  MonitorRegisterId id;
+  uint32_t value;
+} MonitorRegister;
+
+typedef struct MonitorRegisterValues
+{
+  uint32_t sigNo;
+  uint32_t pid;
+  MonitorStatus status;
+  uint32_t registersCount;
+  MonitorRegister registers[1];
+} MonitorRegisterValues;
+
+enum MonitorPowerpcRegisterIdValue
+  {
+    MONITOR_POWERPC_REGISTER_R0 = 0,
+    MONITOR_POWERPC_REGISTER_F0_LO = 32,
+    MONITOR_POWERPC_REGISTER_F0_HI = 64,
+
+    MONITOR_POWERPC_REGISTER_PC = 96,
+    MONITOR_POWERPC_REGISTER_CR = 97,
+    MONITOR_POWERPC_REGISTER_FPSCR = 98,
+    MONITOR_POWERPC_REGISTER_MSR = 99,
+
+    MONITOR_POWERPC_REGISTER_R0_HI = 300,
+    MONITOR_POWERPC_REGISTER_SPEFSCR = 332,
+    MONITOR_POWERPC_REGISTER_ACC_LO = 333,
+    MONITOR_POWERPC_REGISTER_ACC_HI = 334,
+
+    MONITOR_POWERPC_REGISTER_XER = 0x10001,
+    MONITOR_POWERPC_REGISTER_LR = 0x10008,
+    MONITOR_POWERPC_REGISTER_CTR = 0x10009,
+
+    /* Pseudo registers */
+    MONITOR_POWERPC_REGISTER_RA = 200,
+    MONITOR_POWERPC_REGISTER_SSLIMIT = 201
+  };
+
+/* GDB register numbers.  */
+#define GDB_POWERPC_CORE_R0_REGNUM 0
+
+#define GDB_POWERPC_SPE_EV0H_REGNUM 32
+
+#define GDB_POWERPC_CORE_PC_REGNUM 64
+#define GDB_POWERPC_CORE_MSR_REGNUM 65
+#define GDB_POWERPC_CORE_CR_REGNUM 66
+#define GDB_POWERPC_CORE_LR_REGNUM 67
+#define GDB_POWERPC_CORE_CRT_REGNUM 68
+#define GDB_POWERPC_CORE_XER_REGNUM 69
+
+#define GDB_POWERPC_SPE_ACC_REGNUM 73 /* 64-bit */
+#define GDB_POWERPC_SPE_SPEFSCR_REGNUM 74
+
+#define in_range(which, low, high) \
+  ((low) <= (which) && (which) <= (high))
+
+static int
+fill_register_ids_array (int regnum, MonitorRegisterId *array)
+{
+  if (regnum == -1)
+    {
+      gdb_assert (0);
+    }
+  else
+    {
+      if (in_range (regnum,
+		    PPC_R0_REGNUM,
+		    PPC_R0_REGNUM + 31))
+	{
+	  array[0] = (MONITOR_POWERPC_REGISTER_R0
+		      + (regnum - PPC_R0_REGNUM));
+	  return 1;
+	}
+      else if (in_range (regnum,
+			 PPC_SPE_UPPER_GP0_REGNUM,
+			 PPC_SPE_UPPER_GP0_REGNUM + 31))
+	{
+	  array[0] = (MONITOR_POWERPC_REGISTER_R0_HI
+		      + (regnum - PPC_SPE_UPPER_GP0_REGNUM));
+	  return 1;
+	}
+      else if (in_range (regnum,
+			 PPC_PC_REGNUM,
+			 PPC_PC_REGNUM + 31))
+	{
+	  array[0] = (MONITOR_POWERPC_REGISTER_PC
+		      + (regnum - PPC_PC_REGNUM));
+	  return 1;
+	}
+      else if (regnum == PPC_SPE_ACC_REGNUM)
+	{
+	  array[0] = MONITOR_POWERPC_REGISTER_ACC_LO;
+	  array[1] = MONITOR_POWERPC_REGISTER_ACC_HI;
+	  return 2;
+	}
+      else if (regnum == PPC_SPE_FSCR_REGNUM)
+	{
+	  array[0] = MONITOR_POWERPC_REGISTER_SPEFSCR;
+	  return 1;
+	}
+#if 0
+      warning ("no mapping for register %d", regnum);
+#endif
+      return 0;
+      internal_error (__FILE__, __LINE__,
+		      "unknown regnum %d", regnum);
+    }
+}
+
+static void
+supply_regset_from_MonitorRegisterValues (struct regcache *regcache,
+					  const struct MonitorRegisterValues *s,
+					  int regnum)
+{
+  MonitorRegisterId array[2];
+  uint32_t val[2];
+  int count, c;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+  count = fill_register_ids_array (regnum, array);
+
+  if (count == 0)
+    {
+      memset (val, 0, sizeof val);
+      regcache_raw_supply (regcache, regnum, val);
+      return;
+    }
+
+  gdb_assert (count * 4 == register_size (gdbarch, regnum));
+
+  for (c = 0; c < count; c++)
+    {
+      int i = 0;
+
+      for (i = 0; i < s->registersCount; i++)
+	if (s->registers[i].id == array[c])
+	  {
+	    val[c] = s->registers[i].value;
+	    break;
+	  }
+    }
+
+  regcache_raw_supply (regcache, regnum, val);
+}
+
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+   in the general-purpose register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+static void
+ose_supply_gregset (const struct regset *regset,
+		    struct regcache *regcache,
+		    int regnum, const void *gregs, size_t len)
+{
+  const struct MonitorRegisterValues *s = gregs;
+  int i;
+
+  if (regnum == -1)
+    {
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+      for (i = 0; i < PPC_NUM_REGS; i++)
+	if (register_size (gdbarch, i))
+	  ose_supply_gregset (regset, regcache, i, gregs, len);
+    }
+  else
+    supply_regset_from_MonitorRegisterValues (regcache, s, regnum);
+}
+
+static struct regset ose_gregset =
+{
+  NULL,
+  ose_supply_gregset
+};
+
+static const struct regset *
+ose_regset_from_core_section (struct gdbarch *gdbarch,
+			      const char *sect_name, size_t sect_size)
+{
+  /* FIXME: check section size.  */
+  if (strcmp (sect_name, ".reg") == 0)
+    return &ose_gregset;
+
+  return NULL;
+}
+
+static enum gdb_osabi
+ose_core_osabi_sniffer (bfd *abfd)
+{
+  if (strstr (bfd_get_target (abfd), "ose-core") != NULL)
+    return GDB_OSABI_OSE;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+/* Return true if ABFD loos like an OSE load module.  */
+
+static int
+ose_load_module_p (bfd *abfd)
+{
+  static const char OSE_Configuration[] = "OSE Configuration";
+  gdb_byte buf[sizeof (OSE_Configuration) - 1];
+  asection *section;
+  int res;
+
+  /* OSE files don't have a .note.ABI-tag marker or something similar.
+     We do know there's always a "LMCONF" section, and that it starts
+     with a known string.  */
+
+  section = bfd_get_section_by_name (abfd, "LMCONF");
+  if (!section)
+    return 0;
+
+  res = bfd_get_section_contents (abfd, section,
+				  buf, 0, sizeof (OSE_Configuration) - 1);
+  if (res == 0)
+    return 0;
+
+  if (memcmp (buf, OSE_Configuration, sizeof (OSE_Configuration) - 1) != 0)
+    return 0;
+
+  return 1;
+}
+
+static enum gdb_osabi
+ose_elf_osabi_sniffer (bfd *abfd)
+{
+  if (ose_load_module_p (abfd))
+    return GDB_OSABI_OSE;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+static void
+ose_core_relocate (struct gdbarch *gdbarch, bfd *core_bfd)
+{
+  struct load_map_info info = { NULL, NULL };
+  asection *asect;
+  struct PmLoadModuleSectionInfoReply *lmsi;
+  int i;
+  int start, end;
+
+  asect = bfd_get_section_by_name (core_bfd, ".section-info");
+
+  lmsi = (void *) asect->contents;
+
+  start = bfd_get_32 (core_bfd, &lmsi->section_interval_start);
+  end = bfd_get_32 (core_bfd, &lmsi->section_interval_end);
+
+  for (i = start;  i <= end; i++)
+    {
+      uint32_t options = bfd_get_32 (core_bfd,
+				     &lmsi->sections[i].section_options);
+      CORE_ADDR address = bfd_get_32 (core_bfd,
+				      &lmsi->sections[i].section_base);
+
+      if (options == PM_SECTION_LOAD)
+	VEC_safe_push (CORE_ADDR, info.section_bases, address);
+    }
+
+  relocate_with_load_map (&info);
+}
+
+static void
+ose_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  set_gdbarch_core_regset_sections (gdbarch, powerpc_ose_regset_sections);
+
+  set_gdbarch_regset_from_core_section
+    (gdbarch, ose_regset_from_core_section);
+
+  set_gdbarch_core_relocate (gdbarch, ose_core_relocate);
+
+  set_gdbarch_get_siginfo_type (gdbarch, ose_get_siginfo_type);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_ose_tdep (void);
+
+void
+_initialize_ose_tdep (void)
+{
+  /* BFD doesn't set a flavour for OSE style core files.  */
+  gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
+				  ose_core_osabi_sniffer);
+
+  gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_elf_flavour,
+				  ose_elf_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_OSE,
+			  ose_init_abi);
+}


More information about the Binutils mailing list