forked from rpms/elfutils
		
	Drop upstreamed patches elfutils-0.190-fix-core-noncontig.patch Drop testcore-noncontig.bz2 Add elfutils-0.191-profile-empty-urls.patch Add elfutils-0.191-riscv-flatten.patch Add feature flag for reenabling elfutils-libelf-devel-static and elfutils-devel-static Resolves: RHEL-29194
		
			
				
	
	
		
			360 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			360 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From e39336df6588c3f9853be7d02819aee262ba2121 Mon Sep 17 00:00:00 2001
 | |
| From: Mark Wielaard <mark@klomp.org>
 | |
| Date: Tue, 19 Mar 2024 22:43:10 +0000
 | |
| Subject: [PATCH] riscv: Partial implementation of flatten_aggregate
 | |
| 
 | |
| dwfl_module_return_value_location would fail on riscv for functions
 | |
| which return a (small) struct. This patch implements the simplest
 | |
| cases of flatten_aggregate in backends/riscv_retval.c. It just handles
 | |
| structs containing one or two members of the same base type which fit
 | |
| completely or in pieces in one or two general or floating point
 | |
| registers.
 | |
| 
 | |
| It also adds a specific test case run-funcretval-struct.sh containing
 | |
| small structs of ints, longs, floats and doubles. All these testscases
 | |
| now work for riscv. There is already a slightly more extensive
 | |
| testcase for this in tests/run-funcretval.sh but that only has a
 | |
| testcase for aarch64.
 | |
| 
 | |
| 	 * backends/riscv_retval.c (flatten_aggregate_arg): Implement
 | |
|          for the simple cases where we have a struct with one or two
 | |
|          members of the same base type.
 | |
| 	 (pass_by_flattened_arg): Likewise. Call either
 | |
| 	 pass_in_gpr_lp64 or pass_in_fpr_lp64d.
 | |
| 	 (riscv_return_value_location_lp64ifd): Call
 | |
| 	 flatten_aggregate_arg including size.
 | |
| 	 * tests/Makefile.am (TESTS): Add run-funcretval-struct.sh
 | |
| 	 and run-funcretval-struct-native.sh.
 | |
| 	 (check_PROGRAMS): Add funcretval_test_struct.
 | |
| 	 (funcretval_test_struct_SOURCES): New.
 | |
| 	 (EXTRA_DIST): Add run-funcretval-struct.sh,
 | |
| 	 funcretval_test_struct_riscv.bz2 and
 | |
| 	 run-funcretval-struct-native.sh.
 | |
| 	 * tests/funcretval_test_struct_riscv.bz2: New test binary.
 | |
| 	 * tests/run-funcretval-struct-native.sh: New test.
 | |
| 	 * tests/run-funcretval-struct.sh: Likewise.
 | |
| 
 | |
| https://sourceware.org/bugzilla/show_bug.cgi?id=31142
 | |
| 
 | |
| Signed-off-by: Mark Wielaard <mark@klomp.org>
 | |
| ---
 | |
|  backends/riscv_retval.c                | 123 ++++++++++++++++++++++---
 | |
|  tests/Makefile.am                      |   7 ++
 | |
|  tests/funcretval_test_struct.c         |  86 +++++++++++++++++
 | |
|  tests/funcretval_test_struct_riscv.bz2 | Bin 0 -> 3821 bytes
 | |
|  tests/run-funcretval-struct-native.sh  |  22 +++++
 | |
|  tests/run-funcretval-struct.sh         |  35 +++++++
 | |
|  6 files changed, 262 insertions(+), 11 deletions(-)
 | |
|  create mode 100644 tests/funcretval_test_struct.c
 | |
|  create mode 100755 tests/funcretval_test_struct_riscv.bz2
 | |
|  create mode 100755 tests/run-funcretval-struct-native.sh
 | |
|  create mode 100755 tests/run-funcretval-struct.sh
 | |
| 
 | |
| Fedora NOTE: Both the riscv specific test files weren't included
 | |
|              (funcretval_test_struct_riscv.bz2 and run-funcretval-struct.sh)
 | |
|              Because it contained a binary test. The native test is included
 | |
|              though.
 | |
| 
 | |
| diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c
 | |
| index 0a1e02f81cd2..50c451a4ba32 100644
 | |
| --- a/backends/riscv_retval.c
 | |
