[2/5] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips

Message ID 20230411081141.1762395-3-ying.huang@oss.cipunited.com
State Superseded
Headers
Series Add support for MIPS |

Commit Message

Ying Huang April 11, 2023, 8:12 a.m. UTC
  From: Ying Huang <ying.huang@oss.cipunited.com>

-h: support show Flags name
-S: support show mips related section type
-r: support show type and relocation info value of Relocation section
-w: can work and can show correct "strp" contents
-l: support show mips related program header entry type
-d: can show mips related Dynamic type name
-a: support show complete Object attribute section ".gnu.attributes"
---
 backends/Makefile.am       |   2 +-
 backends/mips_attrs.c      | 107 +++++++
 backends/mips_init.c       |   7 +
 backends/mips_symbol.c     | 572 +++++++++++++++++++++++++++++++++++++
 libebl/eblreloctypecheck.c |   8 +-
 libebl/eblreloctypename.c  |   8 +-
 libelf/elf.h               |  93 +++++-
 src/readelf.c              | 190 +++++++++---
 8 files changed, 932 insertions(+), 55 deletions(-)
 create mode 100644 backends/mips_attrs.c
  

Comments

Mark Wielaard May 11, 2023, 2:31 p.m. UTC | #1
Hi,

On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
> From: Ying Huang <ying.huang@oss.cipunited.com>
> 
> -h: support show Flags name
> -S: support show mips related section type
> -r: support show type and relocation info value of Relocation section
> -w: can work and can show correct "strp" contents
> -l: support show mips related program header entry type
> -d: can show mips related Dynamic type name
> -a: support show complete Object attribute section ".gnu.attributes"
> ---
>  backends/Makefile.am       |   2 +-
>  backends/mips_attrs.c      | 107 +++++++
>  backends/mips_init.c       |   7 +
>  backends/mips_symbol.c     | 572 +++++++++++++++++++++++++++++++++++++
>  libebl/eblreloctypecheck.c |   8 +-
>  libebl/eblreloctypename.c  |   8 +-
>  libelf/elf.h               |  93 +++++-
>  src/readelf.c              | 190 +++++++++---
>  8 files changed, 932 insertions(+), 55 deletions(-)
>  create mode 100644 backends/mips_attrs.c

This is generally OK, but there are a few issues and questions.

> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index bda1b604..428a1a03 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -100,7 +100,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c
>  
>  arc_SRCS = arc_init.c arc_symbol.c
>  
> -mips_SRCS = mips_init.c mips_symbol.c
> +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
>  
>  libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
>  			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \

OK.

> diff --git a/backends/mips_attrs.c b/backends/mips_attrs.c
> new file mode 100644
> index 00000000..1419814e
> --- /dev/null
> +++ b/backends/mips_attrs.c
> @@ -0,0 +1,107 @@
> +/* Object attribute tags for MIPS.
> +   Copyright (C) 2023 CIP United Inc.
> +   This file is part of elfutils.
> +
> +   This file is free software; you can redistribute it and/or modify
> +   it under the terms of either
> +
> +     * the GNU Lesser General Public License as published by the Free
> +       Software Foundation; either version 3 of the License, or (at
> +       your option) any later version
> +
> +   or
> +
> +     * the GNU General Public License as published by the Free
> +       Software Foundation; either version 2 of the License, or (at
> +       your option) any later version
> +
> +   or both in parallel, as here.
> +
> +   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 copies of the GNU General Public License and
> +   the GNU Lesser General Public License along with this program.  If
> +   not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <string.h>
> +#include <dwarf.h>
> +
> +#define BACKEND arm_

You mean mips_

> +#include "libebl_CPU.h"
> +
> +#define KNOWN_VALUES(...) do				\
> +  {							\
> +    static const char *table[] = { __VA_ARGS__ };	\
> +    if (value < sizeof table / sizeof table[0])		\
> +      *value_name = table[value];			\
> +  } while (0)
> +
> +/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */

In this and the few other cases this is OK because it is just taking
the constants/names. For snippets like that where they are adapted to
the elfutils code that is fine. But note that for larger parts the
licenses are slightly different so in general you should write your own
code instead of copy/pasting from binutils.

> +bool
> +mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
> +			    const char *vendor, int tag, uint64_t value,
> +			    const char **tag_name, const char **value_name)
> +{
> +  if (!strcmp (vendor, "gnu"))
> +    switch (tag)
> +      {
> +      case Tag_GNU_MIPS_ABI_FP:
> +	*tag_name = "Tag_GNU_MIPS_ABI_FP";
> +	switch (value)
> +	{
> +	  case Val_GNU_MIPS_ABI_FP_ANY:
> +	    *value_name = "Hard or soft float";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_DOUBLE:
> +	    *value_name = "Hard float (double precision)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_SINGLE:
> +	    *value_name = "Hard float (single precision)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_SOFT:
> +	    *value_name = "Soft float";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_OLD_64:
> +	    *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_XX:
> +	    *value_name = "Hard float (32-bit CPU, Any FPU)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_64:
> +	    *value_name = "Hard float (32-bit CPU, 64-bit FPU)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_64A:
> +	    *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_FP_NAN2008:
> +	    *value_name = "NaN 2008 compatibility";
> +	    return true;
> +	  default:
> +	    return true;
> +	}
> +	return true;
> +      case Tag_GNU_MIPS_ABI_MSA:
> +	*tag_name = "Tag_GNU_MIPS_ABI_MSA";
> +	switch (value)
> +	{
> +	  case Val_GNU_MIPS_ABI_MSA_ANY:
> +	    *value_name = "Any MSA or not";
> +	    return true;
> +	  case Val_GNU_MIPS_ABI_MSA_128:
> +	    *value_name = "128-bit MSA";
> +	    return true;
> +	  default:
> +	    return true;
> +	}
> +	return true;
> +      }
> +
> +  return false;
> +}

OK

> diff --git a/backends/mips_init.c b/backends/mips_init.c
> index f70d62e4..5bba822b 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -45,5 +45,12 @@ mips_init (Elf *elf __attribute__ ((unused)),
>    /* We handle it.  */
>    mips_init_reloc (eh);
>    HOOK (eh, reloc_simple_type);
> +  HOOK (eh, section_type_name);
> +  HOOK (eh, machine_flag_check);
> +  HOOK (eh, machine_flag_name);
> +  HOOK (eh, segment_type_name);
> +  HOOK (eh, dynamic_tag_check);
> +  HOOK (eh, dynamic_tag_name);
> +  HOOK (eh, check_object_attribute);
>    return eh;
>  }

OK
But see below for also hooking reloc_type_check and reloc_type_name.

> diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
> index 4f1bd3e6..e760d58d 100644
> --- a/backends/mips_symbol.c
> +++ b/backends/mips_symbol.c
> @@ -39,6 +39,7 @@
>  #define BACKEND		mips_
>  #include "libebl_CPU.h"
>  #include "libelfP.h"
> +
>  /* Check for the simple reloc types.  */
>  Elf_Type
>  mips_reloc_simple_type (Ebl *ebl, int type,
> @@ -60,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int type,
>        return ELF_T_NUM;
>      }
>  }
> +
> +/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name  */
> +const char *
> +mips_section_type_name (int type,
> +		       char *buf __attribute__ ((unused)),
> +		       size_t len __attribute__ ((unused)))
> +{
> +  switch (type)
> +    {
> +    case SHT_MIPS_LIBLIST:
> +      return "MIPS_LIBLIST";
> +    case SHT_MIPS_MSYM:
> +      return "MIPS_MSYM";
> +    case SHT_MIPS_CONFLICT:
> +      return "MIPS_CONFLICT";
> +    case SHT_MIPS_GPTAB:
> +      return "MIPS_GPTAB";
> +    case SHT_MIPS_UCODE:
> +      return "MIPS_UCODE";
> +    case SHT_MIPS_DEBUG:
> +      return "MIPS_DEBUG";
> +    case SHT_MIPS_REGINFO:
> +      return "MIPS_REGINFO";
> +    case SHT_MIPS_PACKAGE:
> +      return "MIPS_PACKAGE";
> +    case SHT_MIPS_PACKSYM:
> +      return "MIPS_PACKSYM";
> +    case SHT_MIPS_RELD:
> +      return "MIPS_RELD";
> +    case SHT_MIPS_IFACE:
> +      return "MIPS_IFACE";
> +    case SHT_MIPS_CONTENT:
> +      return "MIPS_CONTENT";
> +    case SHT_MIPS_OPTIONS:
> +      return "MIPS_OPTIONS";
> +    case SHT_MIPS_SHDR:
> +      return "MIPS_SHDR";
> +    case SHT_MIPS_FDESC:
> +      return "MIPS_FDESC";
> +    case SHT_MIPS_EXTSYM:
> +      return "MIPS_EXTSYM";
> +    case SHT_MIPS_DENSE:
> +      return "MIPS_DENSE";
> +    case SHT_MIPS_PDESC:
> +      return "MIPS_PDESC";
> +    case SHT_MIPS_LOCSYM:
> +      return "MIPS_LOCSYM";
> +    case SHT_MIPS_AUXSYM:
> +      return "MIPS_AUXSYM";
> +    case SHT_MIPS_OPTSYM:
> +      return "MIPS_OPTSYM";
> +    case SHT_MIPS_LOCSTR:
> +      return "MIPS_LOCSTR";
> +    case SHT_MIPS_LINE:
> +      return "MIPS_LINE";
> +    case SHT_MIPS_RFDESC:
> +      return "MIPS_RFDESC";
> +    case SHT_MIPS_DELTASYM:
> +      return "MIPS_DELTASYM";
> +    case SHT_MIPS_DELTAINST:
> +      return "MIPS_DELTAINST";
> +    case SHT_MIPS_DELTACLASS:
> +      return "MIPS_DELTACLASS";
> +    case SHT_MIPS_DWARF:
> +      return "MIPS_DWARF";
> +    case SHT_MIPS_DELTADECL:
> +      return "MIPS_DELTADECL";
> +    case SHT_MIPS_SYMBOL_LIB:
> +      return "MIPS_SYMBOL_LIB";
> +    case SHT_MIPS_EVENTS:
> +      return "MIPS_EVENTS";
> +    case SHT_MIPS_TRANSLATE:
> +      return "MIPS_TRANSLATE";
> +    case SHT_MIPS_PIXIE:
> +      return "MIPS_PIXIE";
> +    case SHT_MIPS_XLATE:
> +      return "MIPS_XLATE";
> +    case SHT_MIPS_XLATE_DEBUG:
> +      return "MIPS_XLATE_DEBUG";
> +    case SHT_MIPS_WHIRL:
> +      return "MIPS_WHIRL";
> +    case SHT_MIPS_EH_REGION:
> +      return "MIPS_EH_REGION";
> +    case SHT_MIPS_XLATE_OLD:
> +      return "MIPS_XLATE_OLD";
> +    case SHT_MIPS_PDR_EXCEPTION:
> +      return "MIPS_PDR_EXCEPTION";
> +    case SHT_MIPS_ABIFLAGS:
> +      return "MIPS_ABIFLAGS";
> +    case SHT_MIPS_XHASH:
> +      return "MIPS_XHASH";
> +    default:
> +      break;
> +    }
> +  return NULL;
> +}

OK

> +/* Check whether machine flags are valid.  */
> +bool
> +mips_machine_flag_check (GElf_Word flags)
> +{
> +  if ((flags &~ (EF_MIPS_NOREORDER |
> +		 EF_MIPS_PIC |
> +		 EF_MIPS_CPIC |
> +		 EF_MIPS_UCODE |
> +		 EF_MIPS_ABI2 |
> +		 EF_MIPS_OPTIONS_FIRST |
> +		 EF_MIPS_32BITMODE |
> +		 EF_MIPS_NAN2008 |
> +		 EF_MIPS_FP64 |
> +		 EF_MIPS_ARCH_ASE_MDMX |
> +		 EF_MIPS_ARCH_ASE_M16 |
> +		 EF_MIPS_ARCH_ASE_MICROMIPS)) == 0)
> +    return false;
> +
> +  switch(flags & EF_MIPS_MACH)
> +    {
> +    case E_MIPS_MACH_3900:
> +    case E_MIPS_MACH_4010:
> +    case E_MIPS_MACH_4100:
> +    case E_MIPS_MACH_4111:
> +    case E_MIPS_MACH_4120:
> +    case E_MIPS_MACH_4650:
> +    case E_MIPS_MACH_5400:
> +    case E_MIPS_MACH_5500:
> +    case E_MIPS_MACH_5900:
> +    case E_MIPS_MACH_SB1:
> +    case E_MIPS_MACH_9000:
> +    case E_MIPS_MACH_LS2E:
> +    case E_MIPS_MACH_LS2F:
> +    case E_MIPS_MACH_GS464:
> +    case E_MIPS_MACH_GS464E:
> +    case E_MIPS_MACH_GS264E:
> +    case E_MIPS_MACH_OCTEON:
> +    case E_MIPS_MACH_OCTEON2:
> +    case E_MIPS_MACH_OCTEON3:
> +    case E_MIPS_MACH_XLR:
> +    case E_MIPS_MACH_IAMR2:
> +    case 0:
> +      break;
> +    default:
> +      return false;
> +    }
> +
> +  switch ((flags & EF_MIPS_ABI))
> +    {
> +    case E_MIPS_ABI_O32:
> +    case E_MIPS_ABI_O64:
> +    case E_MIPS_ABI_EABI32:
> +    case E_MIPS_ABI_EABI64:
> +    case 0:
> +      break;
> +    default:
> +      return false;
> +    }
> +
> +  switch ((flags & EF_MIPS_ARCH))
> +    {
> +    case E_MIPS_ARCH_1:
> +    case E_MIPS_ARCH_2:
> +    case E_MIPS_ARCH_3:
> +    case E_MIPS_ARCH_4:
> +    case E_MIPS_ARCH_5:
> +    case E_MIPS_ARCH_32:
> +    case EF_MIPS_ARCH_32R2:
> +    case E_MIPS_ARCH_32R6:
> +    case E_MIPS_ARCH_64:
> +    case EF_MIPS_ARCH_64R2:
> +    case E_MIPS_ARCH_64R6:
> +      return true;
> +    default:
> +      return false;
> +    }
> +  return false;
> +}

