This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/2] Support AArch64 architecture


Hi Petr,

This all looks good. Just some nitpicks below. Feel free to ignore, I
don't actually expect you to refactor other backends and common methods.
Just noted you had some nice helpers that might be helpful for the next
backend porter.

On Thu, 2013-11-14 at 01:05 +0100, Petr Machata wrote:
> diff --git a/backends/ChangeLog b/backends/ChangeLog
> +2013-11-14  Petr Machata  <pmachata@redhat.com>
> +
> +	* Makefile.am (modules): Add aarch64.
> +	(libebl_pic): Add libebl_aarch64_pic.a.
> +	(aarch64_SRCS): New variable.
> +	(libebl_aarch64_pic_a_SOURCES): Likewise.
> +	(am_libebl_aarch64_pic_a_OBJECTS): Likewise.
> +	(aarch64_regs_no_Wformat): Likewise.

OK, but why do you need no_Wformat?

> +	* aarch64_corenote.c, aarch64_init.c: New files.
> +	* aarch64_regs.c, aarch64_reloc.def: Likewise.
> +	* aarch64_retval.c, aarch64_symbol.c: Likewise.

> +++ b/backends/aarch64_corenote.c
> @@ -0,0 +1,162 @@
> +/* AArch64 specific core note handling.

> +++ b/backends/aarch64_init.c
> @@ -0,0 +1,61 @@
> +/* Initialization of AArch64 specific backend library.

> diff --git a/backends/aarch64_regs.c b/backends/aarch64_regs.c
> +/* Register names and numbers for AArch64 DWARF.
> +  ssize_t
> +  regtype (const char *setname, int type, const char *fmt, int arg)
> +  {
> +    *setnamep = setname;
> +    *typep = type;
> +    int s = snprintf (name, namelen, fmt, arg);
> +    if (s > 0 && (unsigned) s >= namelen)
> +      s = -1;
> +    return s;
> +  }
> +
> +  ssize_t
> +  reserved (void)
> +  {
> +    return regtype (NULL, DW_ATE_void, "", 0);
> +  }

I would just have done *setnamep = NULL; return 0;
But I guess that will be how the compiler eventually optimizes it.

> diff --git a/backends/aarch64_reloc.def b/backends/aarch64_reloc.def
> @@ -0,0 +1,157 @@
> +/* List the relocation types for AArch64.  -*- C -*-

> diff --git a/backends/aarch64_retval.c b/backends/aarch64_retval.c
> +/* Function return value location for Linux/AArch64 ABI.

> +static int
> +peel_type (Dwarf_Die **typediep, Dwarf_Attribute **attrp)
> +{
> +  int tag = DWARF_TAG_OR_RETURN (*typediep);
> +  /* 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)
> +    {
> +      *attrp = dwarf_attr_integrate (*typediep, DW_AT_type, *attrp);
> +      *typediep = dwarf_formref_die (*attrp, *typediep);
> +      tag = DWARF_TAG_OR_RETURN (*typediep);
> +    }
> +
> +  return tag;
> +}

That might be handy in libebl_CPU.h so other backends can reuse it.

> +static int
> +get_die_type (Dwarf_Die *die, Dwarf_Die *result)
> +{
> +  Dwarf_Attribute attr_mem;
> +  Dwarf_Attribute *attr = dwarf_attr_integrate (die, DW_AT_type, &attr_mem);
> +  if (attr == NULL)
> +    /* The function has no return value, like a `void' function in C.  */
> +    return 0;
> +
> +  if (dwarf_formref_die (attr, result) == NULL)
> +    return -1;
> +
> +  return peel_type (&result, &attr);
> +}

Likewise.

> +static int
> +skip_until (Dwarf_Die *child, int tag)
> +{
> +  int i;
> +  while (DWARF_TAG_OR_RETURN (child) != tag)
> +    if ((i = dwarf_siblingof (child, child)) != 0)
> +      /* If there are no members, then this is not a HFA.  Errors
> +	 are propagated.  */
> +      return i;
> +  return 0;
> +}