| +++ b/backends/riscv_retval.c
 | |
| @@ -1,6 +1,7 @@
 | |
|  /* Function return value location for Linux/RISC-V ABI.
 | |
|     Copyright (C) 2018 Sifive, Inc.
 | |
|     Copyright (C) 2013 Red Hat, Inc.
 | |
| +   Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
 | |
|     This file is part of elfutils.
 | |
|  
 | |
|     This file is free software; you can redistribute it and/or modify
 | |
| @@ -105,23 +106,123 @@ pass_in_fpr_lp64d (const Dwarf_Op **locp, Dwarf_Word size)
 | |
|    return size <= 8 ? 1 : 4;
 | |
|  }
 | |
|  
 | |
| +/* Checks if we can "flatten" the given type, Only handles the simple
 | |
| +   cases where we have a struct with one or two the same base type
 | |
| +   elements.  */
 | |
|  static int
 | |
| -flatten_aggregate_arg (Dwarf_Die *typedie __attribute__ ((unused)),
 | |
| -		       Dwarf_Die *arg0 __attribute__ ((unused)),
 | |
| -		       Dwarf_Die *arg1 __attribute__ ((unused)))
 | |
| +flatten_aggregate_arg (Dwarf_Die *typedie,
 | |
| +		       Dwarf_Word size,
 | |
| +		       Dwarf_Die *arg0,
 | |
| +		       Dwarf_Die *arg1)
 | |
|  {
 | |
| -  /* ??? */
 | |
| +  int tag0, tag1;
 | |
| +  Dwarf_Die member;
 | |
| +  Dwarf_Word encoding0, encoding1;
 | |
| +  Dwarf_Attribute attr;
 | |
| +  Dwarf_Word size0, size1;
 | |
| +
 | |
| +  if (size < 8 || size > 16)
 | |
| +    return 0;
 | |
| +
 | |
| +  if (dwarf_child (typedie, arg0) != 0)
 | |
| +    return 0;
 | |
| +
 | |
| +  tag0 = dwarf_tag (arg0);
 | |
| +  while (tag0 != -1 && tag0 != DW_TAG_member)
 | |
| +    {
 | |
| +      if (dwarf_siblingof (arg0, arg0) != 0)
 | |
| +	return 0;
 | |
| +      tag0 = dwarf_tag (arg0);
 | |
| +    }
 | |
| +
 | |
| +  if (tag0 != DW_TAG_member)
 | |
| +    return 0;
 | |
| +
 | |
| +  /* Remember where we are.  */
 | |
| +  member = *arg0;
 | |
| +
 | |
| +  tag0 = dwarf_peeled_die_type (arg0, arg0);
 | |
| +  if (tag0 != DW_TAG_base_type)
 | |
| +    return 0;
 | |
| +
 | |
| +  if (dwarf_attr_integrate (arg0, DW_AT_encoding, &attr) == NULL
 | |
| +      || dwarf_formudata (&attr, &encoding0) != 0)
 | |
| +    return 0;
 | |
| +
 | |
| +  if (dwarf_bytesize_aux (arg0, &size0) != 0)
 | |
| +    return 0;
 | |
| +
 | |
| +  if (size == size0)
 | |
| +    return 1; /* This one member is the whole size. */
 | |
| +
 | |
| +  if (size != 2 * size0)
 | |
| +    return 0; /* We only handle two of the same.  */
 | |
| +
 | |
| +  /* Look for another member with the same encoding.  */
 | |
| +  if (dwarf_siblingof (&member, arg1) != 0)
 | |
| +    return 0;
 | |
| +
 | |
| +  tag1 = dwarf_tag (arg1);
 | |
| +  while (tag1 != -1 && tag1 != DW_TAG_member)
 | |
| +    {
 | |
| +      if (dwarf_siblingof (arg1, arg1) != 0)
 | |
| +	return 0;
 | |
| +      tag1 = dwarf_tag (arg1);
 | |
| +    }
 | |
| +
 | |
| +  if (tag1 != DW_TAG_member)
 | |
| +    return 0;
 | |
| +
 | |
| +  tag1 = dwarf_peeled_die_type (arg1, arg1);
 | |
| +  if (tag1 != DW_TAG_base_type)
 | |
| +    return 0; /* We can only handle two equal base types for now. */
 | |
| +
 | |
| +  if (dwarf_attr_integrate (arg1, DW_AT_encoding, &attr) == NULL
 | |
| +      || dwarf_formudata (&attr, &encoding1) != 0
 | |
| +      || encoding0 != encoding1)
 | |
| +    return 0; /* We can only handle two of the same for now. */
 | |
| +
 | |
| +  if (dwarf_bytesize_aux (arg1, &size1) != 0)
 | |
| +    return 0;
 | |
| +
 | |
| +  if (size0 != size1)
 | |
| +    return 0; /* We can only handle two of the same for now. */
 | |
| +
 | |
|    return 1;
 | |
|  }
 | |