OK

> +/* copy binutils-2.34/binutils/readelf.c get_machine_flags */
> +const char *
> +mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref)
> +{
> +  if (*flagref & EF_MIPS_NOREORDER)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER);
> +      return "noreorder";
> +    }
> +
> +  if (*flagref & EF_MIPS_PIC)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_PIC);
> +      return "pic";
> +    }
> +
> +  if (*flagref & EF_MIPS_CPIC)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_CPIC);
> +      return "cpic";
> +    }
> +
> +  if (*flagref & EF_MIPS_UCODE)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_UCODE);
> +      return "ugen_reserved";
> +    }
> +
> +  if (*flagref & EF_MIPS_ABI2)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ABI2);
> +      return "abi2";
> +    }
> +
> +  if (*flagref & EF_MIPS_OPTIONS_FIRST)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST);
> +      return "odk first";
> +    }
> +
> +  if (*flagref & EF_MIPS_32BITMODE)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE);
> +      return "32bitmode";
> +    }
> +
> +  if (*flagref & EF_MIPS_NAN2008)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008);
> +      return "nan2008";
> +    }
> +
> +  if (*flagref & EF_MIPS_FP64)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_FP64);
> +      return "fp64";
> +    }
> +
> +  switch (*flagref & EF_MIPS_MACH)
> +    {
> +    case E_MIPS_MACH_3900:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_3900);
> +      return "3900";
> +    case E_MIPS_MACH_4010:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4010);
> +      return "4010";
> +    case E_MIPS_MACH_4100:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4100);
> +      return "4100";
> +    case E_MIPS_MACH_4111:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4111);
> +      return "4111";
> +    case E_MIPS_MACH_4120:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4120);
> +      return "4120";
> +    case E_MIPS_MACH_4650:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4650);
> +      return "4650";
> +    case E_MIPS_MACH_5400:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5400);
> +      return "5400";
> +    case E_MIPS_MACH_5500:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5500);
> +      return "5500";
> +    case E_MIPS_MACH_5900:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5900);
> +      return "5900";
> +    case E_MIPS_MACH_SB1:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_SB1);
> +      return "sb1";
> +    case E_MIPS_MACH_9000:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_9000);
> +      return "9000";
> +    case E_MIPS_MACH_LS2E:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_LS2E);
> +      return "loongson-2e";
> +    case E_MIPS_MACH_LS2F:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_LS2F);
> +      return "loongson-2f";
> +    case E_MIPS_MACH_GS464:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS464);
> +      return "gs464";
> +    case E_MIPS_MACH_GS464E:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS464E);
> +      return "gs464e";
> +    case E_MIPS_MACH_GS264E:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS264E);
> +      return "gs264e";
> +    case E_MIPS_MACH_OCTEON:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON);
> +      return "octeon";
> +    case E_MIPS_MACH_OCTEON2:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON2);
> +      return "octeon2";
> +    case E_MIPS_MACH_OCTEON3:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON3);
> +      return "octeon3";
> +    case E_MIPS_MACH_XLR:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_XLR);
> +      return "xlr";
> +    case E_MIPS_MACH_IAMR2:
> +      *flagref &= ~((Elf64_Word) E_MIPS_MACH_IAMR2);
> +      return "interaptiv-mr2";
> +    case 0:
> +      /* We simply ignore the field in this case to avoid confusion:
> +         MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
> +         extension.  */
> +      break;
> +    default:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH);
> +      return "unknown CPU";
> +    }
> +  switch (*flagref & EF_MIPS_ABI)
> +    {
> +    case E_MIPS_ABI_O32:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ABI_O32);
> +      return "o32";
> +    case E_MIPS_ABI_O64:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ABI_O64);
> +      return "o64";
> +    case E_MIPS_ABI_EABI32:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ABI_EABI32);
> +      return "eabi32";
> +    case E_MIPS_ABI_EABI64:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ABI_EABI64);
> +      return "eabi64";
> +    case 0:
> +      /* We simply ignore the field in this case to avoid confusion:
> +         MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
> +	 This means it is likely to be an o32 file, but not for
> +	 sure.  */
> +      break;
> +    default:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ABI);
> +      return "unknown ABI";
> +    }
> +
> +  if (*flagref & EF_MIPS_ARCH_ASE_MDMX)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX);
> +      return "mdmx";
> +    }
> +
> +  if (*flagref & EF_MIPS_ARCH_ASE_M16)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16);
> +      return "mips16";
> +    }
> +
> +  if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS)
> +    {
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS);
> +      return "micromips";
> +    }
> +
> +  switch (*flagref & EF_MIPS_ARCH)
> +    {
> +    case E_MIPS_ARCH_1:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_1);
> +      return "mips1";
> +    case E_MIPS_ARCH_2:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_2);
> +      return "mips2";
> +    case E_MIPS_ARCH_3:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_3);
> +      return "mips3";
> +    case E_MIPS_ARCH_4:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_4);
> +      return "mips4";
> +    case E_MIPS_ARCH_5:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_5);
> +      return "mips5";
> +    case E_MIPS_ARCH_32:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_32);
> +      return "mips32";
> +    case EF_MIPS_ARCH_32R2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
> +      return "mips32r2";
> +    case E_MIPS_ARCH_32R6:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_32R6);
> +      return "mips32r6";
> +    case E_MIPS_ARCH_64:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_64);
> +      return "mips64";
> +    case EF_MIPS_ARCH_64R2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
> +      return "mips64r2";
> +    case E_MIPS_ARCH_64R6:
> +      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_64R6);
> +      return "mips64r6";
> +    default:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH);
> +      return "unknown ISA";
> +    }
> +  return NULL;
> +}

OK

> +/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type  */
> +const char *
> +mips_segment_type_name (int segment, char *buf __attribute__ ((unused)),
> +		       size_t len __attribute__ ((unused)))
> +{
> +  switch (segment)
> +    {
> +    case PT_MIPS_REGINFO:
> +      return "REGINFO";
> +    case PT_MIPS_RTPROC:
> +      return "RTPROC";
> +    case PT_MIPS_OPTIONS:
> +      return "OPTIONS";
> +    case PT_MIPS_ABIFLAGS:
> +      return "ABIFLAGS";
> +    default:
> +      return NULL;
> +    }
> +}

OK
Odd that the buf/len are ignored, but that is the same for all other
implementations too.

> +bool
> +mips_dynamic_tag_check (int64_t tag)
> +{
> +  return ((tag &~ (DT_MIPS_RLD_VERSION
> +	  | DT_MIPS_TIME_STAMP
> +	  | DT_MIPS_ICHECKSUM
> +	  | DT_MIPS_IVERSION
> +	  | DT_MIPS_FLAGS
> +	  | DT_MIPS_BASE_ADDRESS
> +	  | DT_MIPS_MSYM
> +	  | DT_MIPS_CONFLICT
> +	  | DT_MIPS_LIBLIST
> +	  | DT_MIPS_LOCAL_GOTNO
> +	  | DT_MIPS_CONFLICTNO
> +	  | DT_MIPS_LIBLISTNO
> +	  | DT_MIPS_SYMTABNO
> +	  | DT_MIPS_UNREFEXTNO
> +	  | DT_MIPS_GOTSYM
> +	  | DT_MIPS_HIPAGENO
> +	  | DT_MIPS_RLD_MAP
> +	  | DT_MIPS_DELTA_CLASS
> +	  | DT_MIPS_DELTA_CLASS_NO
> +	  | DT_MIPS_DELTA_INSTANCE
> +	  | DT_MIPS_DELTA_INSTANCE_NO
> +	  | DT_MIPS_DELTA_RELOC
> +	  | DT_MIPS_DELTA_RELOC_NO
> +	  | DT_MIPS_DELTA_SYM
> +	  | DT_MIPS_DELTA_SYM_NO
> +	  | DT_MIPS_DELTA_CLASSSYM
> +	  | DT_MIPS_DELTA_CLASSSYM_NO
> +	  | DT_MIPS_CXX_FLAGS
> +	  | DT_MIPS_PIXIE_INIT
> +	  | DT_MIPS_SYMBOL_LIB
> +	  | DT_MIPS_LOCALPAGE_GOTIDX
> +	  | DT_MIPS_LOCAL_GOTIDX
> +	  | DT_MIPS_HIDDEN_GOTIDX
> +	  | DT_MIPS_PROTECTED_GOTIDX
> +	  | DT_MIPS_OPTIONS
> +	  | DT_MIPS_INTERFACE
> +	  | DT_MIPS_DYNSTR_ALIGN
> +	  | DT_MIPS_INTERFACE_SIZE
> +	  | DT_MIPS_RLD_TEXT_RESOLVE_ADDR
> +	  | DT_MIPS_PERF_SUFFIX
> +	  | DT_MIPS_COMPACT_SIZE
> +	  | DT_MIPS_GP_VALUE
> +	  | DT_MIPS_AUX_DYNAMIC
> +	  | DT_MIPS_PLTGOT
> +	  | DT_MIPS_RWPLT
> +	  | DT_MIPS_RLD_MAP_REL
> +	  | DT_MIPS_XHASH)) == 0);
> +}

OK

> +/* copy binutils-2.34/binutils/readelf.c  get_mips_dynamic_type*/
> +const char *
> +mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
> +			  size_t len __attribute__ ((unused)))
> +{
> +  switch (tag)
> +    {
> +    case DT_MIPS_RLD_VERSION:
> +      return "MIPS_RLD_VERSION";
> +    case DT_MIPS_TIME_STAMP:
> +      return "MIPS_TIME_STAMP";
> +    case DT_MIPS_ICHECKSUM:
> +      return "MIPS_ICHECKSUM";
> +    case DT_MIPS_IVERSION:
> +      return "MIPS_IVERSION";
> +    case DT_MIPS_FLAGS:
> +      return "MIPS_FLAGS";
> +    case DT_MIPS_BASE_ADDRESS:
> +      return "MIPS_BASE_ADDRESS";
> +    case DT_MIPS_MSYM:
> +      return "MIPS_MSYM";
> +    case DT_MIPS_CONFLICT:
> +      return "MIPS_CONFLICT";
> +    case DT_MIPS_LIBLIST:
> +      return "MIPS_LIBLIST";
> +    case DT_MIPS_LOCAL_GOTNO:
> +      return "MIPS_LOCAL_GOTNO";
> +    case DT_MIPS_CONFLICTNO:
> +      return "MIPS_CONFLICTNO";
> +    case DT_MIPS_LIBLISTNO:
> +      return "MIPS_LIBLISTNO";
> +    case DT_MIPS_SYMTABNO:
> +      return "MIPS_SYMTABNO";
> +    case DT_MIPS_UNREFEXTNO:
> +      return "MIPS_UNREFEXTNO";
> +    case DT_MIPS_GOTSYM:
> +      return "MIPS_GOTSYM";
> +    case DT_MIPS_HIPAGENO:
> +      return "MIPS_HIPAGENO";
> +    case DT_MIPS_RLD_MAP:
> +      return "MIPS_RLD_MAP";
> +    case DT_MIPS_RLD_MAP_REL:
> +      return "MIPS_RLD_MAP_REL";
> +    case DT_MIPS_DELTA_CLASS:
> +      return "MIPS_DELTA_CLASS";
> +    case DT_MIPS_DELTA_CLASS_NO:
> +      return "MIPS_DELTA_CLASS_NO";
> +    case DT_MIPS_DELTA_INSTANCE:
> +      return "MIPS_DELTA_INSTANCE";
> +    case DT_MIPS_DELTA_INSTANCE_NO:
> +      return "MIPS_DELTA_INSTANCE_NO";
> +    case DT_MIPS_DELTA_RELOC:
> +      return "MIPS_DELTA_RELOC";
> +    case DT_MIPS_DELTA_RELOC_NO:
> +      return "MIPS_DELTA_RELOC_NO";
> +    case DT_MIPS_DELTA_SYM:
> +      return "MIPS_DELTA_SYM";
> +    case DT_MIPS_DELTA_SYM_NO:
> +      return "MIPS_DELTA_SYM_NO";
> +    case DT_MIPS_DELTA_CLASSSYM:
> +      return "MIPS_DELTA_CLASSSYM";
> +    case DT_MIPS_DELTA_CLASSSYM_NO:
> +      return "MIPS_DELTA_CLASSSYM_NO";
> +    case DT_MIPS_CXX_FLAGS:
> +      return "MIPS_CXX_FLAGS";
> +    case DT_MIPS_PIXIE_INIT:
> +      return "MIPS_PIXIE_INIT";
> +    case DT_MIPS_SYMBOL_LIB:
> +      return "MIPS_SYMBOL_LIB";
> +    case DT_MIPS_LOCALPAGE_GOTIDX:
> +      return "MIPS_LOCALPAGE_GOTIDX";
> +    case DT_MIPS_LOCAL_GOTIDX:
> +      return "MIPS_LOCAL_GOTIDX";
> +    case DT_MIPS_HIDDEN_GOTIDX:
> +      return "MIPS_HIDDEN_GOTIDX";
> +    case DT_MIPS_PROTECTED_GOTIDX:
> +      return "MIPS_PROTECTED_GOTIDX";
> +    case DT_MIPS_OPTIONS:
> +      return "MIPS_OPTIONS";
> +    case DT_MIPS_INTERFACE:
> +      return "MIPS_INTERFACE";
> +    case DT_MIPS_DYNSTR_ALIGN:
> +      return "MIPS_DYNSTR_ALIGN";
> +    case DT_MIPS_INTERFACE_SIZE:
> +      return "MIPS_INTERFACE_SIZE";
> +    case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
> +      return "MIPS_RLD_TEXT_RESOLVE_ADDR";
> +    case DT_MIPS_PERF_SUFFIX:
> +      return "MIPS_PERF_SUFFIX";
> +    case DT_MIPS_COMPACT_SIZE:
> +      return "MIPS_COMPACT_SIZE";
> +    case DT_MIPS_GP_VALUE:
> +      return "MIPS_GP_VALUE";
> +    case DT_MIPS_AUX_DYNAMIC:
> +      return "MIPS_AUX_DYNAMIC";
> +    case DT_MIPS_PLTGOT:
> +      return "MIPS_PLTGOT";
> +    case DT_MIPS_RWPLT:
> +      return "MIPS_RWPLT";
> +    case DT_MIPS_XHASH:
> +      return "MIPS_XHASH";
> +    default:
> +      return NULL;
> +    }
> +  return NULL;
> +}