Generic function, but specific to hfa_type. Maybe define there?

> +static int hfa_type (Dwarf_Die *ftypedie, int tag,
> +		     Dwarf_Word *sizep, Dwarf_Word *countp);

hfa is "homogeneous floating-point aggregate"?

> +/* Return 0 if MEMBDIE refers to a member with a floating-point or HFA
> +   type, or 1 if it's not.  Return -1 for errors.  The meaning of the
> +   remaining arguments is as documented at hfa_type.  */
> +static int
> +member_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp)
> +{
> +  Dwarf_Die type_die;
> +  int tag = get_die_type (membdie, &type_die);
> +  switch (tag)
> +    {
> +    case DW_TAG_base_type:;
> +      Dwarf_Word encoding;
> +      Dwarf_Attribute attr_mem;
> +      if (dwarf_attr_integrate (&type_die, DW_AT_encoding, &attr_mem) == NULL
> +	  || dwarf_formudata (&attr_mem, &encoding) != 0)
> +	return -1;
> +
> +      switch (encoding)
> +	{
> +	case DW_ATE_complex_float:
> +	  *countp = 2;
> +	  break;
> +
> +	case DW_ATE_float:
> +	  *countp = 1;
> +	  break;
> +
> +	default:
> +	  return 1;
> +	}
> +
> +      if (dwarf_formudata (dwarf_attr_integrate (&type_die, DW_AT_byte_size,
> +						 &attr_mem), sizep) != 0)
> +	return -1;

I guess we will never actually see DW_AT_bit_size.

> +      *sizep /= *countp;
> +      return 0;
> +
> +    case DW_TAG_structure_type:
> +    case DW_TAG_union_type:
> +    case DW_TAG_array_type:
> +      return hfa_type (&type_die, tag, sizep, countp);
> +    }
> +
> +  return 1;
> +}
> +
> +/* HFA (Homogeneous Floating-point Aggregate) is an aggregate type
> +   whose members are all of the same floating-point type, which is
> +   then base type of this HFA.  Instead of being floating-point types
> +   directly, members can instead themselves be HFA.  Such HFA fields
> +   are handled as if their type were HFA base type.
> +
> +   This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if
> +   there were errors.  In the former case, *SIZEP contains byte size
> +   of the base type (e.g. 8 for IEEE double).  *COUNT is set to the
> +   number of leaf members of the HFA.  */
> +static int
> +hfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp)
> +{
> +  assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type
> +	  || tag == DW_TAG_union_type || tag == DW_TAG_array_type);
> +
> +  int i;
> +  if (tag == DW_TAG_array_type)
> +    {
> +      Dwarf_Word tot_size;
> +      if (dwarf_aggregate_size (ftypedie, &tot_size) < 0)
> +	return -1;
> +
> +      /* For vector types, we don't care about the underlying
> +	 type, but only about the vector type itself.  */
> +      bool vec;
> +      Dwarf_Attribute attr_mem;
> +      if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector,
> +						&attr_mem), &vec) == 0
> +	  && vec)
> +	{
> +	  *sizep = tot_size;
> +	  *countp = 1;
> +
> +	  return 0;
> +	}
> +
> +      if ((i = member_is_fp (ftypedie, sizep, countp)) == 0)
> +	{
> +	  *countp = tot_size / *sizep;
> +	  return 0;
> +	}
> +
> +      return 1;

You already saw this should return i.
I would have missed it.

