]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Complete SH port.
authorMatt Fleming <matt@console-pimps.org>
Sun, 11 Apr 2010 02:13:37 +0000 (19:13 -0700)
committerUlrich Drepper <drepper@redhat.com>
Sun, 11 Apr 2010 02:13:37 +0000 (19:13 -0700)
backends/ChangeLog
backends/Makefile.am
backends/sh_corenote.c [new file with mode: 0644]
backends/sh_init.c
backends/sh_regs.c [new file with mode: 0644]
backends/sh_retval.c [new file with mode: 0644]
backends/sh_symbol.c
libelf/ChangeLog
libelf/elf.h

index 99d01ce0671074efa6050ab0f88164ff743c8486..9fd9745d0e4699b00fcd34f2527ecf21da87ac20 100644 (file)
@@ -1,3 +1,12 @@
+2010-04-10  Matt Fleming  <matt@console-pimps.org>
+
+       * sh_corenote.c: New file.
+       * sh_regs.c: New file.
+       * sh_retval.c: New file.
+       * sh_symbol.c (sh_machine_flag_check): New function.
+       * Makefile.am (sh_SRCS): Add new files.
+       * sh_init.c (sh_init): Add initializers.
+
 2010-04-07  Roland McGrath  <roland@redhat.com>
 
        * arm_reloc.def: Accept PC24 and ABS32 in EXEC|DYN too.
index a18454d62c3c5e52d2a4b627c44c53f6ade53393..3ce448a9d4eb3a3ad11fd075dd4d48cd84206a55 100644 (file)
@@ -52,7 +52,7 @@ cpu_i386 = ../libcpu/libcpu_i386.a
 libebl_i386_pic_a_SOURCES = $(i386_SRCS)
 am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
 
-sh_SRCS = sh_init.c sh_symbol.c
+sh_SRCS = sh_init.c sh_symbol.c sh_corenote.c sh_regs.c sh_retval.c
 libebl_sh_pic_a_SOURCES = $(sh_SRCS)
 am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
 
diff --git a/backends/sh_corenote.c b/backends/sh_corenote.c
new file mode 100644 (file)
index 0000000..6887120
--- /dev/null
@@ -0,0 +1,84 @@
+/* SH specific core note handling.
+   Copyright (C) 2010 Matt Fleming <matt@console-pimps.org>
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils 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; version 2 of the License.
+
+   Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND                sh_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)                                               \
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+    GR (0, 16, 0),             /* r0-r15 */
+    GR (16, 1, 16),            /* pc */
+    GR (17, 1, 17),            /* pr */
+    GR (18, 1, 22),            /* sr */
+    GR (19, 1, 18),            /* gbr */
+    GR (20, 1, 20),            /* mach */
+    GR (21, 1, 21),            /* macl */
+    /*  22, 1,                    tra */
+#undef GR
+  };
+#define PRSTATUS_REGS_SIZE     (23 * 4)
+
+#define        ULONG                   uint32_t
+#define PID_T                  int32_t
+#define        UID_T                   uint16_t
+#define        GID_T                   uint16_t
+#define ALIGN_ULONG            4
+#define ALIGN_PID_T            4
+#define ALIGN_UID_T            2
+#define ALIGN_GID_T            2
+#define TYPE_ULONG             ELF_T_WORD
+#define TYPE_PID_T             ELF_T_SWORD
+#define TYPE_UID_T             ELF_T_HALF
+#define TYPE_GID_T             ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS                                                \
+  {                                                                          \
+    .name = "tra", .type = ELF_T_ADDR, .format = 'x',                        \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[22]),               \
+    .group = "register"                                                              \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 25, .count = 16, .bits = 32 }, /* fr0-fr15 */
+    { .offset = 16, .regno = 87, .count = 16, .bits = 32 }, /* xf0-xf15 */
+    { .offset = 32, .regno = 24, .count = 1, .bits = 32 }, /* fpscr */
+    { .offset = 33, .regno = 23, .count = 1, .bits = 32 }  /* fpul */
+  };
+#define FPREGSET_SIZE          (50 * 4)
+
+#include "linux-core-note.c"
index 02502ab222bdfa40cd3880c3a2f8094f350b573b..7b36e7a34d5f4996cd838774abaaadf08f48d54c 100644 (file)
@@ -51,6 +51,11 @@ sh_init (elf, machine, eh, ehlen)
   eh->name = "Hitachi SH";
   sh_init_reloc (eh);
   HOOK (eh, reloc_simple_type);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, core_note);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
 
   return MODVERSION;
 }