OK

> diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
> index 80e67ef7..e3c43944 100644
> --- a/libebl/eblreloctypecheck.c
> +++ b/libebl/eblreloctypecheck.c
> @@ -32,10 +32,14 @@
>  #endif
>  
>  #include <libeblP.h>
> -
> +#include <libelfP.h>
>  
>  bool
>  ebl_reloc_type_check (Ebl *ebl, int reloc)
>  {
> -  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
> +  int relocNew = reloc;
> +  GElf_Ehdr ehdr;
> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
> +  return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
>  }

This should not go into the generic ebl_reloc_type_check but has to be
hooked so it uses a mips_reloc_type_check.

> diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
> index e53ec0c0..4276d8e3 100644
> --- a/libebl/eblreloctypename.c
> +++ b/libebl/eblreloctypename.c
> @@ -33,14 +33,18 @@
>  
>  #include <stdio.h>
>  #include <libeblP.h>
> -
> +#include <libelfP.h>
>  
>  const char *
>  ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
>  {
>    const char *res;
> +  int relocNew = reloc;
> +  GElf_Ehdr ehdr;
> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>  
> -  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
> +  res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
>    if (res == NULL)
>      /* There are no generic relocation type names.  */
>      res = "<INVALID RELOC>";

Likewise for hooking reloc_type_name.

> diff --git a/libelf/elf.h b/libelf/elf.h
> index aa903837..6284564f 100644
> --- a/libelf/elf.h
> +++ b/libelf/elf.h
> @@ -1684,11 +1684,26 @@ typedef struct
>  #define EF_MIPS_PIC		2     /* Contains PIC code.  */
>  #define EF_MIPS_CPIC		4     /* Uses PIC calling sequence.  */
>  #define EF_MIPS_XGOT		8
> -#define EF_MIPS_64BIT_WHIRL	16
> +//copy binutils-2.34/elfcpp/mips.h
> +#define EF_MIPS_UCODE		16
>  #define EF_MIPS_ABI2		32
>  #define EF_MIPS_ABI_ON32	64
> +//copy machine flag from binutils-2.34/elfcpp/mips.h
> +/* Process the .MIPS.options section first by ld */
> +#define EF_MIPS_OPTIONS_FIRST	0x00000080
> +/* Indicates code compiled for a 64-bit machine in 32-bit mode
> +   (regs are 32-bits wide).  */
> +#define EF_MIPS_32BITMODE	0x00000100
>  #define EF_MIPS_FP64		512  /* Uses FP64 (12 callee-saved).  */
> -#define EF_MIPS_NAN2008	1024  /* Uses IEEE 754-2008 NaN encoding.  */
> +#define EF_MIPS_NAN2008		1024  /* Uses IEEE 754-2008 NaN encoding.  */
> +/* Architectural Extensions used by this file */
> +#define EF_MIPS_ARCH_ASE	0x0f000000
> +/* Use MDMX multimedia extensions */
> +#define EF_MIPS_ARCH_ASE_MDMX	0x08000000
> +/* Use MIPS-16 ISA extensions */
> +#define EF_MIPS_ARCH_ASE_M16	0x04000000
> +/* Use MICROMIPS ISA extensions.  */
> +#define EF_MIPS_ARCH_ASE_MICROMIPS	0x02000000
>  #define EF_MIPS_ARCH		0xf0000000 /* MIPS architecture level.  */
>  
>  /* Legal values for MIPS architecture level.  */
> @@ -1702,6 +1717,49 @@ typedef struct
>  #define EF_MIPS_ARCH_64		0x60000000 /* MIPS64 code.  */
>  #define EF_MIPS_ARCH_32R2	0x70000000 /* MIPS32r2 code.  */
>  #define EF_MIPS_ARCH_64R2	0x80000000 /* MIPS64r2 code.  */
> +/* -mips32r6 code.  */
> +#define E_MIPS_ARCH_32R6        0x90000000
> +/* -mips64r6 code.  */
> +#define E_MIPS_ARCH_64R6        0xa0000000
> +/* The ABI of the file.  Also see EF_MIPS_ABI2 above. */
> +#define EF_MIPS_ABI		0x0000F000
> +/* The original o32 abi. */
> +#define E_MIPS_ABI_O32          0x00001000
> +/* O32 extended to work on 64 bit architectures */
> +#define E_MIPS_ABI_O64          0x00002000
> +/* EABI in 32 bit mode */
> +#define E_MIPS_ABI_EABI32       0x00003000
> +/* EABI in 64 bit mode */
> +#define E_MIPS_ABI_EABI64       0x00004000
> +/* Machine variant if we know it.  This field was invented at Cygnus,
> +   but it is hoped that other vendors will adopt it.  If some standard
> +   is developed, this code should be changed to follow it. */
> +#define EF_MIPS_MACH		0x00FF0000
> +/* Cygnus is choosing values between 80 and 9F;
> +   00 - 7F should be left for a future standard;
> +   the rest are open. */
> +
> +#define E_MIPS_MACH_3900	0x00810000
> +#define E_MIPS_MACH_4010	0x00820000
> +#define E_MIPS_MACH_4100	0x00830000
> +#define E_MIPS_MACH_4650	0x00850000
> +#define E_MIPS_MACH_4120	0x00870000
> +#define E_MIPS_MACH_4111	0x00880000
> +#define E_MIPS_MACH_SB1         0x008a0000
> +#define E_MIPS_MACH_OCTEON	0x008b0000
> +#define E_MIPS_MACH_XLR     	0x008c0000
> +#define E_MIPS_MACH_OCTEON2	0x008d0000
> +#define E_MIPS_MACH_OCTEON3	0x008e0000
> +#define E_MIPS_MACH_5400	0x00910000
> +#define E_MIPS_MACH_5900	0x00920000
> +#define E_MIPS_MACH_IAMR2	0x00930000
> +#define E_MIPS_MACH_5500	0x00980000
> +#define E_MIPS_MACH_9000	0x00990000
> +#define E_MIPS_MACH_LS2E        0x00A00000
> +#define E_MIPS_MACH_LS2F        0x00A10000
> +#define E_MIPS_MACH_GS464       0x00A20000
> +#define E_MIPS_MACH_GS464E	0x00A30000
> +#define E_MIPS_MACH_GS264E	0x00A40000
>  
>  /* The following are unofficial names and should not be used.  */
>  
> @@ -1762,6 +1820,7 @@ typedef struct
>  #define SHT_MIPS_EH_REGION	0x70000027
>  #define SHT_MIPS_XLATE_OLD	0x70000028
>  #define SHT_MIPS_PDR_EXCEPTION	0x70000029
> +#define SHT_MIPS_ABIFLAGS	0x7000002a
>  #define SHT_MIPS_XHASH		0x7000002b
>  
>  /* Legal values for sh_flags field of Elf32_Shdr.  */
> @@ -1789,6 +1848,31 @@ typedef struct
>  /* MIPS specific values for `st_info'.  */
>  #define STB_MIPS_SPLIT_COMMON		13
>  
> +//copy gnu attr tags from binutils-2.34/elfcpp/mips.h
> +/* Object attribute tags.  */
> +enum
> +{
> +  /* 0-3 are generic.  */
> +
> +  /* Floating-point ABI used by this object file.  */
> +  Tag_GNU_MIPS_ABI_FP = 4,
> +
> +  /* MSA ABI used by this object file.  */
> +  Tag_GNU_MIPS_ABI_MSA = 8,
> +};
> +
> +/* Object attribute values.  */
> +enum
> +{
> +  /* Values defined for Tag_GNU_MIPS_ABI_MSA.  */
> +
> +  /* Not tagged or not using any ABIs affected by the differences.  */
> +  Val_GNU_MIPS_ABI_MSA_ANY = 0,
> +
> +  /* Using 128-bit MSA.  */
> +  Val_GNU_MIPS_ABI_MSA_128 = 1,
> +};
> +
>  /* Entries found in sections of type SHT_MIPS_GPTAB.  */
>  
>  typedef union
> @@ -2218,8 +2302,11 @@ enum
>    Val_GNU_MIPS_ABI_FP_64 = 6,
>    /* Using -mips32r2 -mfp64 -mno-odd-spreg.  */
>    Val_GNU_MIPS_ABI_FP_64A = 7,
> +  /* This is reserved for backward-compatibility with an earlier
> +     implementation of the MIPS NaN2008 functionality.  */
> +  Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
>    /* Maximum allocated FP ABI value.  */
> -  Val_GNU_MIPS_ABI_FP_MAX = 7
> +  Val_GNU_MIPS_ABI_FP_MAX = 9
>  };
>  
>  /* HPPA specific definitions.  */

We take elf.h from glibc so please suggest these additions first on
libc-alpha@sourceware.org

> diff --git a/src/readelf.c b/src/readelf.c
> index 6950204e..6e9a02c1 100644
> --- a/src/readelf.c
> +++ b/src/readelf.c
> @@ -1125,7 +1125,7 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
>  	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? _("(current)")
>  	  : "(\?\?\?)");
>  
> -  char buf[512];
> +  char buf[64];
>    printf (_("  OS/ABI:                            %s\n"),
>  	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
> 

Can you explain why reducing this buffer to 64 is OK?

> @@ -2193,17 +2193,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>  			(long int) GELF_R_SYM (rel->r_info));
>  	    }
>  	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
> -	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
> -		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> -		    likely (ebl_reloc_type_check (ebl,
> -						  GELF_R_TYPE (rel->r_info)))
> -		    /* Avoid the leading R_ which isn't carrying any
> -		       information.  */
> -		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> -					   buf, sizeof (buf)) + 2
> -		    : _("<INVALID RELOC>"),
> -		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
> -		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +	    {
> +	      unsigned long inf = rel->r_info;
> +	      printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
> +		      class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> +		      likely (ebl_reloc_type_check (ebl,
> +						    GELF_R_TYPE (rel->r_info)))
> +		      /* Avoid the leading R_ which isn't carrying any
> +		         information.  */
> +		      ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> +					     buf, sizeof (buf)) + 2
> +		      : _("<INVALID RELOC>"),
> +		      class == ELFCLASS32 ? 10 : 18, sym->st_value,
> +		      elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +
> +	      /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
> +              if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> +	        {
> +		  unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> +		  unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> +		  const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> +		  const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> +		  printf("                      Type2: ");
> +		  if (rtype2 == NULL)
> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
> +	          else
> +	            printf ("%-17.17s", rtype2);
> +
> +	          printf ("\n                      Type3: ");
> +		  if (rtype3 == NULL)
> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
> +	          else
> +	            printf ("%-17.17s", rtype3);
> +		  printf("\n");
> +	        }
> +	    }

