[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 Gdb-patches
mailing list