|  
 | |
| +/* arg0 and arg1 should be the peeled die types found by
 | |
| +   flatten_aggregate_arg.  */
 | |
|  static int
 | |
| -pass_by_flattened_arg (const Dwarf_Op **locp __attribute__ ((unused)),
 | |
| -		       Dwarf_Word size __attribute__ ((unused)),
 | |
| -		       Dwarf_Die *arg0 __attribute__ ((unused)),
 | |
| -		       Dwarf_Die *arg1 __attribute__ ((unused)))
 | |
| +pass_by_flattened_arg (const Dwarf_Op **locp,
 | |
| +		       Dwarf_Word size,
 | |
| +		       Dwarf_Die *arg0,
 | |
| +		       Dwarf_Die *arg1 __attribute__((unused)))
 | |
|  {
 | |
| -  /* ??? */
 | |
| -  return -2;
 | |
| +  /* For now we just assume arg0 and arg1 are the same type and
 | |
| +     encoding.  */
 | |
| +  Dwarf_Word encoding;
 | |
| +  Dwarf_Attribute attr;
 | |
| +
 | |
| +  if (dwarf_attr_integrate (arg0, DW_AT_encoding, &attr) == NULL
 | |
| +      || dwarf_formudata (&attr, &encoding) != 0)
 | |
| +    return -1;
 | |
| +
 | |
| +  switch (encoding)
 | |
| +    {
 | |
| +    case DW_ATE_boolean:
 | |
| +    case DW_ATE_signed:
 | |
| +    case DW_ATE_unsigned:
 | |
| +    case DW_ATE_unsigned_char:
 | |
| +    case DW_ATE_signed_char:
 | |
| +      return pass_in_gpr_lp64 (locp, size);
 | |
| +
 | |
| +    case DW_ATE_float:
 | |
| +      return pass_in_fpr_lp64d (locp, size);
 | |
| +
 | |
| +    default:
 | |
| +      return -1;
 | |
| +    }
 | |
|  }
 | |
|  
 | |
|  int
 | |
| @@ -158,7 +259,7 @@ riscv_return_value_location_lp64ifd (int fp, Dwarf_Die *functypedie,
 | |
|  	 provided the floating-point real is no more than FLEN bits wide and
 | |
|  	 the integer is no more than XLEN bits wide.  */
 | |
|        if (tag == DW_TAG_structure_type
 | |
| -	  && flatten_aggregate_arg (&typedie, &arg0, &arg1))
 | |
| +	  && flatten_aggregate_arg (&typedie, size, &arg0, &arg1))
 | |
|  	return pass_by_flattened_arg (locp, size, &arg0, &arg1);
 | |
|        /* Aggregates larger than 2*XLEN bits are passed by reference.  */
 | |
|        else if (size > 16)
 | |
| diff --git a/tests/Makefile.am b/tests/Makefile.am
 | |
| index 9141074fe44c..9315ec3bbe4c 100644
 | |
| --- a/tests/Makefile.am
 | |
| +++ b/tests/Makefile.am
 | |
| @@ -284,6 +285,10 @@ funcretval_test__11_SOURCES = funcretval_test++11.cxx
 | |
|  TESTS += run-funcretval++11.sh
 | |
|  endif
 | |
|  
 | |
| +check_PROGRAMS += funcretval_test_struct
 | |
| +funcretval_test_struct_SOURCES = funcretval_test_struct.c
 | |
| +TESTS += run-funcretval-struct-native.sh
 | |
| +
 | |
|  EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 | |
|  	     run-ar-N.sh \
 | |
|  	     run-show-die-info.sh run-get-files.sh run-get-lines.sh \
 | |