I think this is OK, but it would be good to see an example.

>  	  else
>  	    {
>  	      /* This is a relocation against a STT_SECTION symbol.  */
> @@ -2227,16 +2251,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>  			(long int) (sym->st_shndx == SHN_XINDEX
>  				    ? xndx : sym->st_shndx));
>  	      else
> -		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
> -			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> -			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> -			/* Avoid the leading R_ which isn't carrying any
> -			   information.  */
> -			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> -					       buf, sizeof (buf)) + 2
> -			: _("<INVALID RELOC>"),
> -			class == ELFCLASS32 ? 10 : 18, sym->st_value,
> -			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +	        {
> +		  unsigned long inf = rel->r_info;
> +		  printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
> +			  class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> +			  ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> +			  /* Avoid the leading R_ which isn't carrying any
> +			     information.  */
> +			  ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> +					         buf, sizeof (buf)) + 2
> +			  : _("<INVALID RELOC>"),
> +			  class == ELFCLASS32 ? 10 : 18, sym->st_value,
> +			  elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +
> +		  /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
> +		  if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> +		  {
> +		    unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> +		    unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> +		    const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> +		    const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> +		    printf("                      Type2: ");
> +		    if (rtype2 == NULL)
> +	              printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
> +	            else
> +	              printf ("%-17.17s", rtype2);
> +
> +	            printf ("\n                      Type3: ");
> +		    if (rtype3 == NULL)
> +	              printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
> +	            else
> +	              printf ("%-17.17s", rtype3);
> +		    printf("\n");
> +		  }
> +		}
>  	    }
>  	}
>      }

Likewise.

> @@ -2384,19 +2432,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>  			(long int) GELF_R_SYM (rel->r_info));
>  	    }
>  	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
> -	    printf ("\
> +	    {
> +              unsigned long inf = rel->r_info;
> +	      printf ("\
>    %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
> -		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> -		    likely (ebl_reloc_type_check (ebl,
> -						  GELF_R_TYPE (rel->r_info)))
> -		    /* Avoid the leading R_ which isn't carrying any
> -		       information.  */
> -		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> -					   buf, sizeof (buf)) + 2
> -		    : _("<INVALID RELOC>"),
> -		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
> -		    rel->r_addend,
> -		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +		      class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> +		      likely (ebl_reloc_type_check (ebl,
> +						    GELF_R_TYPE (rel->r_info)))
> +		      /* Avoid the leading R_ which isn't carrying any
> +		         information.  */
> +		      ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> +					     buf, sizeof (buf)) + 2
> +		      : _("<INVALID RELOC>"),
> +		      class == ELFCLASS32 ? 10 : 18, sym->st_value,
> +		      rel->r_addend,
> +		      elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
> +
> +	      /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
> +	      if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> +		{
> +		  unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> +		  unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> +		  const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> +		  const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> +		  printf("                      Type2: ");
> +		  if (rtype2 == NULL)
> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
> +	          else
> +	            printf ("%-17.17s", rtype2);
> +
> +	          printf ("\n                      Type3: ");
> +		  if (rtype3 == NULL)
> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
> +	          else
> +	            printf ("%-17.17s", rtype3);
> +		  printf("\n");
> +		}
> +	    }

And again.

>  	  else
>  	    {
>  	      /* This is a relocation against a STT_SECTION symbol.  */
> @@ -2420,18 +2492,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>  			(long int) (sym->st_shndx == SHN_XINDEX
>  				    ? xndx : sym->st_shndx));
>  	      else
> -		printf ("\
> +	        {
> +                  unsigned long inf = rel->r_info;
> +		  printf ("\
>    %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
> -			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> -			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> -			/* Avoid the leading R_ which isn't carrying any
> -			   information.  */
> -			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> -					       buf, sizeof (buf)) + 2
> -			: _("<INVALID RELOC>"),
> -			class == ELFCLASS32 ? 10 : 18, sym->st_value,
> -			rel->r_addend,
> -			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +			  class == ELFCLASS32 ? 10 : 18, rel->r_offset,
> +			  ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
> +			  /* Avoid the leading R_ which isn't carrying any
> +			     information.  */
> +			  ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
> +					         buf, sizeof (buf)) + 2
> +			  : _("<INVALID RELOC>"),
> +			  class == ELFCLASS32 ? 10 : 18, sym->st_value,
> +			  rel->r_addend,
> +			  elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
> +
> +                  /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
> +		  if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
> +		    {
> +		      unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
> +		      unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
> +		      const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
> +		      const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
> +		      printf("                      Type2: ");
> +		      if (rtype2 == NULL)
> +	                printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
> +	              else
> +	                printf ("%-17.17s", rtype2);
> +
> +	              printf ("\n                      Type3: ");
> +		      if (rtype3 == NULL)
> +	                printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
> +	              else
> +	                printf ("%-17.17s", rtype3);
> +		      printf("\n");
> +		    }
> +	        }
>  	    }
>  	}
>      }

And again. Adding testcase would be nice.

So this handles both REL and RELA, does mips support both?

> @@ -11633,7 +11729,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
>  	  GElf_Shdr shdr_mem;
>  	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>  
> -	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
> +	  if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
>  	    {
>  	      const char *name = elf_strptr (ebl->elf, shstrndx,
>  					     shdr->sh_name);
> @@ -11663,7 +11759,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
>        GElf_Shdr shdr_mem;
>        GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>  
> -      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
> +      if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
>  	{
>  	  static const struct
>  	  {

OK. There are probably other places in the code where this might be an
issue. Maybe we need an is_debug_section_type macro?

Cheers,

Mark
  
Ying Huang May 16, 2023, 8:01 a.m. UTC | #2
Hi,

在 2023/5/11 22:31, Mark Wielaard 写道:
> Hi,
>
> On Tue, 2023-04-11 at 16:12 +0800, Ying Huang wrote:
>> diff --git a/backends/mips_attrs.c b/backends/mips_attrs.c
>> new file mode 100644
>> index 00000000..1419814e
>> --- /dev/null
>> +++ b/backends/mips_attrs.c
>> @@ -0,0 +1,107 @@
>> +/* Object attribute tags for MIPS.
>> +   Copyright (C) 2023 CIP United Inc.
>> +   This file is part of elfutils.
>> +
>> +   This file is free software; you can redistribute it and/or modify
>> +   it under the terms of either
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at
>> +       your option) any later version
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at
>> +       your option) any later version
>> +
>> +   or both in parallel, as here.
>> +
>> +   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 copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include <config.h>
>> +#endif
>> +
>> +#include <string.h>
>> +#include <dwarf.h>
>> +
>> +#define BACKEND arm_
> You mean mips_

    Yes, it should be mips_, thanks!


>> diff --git a/backends/mips_init.c b/backends/mips_init.c
>> index f70d62e4..5bba822b 100644
>> --- a/backends/mips_init.c
>> +++ b/backends/mips_init.c
>> @@ -45,5 +45,12 @@ mips_init (Elf *elf __attribute__ ((unused)),
>>    /* We handle it.  */
>>    mips_init_reloc (eh);
>>    HOOK (eh, reloc_simple_type);
>> +  HOOK (eh, section_type_name);
>> +  HOOK (eh, machine_flag_check);
>> +  HOOK (eh, machine_flag_name);
>> +  HOOK (eh, segment_type_name);
>> +  HOOK (eh, dynamic_tag_check);
>> +  HOOK (eh, dynamic_tag_name);
>> +  HOOK (eh, check_object_attribute);
>>    return eh;
>>  }
> OK
> But see below for also hooking reloc_type_check and reloc_type_name.


    OK, I would add hook for reloc_type_check and reloc_type_name.


>>  
>>  typedef union
>> @@ -2218,8 +2302,11 @@ enum
>>    Val_GNU_MIPS_ABI_FP_64 = 6,
>>    /* Using -mips32r2 -mfp64 -mno-odd-spreg.  */
>>    Val_GNU_MIPS_ABI_FP_64A = 7,
>> +  /* This is reserved for backward-compatibility with an earlier
>> +     implementation of the MIPS NaN2008 functionality.  */
>> +  Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
>>    /* Maximum allocated FP ABI value.  */
>> -  Val_GNU_MIPS_ABI_FP_MAX = 7
>> +  Val_GNU_MIPS_ABI_FP_MAX = 9
>>  };
>>  
>>  /* HPPA specific definitions.  */
> We take elf.h from glibc so please suggest these additions first on
> libc-alpha@sourceware.org

    I have submitted patch to libc-alpha@sourceware.org and modify the  Val_GNU_MIPS_ABI_FP_MAX to 8.

  https://sourceware.org/pipermail/libc-alpha/2023-May/148112.html

>
>> diff --git a/src/readelf.c b/src/readelf.c
>> index 6950204e..6e9a02c1 100644
>> --- a/src/readelf.c
>> +++ b/src/readelf.c
>> @@ -1125,7 +1125,7 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
>>  	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? _("(current)")
>>  	  : "(\?\?\?)");
>>  
>> -  char buf[512];
>> +  char buf[64];
>>    printf (_("  OS/ABI:                            %s\n"),
>>  	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
>>
> Can you explain why reducing this buffer to 64 is OK?

    Because the OS/ABI and Flags are not as long as 256, maybe I did not think enough, can not it be reduced?


>
>> @@ -2193,17 +2193,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>>  			(long int) GELF_R_SYM (rel->r_info));
>>  	    }
>>  	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
>> -	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
>> -		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
>> -		    likely (ebl_reloc_type_check (ebl,
>> -						  GELF_R_TYPE (rel->r_info)))
>> -		    /* Avoid the leading R_ which isn't carrying any
>> -		       information.  */
>> -		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
>> -					   buf, sizeof (buf)) + 2
>> -		    : _("<INVALID RELOC>"),
>> -		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
>> -		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
>> +	    {
>> +	      unsigned long inf = rel->r_info;
>> +	      printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
>> +		      class == ELFCLASS32 ? 10 : 18, rel->r_offset,
>> +		      likely (ebl_reloc_type_check (ebl,
>> +						    GELF_R_TYPE (rel->r_info)))
>> +		      /* Avoid the leading R_ which isn't carrying any
>> +		         information.  */
>> +		      ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
>> +					     buf, sizeof (buf)) + 2
>> +		      : _("<INVALID RELOC>"),
>> +		      class == ELFCLASS32 ? 10 : 18, sym->st_value,
>> +		      elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
>> +
>> +	      /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
>> +              if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
>> +	        {
>> +		  unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
>> +		  unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
>> +		  const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
>> +		  const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
>> +		  printf("                      Type2: ");
>> +		  if (rtype2 == NULL)
>> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
>> +	          else
>> +	            printf ("%-17.17s", rtype2);
>> +
>> +	          printf ("\n                      Type3: ");
>> +		  if (rtype3 == NULL)
>> +	            printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
>> +	          else
>> +	            printf ("%-17.17s", rtype3);
>> +		  printf("\n");
>> +	        }
>> +	    }
> I think this is OK, but it would be good to see an example.

  

    Relocation section [ 2] '.rela.text' for section [ 1] '.text' at offset 0x29908 contains 1979 entries:
  Offset              Type            Value               Addend Name
  0x0000000000000008  MIPS_GPREL16    000000000000000000      +0 .text
                      Type2: MIPS_SUB         
                      Type3: MIPS_HI16        
  0x0000000000000010  MIPS_GPREL16    000000000000000000      +0 .text
                      Type2: MIPS_SUB         
                      Type3: MIPS_LO16        
  0x0000000000000014  MIPS_CALL16     000000000000000000      +0 gelf_getehdr
                      Type2: MIPS_NONE        
                      Type3: MIPS_NONE        
  0x0000000000000034  MIPS_JALR       000000000000000000      +0 gelf_getehdr
                      Type2: MIPS_NONE        
                      Type3: MIPS_NONE        
  0x000000000000004c  MIPS_CALL16     000000000000000000      +0 elf_getscn
                      Type2: MIPS_NONE        
                      Type3: MIPS_NONE        
  0x0000000000000054  MIPS_CALL16     000000000000000000      +0 gelf_update_ehdr
                      Type2: MIPS_NONE        
                      Type3: MIPS_NONE

   