> +    }
> +
> +  /* Find first DW_TAG_member and determine its type.  */
> +  Dwarf_Die member;
> +  if ((i = dwarf_child (ftypedie, &member) != 0))
> +    return i;
> +
> +  if ((i = skip_until (&member, DW_TAG_member)) != 0)
> +    return i;
> +
> +  *countp = 0;
> +  if ((i = member_is_fp (&member, sizep, countp)) != 0)
> +    return i;
> +
> +  while ((i = dwarf_siblingof (&member, &member)) == 0
> +	 && (i = skip_until (&member, DW_TAG_member)) == 0)
> +    {
> +      Dwarf_Word size, count;
> +      if ((i = member_is_fp (&member, &size, &count)) != 0)
> +	return i;
> +
> +      if (*sizep != size)
> +	return 1;
> +
> +      *countp += count;
> +    }
> +
> +  return i < 0 ? i : 0;
> +}

Wow, would be nice to have some testcases for these.
Your suggested comment would be nice.

The rest looks OK.

> diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
> +/* AArch64 specific symbolic name handling.
> [...]
> +/* Check for the simple reloc types.  */
> +Elf_Type
> +aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
> +{
> +  switch (type)
> +    {
> +    case R_AARCH64_ABS64:
> +      return ELF_T_XWORD;
> +    case R_AARCH64_ABS32:
> +      return ELF_T_WORD;
> +    case R_AARCH64_ABS16:
> +      return ELF_T_HALF;
> +
> +    default:
> +      return ELF_T_NUM;
> +    }
> +}

Looks OK.
BTW. tests/run-strip-reloc.sh might be nice to add for aarch64.

> diff --git a/libebl/ChangeLog b/libebl/ChangeLog
> index 57f9f46..0ecd16f 100644
> --- a/libebl/ChangeLog
> +++ b/libebl/ChangeLog
> @@ -1,3 +1,7 @@
> +2013-11-14  Petr Machata  <pmachata@redhat.com>
> +
> +	* eblopenbackend.c (machines): Add entry for AArch64.

OK.

> +2013-11-14  Petr Machata  <pmachata@redhat.com>
> +
> +	* elflint.c (valid_e_machine): Add EM_AARCH64.

OK.

> +2013-11-14  Petr Machata  <pmachata@redhat.com>
> +
> +	* testfile_aarch64_core.bz2: New file.
> +	* Makefile.am (EXTRA_DIST): Add it.

OK.

> +	* run-allregs.sh: Use it to add a regs_test.
> +	* run-readelf-mixed-corenote.sh: Use it to add a readelf -n test.

> diff --git a/tests/run-allregs.sh b/tests/run-allregs.sh
> index 885a1d1..e4a40ce 100755
> --- a/tests/run-allregs.sh
> +++ b/tests/run-allregs.sh
> @@ -1,5 +1,5 @@
>  #! /bin/sh
> -# Copyright (C) 2005, 2006, 2007, 2012 Red Hat, Inc.
> +# Copyright (C) 2005, 2006, 2007, 2012, 2013 Red Hat, Inc.
>  # This file is part of elfutils.
>  #
>  # This file is free software; you can redistribute it and/or modify
> @@ -2724,4 +2724,74 @@ VFP registers:
>  	287: d31 (d31), float 64 bits
>  EOF
>  
> +regs_test testfile_aarch64_core <<\EOF
> +integer registers:

Add a comment, see run-readelf-mixed-corenote.sh how to regenerate this
core file.

> diff --git a/tests/run-readelf-mixed-corenote.sh b/tests/run-readelf-mixed-corenote.sh
> index 9a43809..c176e28 100755
> --- a/tests/run-readelf-mixed-corenote.sh
> +++ b/tests/run-readelf-mixed-corenote.sh
> @@ -285,4 +285,144 @@ Note segment of 1476 bytes at offset 0x430:
>        3e001ba000-3e001bc000 001ba000 8192            /usr/lib64/libc-2.17.so
>  EOF
>  
> +# To reproduce this core dump, do this on an aarch64 machine:
> +# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
> +# $ ./a.out
> +testfiles testfile_aarch64_core
> +testrun_compare ${abs_top_builddir}/src/readelf -n testfile_aarch64_core <<\EOF

OK.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]