[v3,3/6] readelf: Adapt src/readelf -h/-S/-r/-w/-l/-d/-a on mips

Message ID 20240305095122.889077-4-ying.huang@oss.cipunited.com
State New
Delegated to: Mark Wielaard
Headers
Series Add support for MIPS |

Commit Message

Ying Huang March 5, 2024, 9:51 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 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"

Also add test/run-readelf-reloc.sh file to test new type2/type3 of
src/readelf -r.

Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
---
 backends/Makefile.am       |   2 +-
 backends/mips_attrs.c      | 140 +++++++++
 backends/mips_init.c       |   7 +
 backends/mips_symbol.c     | 571 +++++++++++++++++++++++++++++++++++++
 libelf/libelfP.h           |   1 +
 src/readelf.c              | 188 +++++++++---
 tests/Makefile.am          |   5 +-
 tests/run-readelf-reloc.sh |  42 +++
 8 files changed, 907 insertions(+), 49 deletions(-)
 create mode 100644 backends/mips_attrs.c
 create mode 100755 tests/run-readelf-reloc.sh
  

Comments

Ying Huang May 24, 2024, 9:55 a.m. UTC | #1
Hi Mark,

Could you help review these two patches 3/6 and 4/6, all have been modified according your previous review comments.

If OK, I would update and resubmit again with ChangeLog commit message because there seems to be a conflict in merge now.


Thanks,

Ying

 