>>  	  else
>>  	    {
>>  	      /* This is a relocation against a STT_SECTION symbol.  */
>> @@ -2420,18 +2492,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
>>  			(long int) (sym->st_shndx == SHN_XINDEX
>>  				    ? xndx : sym->st_shndx));
>>  	      else
>> -		printf ("\
>> +	        {
>> +                  unsigned long inf = rel->r_info;
>> +		  printf ("\
>>    %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
>> -			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
>> -			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
>> -			/* Avoid the leading R_ which isn't carrying any
>> -			   information.  */
>> -			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
>> -					       buf, sizeof (buf)) + 2
>> -			: _("<INVALID RELOC>"),
>> -			class == ELFCLASS32 ? 10 : 18, sym->st_value,
>> -			rel->r_addend,
>> -			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
>> +			  class == ELFCLASS32 ? 10 : 18, rel->r_offset,
>> +			  ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
>> +			  /* Avoid the leading R_ which isn't carrying any
>> +			     information.  */
>> +			  ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
>> +					         buf, sizeof (buf)) + 2
>> +			  : _("<INVALID RELOC>"),
>> +			  class == ELFCLASS32 ? 10 : 18, sym->st_value,
>> +			  rel->r_addend,
>> +			  elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
>> +
>> +                  /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
>> +		  if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
>> +		    {
>> +		      unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
>> +		      unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
>> +		      const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
>> +		      const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
>> +		      printf("                      Type2: ");
>> +		      if (rtype2 == NULL)
>> +	                printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
>> +	              else
>> +	                printf ("%-17.17s", rtype2);
>> +
>> +	              printf ("\n                      Type3: ");
>> +		      if (rtype3 == NULL)
>> +	                printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
>> +	              else
>> +	                printf ("%-17.17s", rtype3);
>> +		      printf("\n");
>> +		    }
>> +	        }
>>  	    }
>>  	}
>>      }
> And again. Adding testcase would be nice.
>
> So this handles both REL and RELA, does mips support both?


    OK, I would like to add testcase.

    Both support.