| @@ -635,6 +641,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 | |
|  	     testfile_nvidia_linemap.bz2 \
 | |
|  	     testfile-largealign.o.bz2 run-strip-largealign.sh \
 | |
|  	     run-funcretval++11.sh \
 | |
| +	     run-funcretval-struct-native.sh \
 | |
|  	     test-ar-duplicates.a.bz2 \
 | |
|  	     run-dwfl-core-noncontig.sh testcore-noncontig.bz2 \
 | |
|  	     testfile-dwarf5-line-clang.bz2 \
 | |
| diff --git a/tests/funcretval_test_struct.c b/tests/funcretval_test_struct.c
 | |
| new file mode 100644
 | |
| index 000000000000..df94bde0a42d
 | |
| --- /dev/null
 | |
| +++ b/tests/funcretval_test_struct.c
 | |
| @@ -0,0 +1,86 @@
 | |
| +/* Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
 | |
| +   This file is part of elfutils.
 | |
| +
 | |
| +   This file 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.
 | |
| +
 | |
| +   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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 | |
| +
 | |
| +typedef struct
 | |
| +  {
 | |
| +    int q;
 | |
| +    int r;
 | |
| +  } div_t;
 | |
| +
 | |
| +typedef struct
 | |
| +  {
 | |
| +    long q;
 | |
| +    long r;
 | |
| +  } ldiv_t;
 | |
| +
 | |
| +typedef struct
 | |
| +  {
 | |
| +    float x;
 | |
| +    float y;
 | |
| +  } point_t;
 | |
| +
 | |
| +typedef struct
 | |
| +  {
 | |
| +    double x;
 | |
| +    double y;
 | |
| +  } dpoint_t;
 | |
| +
 | |
| +div_t __attribute__((__noinline__))
 | |
| +div (int n, int d)
 | |
| +{
 | |
| +  div_t r;
 | |
| +  r.q = n / d;
 | |
| +  r.r = n % d;
 | |
| +  return r;
 | |
| +}
 | |
| +
 | |
| +ldiv_t __attribute__((__noinline__))
 | |
| +ldiv (long n, long d)
 | |
| +{
 | |
| +  ldiv_t r;
 | |
| +  r.q = n / d;
 | |
| +  r.r = n % d;
 | |
| +  return r;
 | |
| +}
 | |
| +
 | |
| +point_t __attribute__((__noinline__))
 | |
| +mkpt (float x, float y)
 | |
| +{
 | |
| +  point_t r;
 | |
| +  r.x = x;
 | |
| +  r.y = y;
 | |
| +  return r;
 | |
| +}
 | |
| +
 | |
| +dpoint_t __attribute__((__noinline__))
 | |
| +dmkpt (double x, double y)
 | |
| +{
 | |
| +  dpoint_t r;
 | |
| +  r.x = x;
 | |
| +  r.y = y;
 | |
| +  return r;
 | |
| +}
 | |
| +
 | |
| +int
 | |
| +main (void)
 | |
| +{
 | |
| +  div_t d = div (3, 2);
 | |
| +  ldiv_t ld = ldiv (3, 2);
 | |
| +  point_t p = mkpt (3.0f, 1.0f);
 | |
| +  dpoint_t dp = dmkpt (3.0d, 1.0d);
 | |
| +
 | |
| +  return d.q - (int) p.y + ld.q - (int) dp.y;
 | |
| +}
 | |
| 
 | |
| diff --git a/tests/run-funcretval-struct-native.sh b/tests/run-funcretval-struct-native.sh
 | |
| new file mode 100755
 | |
| index 000000000000..798edb3b61b3
 | |
| --- /dev/null
 | |
| +++ b/tests/run-funcretval-struct-native.sh
 | |
| @@ -0,0 +1,22 @@
 | |
| +#! /bin/sh
 | |
| +# Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
 | |
| +# This file is part of elfutils.
 | |
| +#
 | |
| +# This file 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.
 | |
| +#
 | |
| +# 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| +
 | |
| +. $srcdir/test-subr.sh
 | |
| +
 | |
| +# Just run it, we don't know what the native representation is.
 | |
| +# But it should at least work and not error out.
 | |
| +testrun $abs_builddir/funcretval -e $abs_builddir/funcretval_test_struct
 | |
| -- 
 | |
| 2.44.0
 | |
| 
 |