diff --git a/backends/sh_regs.c b/backends/sh_regs.c
new file mode 100644 (file)
index 0000000..dbf4acc
--- /dev/null
@@ -0,0 +1,187 @@
+/* Register names and numbers for SH DWARF.
+   Copyright (C) 2010 Matt Fleming <matt@console-pimps.org>
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils 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; version 2 of the License.
+
+   Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+ssize_t
+sh_register_info (Ebl *ebl __attribute__ ((unused)),
+                 int regno, char *name, size_t namelen,
+                 const char **prefix, const char **setname,
+                 int *bits, int *type)
+{
+  if (name == NULL)
+    return 104;
+
+  if (regno < 0 || regno > 103 || namelen < 6)
+    return -1;
+
+  *prefix = NULL;
+  *bits = 32;
+  *type = DW_ATE_signed;
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'c';
+      namelen = 2;
+      break;
+
+    case 17:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 18:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 's';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 19:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 'g';
+      name[1] = 'b';
+      name[2] = 'r';
+      namelen = 3;
+      break;
+
+    case 20:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'h';
+      namelen = 4;
+      break;
+
+    case 21:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'l';
+      namelen = 4;
+
+      break;
+
+    case 23:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 'u';
+      name[3] = 'l';
+      namelen = 4;
+      break;
+
+    case 24:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 's';
+      name[3] = 'c';
+      name[4] = 'r';
+      namelen = 5;
+      break;
+
+    case 25 ... 34:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = regno - 25 + '0';
+      namelen = 3;
+      break;
+
+    case 35 ... 40:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = '1';
+      name[3] = regno - 35 + '0';
+      namelen = 4;
+      break;
+
+    case 87 ... 96:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = regno - 87 + '0';
+      namelen = 3;
+      break;
+
+    case 97 ... 103:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = '1';
+      name[3] = regno - 97 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
new file mode 100644 (file)
index 0000000..07769a3
--- /dev/null
@@ -0,0 +1,138 @@
+/* Function return value location for Linux/SH ABI.
+   Copyright (C) 2010 Matt Fleming <matt@console-pimps.org>
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils 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; version 2 of the License.
+
+   Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+
+/* This is the SVR4 ELF ABI convention, but AIX and Linux do not use it.  */
+#define SVR4_STRUCT_RETURN 0
+
+
+/* r0, or pair r0, r1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg    1
+#define nloc_intregpair        4
+
+/* fr0 or fr1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg25 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg26 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg     1
+#define nloc_fpregpair 2
+
+int
+sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type,
+                                               &attr_mem);
+  if (attr == NULL)
+    /* The function has no return value, like a `void' function in C.  */
+    return 0;
+
+  Dwarf_Die die_mem;
+  Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
+  int tag = dwarf_tag (typedie);
+
+  /* Follow typedefs and qualifiers to get to the actual type.  */
+  while (tag == DW_TAG_typedef
+        || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
+        || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+    {
+      attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+      typedie = dwarf_formref_die (attr, &die_mem);
+      tag = dwarf_tag (typedie);
+    }
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+       {
+         attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+         typedie = dwarf_formref_die (attr, &die_mem);
+         tag = dwarf_tag (typedie);
+       }
+      /* Fall through.  */
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+                                                &attr_mem), &size) != 0)
+       {
+         if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+           size = 4;
+         else
+           return -1;
+       }
+      if (size <= 8)
+       {
+         if (tag == DW_TAG_base_type)
+           {
+             Dwarf_Word encoding;
+             if (dwarf_formudata (dwarf_attr_integrate (typedie,
+                                                        DW_AT_encoding,
+                                                        &attr_mem),
+                                  &encoding) != 0)
+               return -1;
+             if (encoding == DW_ATE_float)
+               {
+                 *locp = loc_fpreg;
+                 return size <= 4 ? nloc_fpreg : nloc_fpregpair;
+               }
+           }
+         *locp = loc_intreg;
+         return size <= 4 ? nloc_intreg : nloc_intregpair;
+       }
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
index 26000ccb5b463744cf538f8bb732b2c1e18578a9..9fb5db44b7b22fbad5f9f7843c475384de9c7d65 100644 (file)
@@ -54,3 +54,38 @@ sh_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
       return ELF_T_NUM;
     }
 }
