summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2005-11-17 03:16:00 +0000
committerRoland McGrath <roland@redhat.com>2005-11-17 03:16:00 +0000
commite47ab76f02c2a4f4d802ec298969ba67956435fe (patch)
tree39dccb25273f15a488632c952738909f860c4b71
parentd7f8d0caa7a357f9f4765e5dc93255f5057eba2e (diff)
downloadelfutils-e47ab76f02c2a4f4d802ec298969ba67956435fe.tar.gz
Update new test after merge.
-rw-r--r--ChangeLog3
-rw-r--r--Makefile.am2
-rw-r--r--backends/ChangeLog3
-rw-r--r--backends/Makefile.am130
-rw-r--r--backends/alpha_init.c (renamed from libebl/alpha_init.c)1
-rw-r--r--backends/alpha_reloc.def (renamed from libebl/alpha_reloc.def)0
-rw-r--r--backends/alpha_retval.c148
-rw-r--r--backends/alpha_symbol.c (renamed from libebl/alpha_symbol.c)0
-rw-r--r--backends/arm_init.c (renamed from libebl/arm_init.c)0
-rw-r--r--backends/arm_reloc.def (renamed from libebl/arm_reloc.def)0
-rw-r--r--backends/arm_symbol.c (renamed from libebl/arm_symbol.c)0
-rw-r--r--backends/common-reloc.c (renamed from libebl/common-reloc.c)0
-rw-r--r--backends/i386_corenote.c (renamed from libebl/i386_corenote.c)0
-rw-r--r--backends/i386_init.c (renamed from libebl/i386_init.c)1
-rw-r--r--backends/i386_reloc.def (renamed from libebl/i386_reloc.def)0
-rw-r--r--backends/i386_retval.c139
-rw-r--r--backends/i386_symbol.c (renamed from libebl/i386_symbol.c)0
-rw-r--r--backends/ia64_init.c (renamed from libebl/ia64_init.c)0
-rw-r--r--backends/ia64_reloc.def (renamed from libebl/ia64_reloc.def)0
-rw-r--r--backends/ia64_symbol.c (renamed from libebl/ia64_symbol.c)0
-rw-r--r--backends/libebl_CPU.h (renamed from libebl/libebl_CPU.h)0
-rw-r--r--backends/ppc64_init.c (renamed from libebl/ppc64_init.c)1
-rw-r--r--backends/ppc64_reloc.def (renamed from libebl/ppc64_reloc.def)0
-rw-r--r--backends/ppc64_retval.c168
-rw-r--r--backends/ppc64_symbol.c (renamed from libebl/ppc64_symbol.c)0
-rw-r--r--backends/ppc_init.c (renamed from libebl/ppc_init.c)1
-rw-r--r--backends/ppc_reloc.def (renamed from libebl/ppc_reloc.def)0
-rw-r--r--backends/ppc_retval.c141
-rw-r--r--backends/ppc_symbol.c (renamed from libebl/ppc_symbol.c)0
-rw-r--r--backends/s390_init.c (renamed from libebl/s390_init.c)0
-rw-r--r--backends/s390_reloc.def (renamed from libebl/s390_reloc.def)0
-rw-r--r--backends/s390_symbol.c (renamed from libebl/s390_symbol.c)0
-rw-r--r--backends/sh_init.c (renamed from libebl/sh_init.c)0
-rw-r--r--backends/sh_reloc.def (renamed from libebl/sh_reloc.def)0
-rw-r--r--backends/sh_symbol.c (renamed from libebl/sh_symbol.c)0
-rw-r--r--backends/sparc_init.c (renamed from libebl/sparc_init.c)0
-rw-r--r--backends/sparc_reloc.def (renamed from libebl/sparc_reloc.def)0
-rw-r--r--backends/sparc_symbol.c (renamed from libebl/sparc_symbol.c)0
-rw-r--r--backends/x86_64_corenote.c (renamed from libebl/x86_64_corenote.c)0
-rw-r--r--backends/x86_64_init.c (renamed from libebl/x86_64_init.c)1
-rw-r--r--backends/x86_64_reloc.def (renamed from libebl/x86_64_reloc.def)0
-rw-r--r--backends/x86_64_retval.c189
-rw-r--r--backends/x86_64_symbol.c (renamed from libebl/x86_64_symbol.c)0
-rw-r--r--configure.ac3
-rw-r--r--libasm/ChangeLog4
-rw-r--r--libasm/Makefile.am3
-rw-r--r--libdw/ChangeLog8
-rw-r--r--libdw/Makefile.am3
-rw-r--r--libdw/libdw.map3
-rw-r--r--libdwfl/ChangeLog13
-rw-r--r--libdwfl/Makefile.am3
-rw-r--r--libdwfl/dwfl_module_return_value_location.c49
-rw-r--r--libdwfl/libdwfl.h15
-rw-r--r--libdwfl/libdwflP.h3
-rw-r--r--libebl/ChangeLog78
-rw-r--r--libebl/Makefile.am93
-rw-r--r--libebl/ebl-hooks.h5
-rw-r--r--libebl/eblopenbackend.c10
-rw-r--r--libebl/eblretval.c29
-rw-r--r--libebl/libebl.h14
-rw-r--r--tests/ChangeLog14
-rw-r--r--tests/Makefile.am10
-rwxr-xr-xtests/coverage.sh2
-rw-r--r--tests/funcretval.c100
64 files changed, 1291 insertions, 99 deletions
diff --git a/ChangeLog b/ChangeLog
index ae80f975..92384a2d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,9 @@
2005-11-15 Roland McGrath <roland@redhat.com>
+ * Makefile.am (all_SUBDIRS): Add backends.
+ * configure.ac: Write backends/Makefile.
+
* configure.ac: Add --enable-tests-rpath option.
2005-09-16 Roland McGrath <roland@redhat.com>
diff --git a/Makefile.am b/Makefile.am
index ef24c416..e7e93cdf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ ACLOCAL_AMFLAGS = -I m4
mini_SUBDIRS = config m4 lib libelf libelf-po
# Add doc back when we have some real content.
-all_SUBDIRS = libebl libdwfl libdw libcpu libasm src po tests
+all_SUBDIRS = libebl libdwfl libdw libcpu libasm backends src po tests
SUBDIRS = $(mini_SUBDIRS) $(all_SUBDIRS)
EXTRA_DIST = elfutils.spec GPG-KEY NOTES COPYING.GPL
diff --git a/backends/ChangeLog b/backends/ChangeLog
new file mode 100644
index 00000000..3715690d
--- /dev/null
+++ b/backends/ChangeLog
@@ -0,0 +1,3 @@
+2005-11-15 Roland McGrath <roland@redhat.com>
+
+ * Contents moved here from ../libebl.
diff --git a/backends/Makefile.am b/backends/Makefile.am
new file mode 100644
index 00000000..eed9badd
--- /dev/null
+++ b/backends/Makefile.am
@@ -0,0 +1,130 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 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.
+##
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DOBJDIR=\"$(shell pwd)\"
+if MUDFLAP
+AM_CFLAGS = -fmudflap
+else
+AM_CFLAGS =
+endif
+AM_CFLAGS += -fpic -Wall -Wshadow -Werror -Wunused -Wextra -Wformat=2 \
+ -std=gnu99
+INCLUDES = -I$(srcdir) -I$(top_srcdir)/libebl \
+ -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw \
+ -I$(top_srcdir)/lib -I..
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+
+modules = i386 sh x86_64 ia64 alpha arm sparc ppc ppc64 s390
+libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a \
+ libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a \
+ libebl_sparc_pic.a libebl_ppc_pic.a libebl_ppc64_pic.a \
+ libebl_s390_pic.a
+noinst_LIBRARIES = $(libebl_pic)
+noinst_DATA = $(libebl_pic:_pic.a=.so)
+
+
+if MUDFLAP
+libelf = ../libelf/libelf.a
+libdw = ../libdw/libdw.a
+libmudflap = -lmudflap
+else
+libelf = ../libelf/libelf.so
+libdw = ../libdw/libdw.so
+libmudflap =
+endif
+
+
+textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+
+libebl_%.so: libebl_%_pic.a libebl_%.map $(libelf) $(libdw)
+ $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
+ -Wl,--version-script,$(word 2,$^) \
+ -Wl,-z,defs -Wl,--as-needed $(libelf) $(libdw) $(libmudflap)
+ $(textrel_check)
+
+libebl_%.map: Makefile
+ echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' > $@
+
+
+i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_retval.c
+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
+libebl_sh_pic_a_SOURCES = $(sh_SRCS)
+am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
+
+x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_retval.c
+libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
+am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
+
+ia64_SRCS = ia64_init.c ia64_symbol.c
+libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
+am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
+
+alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c
+libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
+am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
+
+arm_SRCS = arm_init.c arm_symbol.c
+libebl_arm_pic_a_SOURCES = $(arm_SRCS)
+am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
+
+sparc_SRCS = sparc_init.c sparc_symbol.c
+libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
+am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
+
+ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c
+libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
+am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
+
+ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.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
+libebl_s390_pic_a_SOURCES = $(s390_SRCS)
+am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
+
+
+%.os: %.c %.o
+ if $(COMPILE) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+ rm -f "$(DEPDIR)/$*.Tpo"; \
+ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+ fi
+
+install: install-am install-ebl-modules
+install-ebl-modules:
+ $(mkinstalldirs) $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
+ for m in $(modules); do \
+ $(INSTALL_PROGRAM) libebl_$${m}.so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
+ ln -fs libebl_$${m}-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
+ done
+
+uninstall: uninstall-am
+ for m in $(modules); do \
+ rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
+ rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
+ done
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)$(pkgincludedir)
+
+noinst_HEADERS = libebl_CPU.h common-reloc.c
+EXTRA_DIST = $(foreach m,$(modules),$($(m)_SRCS)) $(modules:=_reloc.def)
+
+CLEANFILES = *.gcno *.gcda \
+ $(foreach m,$(modules),$(am_libebl_$(m)_pic_a_OBJECTS))
diff --git a/libebl/alpha_init.c b/backends/alpha_init.c
index 1ef87d63..76a9bfb3 100644
--- a/libebl/alpha_init.c
+++ b/backends/alpha_init.c
@@ -41,6 +41,7 @@ alpha_init (elf, machine, eh, ehlen)
eh->dynamic_tag_name = alpha_dynamic_tag_name;
eh->dynamic_tag_check = alpha_dynamic_tag_check;
eh->reloc_simple_type = alpha_reloc_simple_type;
+ eh->return_value_location = alpha_return_value_location;
return MODVERSION;
}
diff --git a/libebl/alpha_reloc.def b/backends/alpha_reloc.def
index 488f448c..488f448c 100644
--- a/libebl/alpha_reloc.def
+++ b/backends/alpha_reloc.def
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
new file mode 100644
index 00000000..e1301515
--- /dev/null
+++ b/backends/alpha_retval.c
@@ -0,0 +1,148 @@
+/* Function return value location for Alpha ELF ABI.
+ Copyright (C) 2005 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 alpha_
+#include "libebl_CPU.h"
+
+
+/* $0. */
+static const Dwarf_Op loc_intreg[] =
+ {
+ { .atom = DW_OP_reg0 }
+ };
+#define nloc_intreg 1
+
+/* $f0, or pair $f0, $f1. */
+static const Dwarf_Op loc_fpreg[] =
+ {
+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
+ };
+#define nloc_fpreg 1
+#define nloc_fpregpair 4
+
+/* 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 $0. */
+static const Dwarf_Op loc_aggregate[] =
+ {
+ { .atom = DW_OP_breg0, .number = 0 }
+ };
+#define nloc_aggregate 1
+
+int
+alpha_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);
+ }
+
+ 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_Word size;
+ 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 = 8;
+ 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;
+
+ *locp = loc_fpreg;
+ if (encoding == DW_ATE_float)
+ {
+ if (size <= 8)
+ return nloc_fpreg;
+ goto aggregate;
+ }
+ if (encoding == DW_ATE_complex_float)
+ {
+ if (size <= 8 * 2)
+ return nloc_fpregpair;
+ goto aggregate;
+ }
+ }
+ if (size <= 8)
+ {
+ *locp = loc_intreg;
+ return nloc_intreg;
+ }
+ }
+
+ /* Else fall through. */
+
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ case DW_TAG_string_type:
+ case DW_TAG_array_type:
+ aggregate:
+ *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;
+}
diff --git a/libebl/alpha_symbol.c b/backends/alpha_symbol.c
index b2e4cf77..b2e4cf77 100644
--- a/libebl/alpha_symbol.c
+++ b/backends/alpha_symbol.c
diff --git a/libebl/arm_init.c b/backends/arm_init.c
index ee739078..ee739078 100644
--- a/libebl/arm_init.c
+++ b/backends/arm_init.c
diff --git a/libebl/arm_reloc.def b/backends/arm_reloc.def
index b76be778..b76be778 100644
--- a/libebl/arm_reloc.def
+++ b/backends/arm_reloc.def
diff --git a/libebl/arm_symbol.c b/backends/arm_symbol.c
index 6eb40fc5..6eb40fc5 100644
--- a/libebl/arm_symbol.c
+++ b/backends/arm_symbol.c
diff --git a/libebl/common-reloc.c b/backends/common-reloc.c
index 0575e131..0575e131 100644
--- a/libebl/common-reloc.c
+++ b/backends/common-reloc.c
diff --git a/libebl/i386_corenote.c b/backends/i386_corenote.c
index 20750a9d..20750a9d 100644
--- a/libebl/i386_corenote.c
+++ b/backends/i386_corenote.c
diff --git a/libebl/i386_init.c b/backends/i386_init.c
index 477243f3..a1056e73 100644
--- a/libebl/i386_init.c
+++ b/backends/i386_init.c
@@ -42,6 +42,7 @@ i386_init (elf, machine, eh, ehlen)
eh->core_note = i386_core_note;
generic_debugscn_p = eh->debugscn_p;
eh->debugscn_p = i386_debugscn_p;
+ eh->return_value_location = i386_return_value_location;
return MODVERSION;
}
diff --git a/libebl/i386_reloc.def b/backends/i386_reloc.def
index ba750d0d..ba750d0d 100644
--- a/libebl/i386_reloc.def
+++ b/backends/i386_reloc.def
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
new file mode 100644
index 00000000..34cae064
--- /dev/null
+++ b/backends/i386_retval.c
@@ -0,0 +1,139 @@
+/* Function return value location for Linux/i386 ABI.
+ Copyright (C) 2005 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 i386_
+#include "libebl_CPU.h"
+
+
+/* %eax, or pair %eax, %edx. */
+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
+
+/* %st(0). */
+static const Dwarf_Op loc_fpreg[] =
+ {
+ { .atom = DW_OP_reg11 }
+ };
+#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 %eax. */
+static const Dwarf_Op loc_aggregate[] =
+ {
+ { .atom = DW_OP_breg0, .number = 0 }
+ };
+#define nloc_aggregate 1
+
+int
+i386_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);
+ }
+
+ 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_Word size;
+ 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 = 4;
+ 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)
+ {
+ if (size > 16)
+ return -2;
+ *locp = loc_fpreg;
+ return nloc_fpreg;
+ }
+ }
+ *locp = loc_intreg;
+ if (size <= 4)
+ return nloc_intreg;
+ if (size <= 8)
+ return nloc_intregpair;
+
+ /* Else 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;
+}
diff --git a/libebl/i386_symbol.c b/backends/i386_symbol.c
index dadcc107..dadcc107 100644
--- a/libebl/i386_symbol.c
+++ b/backends/i386_symbol.c
diff --git a/libebl/ia64_init.c b/backends/ia64_init.c
index 1431f2de..1431f2de 100644
--- a/libebl/ia64_init.c
+++ b/backends/ia64_init.c
diff --git a/libebl/ia64_reloc.def b/backends/ia64_reloc.def
index a0d42155..a0d42155 100644
--- a/libebl/ia64_reloc.def
+++ b/backends/ia64_reloc.def
diff --git a/libebl/ia64_symbol.c b/backends/ia64_symbol.c
index 1b500873..1b500873 100644
--- a/libebl/ia64_symbol.c
+++ b/backends/ia64_symbol.c
diff --git a/libebl/libebl_CPU.h b/backends/libebl_CPU.h
index 607c1543..607c1543 100644
--- a/libebl/libebl_CPU.h
+++ b/backends/libebl_CPU.h
diff --git a/libebl/ppc64_init.c b/backends/ppc64_init.c
index c8a93546..9024eafa 100644
--- a/libebl/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -44,6 +44,7 @@ ppc64_init (elf, machine, eh, ehlen)
eh->copy_reloc_p = ppc64_copy_reloc_p;
eh->check_special_symbol = ppc64_check_special_symbol;
eh->bss_plt_p = ppc64_bss_plt_p;
+ eh->return_value_location = ppc64_return_value_location;
return MODVERSION;
}
diff --git a/libebl/ppc64_reloc.def b/backends/ppc64_reloc.def
index d0cb2f91..d0cb2f91 100644
--- a/libebl/ppc64_reloc.def
+++ b/backends/ppc64_reloc.def
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
new file mode 100644
index 00000000..81852915
--- /dev/null
+++ b/backends/ppc64_retval.c
@@ -0,0 +1,168 @@
+/* Function return value location for Linux/PPC64 ABI.
+ Copyright (C) 2005 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 ppc64_
+#include "libebl_CPU.h"
+
+
+/* r3. */
+static const Dwarf_Op loc_intreg[] =
+ {
+ { .atom = DW_OP_reg3 }
+ };
+#define nloc_intreg 1
+
+/* f1, or f1:f2, or f1:f4. */
+static const Dwarf_Op loc_fpreg[] =
+ {
+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 8 },
+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
+ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 8 },
+ { .atom = DW_OP_regx, .number = 36 }, { .atom = DW_OP_piece, .number = 8 },
+ };
+#define nloc_fpreg 1
+#define nloc_fp2regs 4
+#define nloc_fp4regs 8
+
+/* 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 r3. */
+static const Dwarf_Op loc_aggregate[] =
+ {
+ { .atom = DW_OP_breg3, .number = 0 }
+ };
+#define nloc_aggregate 1
+
+int
+ppc64_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:
+ 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 = 8;
+ 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 || encoding == DW_ATE_complex_float)
+ {
+ *locp = loc_fpreg;
+ if (size <= 8)
+ return nloc_fpreg;
+ if (size <= 16)
+ return nloc_fp2regs;
+ if (size <= 32)
+ return nloc_fp4regs;
+ }
+ }
+ if (size <= 8)
+ {
+ intreg:
+ *locp = loc_intreg;
+ return nloc_intreg;
+ }
+
+ /* Else fall through. */
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ aggregate:
+ *locp = loc_aggregate;
+ return nloc_aggregate;
+
+ case DW_TAG_string_type:
+ case DW_TAG_array_type:
+ if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+ &attr_mem), &size) == 0
+ && size <= 8)
+ {
+ if (tag == DW_TAG_array_type)
+ {
+ /* Check if it's a character array. */
+ attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
+ typedie = dwarf_formref_die (attr, &die_mem);
+ tag = dwarf_tag (typedie);
+ if (tag != DW_TAG_base_type)
+ goto aggregate;
+ if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ return -1;
+ if (size != 1)
+ goto aggregate;
+ }
+ goto intreg;
+ }
+ goto 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;
+}
diff --git a/libebl/ppc64_symbol.c b/backends/ppc64_symbol.c
index db486176..db486176 100644
--- a/libebl/ppc64_symbol.c
+++ b/backends/ppc64_symbol.c
diff --git a/libebl/ppc_init.c b/backends/ppc_init.c
index 375b79ed..36ca7a24 100644
--- a/libebl/ppc_init.c
+++ b/backends/ppc_init.c
@@ -43,6 +43,7 @@ ppc_init (elf, machine, eh, ehlen)
eh->dynamic_tag_check = ppc_dynamic_tag_check;
eh->check_special_symbol = ppc_check_special_symbol;
eh->bss_plt_p = ppc_bss_plt_p;
+ eh->return_value_location = ppc_return_value_location;
return MODVERSION;
}
diff --git a/libebl/ppc_reloc.def b/backends/ppc_reloc.def
index 97187381..97187381 100644
--- a/libebl/ppc_reloc.def
+++ b/backends/ppc_reloc.def
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
new file mode 100644
index 00000000..369c5997
--- /dev/null
+++ b/backends/ppc_retval.c
@@ -0,0 +1,141 @@
+/* Function return value location for Linux/PPC ABI.
+ Copyright (C) 2005 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 ppc_
+#include "libebl_CPU.h"
+
+
+/* r3, or pair r3, r4. */
+static const Dwarf_Op loc_intreg[] =
+ {
+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+ { .atom = DW_OP_reg4 }, { .atom = DW_OP_piece, .number = 4 },
+ };
+#define nloc_intreg 1
+#define nloc_intregpair 4
+
+/* f1. */
+static const Dwarf_Op loc_fpreg[] =
+ {
+ { .atom = DW_OP_regx, .number = 33 }
+ };
+#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 r3. */
+static const Dwarf_Op loc_aggregate[] =
+ {
+ { .atom = DW_OP_breg3, .number = 0 }
+ };
+#define nloc_aggregate 1
+
+int
+ppc_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:
+ 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 = 4;
+ else
+ return -1;
+ }
+ if (size <= 8)
+ {
+ 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)
+ {
+ *locp = loc_fpreg;
+ return nloc_fpreg;
+ }
+ }
+ intreg:
+ *locp = loc_intreg;
+ return size <= 4 ? nloc_intreg : nloc_intregpair;
+ }
+
+ aggregate:
+ *locp = loc_aggregate;
+ return nloc_aggregate;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ case DW_TAG_array_type:
+ if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+ &attr_mem), &size) == 0
+ && size > 0 && size <= 8)
+ goto intreg;
+ goto 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;
+}
diff --git a/libebl/ppc_symbol.c b/backends/ppc_symbol.c
index f161d70e..f161d70e 100644
--- a/libebl/ppc_symbol.c
+++ b/backends/ppc_symbol.c
diff --git a/libebl/s390_init.c b/backends/s390_init.c
index 14578660..14578660 100644
--- a/libebl/s390_init.c
+++ b/backends/s390_init.c
diff --git a/libebl/s390_reloc.def b/backends/s390_reloc.def
index bee67b33..bee67b33 100644
--- a/libebl/s390_reloc.def
+++ b/backends/s390_reloc.def
diff --git a/libebl/s390_symbol.c b/backends/s390_symbol.c
index ddfefbb2..ddfefbb2 100644
--- a/libebl/s390_symbol.c
+++ b/backends/s390_symbol.c
diff --git a/libebl/sh_init.c b/backends/sh_init.c
index 4fadd9b4..4fadd9b4 100644
--- a/libebl/sh_init.c
+++ b/backends/sh_init.c
diff --git a/libebl/sh_reloc.def b/backends/sh_reloc.def
index 56db1071..56db1071 100644
--- a/libebl/sh_reloc.def
+++ b/backends/sh_reloc.def
diff --git a/libebl/sh_symbol.c b/backends/sh_symbol.c
index 3209d34e..3209d34e 100644
--- a/libebl/sh_symbol.c
+++ b/backends/sh_symbol.c
diff --git a/libebl/sparc_init.c b/backends/sparc_init.c
index 541df842..541df842 100644
--- a/libebl/sparc_init.c
+++ b/backends/sparc_init.c
diff --git a/libebl/sparc_reloc.def b/backends/sparc_reloc.def
index 91fcad74..91fcad74 100644
--- a/libebl/sparc_reloc.def
+++ b/backends/sparc_reloc.def
diff --git a/libebl/sparc_symbol.c b/backends/sparc_symbol.c
index c83e5d3a..c83e5d3a 100644
--- a/libebl/sparc_symbol.c
+++ b/backends/sparc_symbol.c
diff --git a/libebl/x86_64_corenote.c b/backends/x86_64_corenote.c
index 2fd775b6..2fd775b6 100644
--- a/libebl/x86_64_corenote.c
+++ b/backends/x86_64_corenote.c
diff --git a/libebl/x86_64_init.c b/backends/x86_64_init.c
index e4799725..22147a1f 100644
--- a/libebl/x86_64_init.c
+++ b/backends/x86_64_init.c
@@ -41,6 +41,7 @@ x86_64_init (elf, machine, eh, ehlen)
x86_64_init_reloc (eh);
eh->reloc_simple_type = x86_64_reloc_simple_type;
eh->core_note = x86_64_core_note;
+ eh->return_value_location = x86_64_return_value_location;
return MODVERSION;
}
diff --git a/libebl/x86_64_reloc.def b/backends/x86_64_reloc.def
index 83a18280..83a18280 100644
--- a/libebl/x86_64_reloc.def
+++ b/backends/x86_64_reloc.def
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
new file mode 100644
index 00000000..210d5392
--- /dev/null
+++ b/backends/x86_64_retval.c
@@ -0,0 +1,189 @@
+/* Function return value location for Linux/x86-64 ABI.
+ Copyright (C) 2005 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 x86_64_
+#include "libebl_CPU.h"
+
+
+/* %rax, or pair %rax, %rdx. */
+static const Dwarf_Op loc_intreg[] =
+ {
+ { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+ { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 },
+ };
+#define nloc_intreg 1
+#define nloc_intregpair 4
+
+/* %st(0), or pair %st(0), %st(1). */
+static const Dwarf_Op loc_x87reg[] =
+ {
+ { .atom = DW_OP_regx, .number = 33 },
+ { .atom = DW_OP_piece, .number = 10 },
+ { .atom = DW_OP_regx, .number = 34 },
+ { .atom = DW_OP_piece, .number = 10 },
+ };
+#define nloc_x87reg 1
+#define nloc_x87regpair 4
+
+/* %xmm0, or pair %xmm0, %xmm1. */
+static const Dwarf_Op loc_ssereg[] =
+ {
+ { .atom = DW_OP_reg17 }, { .atom = DW_OP_piece, .number = 16 },
+ { .atom = DW_OP_reg18 }, { .atom = DW_OP_piece, .number = 16 },
+ };
+#define nloc_ssereg 1
+#define nloc_sseregpair 4
+
+/* 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 %rax. */
+static const Dwarf_Op loc_aggregate[] =
+ {
+ { .atom = DW_OP_breg0, .number = 0 }
+ };
+#define nloc_aggregate 1
+
+
+int
+x86_64_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:
+ 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 = 8;
+ 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;
+
+ switch (encoding)
+ {
+ case DW_ATE_complex_float:
+ switch (size)
+ {
+ case 4 * 2: /* complex float */
+ case 8 * 2: /* complex double */
+ *locp = loc_ssereg;
+ return nloc_sseregpair;
+ case 16 * 2: /* complex long double */
+ *locp = loc_x87reg;
+ return nloc_x87regpair;
+ }
+ return -2;
+
+ case DW_ATE_float:
+ switch (size)
+ {
+ case 4: /* float */
+ case 8: /* double */
+ *locp = loc_ssereg;
+ return nloc_ssereg;
+ case 16: /* long double */
+ /* XXX distinguish __float128, which is sseregpair?? */
+ *locp = loc_x87reg;
+ return nloc_x87reg;
+ }
+ return -2;
+ }
+ }
+
+ intreg:
+ *locp = loc_intreg;
+ if (size <= 8)
+ return nloc_intreg;
+ if (size <= 16)
+ return nloc_intregpair;
+
+ large:
+ *locp = loc_aggregate;
+ return nloc_aggregate;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ case DW_TAG_array_type:
+ if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+ &attr_mem), &size) != 0)
+ return -1;
+ if (size > 16)
+ goto large;
+
+ /* XXX
+ Must examine the fields in picayune ways to determine the
+ actual answer. This will be right for small C structs
+ containing integer types and similarly simple cases.
+ */
+
+ goto intreg;
+ }
+
+ /* 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;
+}
diff --git a/libebl/x86_64_symbol.c b/backends/x86_64_symbol.c
index c48af103..c48af103 100644
--- a/libebl/x86_64_symbol.c
+++ b/backends/x86_64_symbol.c
diff --git a/configure.ac b/configure.ac
index 53e33ea2..2d6f2b6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -194,6 +194,9 @@ dnl Assembler library.
AM_CONDITIONAL(HAVE_LIBASM, true)dnl Used in tests/Makefile.am, which see.
AC_CONFIG_FILES([libasm/Makefile])
+dnl CPU-specific backend libraries.
+AC_CONFIG_FILES([backends/Makefile])
+
dnl Tools.
AC_CONFIG_FILES([src/Makefile po/Makefile.in])
diff --git a/libasm/ChangeLog b/libasm/ChangeLog
index e25e197b..56d2961e 100644
--- a/libasm/ChangeLog
+++ b/libasm/ChangeLog
@@ -1,3 +1,7 @@
+2005-11-13 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am (INCLUDES): Search in libdw.
+
2005-09-02 Ulrich Drepper <drepper@redhat.com>
* asm_error.c (asm_errmsg): Unify error message.
diff --git a/libasm/Makefile.am b/libasm/Makefile.am
index e9b99397..03c4ce04 100644
--- a/libasm/Makefile.am
+++ b/libasm/Makefile.am
@@ -19,7 +19,8 @@ else
AM_CFLAGS =
endif
AM_CFLAGS += -std=gnu99 -Wall -Wshadow -Werror -Wunused -Wextra -Wformat=2
-INCLUDES = -I. -I$(srcdir) -I.. -I$(top_srcdir)/libelf -I$(top_srcdir)/libebl \
+INCLUDES = -I. -I$(srcdir) -I.. \
+ -I$(top_srcdir)/libelf -I$(top_srcdir)/libebl -I$(top_srcdir)/libdw\
-I$(top_srcdir)/lib
GCC_INCLUDE = -I$(shell $(CC) -print-file-name=include)
VERSION = 1
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 0c8539ef..4ccaf95a 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2005-11-15 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am [BUILD_STATIC] (AM_CFLAGS): Add -fpic.
+
+2005-11-13 Roland McGrath <roland@redhat.com>
+
+ * libdw.map: Bump to 0.117; export dwfl_module_return_value_location.
+
2005-10-27 Roland McGrath <roland@redhat.com>
* dwarf_entry_breakpoints.c (search_range): Fix binary search code;
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 6e53312e..daa807cd 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -18,6 +18,9 @@ AM_CFLAGS = -fmudflap
else
AM_CFLAGS =
endif
+if BUILD_STATIC
+AM_CFLAGS += -fpic
+endif
AM_CFLAGS += -Wall -Werror -Wshadow -Wunused -Wformat=2 -Wextra -std=gnu99
INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libelf -I.. -I$(srcdir)/../lib
VERSION = 1
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 493df48e..15e5d0ae 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -1,5 +1,5 @@
ELFUTILS_0 { };
-ELFUTILS_0.116 {
+ELFUTILS_0.117 {
global:
dwarf_abbrevhaschildren;
dwarf_addrdie;
@@ -124,6 +124,7 @@ ELFUTILS_0.116 {
dwfl_module_relocate_address;
dwfl_module_relocation_info;
dwfl_module_relocations;
+ dwfl_module_return_value_location;
dwfl_nextcu;
dwfl_offline_section_address;
dwfl_onesrcline;
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 60bd68b3..0a015e76 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,16 @@
+2005-11-15 Roland McGrath <roland@redhat.com>
+
+ * libdwfl.h: Comment fixes.
+
+ * dwfl_module_return_value_location.c: Add unlikely for error case.
+
+2005-11-13 Roland McGrath <roland@redhat.com>
+
+ * dwfl_return_value_location.c: New file.
+ * Makefile.am (libdwfl_a_SOURCES): Add it.
+ * libdwfl.h: Declare dwfl_module_return_value_location.
+ * libdwflP.h (DWFL_ERRORS): Add DWFL_E_WEIRD_TYPE.
+
2005-10-20 Roland McGrath <roland@redhat.com>
* libdwflP.h (DWFL_ERRORS): New error UNKNOWN_MACHINE.
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
index 510e7599..b2f4e9d2 100644
--- a/libdwfl/Makefile.am
+++ b/libdwfl/Makefile.am
@@ -52,7 +52,8 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c \
dwfl_module_getsrc.c dwfl_getsrc.c \
dwfl_module_getsrc_file.c \
libdwfl_crc32.c libdwfl_crc32_file.c \
- elf-from-memory.c
+ elf-from-memory.c \
+ dwfl_module_return_value_location.c
if MUDFLAP
diff --git a/libdwfl/dwfl_module_return_value_location.c b/libdwfl/dwfl_module_return_value_location.c
new file mode 100644
index 00000000..336e8f39
--- /dev/null
+++ b/libdwfl/dwfl_module_return_value_location.c
@@ -0,0 +1,49 @@
+/* Return location expression to find return value given a function type DIE.
+ Copyright (C) 2005 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. */
+
+#include "libdwflP.h"
+
+
+int
+dwfl_module_return_value_location (mod, functypedie, locops)
+ Dwfl_Module *mod;
+ Dwarf_Die *functypedie;
+ const Dwarf_Op **locops;
+{
+ if (mod == NULL)
+ return -1;
+
+ if (mod->ebl == NULL)
+ {
+ mod->ebl = ebl_openbackend (mod->main.elf);
+ if (mod->ebl == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBEBL);
+ return -1;
+ }
+ }
+
+ int nops = ebl_return_value_location (mod->ebl, functypedie, locops);
+ if (unlikely (nops < 0))
+ {
+ if (nops == -1)
+ __libdwfl_seterrno (DWFL_E_LIBDW);
+ else if (nops == -2)
+ __libdwfl_seterrno (DWFL_E_WEIRD_TYPE);
+ else
+ __libdwfl_seterrno (DWFL_E_LIBEBL);
+ nops = -1;
+ }
+
+ return nops;
+}
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 64e38d59..8b069e27 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -328,8 +328,21 @@ extern const char *dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr,
/* Find the symbol that ADDRESS lies inside, and return its name. */
-const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address);
+extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address);
+/* Return location expression to find return value given a
+ DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing
+ function itself (whose DW_AT_type attribute describes its return type).
+ The given DIE must come from the given module. Returns -1 for errors.
+ Returns zero if the function has no return value (e.g. "void" in C).
+ Otherwise, *LOCOPS gets a location expression to find the return value,
+ and returns the number of operations in the expression. The pointer is
+ permanently allocated at least as long as the module is live. */
+extern int dwfl_module_return_value_location (Dwfl_Module *mod,
+ Dwarf_Die *functypedie,
+ const Dwarf_Op **locops);
+
+
#endif /* libdwfl.h */
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index c4f303ed..6c1bcd8e 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -52,7 +52,8 @@
DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range")) \
DWFL_ERROR (NO_MATCH, N_("no matching address range")) \
DWFL_ERROR (TRUNCATED, N_("image truncated")) \
- DWFL_ERROR (BADELF, N_("not a valid ELF file"))
+ DWFL_ERROR (BADELF, N_("not a valid ELF file")) \
+ DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description"))
#define DWFL_ERROR(name, text) DWFL_E_##name,
typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 5c66d56f..be170608 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -2,6 +2,64 @@
* libebl.h: Use "" for elf-knowledge.h, not <>.
+2005-11-15 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am: Removed everything for building libebl_*.so modules,
+ now in ../backends/Makefile.am instead.
+ * alpha_init.c: Moved to ../backends.
+ * alpha_reloc.def: Likewise.
+ * alpha_retval.c: Likewise.
+ * alpha_symbol.c: Likewise.
+ * arm_init.c: Likewise.
+ * arm_reloc.def: Likewise.
+ * arm_symbol.c: Likewise.
+ * common-reloc.c: Likewise.
+ * i386_corenote.c: Likewise.
+ * i386_init.c: Likewise.
+ * i386_reloc.def: Likewise.
+ * i386_retval.c: Likewise.
+ * i386_symbol.c: Likewise.
+ * ia64_init.c: Likewise.
+ * ia64_reloc.def: Likewise.
+ * ia64_symbol.c: Likewise.
+ * libebl_CPU.h: Likewise.
+ * ppc64_init.c: Likewise.
+ * ppc64_reloc.def: Likewise.
+ * ppc64_retval.c: Likewise.
+ * ppc64_symbol.c: Likewise.
+ * ppc_init.c: Likewise.
+ * ppc_reloc.def: Likewise.
+ * ppc_retval.c: Likewise.
+ * ppc_symbol.c: Likewise.
+ * s390_init.c: Likewise.
+ * s390_reloc.def: Likewise.
+ * s390_symbol.c: Likewise.
+ * sh_init.c: Likewise.
+ * sh_reloc.def: Likewise.
+ * sh_symbol.c: Likewise.
+ * sparc_init.c: Likewise.
+ * sparc_reloc.def: Likewise.
+ * sparc_symbol.c: Likewise.
+ * x86_64_corenote.c: Likewise.
+ * x86_64_init.c: Likewise.
+ * x86_64_reloc.def: Likewise.
+ * x86_64_retval.c: Likewise.
+ * x86_64_symbol.c: Likewise.
+
+ * libebl.h: Comment fixes.
+
+ * alpha_retval.c: New file.
+ * Makefile.am (alpha_SRCS): Add it.
+ * alpha_init.c (alpha_init): Initialize return_value_location hook.
+
+ * ppc64_retval.c: New file.
+ * Makefile.am (ppc64_SRCS): Add it.
+ * ppc64_init.c (ppc64_init): Initialize return_value_location hook.
+
+ * ppc_retval.c: New file.
+ * Makefile.am (ppc_SRCS): Add it.
+ * ppc_init.c (ppc_init): Initialize return_value_location hook.
+
2005-11-14 Roland McGrath <roland@redhat.com>
* ia64_init.c (ia64_init): Initialize EH->reloc_simple_type.
@@ -23,6 +81,26 @@
* alpha_reloc.def: Update bits per Richard Henderson <rth@redhat.com>.
+2005-11-13 Roland McGrath <roland@redhat.com>
+
+ * x86_64_retval.c: New file.
+ * Makefile.am (x86_64_SRCS): Add it.
+ * x86_64_init.c (x86_64_init): Use x86_64_return_value_location.
+
+ * i386_retval.c: New file.
+ * Makefile.am (i386_SRCS): Add it.
+ (libdw): New variable.
+ (libebl_%.so): Use $(libdw) in link; use --as-needed.
+ * i386_init.c (i386_init): Use i386_return_value_location.
+
+ * eblretval.c: New file.
+ * Makefile.am (gen_SOURCES): Add it.
+ (INCLUDES): Search in libdw.
+ * libebl.h: Include <libdw.h>. Declare ebl_return_value_location.
+ * ebl-hooks.h: Declare return_value_location hook.
+ * eblopenbackend.c (default_return_value_location): New function.
+ (fill_defaults): Use it.
+
2005-11-10 Roland McGrath <roland@redhat.com>
* s390_init.c: New file.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 51b97ff2..f7c4a953 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -21,19 +21,13 @@ endif
AM_CFLAGS += -fpic -Wall -Wshadow -Werror -Wunused -Wextra -Wformat=2 \
-std=gnu99
-INCLUDES = -I$(srcdir) -I$(top_srcdir)/libelf -I$(top_srcdir)/lib -I..
+INCLUDES = -I$(srcdir) -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw \
+ -I$(top_srcdir)/lib -I..
VERSION = 1
PACKAGE_VERSION = @PACKAGE_VERSION@
LIBEBL_SUBDIR = @LIBEBL_SUBDIR@
lib_LIBRARIES = libebl.a
-modules = i386 sh x86_64 ia64 alpha arm sparc ppc ppc64 s390
-libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a \
- libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a \
- libebl_sparc_pic.a libebl_ppc_pic.a libebl_ppc64_pic.a \
- libebl_s390_pic.a
-noinst_LIBRARIES = $(libebl_pic)
-noinst_DATA = $(libebl_pic:_pic.a=.so)
pkginclude_HEADERS = libebl.h
@@ -49,69 +43,10 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
eblcorenote.c eblobjnote.c ebldebugscnp.c \
eblgotpcreloccheck.c eblcopyrelocp.c eblsectionstripp.c \
eblelfclass.c eblelfdata.c eblelfmachine.c \
- ebl_check_special_symbol.c eblbsspltp.c
+ ebl_check_special_symbol.c eblbsspltp.c eblretval.c
libebl_a_SOURCES = $(gen_SOURCES)
-i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c
-libebl_i386_pic_a_SOURCES = $(i386_SRCS)
-am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
-
-if MUDFLAP
-libelf = ../libelf/libelf.a
-libmudflap = -lmudflap
-else
-libelf = ../libelf/libelf.so
-libmudflap =
-endif
-
-textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
-
-libebl_%.so: libebl_%_pic.a libebl_%.map
- $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
- -Wl,--version-script,$(word 2,$^) \
- -Wl,-z,defs $(libelf) $(libmudflap)
- $(textrel_check)
-
-libebl_%.map: Makefile
- echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' > $@
-
-sh_SRCS = sh_init.c sh_symbol.c
-libebl_sh_pic_a_SOURCES = $(sh_SRCS)
-am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
-
-x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c
-libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
-am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
-
-ia64_SRCS = ia64_init.c ia64_symbol.c
-libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
-am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
-
-alpha_SRCS = alpha_init.c alpha_symbol.c
-libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
-am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
-
-arm_SRCS = arm_init.c arm_symbol.c
-libebl_arm_pic_a_SOURCES = $(arm_SRCS)
-am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
-
-sparc_SRCS = sparc_init.c sparc_symbol.c
-libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
-am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
-
-ppc_SRCS = ppc_init.c ppc_symbol.c
-libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
-am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
-
-ppc64_SRCS = ppc64_init.c ppc64_symbol.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
-libebl_s390_pic_a_SOURCES = $(s390_SRCS)
-am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
-
%.os: %.c %.o
if $(COMPILE) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
@@ -121,24 +56,6 @@ am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
fi
-install: install-am install-ebl-modules
-install-ebl-modules:
- $(mkinstalldirs) $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
- for m in $(modules); do \
- $(INSTALL_PROGRAM) libebl_$${m}.so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
- ln -fs libebl_$${m}-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
- done
-
-uninstall: uninstall-am
- for m in $(modules); do \
- rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
- rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
- done
- rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
- rmdir --ignore-fail-on-non-empty $(DESTDIR)$(pkgincludedir)
-
-noinst_HEADERS = libeblP.h ebl-hooks.h libebl_CPU.h common-reloc.c
-EXTRA_DIST = $(foreach m,$(modules),$($(m)_SRCS)) $(modules:=_reloc.def)
+noinst_HEADERS = libeblP.h ebl-hooks.h
-CLEANFILES = $(am_libebl_pic_a_OBJECTS) *.gcno *.gcda \
- $(foreach m,$(modules),$(am_libebl_$(m)_pic_a_OBJECTS))
+CLEANFILES = $(am_libebl_pic_a_OBJECTS) *.gcno *.gcda
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 1056c42b..90a66c18 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -87,5 +87,10 @@ bool EBLHOOK(check_special_symbol) (Elf *, GElf_Ehdr *, const GElf_Sym *,
/* Check if backend uses a bss PLT in this file. */
bool EBLHOOK(bss_plt_p) (Elf *, GElf_Ehdr *);
+/* Return location expression to find return value given the
+ DW_AT_type DIE of a DW_TAG_subprogram DIE. */
+int EBLHOOK(return_value_location) (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp);
+
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 9afbc88b..092cb97a 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -158,6 +158,8 @@ static bool default_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
const char *name,
const GElf_Shdr *destshdr);
static bool default_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr);
+static int default_return_value_location (Dwarf_Die *functypedie,
+ const Dwarf_Op **locops);
static void
@@ -188,6 +190,7 @@ fill_defaults (Ebl *result)
result->copy_reloc_p = default_copy_reloc_p;
result->check_special_symbol = default_check_special_symbol;
result->bss_plt_p = default_bss_plt_p;
+ result->return_value_location = default_return_value_location;
result->destr = default_destr;
}
@@ -577,3 +580,10 @@ default_bss_plt_p (Elf *elf __attribute__ ((unused)),
{
return false;
}
+
+static int
+default_return_value_location (Dwarf_Die *functypedie __attribute__ ((unused)),
+ const Dwarf_Op **locops __attribute__ ((unused)))
+{
+ return -2;
+}
diff --git a/libebl/eblretval.c b/libebl/eblretval.c
new file mode 100644
index 00000000..d23d9805
--- /dev/null
+++ b/libebl/eblretval.c
@@ -0,0 +1,29 @@
+/* Return location expression to find return value given a function type DIE.
+ Copyright (C) 2005 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 <inttypes.h>
+#include <libeblP.h>
+
+
+int
+ebl_return_value_location (ebl, functypedie, locops)
+ Ebl *ebl;
+ Dwarf_Die *functypedie;
+ const Dwarf_Op **locops;
+{
+ return ebl == NULL ? -1 : ebl->return_value_location (functypedie, locops);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 1f9a5a25..7e91b308 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -15,6 +15,7 @@
#define _LIBEBL_H 1
#include <gelf.h>
+#include "libdw.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -156,6 +157,19 @@ extern bool ebl_section_strip_p (Ebl *ebl, const GElf_Ehdr *ehdr,
/* Check if backend uses a bss PLT in this file. */
extern bool ebl_bss_plt_p (Ebl *ebl, GElf_Ehdr *ehdr);
+/* Return location expression to find return value given a
+ DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing
+ function itself (whose DW_AT_type attribute describes its return type).
+ Returns -1 for a libdw error (see dwarf_errno).
+ Returns -2 for an unrecognized type formation.
+ Returns zero if the function has no return value (e.g. "void" in C).
+ Otherwise, *LOCOPS gets a location expression to find the return value,
+ and returns the number of operations in the expression. The pointer is
+ permanently allocated at least as long as the Ebl handle is open. */
+extern int ebl_return_value_location (Ebl *ebl,
+ Dwarf_Die *functypedie,
+ const Dwarf_Op **locops);
+
/* ELF string table handling. */
struct Ebl_Strtab;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index e74b639c..956955c5 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -34,12 +34,20 @@
* show-die-info.c: Likewise.
* update3.c: Likewise.
* update4.c: Likewise.
+ * funcretval.c: Likewise.
* dwflmodtest.c (print_instance): Don't use INTUSE.
(options): Don't use N_ macro.
2005-11-15 Roland McGrath <roland@redhat.com>
+ * coverage.sh: Look in backends.
+ * Makefile.am (BUILD_RPATH): Search ../backends, not ../libebl.
+ (TESTS_ENVIRONMENT): Likewise.
+
+ * funcretval.c (handle_function): Don't take DW_AT_type of FUNCDIE,
+ pass FUNCDIE direclty to dwfl_module_return_value_location.
+
* Makefile.am (BUILD_RPATH): New variable.
[TESTS_RPATH] (AM_LDFLAGS): Pass -rpath option using that value.
(tests_rpath): New variable.
@@ -79,6 +87,12 @@
* run-strings-test.sh: Likewise.
* run-strip-test.sh: Likewise.
+2005-11-13 Roland McGrath <roland@redhat.com>
+
+ * funcretval.c: New file.
+ * Makefile.am (noinst_PROGRAMS): Add it.
+ (funcretval_LDADD): New variable.
+
2005-11-09 Ulrich Drepper <drepper@redhat.com>
* line2addr.c (handle_module): Add missing parameter to printf.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 98e6f035..8cc73284 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,11 +16,11 @@ DEFS = -DHAVE_CONFIG_H -D_GNU_SOURCE
if MUDFLAP
AM_CFLAGS = -Wall -Werror -Wextra -std=gnu99 -fmudflap\
$(if $($(*F)_no_Wformat),-Wno-format,-Wformat=2)
-BUILD_RPATH = \$$ORIGIN/../libebl
+BUILD_RPATH = \$$ORIGIN/../backends
else
AM_CFLAGS = -Wall -Werror -Wextra -std=gnu99 \
$(if $($(*F)_no_Wformat),-Wno-format,-Wformat=2)
-BUILT_RPATH = \$$ORIGIN/../libasm:\$$ORIGIN/../libdw:\$$ORIGIN/../libebl:\$$ORIGIN/../libelf
+BUILT_RPATH = \$$ORIGIN/../libasm:\$$ORIGIN/../libdw:\$$ORIGIN/../backends:\$$ORIGIN/../libelf
endif
if !STANDALONE
@@ -41,7 +41,8 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
showptable update1 update2 update3 update4 test-nlist \
show-die-info get-files get-lines get-pubnames \
get-aranges allfcts line2addr addrscopes funcscopes \
- show-abbrev hash newscn ecp dwflmodtest find-prologues
+ show-abbrev hash newscn ecp dwflmodtest \
+ find-prologues funcretval
# get-ciefde
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -102,7 +103,7 @@ if STANDALONE
TESTS_ENVIRONMENT = $(installed_TESTS_ENVIRONMENT)
else !STANDALONE
TESTS_ENVIRONMENT = $(srcdir)/test-wrapper.sh \
- ../libdw:../libebl:../libelf:../libasm
+ ../libdw:../backends:../libelf:../libasm
installcheck-local:
$(MAKE) $(AM_MAKEFLAGS) \
@@ -159,6 +160,7 @@ line2addr_no_Wformat = yes
line2addr_LDADD = $(libdw) $(libmudflap)
addrscopes_LDADD = $(libdw) $(libmudflap)
funcscopes_LDADD = $(libdw) $(libmudflap)
+funcretval_LDADD = $(libdw) $(libmudflap)
find_prologues_LDADD = $(libdw) $(libmudflap)
#show_ciefde_LDADD = ../libdwarf/libdwarf.so $(libelf) $(libmudflap)
asm_tst1_LDADD = $(libasm) $(libebl) $(libelf) $(libmudflap) -ldl
diff --git a/tests/coverage.sh b/tests/coverage.sh
index f09f644f..288ee990 100755
--- a/tests/coverage.sh
+++ b/tests/coverage.sh
@@ -2,7 +2,7 @@
cd ..
-for d in lib libasm libdw libdwfl libebl libelf src; do
+for d in lib libasm libdw libdwfl libebl libelf backends src; do
tmp=$d-data
cd $d
unused=0
diff --git a/tests/funcretval.c b/tests/funcretval.c
new file mode 100644
index 00000000..66e04f6b
--- /dev/null
+++ b/tests/funcretval.c
@@ -0,0 +1,100 @@
+/* Test program for dwfl_module_return_value_location.
+ Copyright (C) 2005 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. */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <error.h>
+#include <string.h>
+#include <fnmatch.h>
+
+
+struct args
+{
+ Dwfl *dwfl;
+ Dwarf_Die *cu;
+ Dwarf_Addr dwbias;
+ char **argv;
+};
+
+static int
+handle_function (Dwarf_Die *funcdie, void *arg)
+{
+ struct args *a = arg;
+
+ const char *name = dwarf_diename (funcdie);
+ char **argv = a->argv;
+ if (argv[0] != NULL)
+ {
+ bool match;
+ do
+ match = fnmatch (*argv, name, 0) == 0;
+ while (!match && *++argv);
+ if (!match)
+ return 0;
+ }
+
+ printf ("(%s) %s: ", dwfl_module_info (dwfl_cumodule (a->cu), NULL,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL), name);
+
+ const Dwarf_Op *locops;
+ int nlocops = dwfl_module_return_value_location (dwfl_cumodule (a->cu),
+ funcdie, &locops);
+ if (nlocops < 0)
+ error (EXIT_FAILURE, 0, "dwfl_module_return_value_location: %s",
+ dwfl_errmsg (-1));
+ else if (nlocops == 0)
+ puts ("returns no value");
+ else
+ {
+ printf ("return value location:");
+ for (int i = 0; i < nlocops; ++i)
+ printf (" {%#x, %#" PRIx64 "}", locops[i].atom, locops[i].number);
+ puts ("");
+ }
+
+ return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int remaining;
+
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ struct args a = { .dwfl = NULL, .cu = NULL };
+
+ (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+ &a.dwfl);
+ assert (a.dwfl != NULL);
+ a.argv = &argv[remaining];
+
+ int result = 0;
+
+ while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
+ dwarf_getfuncs (a.cu, &handle_function, &a, 0);
+
+ return result;
+}