>
>> @@ -11633,7 +11729,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
>>  	  GElf_Shdr shdr_mem;
>>  	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>>  
>> -	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
>> +	  if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
>>  	    {
>>  	      const char *name = elf_strptr (ebl->elf, shstrndx,
>>  					     shdr->sh_name);
>> @@ -11663,7 +11759,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
>>        GElf_Shdr shdr_mem;
>>        GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
>>  
>> -      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
>> +      if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
>>  	{
>>  	  static const struct
>>  	  {
> OK. There are probably other places in the code where this might be an
> issue. Maybe we need an is_debug_section_type macro?
>
> Cheers,
>
> Mark

    Yes, I think it is good to add a new macro && need to check carefully.


Thanks,

Ying
  
Ying Huang July 24, 2023, 8:35 a.m. UTC | #3
Hi Mark,

>> diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
>> index 80e67ef7..e3c43944 100644
>> --- a/libebl/eblreloctypecheck.c
>> +++ b/libebl/eblreloctypecheck.c
>> @@ -32,10 +32,14 @@
>>  #endif
>>  
>>  #include <libeblP.h>
>> -
>> +#include <libelfP.h>
>>  
>>  bool
>>  ebl_reloc_type_check (Ebl *ebl, int reloc)
>>  {
>> -  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
>> +  int relocNew = reloc;
>> +  GElf_Ehdr ehdr;
>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>> +  return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
>>  }
> This should not go into the generic ebl_reloc_type_check but has to be
> hooked so it uses a mips_reloc_type_check.
>
>> diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
>> index e53ec0c0..4276d8e3 100644
>> --- a/libebl/eblreloctypename.c
>> +++ b/libebl/eblreloctypename.c
>> @@ -33,14 +33,18 @@
>>  
>>  #include <stdio.h>
>>  #include <libeblP.h>
>> -
>> +#include <libelfP.h>
>>  
>>  const char *
>>  ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
>>  {
>>    const char *res;
>> +  int relocNew = reloc;
>> +  GElf_Ehdr ehdr;
>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>>  
>> -  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
>> +  res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
>>    if (res == NULL)
>>      /* There are no generic relocation type names.  */
>>      res = "<INVALID RELOC>";
> Likewise for hooking reloc_type_name.
>
The function reloc_type_check and reloc_type_name were common hooks in file backends/common-reloc.c, so if we also need a new hook for mips and copy the check codes from common-reloc.c?

Thanks,

Ying
  
Ying Huang July 25, 2023, 8:15 a.m. UTC | #4
Hi Mark,

In file common-reloc.c, hook functions reloc_type_check/reloc_type_use/reloc_type_name have these codes:

#ifdef RELOC_TYPE_ID
  reloc = RELOC_TYPE_ID (reloc);
#endif

And the macro RELOC_TYPE_ID was defined in file backends/sparc_init.c:

/* In SPARC some relocations use the most significative 24 bits of the
   r_type field to encode a secondary addend.  Make sure the routines
   in common-reloc.c acknowledge this.  */
#define RELOC_TYPE_ID(type) ((type) & 0xff)

The contents of macro RELOC_TYPE_ID were same as ELF64_MIPS_R_TYPE(new added), so my view is did not add new hook for mips, if we can do like sparc?

Thanks,

Ying

在 2023/7/24 16:35, Ying Huang 写道:
> Hi Mark,
>
>>> diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
>>> index 80e67ef7..e3c43944 100644
>>> --- a/libebl/eblreloctypecheck.c
>>> +++ b/libebl/eblreloctypecheck.c
>>> @@ -32,10 +32,14 @@
>>>  #endif
>>>  
>>>  #include <libeblP.h>
>>> -
>>> +#include <libelfP.h>
>>>  
>>>  bool
>>>  ebl_reloc_type_check (Ebl *ebl, int reloc)
>>>  {
>>> -  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
>>> +  int relocNew = reloc;
>>> +  GElf_Ehdr ehdr;
>>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>>> +  return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
>>>  }
>> This should not go into the generic ebl_reloc_type_check but has to be
>> hooked so it uses a mips_reloc_type_check.
>>
>>> diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
>>> index e53ec0c0..4276d8e3 100644
>>> --- a/libebl/eblreloctypename.c
>>> +++ b/libebl/eblreloctypename.c
>>> @@ -33,14 +33,18 @@
>>>  
>>>  #include <stdio.h>
>>>  #include <libeblP.h>
>>> -
>>> +#include <libelfP.h>
>>>  
>>>  const char *
>>>  ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
>>>  {
>>>    const char *res;
>>> +  int relocNew = reloc;
>>> +  GElf_Ehdr ehdr;
>>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>>>  
>>> -  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
>>> +  res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
>>>    if (res == NULL)
>>>      /* There are no generic relocation type names.  */
>>>      res = "<INVALID RELOC>";
>> Likewise for hooking reloc_type_name.
>>
> The function reloc_type_check and reloc_type_name were common hooks in file backends/common-reloc.c, so if we also need a new hook for mips and copy the check codes from common-reloc.c?
>
> Thanks,
>
> Ying
>
>
  
Ying Huang July 27, 2023, 6:08 a.m. UTC | #5
Hi Mark,

Can we add a new file mips.h in backends, and move defines of ELF64_MIPS_R_TYPE/ELF64_MIPS_R_TYPE2/ELF64_MIPS_R_TYPE3 from elf.h to mips.h?

And rename the macro name ELF64_MIPS_R_TYPE to ELF64_MIPS_R_TYPE1 in mips.h? Or rename it directly in elf.h of glibc?

Thanks,

Ying

在 2023/7/25 16:15, Ying Huang 写道:
> Hi Mark,
>
> In file common-reloc.c, hook functions reloc_type_check/reloc_type_use/reloc_type_name have these codes:
>
> #ifdef RELOC_TYPE_ID
>   reloc = RELOC_TYPE_ID (reloc);
> #endif
>
> And the macro RELOC_TYPE_ID was defined in file backends/sparc_init.c:
>
> /* In SPARC some relocations use the most significative 24 bits of the
>    r_type field to encode a secondary addend.  Make sure the routines
>    in common-reloc.c acknowledge this.  */
> #define RELOC_TYPE_ID(type) ((type) & 0xff)
>
> The contents of macro RELOC_TYPE_ID were same as ELF64_MIPS_R_TYPE(new added), so my view is did not add new hook for mips, if we can do like sparc?
>
> Thanks,
>
> Ying
>
> 在 2023/7/24 16:35, Ying Huang 写道:
>> Hi Mark,
>>
>>>> diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
>>>> index 80e67ef7..e3c43944 100644
>>>> --- a/libebl/eblreloctypecheck.c
>>>> +++ b/libebl/eblreloctypecheck.c
>>>> @@ -32,10 +32,14 @@
>>>>  #endif
>>>>  
>>>>  #include <libeblP.h>
>>>> -
>>>> +#include <libelfP.h>
>>>>  
>>>>  bool
>>>>  ebl_reloc_type_check (Ebl *ebl, int reloc)
>>>>  {
>>>> -  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
>>>> +  int relocNew = reloc;
>>>> +  GElf_Ehdr ehdr;
>>>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>>>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>>>> +  return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
>>>>  }
>>> This should not go into the generic ebl_reloc_type_check but has to be
>>> hooked so it uses a mips_reloc_type_check.
>>>
>>>> diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
>>>> index e53ec0c0..4276d8e3 100644
>>>> --- a/libebl/eblreloctypename.c
>>>> +++ b/libebl/eblreloctypename.c
>>>> @@ -33,14 +33,18 @@
>>>>  
>>>>  #include <stdio.h>
>>>>  #include <libeblP.h>
>>>> -
>>>> +#include <libelfP.h>
>>>>  
>>>>  const char *
>>>>  ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
>>>>  {
>>>>    const char *res;
>>>> +  int relocNew = reloc;
>>>> +  GElf_Ehdr ehdr;
>>>> +  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
>>>> +    relocNew = ELF64_MIPS_R_TYPE(reloc);
>>>>  
>>>> -  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
>>>> +  res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
>>>>    if (res == NULL)
>>>>      /* There are no generic relocation type names.  */
>>>>      res = "<INVALID RELOC>";
>>> Likewise for hooking reloc_type_name.
>>>
>> The function reloc_type_check and reloc_type_name were common hooks in file backends/common-reloc.c, so if we also need a new hook for mips and copy the check codes from common-reloc.c?
>>
>> Thanks,
>>
>> Ying
>>
>>
  
Mark Wielaard Aug. 1, 2023, 9:25 a.m. UTC | #6
Hi Ying,

On Mon, 2023-07-24 at 16:35 +0800, Ying Huang wrote:
> Hi Mark,
> 
> > > diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
> > > index 80e67ef7..e3c43944 100644
> > > --- a/libebl/eblreloctypecheck.c
> > > +++ b/libebl/eblreloctypecheck.c
> > > @@ -32,10 +32,14 @@
> > > #endif
> > > 
> > >  #include 
> 
> > > -
> > > +#include 
> 
> > > 
> > > bool
> > > ebl_reloc_type_check (Ebl *ebl, int reloc)
> > > {
> > > - return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
> > > + int relocNew = reloc;
> > > + GElf_Ehdr ehdr;
> > > + if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
> > > + relocNew = ELF64_MIPS_R_TYPE(reloc);
> > > + return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
> > > }
> > This should not go into the generic ebl_reloc_type_check but has to be
> > hooked so it uses a mips_reloc_type_check.
> > 
> > > diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
> > > index e53ec0c0..4276d8e3 100644
> > > --- a/libebl/eblreloctypename.c
> > > +++ b/libebl/eblreloctypename.c
> > > @@ -33,14 +33,18 @@
> > > 
> > >  #include 
> 
> > >  #include 
> 
> > > -
> > > +#include 
> 
> > > 
> > > const char *
> > > ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
> > > {
> > > const char *res;
> > > + int relocNew = reloc;
> > > + GElf_Ehdr ehdr;
> > > + if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
> > > + relocNew = ELF64_MIPS_R_TYPE(reloc);
> > > 
> > > - res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
> > > + res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
> > > if (res == NULL)
> > > /* There are no generic relocation type names. */
> > >      res = "";
> > Likewise for hooking reloc_type_name.
> > 
> The function reloc_type_check and reloc_type_name were common hooks in file backends/common-reloc.c, so if we also need a new hook for mips and copy the check codes from common-reloc.c?

There are no other arches which use those hooks at the moment. But you
should be able to simply define them as mips_reloc_type_xxx and then
HOOK them in your mips.c init function.

Cheers,

Mark
  
Mark Wielaard Aug. 1, 2023, 1:14 p.m. UTC | #7
Hi Ying,

On Tue, 2023-07-25 at 16:15 +0800, Ying Huang wrote:
> In file common-reloc.c, hook functions reloc_type_check/reloc_type_use/reloc_type_name have these codes:
> 
> #ifdef RELOC_TYPE_ID
>   reloc = RELOC_TYPE_ID (reloc);
> #endif
> 
> And the macro RELOC_TYPE_ID was defined in file backends/sparc_init.c:
> 
> /* In SPARC some relocations use the most significative 24 bits of the
>    r_type field to encode a secondary addend.  Make sure the routines
>    in common-reloc.c acknowledge this.  */
> #define RELOC_TYPE_ID(type) ((type) & 0xff)
> 
> The contents of macro RELOC_TYPE_ID were same as ELF64_MIPS_R_TYPE(new added), so my view is did not add new hook for mips, if we can do like sparc?

Sorry, hadn't seen this message before. But yes, if you can do like
sparc and define RELOC_TYPE_ID then that would be simpler than creating
a full new HOOK for reloc_type_check.

Cheers,

Mark
  
Mark Wielaard Aug. 1, 2023, 9:43 p.m. UTC | #8
Hi Ying,

On Thu, Jul 27, 2023 at 02:08:52PM +0800, Ying Huang wrote:
>
> Can we add a new file mips.h in backends, and move defines of
> ELF64_MIPS_R_TYPE/ELF64_MIPS_R_TYPE2/ELF64_MIPS_R_TYPE3 from elf.h
> to mips.h?
>
> And rename the macro name ELF64_MIPS_R_TYPE to ELF64_MIPS_R_TYPE1 in
> mips.h? Or rename it directly in elf.h of glibc?

I would prefer the macros to get defined in elf.h if they are
generally useful to get at the relocation type. But if that isn't
possible we can certainly define them in some internal header file.

Is there a specific mips elf specification we are following?

Cheers,

Mark
  

Patch

diff --git a/backends/Makefile.am b/backends/Makefile.am
index bda1b604..428a1a03 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -100,7 +100,7 @@  loongarch_SRCS = loongarch_init.c loongarch_symbol.c
 
 arc_SRCS = arc_init.c arc_symbol.c
 
-mips_SRCS = mips_init.c mips_symbol.c
+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
 
 libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
 			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
diff --git a/backends/mips_attrs.c b/backends/mips_attrs.c
new file mode 100644
index 00000000..1419814e
--- /dev/null
+++ b/backends/mips_attrs.c
@@ -0,0 +1,107 @@ 
+/* Object attribute tags for MIPS.
+   Copyright (C) 2023 CIP United Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+#define KNOWN_VALUES(...) do				\
+  {							\
+    static const char *table[] = { __VA_ARGS__ };	\
+    if (value < sizeof table / sizeof table[0])		\
+      *value_name = table[value];			\
+  } while (0)
+
+/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */
+bool
+mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag, uint64_t value,
+			    const char **tag_name, const char **value_name)
+{
+  if (!strcmp (vendor, "gnu"))
+    switch (tag)
+      {
+      case Tag_GNU_MIPS_ABI_FP:
+	*tag_name = "Tag_GNU_MIPS_ABI_FP";
+	switch (value)
+	{
+	  case Val_GNU_MIPS_ABI_FP_ANY:
+	    *value_name = "Hard or soft float";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_DOUBLE:
+	    *value_name = "Hard float (double precision)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_SINGLE:
+	    *value_name = "Hard float (single precision)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_SOFT:
+	    *value_name = "Soft float";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_OLD_64:
+	    *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_XX:
+	    *value_name = "Hard float (32-bit CPU, Any FPU)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_64:
+	    *value_name = "Hard float (32-bit CPU, 64-bit FPU)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_64A:
+	    *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)";
+	    return true;
+	  case Val_GNU_MIPS_ABI_FP_NAN2008:
+	    *value_name = "NaN 2008 compatibility";
+	    return true;
+	  default:
+	    return true;
+	}
+	return true;
+      case Tag_GNU_MIPS_ABI_MSA:
+	*tag_name = "Tag_GNU_MIPS_ABI_MSA";
+	switch (value)
+	{
+	  case Val_GNU_MIPS_ABI_MSA_ANY:
+	    *value_name = "Any MSA or not";
+	    return true;
+	  case Val_GNU_MIPS_ABI_MSA_128:
+	    *value_name = "128-bit MSA";
+	    return true;
+	  default:
+	    return true;
+	}
+	return true;
+      }
+
+  return false;
+}
diff --git a/backends/mips_init.c b/backends/mips_init.c
index f70d62e4..5bba822b 100644
--- a/backends/mips_init.c
+++ b/backends/mips_init.c
@@ -45,5 +45,12 @@  mips_init (Elf *elf __attribute__ ((unused)),
   /* We handle it.  */
   mips_init_reloc (eh);
   HOOK (eh, reloc_simple_type);
+  HOOK (eh, section_type_name);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, machine_flag_name);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, check_object_attribute);
   return eh;
 }
diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
index 4f1bd3e6..e760d58d 100644
--- a/backends/mips_symbol.c
+++ b/backends/mips_symbol.c
@@ -39,6 +39,7 @@ 
 #define BACKEND		mips_
 #include "libebl_CPU.h"
 #include "libelfP.h"
+
 /* Check for the simple reloc types.  */
 Elf_Type
 mips_reloc_simple_type (Ebl *ebl, int type,
@@ -60,3 +61,574 @@  mips_reloc_simple_type (Ebl *ebl, int type,
       return ELF_T_NUM;
     }
 }
+
+/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name  */
+const char *
+mips_section_type_name (int type,
+		       char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_MIPS_LIBLIST:
+      return "MIPS_LIBLIST";
+    case SHT_MIPS_MSYM:
+      return "MIPS_MSYM";
+    case SHT_MIPS_CONFLICT:
+      return "MIPS_CONFLICT";
+    case SHT_MIPS_GPTAB:
+      return "MIPS_GPTAB";
+    case SHT_MIPS_UCODE:
+      return "MIPS_UCODE";
+    case SHT_MIPS_DEBUG:
+      return "MIPS_DEBUG";
+    case SHT_MIPS_REGINFO:
+      return "MIPS_REGINFO";
+    case SHT_MIPS_PACKAGE:
+      return "MIPS_PACKAGE";
+    case SHT_MIPS_PACKSYM:
+      return "MIPS_PACKSYM";
+    case SHT_MIPS_RELD:
+      return "MIPS_RELD";
+    case SHT_MIPS_IFACE:
+      return "MIPS_IFACE";
+    case SHT_MIPS_CONTENT:
+      return "MIPS_CONTENT";
+    case SHT_MIPS_OPTIONS:
+      return "MIPS_OPTIONS";
+    case SHT_MIPS_SHDR:
+      return "MIPS_SHDR";
+    case SHT_MIPS_FDESC:
+      return "MIPS_FDESC";
+    case SHT_MIPS_EXTSYM:
+      return "MIPS_EXTSYM";
+    case SHT_MIPS_DENSE:
+      return "MIPS_DENSE";
+    case SHT_MIPS_PDESC:
+      return "MIPS_PDESC";
+    case SHT_MIPS_LOCSYM:
+      return "MIPS_LOCSYM";
+    case SHT_MIPS_AUXSYM:
+      return "MIPS_AUXSYM";
+    case SHT_MIPS_OPTSYM:
+      return "MIPS_OPTSYM";
+    case SHT_MIPS_LOCSTR:
+      return "MIPS_LOCSTR";
+    case SHT_MIPS_LINE:
+      return "MIPS_LINE";
+    case SHT_MIPS_RFDESC:
+      return "MIPS_RFDESC";
+    case SHT_MIPS_DELTASYM:
+      return "MIPS_DELTASYM";
+    case SHT_MIPS_DELTAINST:
+      return "MIPS_DELTAINST";
+    case SHT_MIPS_DELTACLASS:
+      return "MIPS_DELTACLASS";
+    case SHT_MIPS_DWARF:
+      return "MIPS_DWARF";
+    case SHT_MIPS_DELTADECL:
+      return "MIPS_DELTADECL";
+    case SHT_MIPS_SYMBOL_LIB:
+      return "MIPS_SYMBOL_LIB";
+    case SHT_MIPS_EVENTS:
+      return "MIPS_EVENTS";
+    case SHT_MIPS_TRANSLATE:
+      return "MIPS_TRANSLATE";
+    case SHT_MIPS_PIXIE:
+      return "MIPS_PIXIE";
+    case SHT_MIPS_XLATE:
+      return "MIPS_XLATE";
+    case SHT_MIPS_XLATE_DEBUG:
+      return "MIPS_XLATE_DEBUG";
+    case SHT_MIPS_WHIRL:
+      return "MIPS_WHIRL";
+    case SHT_MIPS_EH_REGION:
+      return "MIPS_EH_REGION";
+    case SHT_MIPS_XLATE_OLD:
+      return "MIPS_XLATE_OLD";
+    case SHT_MIPS_PDR_EXCEPTION:
+      return "MIPS_PDR_EXCEPTION";
+    case SHT_MIPS_ABIFLAGS:
+      return "MIPS_ABIFLAGS";
+    case SHT_MIPS_XHASH:
+      return "MIPS_XHASH";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+/* Check whether machine flags are valid.  */
+bool
+mips_machine_flag_check (GElf_Word flags)
+{
+  if ((flags &~ (EF_MIPS_NOREORDER |
+		 EF_MIPS_PIC |
+		 EF_MIPS_CPIC |
+		 EF_MIPS_UCODE |
+		 EF_MIPS_ABI2 |
+		 EF_MIPS_OPTIONS_FIRST |
+		 EF_MIPS_32BITMODE |
+		 EF_MIPS_NAN2008 |
+		 EF_MIPS_FP64 |
+		 EF_MIPS_ARCH_ASE_MDMX |
+		 EF_MIPS_ARCH_ASE_M16 |
+		 EF_MIPS_ARCH_ASE_MICROMIPS)) == 0)
+    return false;
+
+  switch(flags & EF_MIPS_MACH)
+    {
+    case E_MIPS_MACH_3900:
+    case E_MIPS_MACH_4010:
+    case E_MIPS_MACH_4100:
+    case E_MIPS_MACH_4111:
+    case E_MIPS_MACH_4120:
+    case E_MIPS_MACH_4650:
+    case E_MIPS_MACH_5400:
+    case E_MIPS_MACH_5500:
+    case E_MIPS_MACH_5900:
+    case E_MIPS_MACH_SB1:
+    case E_MIPS_MACH_9000:
+    case E_MIPS_MACH_LS2E:
+    case E_MIPS_MACH_LS2F:
+    case E_MIPS_MACH_GS464:
+    case E_MIPS_MACH_GS464E:
+    case E_MIPS_MACH_GS264E:
+    case E_MIPS_MACH_OCTEON:
+    case E_MIPS_MACH_OCTEON2:
+    case E_MIPS_MACH_OCTEON3:
+    case E_MIPS_MACH_XLR:
+    case E_MIPS_MACH_IAMR2:
+    case 0:
+      break;
+    default:
+      return false;
+    }
+
+  switch ((flags & EF_MIPS_ABI))
+    {
+    case E_MIPS_ABI_O32:
+    case E_MIPS_ABI_O64:
+    case E_MIPS_ABI_EABI32:
+    case E_MIPS_ABI_EABI64:
+    case 0:
+      break;
+    default:
+      return false;
+    }
+
+  switch ((flags & EF_MIPS_ARCH))
+    {
+    case E_MIPS_ARCH_1:
+    case E_MIPS_ARCH_2:
+    case E_MIPS_ARCH_3:
+    case E_MIPS_ARCH_4:
+    case E_MIPS_ARCH_5:
+    case E_MIPS_ARCH_32:
+    case EF_MIPS_ARCH_32R2:
+    case E_MIPS_ARCH_32R6:
+    case E_MIPS_ARCH_64:
+    case EF_MIPS_ARCH_64R2:
+    case E_MIPS_ARCH_64R6:
+      return true;
+    default:
+      return false;
+    }
+  return false;
+}
+
+/* copy binutils-2.34/binutils/readelf.c get_machine_flags */
+const char *
+mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref)
+{
+  if (*flagref & EF_MIPS_NOREORDER)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER);
+      return "noreorder";
+    }
+
+  if (*flagref & EF_MIPS_PIC)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_PIC);
+      return "pic";
+    }
+
+  if (*flagref & EF_MIPS_CPIC)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_CPIC);
+      return "cpic";
+    }
+
+  if (*flagref & EF_MIPS_UCODE)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_UCODE);
+      return "ugen_reserved";
+    }
+
+  if (*flagref & EF_MIPS_ABI2)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_ABI2);
+      return "abi2";
+    }
+
+  if (*flagref & EF_MIPS_OPTIONS_FIRST)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST);
+      return "odk first";
+    }
+
+  if (*flagref & EF_MIPS_32BITMODE)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE);
+      return "32bitmode";
+    }
+
+  if (*flagref & EF_MIPS_NAN2008)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008);
+      return "nan2008";
+    }
+
+  if (*flagref & EF_MIPS_FP64)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_FP64);
+      return "fp64";
+    }
+
+  switch (*flagref & EF_MIPS_MACH)
+    {
+    case E_MIPS_MACH_3900:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_3900);
+      return "3900";
+    case E_MIPS_MACH_4010:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4010);
+      return "4010";
+    case E_MIPS_MACH_4100:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4100);
+      return "4100";
+    case E_MIPS_MACH_4111:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4111);
+      return "4111";
+    case E_MIPS_MACH_4120:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4120);
+      return "4120";
+    case E_MIPS_MACH_4650:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_4650);
+      return "4650";
+    case E_MIPS_MACH_5400:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5400);
+      return "5400";
+    case E_MIPS_MACH_5500:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5500);
+      return "5500";
+    case E_MIPS_MACH_5900:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_5900);
+      return "5900";
+    case E_MIPS_MACH_SB1:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_SB1);
+      return "sb1";
+    case E_MIPS_MACH_9000:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_9000);
+      return "9000";
+    case E_MIPS_MACH_LS2E:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_LS2E);
+      return "loongson-2e";
+    case E_MIPS_MACH_LS2F:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_LS2F);
+      return "loongson-2f";
+    case E_MIPS_MACH_GS464:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS464);
+      return "gs464";
+    case E_MIPS_MACH_GS464E:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS464E);
+      return "gs464e";
+    case E_MIPS_MACH_GS264E:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_GS264E);
+      return "gs264e";
+    case E_MIPS_MACH_OCTEON:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON);
+      return "octeon";
+    case E_MIPS_MACH_OCTEON2:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON2);
+      return "octeon2";
+    case E_MIPS_MACH_OCTEON3:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_OCTEON3);
+      return "octeon3";
+    case E_MIPS_MACH_XLR:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_XLR);
+      return "xlr";
+    case E_MIPS_MACH_IAMR2:
+      *flagref &= ~((Elf64_Word) E_MIPS_MACH_IAMR2);
+      return "interaptiv-mr2";
+    case 0:
+      /* We simply ignore the field in this case to avoid confusion:
+         MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
+         extension.  */
+      break;
+    default:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH);
+      return "unknown CPU";
+    }
+  switch (*flagref & EF_MIPS_ABI)
+    {
+    case E_MIPS_ABI_O32:
+      *flagref &= ~((Elf64_Word) E_MIPS_ABI_O32);
+      return "o32";
+    case E_MIPS_ABI_O64:
+      *flagref &= ~((Elf64_Word) E_MIPS_ABI_O64);
+      return "o64";
+    case E_MIPS_ABI_EABI32:
+      *flagref &= ~((Elf64_Word) E_MIPS_ABI_EABI32);
+      return "eabi32";
+    case E_MIPS_ABI_EABI64:
+      *flagref &= ~((Elf64_Word) E_MIPS_ABI_EABI64);
+      return "eabi64";
+    case 0:
+      /* We simply ignore the field in this case to avoid confusion:
+         MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
+	 This means it is likely to be an o32 file, but not for
+	 sure.  */
+      break;
+    default:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ABI);
+      return "unknown ABI";
+    }
+
+  if (*flagref & EF_MIPS_ARCH_ASE_MDMX)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX);
+      return "mdmx";
+    }
+
+  if (*flagref & EF_MIPS_ARCH_ASE_M16)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16);
+      return "mips16";
+    }
+
+  if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS)
+    {
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS);
+      return "micromips";
+    }
+
+  switch (*flagref & EF_MIPS_ARCH)
+    {
+    case E_MIPS_ARCH_1:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_1);
+      return "mips1";
+    case E_MIPS_ARCH_2:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_2);
+      return "mips2";
+    case E_MIPS_ARCH_3:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_3);
+      return "mips3";
+    case E_MIPS_ARCH_4:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_4);
+      return "mips4";
+    case E_MIPS_ARCH_5:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_5);
+      return "mips5";
+    case E_MIPS_ARCH_32:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_32);
+      return "mips32";
+    case EF_MIPS_ARCH_32R2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
+      return "mips32r2";
+    case E_MIPS_ARCH_32R6:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_32R6);
+      return "mips32r6";
+    case E_MIPS_ARCH_64:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_64);
+      return "mips64";
+    case EF_MIPS_ARCH_64R2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
+      return "mips64r2";
+    case E_MIPS_ARCH_64R6:
+      *flagref &= ~((Elf64_Word) E_MIPS_ARCH_64R6);
+      return "mips64r6";
+    default:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH);
+      return "unknown ISA";
+    }
+  return NULL;
+}
+
+/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type  */
+const char *
+mips_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_MIPS_REGINFO:
+      return "REGINFO";
+    case PT_MIPS_RTPROC:
+      return "RTPROC";
+    case PT_MIPS_OPTIONS:
+      return "OPTIONS";
+    case PT_MIPS_ABIFLAGS:
+      return "ABIFLAGS";
+    default:
+      return NULL;
+    }
+}
+
+bool
+mips_dynamic_tag_check (int64_t tag)
+{
+  return ((tag &~ (DT_MIPS_RLD_VERSION
+	  | DT_MIPS_TIME_STAMP
+	  | DT_MIPS_ICHECKSUM
+	  | DT_MIPS_IVERSION
+	  | DT_MIPS_FLAGS
+	  | DT_MIPS_BASE_ADDRESS
+	  | DT_MIPS_MSYM
+	  | DT_MIPS_CONFLICT
+	  | DT_MIPS_LIBLIST
+	  | DT_MIPS_LOCAL_GOTNO
+	  | DT_MIPS_CONFLICTNO
+	  | DT_MIPS_LIBLISTNO
+	  | DT_MIPS_SYMTABNO
+	  | DT_MIPS_UNREFEXTNO
+	  | DT_MIPS_GOTSYM
+	  | DT_MIPS_HIPAGENO
+	  | DT_MIPS_RLD_MAP
+	  | DT_MIPS_DELTA_CLASS
+	  | DT_MIPS_DELTA_CLASS_NO
+	  | DT_MIPS_DELTA_INSTANCE
+	  | DT_MIPS_DELTA_INSTANCE_NO
+	  | DT_MIPS_DELTA_RELOC
+	  | DT_MIPS_DELTA_RELOC_NO
+	  | DT_MIPS_DELTA_SYM
+	  | DT_MIPS_DELTA_SYM_NO
+	  | DT_MIPS_DELTA_CLASSSYM
+	  | DT_MIPS_DELTA_CLASSSYM_NO
+	  | DT_MIPS_CXX_FLAGS
+	  | DT_MIPS_PIXIE_INIT
+	  | DT_MIPS_SYMBOL_LIB
+	  | DT_MIPS_LOCALPAGE_GOTIDX
+	  | DT_MIPS_LOCAL_GOTIDX
+	  | DT_MIPS_HIDDEN_GOTIDX
+	  | DT_MIPS_PROTECTED_GOTIDX
+	  | DT_MIPS_OPTIONS
+	  | DT_MIPS_INTERFACE
+	  | DT_MIPS_DYNSTR_ALIGN
+	  | DT_MIPS_INTERFACE_SIZE
+	  | DT_MIPS_RLD_TEXT_RESOLVE_ADDR
+	  | DT_MIPS_PERF_SUFFIX
+	  | DT_MIPS_COMPACT_SIZE
+	  | DT_MIPS_GP_VALUE
+	  | DT_MIPS_AUX_DYNAMIC
+	  | DT_MIPS_PLTGOT
+	  | DT_MIPS_RWPLT
+	  | DT_MIPS_RLD_MAP_REL
+	  | DT_MIPS_XHASH)) == 0);
+}
+
+/* copy binutils-2.34/binutils/readelf.c  get_mips_dynamic_type*/
+const char *
+mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_MIPS_RLD_VERSION:
+      return "MIPS_RLD_VERSION";
+    case DT_MIPS_TIME_STAMP:
+      return "MIPS_TIME_STAMP";
+    case DT_MIPS_ICHECKSUM:
+      return "MIPS_ICHECKSUM";
+    case DT_MIPS_IVERSION:
+      return "MIPS_IVERSION";
+    case DT_MIPS_FLAGS:
+      return "MIPS_FLAGS";
+    case DT_MIPS_BASE_ADDRESS:
+      return "MIPS_BASE_ADDRESS";
+    case DT_MIPS_MSYM:
+      return "MIPS_MSYM";
+    case DT_MIPS_CONFLICT:
+      return "MIPS_CONFLICT";
+    case DT_MIPS_LIBLIST:
+      return "MIPS_LIBLIST";
+    case DT_MIPS_LOCAL_GOTNO:
+      return "MIPS_LOCAL_GOTNO";
+    case DT_MIPS_CONFLICTNO:
+      return "MIPS_CONFLICTNO";
+    case DT_MIPS_LIBLISTNO:
+      return "MIPS_LIBLISTNO";
+    case DT_MIPS_SYMTABNO:
+      return "MIPS_SYMTABNO";
+    case DT_MIPS_UNREFEXTNO:
+      return "MIPS_UNREFEXTNO";
+    case DT_MIPS_GOTSYM:
+      return "MIPS_GOTSYM";
+    case DT_MIPS_HIPAGENO:
+      return "MIPS_HIPAGENO";
+    case DT_MIPS_RLD_MAP:
+      return "MIPS_RLD_MAP";
+    case DT_MIPS_RLD_MAP_REL:
+      return "MIPS_RLD_MAP_REL";
+    case DT_MIPS_DELTA_CLASS:
+      return "MIPS_DELTA_CLASS";
+    case DT_MIPS_DELTA_CLASS_NO:
+      return "MIPS_DELTA_CLASS_NO";
+    case DT_MIPS_DELTA_INSTANCE:
+      return "MIPS_DELTA_INSTANCE";
+    case DT_MIPS_DELTA_INSTANCE_NO:
+      return "MIPS_DELTA_INSTANCE_NO";
+    case DT_MIPS_DELTA_RELOC:
+      return "MIPS_DELTA_RELOC";
+    case DT_MIPS_DELTA_RELOC_NO:
+      return "MIPS_DELTA_RELOC_NO";
+    case DT_MIPS_DELTA_SYM:
+      return "MIPS_DELTA_SYM";
+    case DT_MIPS_DELTA_SYM_NO:
+      return "MIPS_DELTA_SYM_NO";
+    case DT_MIPS_DELTA_CLASSSYM:
+      return "MIPS_DELTA_CLASSSYM";
+    case DT_MIPS_DELTA_CLASSSYM_NO:
+      return "MIPS_DELTA_CLASSSYM_NO";
+    case DT_MIPS_CXX_FLAGS:
+      return "MIPS_CXX_FLAGS";
+    case DT_MIPS_PIXIE_INIT:
+      return "MIPS_PIXIE_INIT";
+    case DT_MIPS_SYMBOL_LIB:
+      return "MIPS_SYMBOL_LIB";
+    case DT_MIPS_LOCALPAGE_GOTIDX:
+      return "MIPS_LOCALPAGE_GOTIDX";
+    case DT_MIPS_LOCAL_GOTIDX:
+      return "MIPS_LOCAL_GOTIDX";
+    case DT_MIPS_HIDDEN_GOTIDX:
+      return "MIPS_HIDDEN_GOTIDX";
+    case DT_MIPS_PROTECTED_GOTIDX:
+      return "MIPS_PROTECTED_GOTIDX";
+    case DT_MIPS_OPTIONS:
+      return "MIPS_OPTIONS";
+    case DT_MIPS_INTERFACE:
+      return "MIPS_INTERFACE";
+    case DT_MIPS_DYNSTR_ALIGN:
+      return "MIPS_DYNSTR_ALIGN";
+    case DT_MIPS_INTERFACE_SIZE:
+      return "MIPS_INTERFACE_SIZE";
+    case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
+      return "MIPS_RLD_TEXT_RESOLVE_ADDR";
+    case DT_MIPS_PERF_SUFFIX:
+      return "MIPS_PERF_SUFFIX";
+    case DT_MIPS_COMPACT_SIZE:
+      return "MIPS_COMPACT_SIZE";
+    case DT_MIPS_GP_VALUE:
+      return "MIPS_GP_VALUE";
+    case DT_MIPS_AUX_DYNAMIC:
+      return "MIPS_AUX_DYNAMIC";
+    case DT_MIPS_PLTGOT:
+      return "MIPS_PLTGOT";
+    case DT_MIPS_RWPLT:
+      return "MIPS_RWPLT";
+    case DT_MIPS_XHASH:
+      return "MIPS_XHASH";
+    default:
+      return NULL;
+    }
+  return NULL;
+}
diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
index 80e67ef7..e3c43944 100644
--- a/libebl/eblreloctypecheck.c
+++ b/libebl/eblreloctypecheck.c
@@ -32,10 +32,14 @@ 
 #endif
 
 #include <libeblP.h>