在 2024/3/5 17:51, Ying Huang 写道:
> From: Ying Huang <ying.huang@oss.cipunited.com>
>
> -h: support show Flags name
> -S: support show mips related section type
> -r: support show type 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"
>
> Also add test/run-readelf-reloc.sh file to test new type2/type3 of
> src/readelf -r.
>
> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
> ---
>  backends/Makefile.am       |   2 +-
>  backends/mips_attrs.c      | 140 +++++++++
>  backends/mips_init.c       |   7 +
>  backends/mips_symbol.c     | 571 +++++++++++++++++++++++++++++++++++++
>  libelf/libelfP.h           |   1 +
>  src/readelf.c              | 188 +++++++++---
>  tests/Makefile.am          |   5 +-
>  tests/run-readelf-reloc.sh |  42 +++
>  8 files changed, 907 insertions(+), 49 deletions(-)
>  create mode 100644 backends/mips_attrs.c
>  create mode 100755 tests/run-readelf-reloc.sh
>
> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index b946fd30..ad95526e 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -102,7 +102,7 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.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..54fd3ce3
> --- /dev/null
> +++ b/backends/mips_attrs.c
> @@ -0,0 +1,140 @@
> +/* Object attribute tags for MIPS.
> +   Copyright (C) 2024 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 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 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,
> +};
> +
> +/* Object attribute values.  */
> +enum
> +{
> +  /* This is reserved for backward-compatibility with an earlier
> +     implementation of the MIPS NaN2008 functionality.  */
> +  Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
> +};
> +
> +/* 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 cedd08ca..6b9bd4c8 100644
> --- a/backends/mips_init.c
> +++ b/backends/mips_init.c
> @@ -48,5 +48,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 f2a46495..1545fc4b 100644
> --- a/backends/mips_symbol.c
> +++ b/backends/mips_symbol.c
> @@ -61,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 EF_MIPS_MACH_3900:
> +    case EF_MIPS_MACH_4010:
> +    case EF_MIPS_MACH_4100:
> +    case EF_MIPS_MACH_4111:
> +    case EF_MIPS_MACH_4120:
> +    case EF_MIPS_MACH_4650:
> +    case EF_MIPS_MACH_5400:
> +    case EF_MIPS_MACH_5500:
> +    case EF_MIPS_MACH_5900:
> +    case EF_MIPS_MACH_SB1:
> +    case EF_MIPS_MACH_9000:
> +    case EF_MIPS_MACH_LS2E:
> +    case EF_MIPS_MACH_LS2F:
> +    case EF_MIPS_MACH_GS464:
> +    case EF_MIPS_MACH_GS464E:
> +    case EF_MIPS_MACH_GS264E:
> +    case EF_MIPS_MACH_OCTEON:
> +    case EF_MIPS_MACH_OCTEON2:
> +    case EF_MIPS_MACH_OCTEON3:
> +    case EF_MIPS_MACH_XLR:
> +    case EF_MIPS_MACH_IAMR2:
> +    case 0:
> +      break;
> +    default:
> +      return false;
> +    }
> +
> +  switch ((flags & EF_MIPS_ABI))
> +    {
> +    case EF_MIPS_ABI_O32:
> +    case EF_MIPS_ABI_O64:
> +    case EF_MIPS_ABI_EABI32:
> +    case EF_MIPS_ABI_EABI64:
> +    case 0:
> +      break;
> +    default:
> +      return false;
> +    }
> +
> +  switch ((flags & EF_MIPS_ARCH))
> +    {
> +    case EF_MIPS_ARCH_1:
> +    case EF_MIPS_ARCH_2:
> +    case EF_MIPS_ARCH_3:
> +    case EF_MIPS_ARCH_4:
> +    case EF_MIPS_ARCH_5:
> +    case EF_MIPS_ARCH_32:
> +    case EF_MIPS_ARCH_32R2:
> +    case EF_MIPS_ARCH_32R6:
> +    case EF_MIPS_ARCH_64:
> +    case EF_MIPS_ARCH_64R2:
> +    case EF_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 EF_MIPS_MACH_3900:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900);
> +      return "3900";
> +    case EF_MIPS_MACH_4010:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010);
> +      return "4010";
> +    case EF_MIPS_MACH_4100:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100);
> +      return "4100";
> +    case EF_MIPS_MACH_4111:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111);
> +      return "4111";
> +    case EF_MIPS_MACH_4120:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120);
> +      return "4120";
> +    case EF_MIPS_MACH_4650:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650);
> +      return "4650";
> +    case EF_MIPS_MACH_5400:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400);
> +      return "5400";
> +    case EF_MIPS_MACH_5500:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500);
> +      return "5500";
> +    case EF_MIPS_MACH_5900:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900);
> +      return "5900";
> +    case EF_MIPS_MACH_SB1:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1);
> +      return "sb1";
> +    case EF_MIPS_MACH_9000:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000);
> +      return "9000";
> +    case EF_MIPS_MACH_LS2E:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E);
> +      return "loongson-2e";
> +    case EF_MIPS_MACH_LS2F:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F);
> +      return "loongson-2f";
> +    case EF_MIPS_MACH_GS464:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464);
> +      return "gs464";
> +    case EF_MIPS_MACH_GS464E:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E);
> +      return "gs464e";
> +    case EF_MIPS_MACH_GS264E:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E);
> +      return "gs264e";
> +    case EF_MIPS_MACH_OCTEON:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON);
> +      return "octeon";
> +    case EF_MIPS_MACH_OCTEON2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2);
> +      return "octeon2";
> +    case EF_MIPS_MACH_OCTEON3:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3);
> +      return "octeon3";
> +    case EF_MIPS_MACH_XLR:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR);
> +      return "xlr";
> +    case EF_MIPS_MACH_IAMR2:
> +      *flagref &= ~((Elf64_Word) EF_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 EF_MIPS_ABI_O32:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32);
> +      return "o32";
> +    case EF_MIPS_ABI_O64:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64);
> +      return "o64";
> +    case EF_MIPS_ABI_EABI32:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32);
> +      return "eabi32";
> +    case EF_MIPS_ABI_EABI64:
> +      *flagref &= ~((Elf64_Word) EF_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 EF_MIPS_ARCH_1:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1);
> +      return "mips1";
> +    case EF_MIPS_ARCH_2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2);
> +      return "mips2";
> +    case EF_MIPS_ARCH_3:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3);
> +      return "mips3";
> +    case EF_MIPS_ARCH_4:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4);
> +      return "mips4";
> +    case EF_MIPS_ARCH_5:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5);
> +      return "mips5";
> +    case EF_MIPS_ARCH_32:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32);
> +      return "mips32";
> +    case EF_MIPS_ARCH_32R2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
> +      return "mips32r2";
> +    case EF_MIPS_ARCH_32R6:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6);
> +      return "mips32r6";
> +    case EF_MIPS_ARCH_64:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64);
> +      return "mips64";
> +    case EF_MIPS_ARCH_64R2:
> +      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
> +      return "mips64r2";
> +    case EF_MIPS_ARCH_64R6:
> +      *flagref &= ~((Elf64_Word) EF_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/libelf/libelfP.h b/libelf/libelfP.h
> index bdd2cc6a..6565ee02 100644
> --- a/libelf/libelfP.h
> +++ b/libelf/libelfP.h
> @@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
>  #define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
>  #define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
>  #define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
> +#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF)
>  #endif  /* libelfP.h */
> diff --git a/src/readelf.c b/src/readelf.c
> index 0e931184..e88cf67c 100644
> --- a/src/readelf.c
> +++ b/src/readelf.c
> @@ -2219,17 +2219,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: %lx"), (unsigned long) type2 & 0xffffffff);
> +		  else
> +		    printf ("%s", rtype2);
> +
> +		  printf ("\n		      Type3: ");
> +		  if (rtype3 == NULL)
> +		    printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> +		  else
> +		    printf ("%s", rtype3);
> +		  printf("\n");
> +		}
> +	    }
>  	  else
>  	    {
>  	      /* This is a relocation against a STT_SECTION symbol.  */
> @@ -2253,16 +2277,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: %lx"), (unsigned long) type2 & 0xffffffff);
> +		    else
> +		      printf ("%s", rtype2);
> +
> +		    printf ("\n		      Type3: ");
> +		    if (rtype3 == NULL)
> +		      printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> +		    else
> +		      printf ("%s", rtype3);
> +		    printf("\n");
> +		  }
> +		}
>  	    }
>  	}
>      }
> @@ -2410,19 +2458,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: %lx"), (unsigned long) type2 & 0xffffffff);
> +		  else
> +		    printf ("%s", rtype2);
> +
> +		  printf ("\n		      Type3: ");
> +		  if (rtype3 == NULL)
> +		    printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> +		  else
> +		    printf ("%s", rtype3);
> +		  printf("\n");
> +		}
> +	    }
>  	  else
>  	    {
>  	      /* This is a relocation against a STT_SECTION symbol.  */
> @@ -2446,18 +2518,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 ("%s", rtype2);
> +
> +		      printf ("\n		      Type3: ");
> +		      if (rtype3 == NULL)
> +			printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
> +		      else
> +			printf ("%s", rtype3);
> +		      printf("\n");
> +		    }
> +		}
>  	    }
>  	}
>      }
> @@ -12043,7 +12139,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 && is_debug_section_type(shdr->sh_type))
>  	    {
>  	      const char *name = elf_strptr (ebl->elf, shstrndx,
>  					     shdr->sh_name);
> @@ -12073,7 +12169,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 && is_debug_section_type(shdr->sh_type))
>  	{
>  	  static const struct
>  	  {
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 9141074f..18db4047 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
>  	run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
>  	run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
>  	run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
> -	run-declfiles.sh
> +	run-declfiles.sh run-readelf-reloc.sh
>  
>  if !BIARCH
>  export ELFUTILS_DISABLE_BIARCH = 1
> @@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
>  	     testfile-dwp-5-cu-index-overflow.dwp.bz2 \
>  	     testfile-dwp-4-cu-index-overflow.bz2 \
>  	     testfile-dwp-4-cu-index-overflow.dwp.bz2 \
> -	     testfile-dwp-cu-index-overflow.source
> +	     testfile-dwp-cu-index-overflow.source \
> +	     run-readelf-reloc.sh
>  
>  
>  if USE_VALGRIND
> diff --git a/tests/run-readelf-reloc.sh b/tests/run-readelf-reloc.sh
> new file mode 100755
> index 00000000..c1a081dd
> --- /dev/null
> +++ b/tests/run-readelf-reloc.sh
> @@ -0,0 +1,42 @@
> +#! /bin/bash
> +# Copyright (C) 2024 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 the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# elfutils is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +. $srcdir/test-subr.sh
> +
> +tempfiles test-readelf-h.txt test-readelf-reloc.txt
> +testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt
> +machine=`cat test-readelf-h.txt | grep Machine`
> +class=`cat test-readelf-h.txt | grep Class`
> +endian=`cat test-readelf-h.txt | grep Data`
> +if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then
> +testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt
> +
> +testrun_compare cat test-readelf-reloc.txt  << EOF
> +  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
> +EOF
> +fi
> +
> +exit 0
  

Patch

diff --git a/backends/Makefile.am b/backends/Makefile.am
index b946fd30..ad95526e 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -102,7 +102,7 @@  loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.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..54fd3ce3
--- /dev/null
+++ b/backends/mips_attrs.c
@@ -0,0 +1,140 @@ 
+/* Object attribute tags for MIPS.
+   Copyright (C) 2024 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 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 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,
+};
+
+/* Object attribute values.  */
+enum
+{
+  /* This is reserved for backward-compatibility with an earlier
+     implementation of the MIPS NaN2008 functionality.  */
+  Val_GNU_MIPS_ABI_FP_NAN2008 = 8,
+};
+
+/* 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 cedd08ca..6b9bd4c8 100644
--- a/backends/mips_init.c
+++ b/backends/mips_init.c
@@ -48,5 +48,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 f2a46495..1545fc4b 100644
--- a/backends/mips_symbol.c
+++ b/backends/mips_symbol.c
@@ -61,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 EF_MIPS_MACH_3900:
+    case EF_MIPS_MACH_4010:
+    case EF_MIPS_MACH_4100:
+    case EF_MIPS_MACH_4111:
+    case EF_MIPS_MACH_4120:
+    case EF_MIPS_MACH_4650:
+    case EF_MIPS_MACH_5400:
+    case EF_MIPS_MACH_5500:
+    case EF_MIPS_MACH_5900:
+    case EF_MIPS_MACH_SB1:
+    case EF_MIPS_MACH_9000:
+    case EF_MIPS_MACH_LS2E:
+    case EF_MIPS_MACH_LS2F:
+    case EF_MIPS_MACH_GS464:
+    case EF_MIPS_MACH_GS464E:
+    case EF_MIPS_MACH_GS264E:
+    case EF_MIPS_MACH_OCTEON:
+    case EF_MIPS_MACH_OCTEON2:
+    case EF_MIPS_MACH_OCTEON3:
+    case EF_MIPS_MACH_XLR:
+    case EF_MIPS_MACH_IAMR2:
+    case 0:
+      break;
+    default:
+      return false;
+    }
+
+  switch ((flags & EF_MIPS_ABI))
+    {
+    case EF_MIPS_ABI_O32:
+    case EF_MIPS_ABI_O64:
+    case EF_MIPS_ABI_EABI32:
+    case EF_MIPS_ABI_EABI64:
+    case 0:
+      break;
+    default:
+      return false;
+    }
+
+  switch ((flags & EF_MIPS_ARCH))
+    {
+    case EF_MIPS_ARCH_1:
+    case EF_MIPS_ARCH_2:
+    case EF_MIPS_ARCH_3:
+    case EF_MIPS_ARCH_4:
+    case EF_MIPS_ARCH_5:
+    case EF_MIPS_ARCH_32:
+    case EF_MIPS_ARCH_32R2:
+    case EF_MIPS_ARCH_32R6:
+    case EF_MIPS_ARCH_64:
+    case EF_MIPS_ARCH_64R2:
+    case EF_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 EF_MIPS_MACH_3900:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900);
+      return "3900";
+    case EF_MIPS_MACH_4010:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010);
+      return "4010";
+    case EF_MIPS_MACH_4100:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100);
+      return "4100";
+    case EF_MIPS_MACH_4111:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111);
+      return "4111";
+    case EF_MIPS_MACH_4120:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120);
+      return "4120";
+    case EF_MIPS_MACH_4650:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650);
+      return "4650";
+    case EF_MIPS_MACH_5400:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400);
+      return "5400";
+    case EF_MIPS_MACH_5500:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500);
+      return "5500";
+    case EF_MIPS_MACH_5900:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900);
+      return "5900";
+    case EF_MIPS_MACH_SB1:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1);
+      return "sb1";
+    case EF_MIPS_MACH_9000:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000);
+      return "9000";
+    case EF_MIPS_MACH_LS2E:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E);
+      return "loongson-2e";
+    case EF_MIPS_MACH_LS2F:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F);
+      return "loongson-2f";
+    case EF_MIPS_MACH_GS464:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464);
+      return "gs464";
+    case EF_MIPS_MACH_GS464E:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E);
+      return "gs464e";
+    case EF_MIPS_MACH_GS264E:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E);
+      return "gs264e";
+    case EF_MIPS_MACH_OCTEON:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON);
+      return "octeon";
+    case EF_MIPS_MACH_OCTEON2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2);
+      return "octeon2";
+    case EF_MIPS_MACH_OCTEON3:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3);
+      return "octeon3";
+    case EF_MIPS_MACH_XLR:
+      *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR);
+      return "xlr";
+    case EF_MIPS_MACH_IAMR2:
+      *flagref &= ~((Elf64_Word) EF_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 EF_MIPS_ABI_O32:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32);
+      return "o32";
+    case EF_MIPS_ABI_O64:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64);
+      return "o64";
+    case EF_MIPS_ABI_EABI32:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32);
+      return "eabi32";
+    case EF_MIPS_ABI_EABI64:
+      *flagref &= ~((Elf64_Word) EF_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 EF_MIPS_ARCH_1:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1);
+      return "mips1";
+    case EF_MIPS_ARCH_2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2);
+      return "mips2";
+    case EF_MIPS_ARCH_3:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3);
+      return "mips3";
+    case EF_MIPS_ARCH_4:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4);
+      return "mips4";
+    case EF_MIPS_ARCH_5:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5);
+      return "mips5";
+    case EF_MIPS_ARCH_32:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32);
+      return "mips32";
+    case EF_MIPS_ARCH_32R2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2);
+      return "mips32r2";
+    case EF_MIPS_ARCH_32R6:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6);
+      return "mips32r6";
+    case EF_MIPS_ARCH_64:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64);
+      return "mips64";
+    case EF_MIPS_ARCH_64R2:
+      *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2);
+      return "mips64r2";
+    case EF_MIPS_ARCH_64R6:
+      *flagref &= ~((Elf64_Word) EF_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/libelf/libelfP.h b/libelf/libelfP.h
index bdd2cc6a..6565ee02 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -620,4 +620,5 @@  extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
 #define ELF64_MIPS_R_TYPE1(i)          ((i) & 0xff)
 #define ELF64_MIPS_R_TYPE2(i)           (((i) >> 8) & 0xff)
 #define ELF64_MIPS_R_TYPE3(i)           (((i) >> 16) & 0xff)
+#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF)
 #endif  /* libelfP.h */
diff --git a/src/readelf.c b/src/readelf.c
index 0e931184..e88cf67c 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -2219,17 +2219,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: %lx"), (unsigned long) type2 & 0xffffffff);
+		  else
+		    printf ("%s", rtype2);
+
+		  printf ("\n		      Type3: ");
+		  if (rtype3 == NULL)
+		    printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+		  else
+		    printf ("%s", rtype3);
+		  printf("\n");
+		}
+	    }
 	  else
 	    {
 	      /* This is a relocation against a STT_SECTION symbol.  */
@@ -2253,16 +2277,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: %lx"), (unsigned long) type2 & 0xffffffff);
+		    else
+		      printf ("%s", rtype2);
+
+		    printf ("\n		      Type3: ");
+		    if (rtype3 == NULL)
+		      printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+		    else
+		      printf ("%s", rtype3);
+		    printf("\n");
+		  }
+		}
 	    }
 	}
     }
