]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
2006-01-12 Roland McGrath <roland@redhat.com>
authorRoland McGrath <roland@redhat.com>
Fri, 13 Jan 2006 00:51:21 +0000 (00:51 +0000)
committerRoland McGrath <roland@redhat.com>
Fri, 13 Jan 2006 00:51:21 +0000 (00:51 +0000)
* s390_retval.c: New file.
* Makefile.am (s390_SRCS): Add it.
* s390_init.c (s390_init): Install return_value_location hook.

backends/ChangeLog
backends/Makefile.am
backends/s390_init.c
backends/s390_retval.c [new file with mode: 0644]
config/elfutils.spec.in

index c7f82a979315bb6fe7aeaa2e0e97648a08562b98..84515e51d97b3a1ca9d10586f101cd22447d2a84 100644 (file)
@@ -1,3 +1,9 @@
+2006-01-12  Roland McGrath  <roland@redhat.com>
+
+       * s390_retval.c: New file.
+       * Makefile.am (s390_SRCS): Add it.
+       * s390_init.c (s390_init): Install return_value_location hook.
+
 2006-01-11  Roland McGrath  <roland@redhat.com>
 
        * s390_regs.c: New file.
index 7719b6f27d9e1a48cdc57ae88ec4b3591b16e4fe..d85d52fc7d349b65349a219add712ce509a8d262 100644 (file)
@@ -96,7 +96,7 @@ ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c ppc_regs.c
 libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
 am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
 
-s390_SRCS = s390_init.c s390_symbol.c s390_regs.c
+s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c
 libebl_s390_pic_a_SOURCES = $(s390_SRCS)
 am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
 
index d39495cf42703883657a31991f11bf3353f0d294..c956e82aa0f49ee2b5fd9cbee4b75f0d2de3d0ff 100644 (file)
@@ -39,6 +39,7 @@ s390_init (elf, machine, eh, ehlen)
   s390_init_reloc (eh);
   HOOK (eh, reloc_simple_type);
   HOOK (eh, register_name);
+  HOOK (eh, return_value_location);
 
   return MODVERSION;
 }
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
new file mode 100644 (file)
index 0000000..ca4da9c
--- /dev/null
@@ -0,0 +1,142 @@
+/* Function return value location for S/390 ABI.
+   Copyright (C) 2006 Red Hat, Inc.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+
+/* %r2, or pair %r2, %r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg    1
+#define nloc_intregpair        4
+
+/* %f0.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 },
+  };
+#define nloc_fpreg     1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %r2.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg2, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+s390_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 (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 (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 (typedie, DW_AT_byte_size))
+       {
+         attr = dwarf_attr (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:
+      {
+       Dwarf_Die cudie;
+       uint8_t asize;
+       if (dwarf_diecu (typedie, &cudie, &asize, NULL) == NULL)
+         return -1;
+
+       if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+                                        &attr_mem), &size) != 0)
+         {
+           if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+             size = asize;
+           else
+             return -1;
+         }
+       if (tag == DW_TAG_base_type)
+         {
+           Dwarf_Word encoding;
+           if (dwarf_formudata (dwarf_attr (typedie, DW_AT_encoding,
+                                            &attr_mem), &encoding) != 0)
+             return -1;
+           if (encoding == DW_ATE_float && size <= 8)
+             {
+               *locp = loc_fpreg;
+               return nloc_fpreg;
+             }
+         }
+       if (size <= 8)
+         {
+           *locp = loc_intreg;
+           return size <= asize ? nloc_intreg : nloc_intregpair;
+         }
+      }
+      /* Fall through.  */
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* 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 2c8245eb2d92bdc1de4b38b873cad30bc90677dd..70bdd79ad3e42b682b490a2e802b59b0faf7578f 100644 (file)
@@ -185,6 +185,11 @@ rm -rf ${RPM_BUILD_ROOT}
 %{_libdir}/libelf.so
 
 %changelog
+* Thu Jan 12 2006 Roland McGrath <roland@redhat.com> 0.118-1
+- elflint: more tests.
+- libdwfl: New function dwfl_module_register_names.
+- libebl: New backend hook for register names.
+
 * Tue Dec  6 2005 Ulrich Drepper <drepper@redhat.com> 0.118-1
 - elflint: more tests.
 - libdwfl: New function dwfl_module_register_names.