+
+/* Check whether machine flags are valid.  */
+bool
+sh_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH_UNKNOWN:
+    case EF_SH1:
+    case EF_SH2:
+    case EF_SH3:
+    case EF_SH_DSP:
+    case EF_SH3_DSP:
+    case EF_SH4AL_DSP:
+    case EF_SH3E:
+    case EF_SH4:
+    case EF_SH2E:
+    case EF_SH4A:
+    case EF_SH2A:
+    case EF_SH4_NOFPU:
+    case EF_SH4A_NOFPU:
+    case EF_SH4_NOMMU_NOFPU:
+    case EF_SH2A_NOFPU:
+    case EF_SH3_NOMMU:
+    case EF_SH2A_SH4_NOFPU:
+    case EF_SH2A_SH3_NOFPU:
+    case EF_SH2A_SH4:
+    case EF_SH2A_SH3E:
+      break;
+    default:
+      return false;
+    }
+
+  return ((flags &~ (EF_SH_MACH_MASK)) == 0);
+}
index b6e9f32b8ac179a190f8a676409ce3363751d687..158c3049828f67897d692ba66ecfd9d2514c87e0 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-10  Matt Fleming  <matt@console-pimps.org>
+
+       * elf.h: Add SH specific ELF header flags.
+
 2010-04-06  Roland McGrath  <roland@redhat.com>
 
        * elf_error.c (ELF_E_FD_MISMATCH_IDX): Avoid nonobvious abbreviation
index f41a02649e37639b26f4a832c2a545ee96e5e166..418bbd5528ea2e80c44f49cad1df415c58acd7ef 100644 (file)
@@ -2476,6 +2476,30 @@ typedef Elf32_Addr Elf32_Conflict;
 
 /* SH specific declarations */
 
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_SH_MACH_MASK                0x1f
+#define EF_SH_UNKNOWN          0x0
+#define EF_SH1                 0x1
+#define EF_SH2                 0x2
+#define EF_SH3                 0x3
+#define EF_SH_DSP              0x4
+#define EF_SH3_DSP             0x5
+#define EF_SH4AL_DSP           0x6
+#define EF_SH3E                        0x8
+#define EF_SH4                 0x9
+#define EF_SH2E                        0xb
+#define EF_SH4A                        0xc
+#define EF_SH2A                        0xd
+#define EF_SH4_NOFPU           0x10
+#define EF_SH4A_NOFPU          0x11
+#define EF_SH4_NOMMU_NOFPU     0x12
+#define EF_SH2A_NOFPU          0x13
+#define EF_SH3_NOMMU           0x14
+#define EF_SH2A_SH4_NOFPU      0x15
+#define EF_SH2A_SH3_NOFPU      0x16
+#define EF_SH2A_SH4            0x17
+#define EF_SH2A_SH3E           0x18
+
 /* SH relocs.  */
 #define        R_SH_NONE               0
 #define        R_SH_DIR32              1