@@ -2410,19 +2458,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: %lx"), (unsigned long) type2 & 0xffffffff);
+		  else
+		    printf ("%s", rtype2);
+
+		  printf ("\n		      Type3: ");
+		  if (rtype3 == NULL)
+		    printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+		  else
+		    printf ("%s", rtype3);
+		  printf("\n");
+		}
+	    }
 	  else
 	    {
 	      /* This is a relocation against a STT_SECTION symbol.  */
@@ -2446,18 +2518,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 ("%s", rtype2);
+
+		      printf ("\n		      Type3: ");
+		      if (rtype3 == NULL)
+			printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff);
+		      else
+			printf ("%s", rtype3);
+		      printf("\n");
+		    }
+		}
 	    }
 	}
     }
@@ -12043,7 +12139,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 && is_debug_section_type(shdr->sh_type))
 	    {
 	      const char *name = elf_strptr (ebl->elf, shstrndx,
 					     shdr->sh_name);
@@ -12073,7 +12169,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 && is_debug_section_type(shdr->sh_type))
 	{
 	  static const struct
 	  {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9141074f..18db4047 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -214,7 +214,7 @@  TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
 	run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
 	run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
 	run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
-	run-declfiles.sh
+	run-declfiles.sh run-readelf-reloc.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -646,7 +646,8 @@  EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     testfile-dwp-5-cu-index-overflow.dwp.bz2 \
 	     testfile-dwp-4-cu-index-overflow.bz2 \
 	     testfile-dwp-4-cu-index-overflow.dwp.bz2 \
-	     testfile-dwp-cu-index-overflow.source
+	     testfile-dwp-cu-index-overflow.source \
+	     run-readelf-reloc.sh
 
 
 if USE_VALGRIND
diff --git a/tests/run-readelf-reloc.sh b/tests/run-readelf-reloc.sh
new file mode 100755
index 00000000..c1a081dd
--- /dev/null
+++ b/tests/run-readelf-reloc.sh
@@ -0,0 +1,42 @@ 
+#! /bin/bash
+# Copyright (C) 2024 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 the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles test-readelf-h.txt test-readelf-reloc.txt
+testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt
+machine=`cat test-readelf-h.txt | grep Machine`
+class=`cat test-readelf-h.txt | grep Class`
+endian=`cat test-readelf-h.txt | grep Data`
+if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then
+testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt
+
+testrun_compare cat test-readelf-reloc.txt  << EOF
+  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
+EOF
+fi
+
+exit 0