-
+#include <libelfP.h>
 
 bool
 ebl_reloc_type_check (Ebl *ebl, int reloc)
 {
-  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
+  int relocNew = reloc;
+  GElf_Ehdr ehdr;
+  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
+    relocNew = ELF64_MIPS_R_TYPE(reloc);
+  return ebl != NULL ? ebl->reloc_type_check (relocNew) : false;
 }
diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
index e53ec0c0..4276d8e3 100644
--- a/libebl/eblreloctypename.c
+++ b/libebl/eblreloctypename.c
@@ -33,14 +33,18 @@ 
 
 #include <stdio.h>
 #include <libeblP.h>
-
+#include <libelfP.h>
 
 const char *
 ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
 {
   const char *res;
+  int relocNew = reloc;
+  GElf_Ehdr ehdr;
+  if(ebl->elf->class == ELFCLASS64 && gelf_getehdr(ebl->elf, &ehdr) != NULL && ehdr.e_machine == EM_MIPS)
+    relocNew = ELF64_MIPS_R_TYPE(reloc);
 
-  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
+  res = ebl != NULL ? ebl->reloc_type_name (relocNew, buf, len) : NULL;
   if (res == NULL)
     /* There are no generic relocation type names.  */
     res = "<INVALID RELOC>";
diff --git a/libelf/elf.h b/libelf/elf.h
index aa903837..6284564f 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -1684,11 +1684,26 @@  typedef struct
 #define EF_MIPS_PIC		2     /* Contains PIC code.  */
 #define EF_MIPS_CPIC		4     /* Uses PIC calling sequence.  */
 #define EF_MIPS_XGOT		8
-#define EF_MIPS_64BIT_WHIRL	16
+//copy binutils-2.34/elfcpp/mips.h
+#define EF_MIPS_UCODE		16
 #define EF_MIPS_ABI2		32
 #define EF_MIPS_ABI_ON32	64
+//copy machine flag from binutils-2.34/elfcpp/mips.h
+/* Process the .MIPS.options section first by ld */
+#define EF_MIPS_OPTIONS_FIRST	0x00000080
+/* Indicates code compiled for a 64-bit machine in 32-bit mode
+   (regs are 32-bits wide).  */
+#define EF_MIPS_32BITMODE	0x00000100
 #define EF_MIPS_FP64		512  /* Uses FP64 (12 callee-saved).  */
-#define EF_MIPS_NAN2008	1024  /* Uses IEEE 754-2008 NaN encoding.  */
+#define EF_MIPS_NAN2008		1024  /* Uses IEEE 754-2008 NaN encoding.  */
+/* Architectural Extensions used by this file */
+#define EF_MIPS_ARCH_ASE	0x0f000000
+/* Use MDMX multimedia extensions */
+#define EF_MIPS_ARCH_ASE_MDMX	0x08000000
+/* Use MIPS-16 ISA extensions */
+#define EF_MIPS_ARCH_ASE_M16	0x04000000
+/* Use MICROMIPS ISA extensions.  */
+#define EF_MIPS_ARCH_ASE_MICROMIPS	0x02000000
 #define EF_MIPS_ARCH		0xf0000000 /* MIPS architecture level.  */
 
 /* Legal values for MIPS architecture level.  */
@@ -1702,6 +1717,49 @@  typedef struct
 #define EF_MIPS_ARCH_64		0x60000000 /* MIPS64 code.  */
 #define EF_MIPS_ARCH_32R2	0x70000000 /* MIPS32r2 code.  */
 #define EF_MIPS_ARCH_64R2	0x80000000 /* MIPS64r2 code.  */
+/* -mips32r6 code.  */
+#define E_MIPS_ARCH_32R6        0x90000000
+/* -mips64r6 code.  */
+#define E_MIPS_ARCH_64R6        0xa0000000
+/* The ABI of the file.  Also see EF_MIPS_ABI2 above. */
+#define EF_MIPS_ABI		0x0000F000
+/* The original o32 abi. */
+#define E_MIPS_ABI_O32          0x00001000
+/* O32 extended to work on 64 bit architectures */
+#define E_MIPS_ABI_O64          0x00002000
+/* EABI in 32 bit mode */
+#define E_MIPS_ABI_EABI32       0x00003000
+/* EABI in 64 bit mode */
+#define E_MIPS_ABI_EABI64       0x00004000
+/* Machine variant if we know it.  This field was invented at Cygnus,
+   but it is hoped that other vendors will adopt it.  If some standard
+   is developed, this code should be changed to follow it. */
+#define EF_MIPS_MACH		0x00FF0000
+/* Cygnus is choosing values between 80 and 9F;
+   00 - 7F should be left for a future standard;
+   the rest are open. */
+
+#define E_MIPS_MACH_3900	0x00810000
+#define E_MIPS_MACH_4010	0x00820000
+#define E_MIPS_MACH_4100	0x00830000
+#define E_MIPS_MACH_4650	0x00850000
+#define E_MIPS_MACH_4120	0x00870000
+#define E_MIPS_MACH_4111	0x00880000
+#define E_MIPS_MACH_SB1         0x008a0000
+#define E_MIPS_MACH_OCTEON	0x008b0000
+#define E_MIPS_MACH_XLR     	0x008c0000
+#define E_MIPS_MACH_OCTEON2	0x008d0000
+#define E_MIPS_MACH_OCTEON3	0x008e0000
+#define E_MIPS_MACH_5400	0x00910000
+#define E_MIPS_MACH_5900	0x00920000
+#define E_MIPS_MACH_IAMR2	0x00930000
+#define E_MIPS_MACH_5500	0x00980000
+#define E_MIPS_MACH_9000	0x00990000
+#define E_MIPS_MACH_LS2E        0x00A00000
+#define E_MIPS_MACH_LS2F        0x00A10000
+#define E_MIPS_MACH_GS464       0x00A20000
+#define E_MIPS_MACH_GS464E	0x00A30000
+#define E_MIPS_MACH_GS264E	0x00A40000
 
 /* The following are unofficial names and should not be used.  */
 
@@ -1762,6 +1820,7 @@  typedef struct
 #define SHT_MIPS_EH_REGION	0x70000027
 #define SHT_MIPS_XLATE_OLD	0x70000028
 #define SHT_MIPS_PDR_EXCEPTION	0x70000029
+#define SHT_MIPS_ABIFLAGS	0x7000002a
 #define SHT_MIPS_XHASH		0x7000002b
 
 /* Legal values for sh_flags field of Elf32_Shdr.  */
@@ -1789,6 +1848,31 @@  typedef struct
 /* MIPS specific values for `st_info'.  */
 #define STB_MIPS_SPLIT_COMMON		13
 
+//copy gnu attr tags from binutils-2.34/elfcpp/mips.h
+/* Object attribute tags.  */
+enum
+{
+  /* 0-3 are generic.  */
+
+  /* Floating-point ABI used by this object file.  */
+  Tag_GNU_MIPS_ABI_FP = 4,
+
+  /* MSA ABI used by this object file.  */
+  Tag_GNU_MIPS_ABI_MSA = 8,
+};
+
+/* Object attribute values.  */
+enum
+{
+  /* Values defined for Tag_GNU_MIPS_ABI_MSA.  */
+
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_MIPS_ABI_MSA_ANY = 0,
+
+  /* Using 128-bit MSA.  */
+  Val_GNU_MIPS_ABI_MSA_128 = 1,
+};
+
 /* Entries found in sections of type SHT_MIPS_GPTAB.  */
 
 typedef union
@@ -2218,8 +2302,11 @@  enum
   Val_GNU_MIPS_ABI_FP_64 = 6,
   /* Using -mips32r2 -mfp64 -mno-odd-spreg.  */
   Val_GNU_MIPS_ABI_FP_64A = 7,
+  /* This is reserved for backward-compatibility with an earlier
+     implementation of the MIPS NaN2008 functionality.  */
+  Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
   /* Maximum allocated FP ABI value.  */
-  Val_GNU_MIPS_ABI_FP_MAX = 7
+  Val_GNU_MIPS_ABI_FP_MAX = 9
 };
 
 /* HPPA specific definitions.  */
