This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[PATCH 5/5] Return value location support for SuperH.
- From: Matt Fleming <matt at console-pimps dot org>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Sat, 27 Mar 2010 19:32:01 +0000
- Subject: [PATCH 5/5] Return value location support for SuperH.
---
backends/Makefile.am | 2 +-
backends/sh_init.c | 1 +
backends/sh_retval.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+), 1 deletions(-)
create mode 100644 backends/sh_retval.c
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 28ea745..3ce448a 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -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_corenote.c sh_regs.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_init.c b/backends/sh_init.c
index 686467b..7b36e7a 100644
--- a/backends/sh_init.c
+++ b/backends/sh_init.c
@@ -55,6 +55,7 @@ sh_init (elf, machine, eh, ehlen)
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_retval.c b/backends/sh_retval.c
new file mode 100644
index 0000000..07769a3
--- /dev/null
+++ b/backends/sh_retval.c
@@ -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;
+}
--
1.7.0.2