diff --git a/src/readelf.c b/src/readelf.c
index 6950204e..6e9a02c1 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -1125,7 +1125,7 @@  print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? _("(current)")
 	  : "(\?\?\?)");
 
-  char buf[512];
+  char buf[64];
   printf (_("  OS/ABI:                            %s\n"),
 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
 
@@ -2193,17 +2193,41 @@  handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 			(long int) GELF_R_SYM (rel->r_info));
 	    }
 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
-	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
-		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
-		    likely (ebl_reloc_type_check (ebl,
-						  GELF_R_TYPE (rel->r_info)))
-		    /* Avoid the leading R_ which isn't carrying any
-		       information.  */
-		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
-					   buf, sizeof (buf)) + 2
-		    : _("<INVALID RELOC>"),
-		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
-		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+	    {
+	      unsigned long inf = rel->r_info;
+	      printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
+		      class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+		      likely (ebl_reloc_type_check (ebl,
+						    GELF_R_TYPE (rel->r_info)))
+		      /* Avoid the leading R_ which isn't carrying any
+		         information.  */
+		      ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					     buf, sizeof (buf)) + 2
+		      : _("<INVALID RELOC>"),
+		      class == ELFCLASS32 ? 10 : 18, sym->st_value,
+		      elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+
+	      /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
+              if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+	        {
+		  unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+		  unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+		  const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+		  const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+		  printf("                      Type2: ");
+		  if (rtype2 == NULL)
+	            printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
+	          else
+	            printf ("%-17.17s", rtype2);
+
+	          printf ("\n                      Type3: ");
+		  if (rtype3 == NULL)
+	            printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
+	          else
+	            printf ("%-17.17s", rtype3);
+		  printf("\n");
+	        }
+	    }
 	  else
 	    {
 	      /* This is a relocation against a STT_SECTION symbol.  */
@@ -2227,16 +2251,40 @@  handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 			(long int) (sym->st_shndx == SHN_XINDEX
 				    ? xndx : sym->st_shndx));
 	      else
-		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
-			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
-			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
-			/* Avoid the leading R_ which isn't carrying any
-			   information.  */
-			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
-					       buf, sizeof (buf)) + 2
-			: _("<INVALID RELOC>"),
-			class == ELFCLASS32 ? 10 : 18, sym->st_value,
-			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+	        {
+		  unsigned long inf = rel->r_info;
+		  printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
+			  class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			  ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			  /* Avoid the leading R_ which isn't carrying any
+			     information.  */
+			  ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					         buf, sizeof (buf)) + 2
+			  : _("<INVALID RELOC>"),
+			  class == ELFCLASS32 ? 10 : 18, sym->st_value,
+			  elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+
+		  /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
+		  if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+		  {
+		    unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+		    unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+		    const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+		    const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+		    printf("                      Type2: ");
+		    if (rtype2 == NULL)
+	              printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
+	            else
+	              printf ("%-17.17s", rtype2);
+
+	            printf ("\n                      Type3: ");
+		    if (rtype3 == NULL)
+	              printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
+	            else
+	              printf ("%-17.17s", rtype3);
+		    printf("\n");
+		  }
+		}
 	    }
 	}
     }
@@ -2384,19 +2432,43 @@  handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 			(long int) GELF_R_SYM (rel->r_info));
 	    }
 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
-	    printf ("\
+	    {
+              unsigned long inf = rel->r_info;
+	      printf ("\
   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
-		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
-		    likely (ebl_reloc_type_check (ebl,
-						  GELF_R_TYPE (rel->r_info)))
-		    /* Avoid the leading R_ which isn't carrying any
-		       information.  */
-		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
-					   buf, sizeof (buf)) + 2
-		    : _("<INVALID RELOC>"),
-		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
-		    rel->r_addend,
-		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+		      class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+		      likely (ebl_reloc_type_check (ebl,
+						    GELF_R_TYPE (rel->r_info)))
+		      /* Avoid the leading R_ which isn't carrying any
+		         information.  */
+		      ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					     buf, sizeof (buf)) + 2
+		      : _("<INVALID RELOC>"),
+		      class == ELFCLASS32 ? 10 : 18, sym->st_value,
+		      rel->r_addend,
+		      elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+
+	      /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
+	      if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+		{
+		  unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+		  unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+		  const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+		  const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+		  printf("                      Type2: ");
+		  if (rtype2 == NULL)
+	            printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
+	          else
+	            printf ("%-17.17s", rtype2);
+
+	          printf ("\n                      Type3: ");
+		  if (rtype3 == NULL)
+	            printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
+	          else
+	            printf ("%-17.17s", rtype3);
+		  printf("\n");
+		}
+	    }
 	  else
 	    {
 	      /* This is a relocation against a STT_SECTION symbol.  */
@@ -2420,18 +2492,42 @@  handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 			(long int) (sym->st_shndx == SHN_XINDEX
 				    ? xndx : sym->st_shndx));
 	      else
-		printf ("\
+	        {
+                  unsigned long inf = rel->r_info;
+		  printf ("\
   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
-			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
-			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
-			/* Avoid the leading R_ which isn't carrying any
-			   information.  */
-			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
-					       buf, sizeof (buf)) + 2
-			: _("<INVALID RELOC>"),
-			class == ELFCLASS32 ? 10 : 18, sym->st_value,
-			rel->r_addend,
-			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+			  class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			  ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			  /* Avoid the leading R_ which isn't carrying any
+			     information.  */
+			  ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					         buf, sizeof (buf)) + 2
+			  : _("<INVALID RELOC>"),
+			  class == ELFCLASS32 ? 10 : 18, sym->st_value,
+			  rel->r_addend,
+			  elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+
+                  /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753  */
+		  if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS)
+		    {
+		      unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf);
+		      unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf);
+		      const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2;
+		      const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2;
+		      printf("                      Type2: ");
+		      if (rtype2 == NULL)
+	                printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff);
+	              else
+	                printf ("%-17.17s", rtype2);
+
+	              printf ("\n                      Type3: ");
+		      if (rtype3 == NULL)
+	                printf (_("unrecognized: %-7lx"), (unsigned long) type3 & 0xffffffff);
+	              else
+	                printf ("%-17.17s", rtype3);
+		      printf("\n");
+		    }
+	        }
 	    }
 	}
     }
@@ -11633,7 +11729,7 @@  print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
 	  GElf_Shdr shdr_mem;
 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
 
-	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+	  if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
 	    {
 	      const char *name = elf_strptr (ebl->elf, shstrndx,
 					     shdr->sh_name);
@@ -11663,7 +11759,7 @@  print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
       GElf_Shdr shdr_mem;
       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
 
-      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+      if (shdr != NULL && (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_MIPS_DWARF))
 	{
 	  static const struct
 	  {