[openwrt/openwrt] tools/elfutils: update MIPS support patches
LEDE Commits
lede-commits at lists.infradead.org
Sat Jul 26 05:38:52 PDT 2025
robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/5bb84fb53bb5fa1215ddcd245ecdd94975484170
commit 5bb84fb53bb5fa1215ddcd245ecdd94975484170
Author: Michael Pratt <mcpratt at pm.me>
AuthorDate: Mon Oct 21 09:47:25 2024 -0400
tools/elfutils: update MIPS support patches
The original patch series partially added by commit
f97da2c61 ("tools/elfutils: add missing MIPS reloc support")
now has a v3 which has half of it's commits accepted.
To prepare for updating to the new release,
use the new series that includes backports.
Manually adjusted patch:
- 010-backport-mips-support-reloc.patch
Add patch:
- 011-backport-mips-support-strip.patch
- 012-backport-mips-support-readelf.patch
- 013-backport-mips-support-elflint.patch
- 014-backport-mips-support-stack.patch
- 015-backport-mips-support-regs.patch
Tested-by: Tony Ambardar <itugrok at yahoo.com>
Signed-off-by: Michael Pratt <mcpratt at pm.me>
Link: https://github.com/openwrt/openwrt/pull/16522
Signed-off-by: Robert Marko <robimarko at gmail.com>
---
.../patches/010-backport-mips-support-reloc.patch | 2239 +-------------------
.../patches/011-backport-mips-support-strip.patch | 230 ++
.../012-backport-mips-support-readelf.patch | 1079 ++++++++++
.../013-backport-mips-support-elflint.patch | 156 ++
.../patches/014-backport-mips-support-stack.patch | 273 +++
.../patches/015-backport-mips-support-regs.patch | 475 +++++
6 files changed, 2220 insertions(+), 2232 deletions(-)
diff --git a/tools/elfutils/patches/010-backport-mips-support-reloc.patch b/tools/elfutils/patches/010-backport-mips-support-reloc.patch
index 8a65e4e464..e9ef3997d2 100644
--- a/tools/elfutils/patches/010-backport-mips-support-reloc.patch
+++ b/tools/elfutils/patches/010-backport-mips-support-reloc.patch
@@ -1,7 +1,7 @@
-From 8d3bb7db9d6f07decfc59d83988cda54e5a8b0cd Mon Sep 17 00:00:00 2001
+From e259f126f5077923e415e306915de50ed0f0db56 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Tue, 5 Mar 2024 17:51:17 +0800
-Subject: [PATCH 1/7] Support Mips architecture
+Subject: [PATCH] Support Mips architecture
* backends/Makefile.am (modules): Add mips.
(mips_SRCS): New var for mips_init.c mips_symbol.c.
@@ -37,13 +37,11 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
i386_retval.c i386_regs.c i386_auxv.c \
-@@ -102,12 +102,16 @@ loongarch_SRCS = loongarch_init.c loonga
+@@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loonga
arc_SRCS = arc_init.c arc_symbol.c
-+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
-+ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \
-+ mips_corenote.c mips64_corenote.c
++mips_SRCS = mips_init.c mips_symbol.c
+
libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
$(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
@@ -57,7 +55,7 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os)
--- /dev/null
+++ b/backends/mips_init.c
-@@ -0,0 +1,74 @@
+@@ -0,0 +1,52 @@
+/* Initialization of MIPS specific backend library.
+ Copyright (C) 2024 CIP United Inc.
+ This file is part of elfutils.
@@ -100,8 +98,6 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+/* This defines the common reloc hooks based on mips_reloc.def. */
+#include "common-reloc.c"
+
-+extern __typeof (EBLHOOK (core_note)) mips64_core_note attribute_hidden;
-+
+Ebl *
+mips_init (Elf *elf __attribute__ ((unused)),
+ GElf_Half machine __attribute__ ((unused)),
@@ -110,26 +106,6 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+ /* 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, machine_section_flag_check);
-+ HOOK (eh, segment_type_name);
-+ HOOK (eh, dynamic_tag_check);
-+ HOOK (eh, dynamic_tag_name);
-+ HOOK (eh, check_object_attribute);
-+ HOOK (eh, check_special_symbol);
-+ HOOK (eh, check_reloc_target_type);
-+ HOOK (eh, set_initial_registers_tid);
-+ HOOK (eh, abi_cfi);
-+ HOOK (eh, unwind);
-+ HOOK (eh, register_info);
-+ HOOK (eh, return_value_location);
-+ if (eh->class == ELFCLASS64)
-+ eh->core_note = mips64_core_note;
-+ else
-+ HOOK (eh, core_note);
-+ eh->frame_nregs = 71;
+ return eh;
+}
--- /dev/null
@@ -230,7 +206,7 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+RELOC_TYPE (GNU_VTENTRY, REL)
--- /dev/null
+++ b/backends/mips_symbol.c
-@@ -0,0 +1,671 @@
+@@ -0,0 +1,63 @@
+/* MIPS specific symbolic name handling.
+ Copyright (C) 2024 CIP United Inc.
+ This file is part of elfutils.
@@ -294,614 +270,6 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+ 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;
-+}
-+
-+bool
-+mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
-+{
-+ return (sh_type == SHT_MIPS_DWARF);
-+}
-+
-+/* Check whether given symbol's st_value and st_size are OK despite failing
-+ normal checks. */
-+bool
-+mips_check_special_symbol (Elf *elf,
-+ const GElf_Sym *sym __attribute__ ((unused)),
-+ const char *name __attribute__ ((unused)),
-+ const GElf_Shdr *destshdr)
-+{
-+ size_t shstrndx;
-+ if (elf_getshdrstrndx (elf, &shstrndx) != 0)
-+ return false;
-+ const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
-+ if (sname == NULL)
-+ return false;
-+ return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0);
-+}
-+
-+/* Check whether SHF_MASKPROC flags are valid. */
-+bool
-+mips_machine_section_flag_check (GElf_Xword sh_flags)
-+{
-+ return ((sh_flags &~ (SHF_MIPS_GPREL |
-+ SHF_MIPS_MERGE |
-+ SHF_MIPS_ADDR |
-+ SHF_MIPS_STRINGS |
-+ SHF_MIPS_NOSTRIP |
-+ SHF_MIPS_LOCAL |
-+ SHF_MIPS_NAMES |
-+ SHF_MIPS_NODUPE)) == 0);
-+}
-+
-+/* 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;
-+}
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl *
@@ -922,1604 +290,11 @@ Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
-@@ -617,4 +617,8 @@ extern void __libelf_reset_rawdata (Elf_
+@@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_
#define INVALID_NDX(ndx, type, data) \
unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
+#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 */
---- /dev/null
-+++ b/backends/mips_cfi.c
-@@ -0,0 +1,68 @@
-+/* MIPS ABI-specified defaults for DWARF CFI.
-+ Copyright (C) 2009 Red Hat, Inc.
-+ 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 <dwarf.h>
-+
-+#define BACKEND mips_
-+#include "libebl_CPU.h"
-+
-+int
-+mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
-+{
-+ static const uint8_t abi_cfi[] =
-+ {
-+ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0),
-+ /* Callee-saved regs. */
-+ DW_CFA_same_value, ULEB128_7 (16), /* s0 */
-+ DW_CFA_same_value, ULEB128_7 (17), /* s1 */
-+ DW_CFA_same_value, ULEB128_7 (18), /* s2 */
-+ DW_CFA_same_value, ULEB128_7 (19), /* s3 */
-+ DW_CFA_same_value, ULEB128_7 (20), /* s4 */
-+ DW_CFA_same_value, ULEB128_7 (21), /* s5 */
-+ DW_CFA_same_value, ULEB128_7 (22), /* s6 */
-+ DW_CFA_same_value, ULEB128_7 (23), /* s7 */
-+ DW_CFA_same_value, ULEB128_7 (28), /* gp */
-+ DW_CFA_same_value, ULEB128_7 (29), /* sp */
-+ DW_CFA_same_value, ULEB128_7 (30), /* fp */
-+
-+ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0),
-+ };
-+
-+ abi_info->initial_instructions = abi_cfi;
-+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
-+ abi_info->data_alignment_factor = 8;
-+
-+ abi_info->return_address_register = 31; /* %ra */
-+
-+ return 0;
-+}
---- /dev/null
-+++ b/backends/mips_initreg.c
-@@ -0,0 +1,61 @@
-+/* Fetch live process registers from TID.
-+ 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 <stdlib.h>
-+#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
-+# include <sys/user.h>
-+# include <sys/ptrace.h>
-+#include <asm/ptrace.h>
-+#endif
-+
-+#define BACKEND mips_
-+#include "libebl_CPU.h"
-+
-+
-+bool
-+mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
-+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
-+ void *arg __attribute__ ((unused)))
-+{
-+#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__)
-+ return false;
-+#else /* __mips__ */
-+/* For PTRACE_GETREGS */
-+
-+ struct pt_regs gregs;
-+ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
-+ return false;
-+ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg))
-+ return false;
-+ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
-+#endif /* __mips__ */
-+}
---- /dev/null
-+++ b/backends/mips_unwind.c
-@@ -0,0 +1,84 @@
-+/* Get previous frame state for an existing frame state.
-+ Copyright (C) 2016 The Qt Company Ltd.
-+ 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
-+
-+#define BACKEND mips_
-+#define SP_REG 29
-+#define FP_REG 30
-+#define LR_REG 31
-+#define FP_OFFSET 0
-+#define LR_OFFSET 8
-+#define SP_OFFSET 16
-+
-+#include "libebl_CPU.h"
-+
-+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */
-+
-+bool
-+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
-+ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
-+ ebl_pid_memory_read_t *readfunc, void *arg,
-+ bool *signal_framep __attribute__ ((unused)))
-+{
-+ Dwarf_Word fp, lr, sp;
-+
-+ if (!getfunc(LR_REG, 1, &lr, arg))
-+ return false;
-+
-+ if (lr == 0 || !setfunc(-1, 1, &lr, arg))
-+ return false;
-+
-+ if (!getfunc(FP_REG, 1, &fp, arg))
-+ fp = 0;
-+
-+ if (!getfunc(SP_REG, 1, &sp, arg))
-+ sp = 0;
-+
-+ Dwarf_Word newLr, newFp, newSp;
-+
-+ if (!readfunc(fp + LR_OFFSET, &newLr, arg))
-+ newLr = 0;
-+
-+ if (!readfunc(fp + FP_OFFSET, &newFp, arg))
-+ newFp = 0;
-+
-+ newSp = fp + SP_OFFSET;
-+
-+ // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
-+ setfunc(LR_REG, 1, &newLr, arg);
-+ setfunc(FP_REG, 1, &newFp, arg);
-+ setfunc(SP_REG, 1, &newSp, arg);
-+
-+ // If the fp is invalid, we might still have a valid lr.
-+ // But if the fp is valid, then the stack should be moving in the right direction.
-+ return fp == 0 || newSp > sp;
-+}
---- /dev/null
-+++ b/backends/mips_corenote.c
-@@ -0,0 +1,104 @@
-+/* MIPS specific core note handling.
-+ 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 <elf.h>
-+#include <inttypes.h>
-+#include <stddef.h>
-+#include <stdio.h>
-+#include <sys/time.h>
-+#include "libebl_CPU.h"
-+
-+#ifndef BITS
-+# define BITS 32
-+#define BACKEND mips_
-+#else
-+# define BITS 64
-+# define BACKEND mips64_
-+#endif
-+
-+#define PRSTATUS_REGS_SIZE (45 * (BITS / 8))
-+static const Ebl_Register_Location prstatus_regs[] =
-+ {
-+ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS },
-+ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS },
-+ };
-+
-+#define PRSTATUS_REGSET_ITEMS \
-+ { \
-+ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \
-+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \
-+ .group = "register", \
-+ .pc_register = true \
-+ }
-+
-+static const Ebl_Register_Location mips_fpregset_regs[] =
-+ {
-+ { .offset = 0, .regno = 38, .count = 32, .bits = 64 }, /* fp0-fp31 */
-+ };
-+
-+static const Ebl_Core_Item mips_fpregset_items[] =
-+ {
-+ {
-+ .name = "fcs", .type = ELF_T_WORD, .format = 'x',
-+ .offset = 32 * 8, .group = "register"
-+ },
-+ {
-+ .name = "fir", .type = ELF_T_WORD, .format = 'x',
-+ .offset = 32 * 8 + 4, .group = "register"
-+ }
-+ };
-+
-+#if BITS == 32
-+# define ULONG uint32_t
-+# define ALIGN_ULONG 4
-+# define TYPE_ULONG ELF_T_WORD
-+#define TYPE_LONG ELF_T_SWORD
-+#else
-+#define ULONG uint64_t
-+#define ALIGN_ULONG 8
-+#define TYPE_ULONG ELF_T_XWORD
-+#define TYPE_LONG ELF_T_SXWORD
-+#endif
-+#define PID_T int32_t
-+#define UID_T uint32_t
-+#define GID_T uint32_t
-+#define ALIGN_PID_T 4
-+#define ALIGN_UID_T 4
-+#define ALIGN_GID_T 4
-+#define TYPE_PID_T ELF_T_SWORD
-+#define TYPE_UID_T ELF_T_WORD
-+#define TYPE_GID_T ELF_T_WORD
-+
-+#define EXTRA_NOTES \
-+ EXTRA_REGSET_ITEMS (NT_FPREGSET, 32 * 8 + 4 * 2, mips_fpregset_regs, mips_fpregset_items)
-+
-+#include "linux-core-note.c"
---- /dev/null
-+++ b/backends/mips_regs.c
-@@ -0,0 +1,135 @@
-+/* Register names and numbers for mips DWARF.
-+ Copyright (C) 2006 Red Hat, Inc.
-+ 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 <assert.h>
-+#include <dwarf.h>
-+#include <string.h>
-+
-+#define BACKEND mips_
-+#include "libebl_CPU.h"
-+#include <system.h>
-+ssize_t
-+mips_register_info (Ebl *ebl __attribute__ ((unused)),
-+ int regno, char *name, size_t namelen,
-+ const char **prefix, const char **setname,
-+ int *bits, int *type)
-+{
-+ if (name == NULL)
-+ return 72;
-+
-+ if (regno < 0 || regno > 71 || namelen < 4)
-+ return -1;
-+
-+ *prefix = "$";
-+ if (regno < 38)
-+ {
-+ *setname = "integer";
-+ *type = DW_ATE_signed;
-+ *bits = 32;
-+ }
-+ else
-+ {
-+ *setname = "FPU";
-+ *type = DW_ATE_float;
-+ *bits = 64;
-+ }
-+
-+ if (regno < 32)
-+ {
-+ if (regno < 10)
-+ {
-+ name[0] = regno + '0';
-+ namelen = 1;
-+ }
-+ else
-+ {
-+ name[0] = (regno / 10) + '0';
-+ name[1] = (regno % 10) + '0';
-+ namelen = 2;
-+ }
-+ if (regno == 28 || regno == 29 || regno == 31)
-+ *type = DW_ATE_address;
-+ }
-+ else if (regno == 32)
-+ {
-+ return stpcpy (name, "lo") + 1 - name;
-+ }
-+ else if (regno == 33)
-+ {
-+ return stpcpy (name, "hi") + 1 - name;
-+ }
-+ else if (regno == 34)
-+ {
-+ return stpcpy (name, "pc") + 1 - name;
-+ }
-+ else if (regno == 35)
-+ {
-+ *type = DW_ATE_address;
-+ return stpcpy (name, "bad") + 1 - name;
-+ }
-+ else if (regno == 36)
-+ {
-+ return stpcpy (name, "sr") + 1 - name;
-+ }
-+ else if (regno == 37)
-+ {
-+ *type = DW_ATE_address;
-+ return stpcpy (name, "cause") + 1 - name;
-+ }
-+ else if (regno < 70)
-+ {
-+ name[0] = 'f';
-+ if (regno < 38 + 10)
-+ {
-+ name[1] = (regno - 38) + '0';
-+ namelen = 2;
-+ }
-+ else
-+ {
-+ name[1] = (regno - 38) / 10 + '0';
-+ name[2] = (regno - 38) % 10 + '0';
-+ namelen = 3;
-+ }
-+ }
-+ else if (regno == 70)
-+ {
-+ return stpcpy (name, "fsr") + 1 - name;
-+ }
-+ else if (regno == 71)
-+ {
-+ return stpcpy (name, "fir") + 1 - name;
-+ }
-+
-+ name[namelen++] = '\0';
-+ return namelen;
-+}
---- /dev/null
-+++ b/backends/mips_retval.c
-@@ -0,0 +1,196 @@
-+/* Function return value location for Linux/mips ABI.
-+ Copyright (C) 2005 Red Hat, Inc.
-+ 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 <assert.h>
-+#include <dwarf.h>
-+#include <string.h>
-+#include <elf.h>
-+#include <stdio.h>
-+
-+#define BACKEND mips_
-+#include "libebl_CPU.h"
-+#include "libdwP.h"
-+#include <stdio.h>
-+
-+/* $v0 or pair $v0, $v1 */
-+static const Dwarf_Op loc_intreg_o32[] =
-+ {
-+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
-+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
-+ };
-+
-+static const Dwarf_Op loc_intreg[] =
-+ {
-+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 },
-+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 },
-+ };
-+#define nloc_intreg 1
-+#define nloc_intregpair 4
-+
-+/* $f0 (float), or pair $f0, $f1 (double).
-+ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */
-+static const Dwarf_Op loc_fpreg_o32[] =
-+ {
-+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
-+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
-+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 },
-+ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 },
-+ };
-+
-+/* $f0, or pair $f0, $f2. */
-+static const Dwarf_Op loc_fpreg[] =
-+ {
-+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 },
-+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
-+ };
-+#define nloc_fpreg 1
-+#define nloc_fpregpair 4
-+#define nloc_fpregquad 8
-+
-+/* The return value is a structure and is actually stored in stack space
-+ passed in a hidden argument by the caller. But, the compiler
-+ helpfully returns the address of that space in $v0. */
-+static const Dwarf_Op loc_aggregate[] =
-+ {
-+ { .atom = DW_OP_breg2, .number = 0 }
-+ };
-+#define nloc_aggregate 1
-+
-+int
-+mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
-+{
-+ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8;
-+ if (!regsize)
-+ return -2;
-+
-+ /* Start with the function's type, and get the DW_AT_type attribute,
-+ which is the type of the return value. */
-+
-+ Dwarf_Attribute attr_mem;
-+ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem);
-+ if (attr == NULL)
-+ /* The function has no return value, like a `void' function in C. */
-+ return 0;
-+
-+ Dwarf_Die die_mem;
-+ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
-+ int tag = dwarf_tag (typedie);
-+
-+ /* Follow typedefs and qualifiers to get to the actual type. */
-+ while (tag == DW_TAG_typedef
-+ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
-+ || tag == DW_TAG_restrict_type)
-+ {
-+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
-+ typedie = dwarf_formref_die (attr, &die_mem);
-+ tag = dwarf_tag (typedie);
-+ }
-+
-+ switch (tag)
-+ {
-+ case -1:
-+ return -1;
-+
-+ case DW_TAG_subrange_type:
-+ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
-+ {
-+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
-+ typedie = dwarf_formref_die (attr, &die_mem);
-+ tag = dwarf_tag (typedie);
-+ }
-+ /* Fall through. */
-+ FALLTHROUGH;
-+
-+ case DW_TAG_base_type:
-+ case DW_TAG_enumeration_type:
-+ CASE_POINTER:
-+ {
-+ Dwarf_Word size;
-+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
-+ &attr_mem), &size) != 0)
-+ {
-+ if (dwarf_is_pointer (tag))
-+ size = regsize;
-+ else
-+ return -1;
-+ }
-+ if (tag == DW_TAG_base_type)
-+ {
-+ Dwarf_Word encoding;
-+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
-+ &attr_mem), &encoding) != 0)
-+ return -1;
-+
-+#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc))
-+
-+ if (encoding == DW_ATE_float)
-+ {
-+ *locp = ARCH_LOC(loc_fpreg, regsize);
-+ if (size <= regsize)
-+ return nloc_fpreg;
-+
-+ if (size <= 2*regsize)
-+ return nloc_fpregpair;
-+
-+ if (size <= 4*regsize)
-+ return nloc_fpregquad;
-+
-+ goto aggregate;
-+ }
-+ }
-+ *locp = ARCH_LOC(loc_intreg, regsize);
-+ if (size <= regsize)
-+ return nloc_intreg;
-+ if (size <= 2*regsize)
-+ return nloc_intregpair;
-+
-+ /* Else fall through. Shouldn't happen though (at least with gcc) */
-+ }
-+ FALLTHROUGH;
-+
-+ case DW_TAG_structure_type:
-+ case DW_TAG_class_type:
-+ case DW_TAG_union_type:
-+ case DW_TAG_array_type:
-+ aggregate:
-+ *locp = loc_aggregate;
-+ return nloc_aggregate;
-+ case DW_TAG_unspecified_type:
-+ return 0;
-+ }
-+
-+ /* XXX We don't have a good way to return specific errors from ebl calls.
-+ This value means we do not understand the type, but it is well-formed
-+ DWARF and might be valid. */
-+ return -2;
-+}
---- a/libelf/elf_getdata.c
-+++ b/libelf/elf_getdata.c
-@@ -135,6 +135,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int
-
- /* Convert the data in the current section. */
- static void
-+convert_data_for_mips64el (Elf_Scn *scn, int eclass,
-+ int data, size_t size, Elf_Type type)
-+{
-+ /* Do we need to convert the data and/or adjust for alignment? */
-+ if (data == MY_ELFDATA || type == ELF_T_BYTE)
-+ {
-+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
-+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
-+ we need to malloc and memcpy raw data to avoid segment fault. After modification,
-+ the correct value are saved in the malloced memory not in process address space. */
-+ scn->data_base = malloc (size);
-+ if (scn->data_base == NULL)
-+ {
-+ __libelf_seterrno (ELF_E_NOMEM);
-+ return;
-+ }
-+
-+ /* The copy will be appropriately aligned for direct access. */
-+ memcpy (scn->data_base, scn->rawdata_base, size);
-+ }
-+ else
-+ {
-+ xfct_t fp;
-+
-+ scn->data_base = malloc (size);
-+ if (scn->data_base == NULL)
-+ {
-+ __libelf_seterrno (ELF_E_NOMEM);
-+ return;
-+ }
-+
-+ /* Make sure the source is correctly aligned for the conversion
-+ function to directly access the data elements. */
-+ char *rawdata_source;
-+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
-+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
-+ we need to malloc and memcpy raw data to avoid segment fault. After modification,
-+ the correct value are saved in the malloced memory not in process address space. */
-+ rawdata_source = malloc (size);
-+ if (rawdata_source == NULL)
-+ {
-+ __libelf_seterrno (ELF_E_NOMEM);
-+ return;
-+ }
-+
-+ /* The copy will be appropriately aligned for direct access. */
-+ memcpy (rawdata_source, scn->rawdata_base, size);
-+
-+ /* Get the conversion function. */
-+ fp = __elf_xfctstom[eclass - 1][type];
-+
-+ fp (scn->data_base, rawdata_source, size, 0);
-+
-+ if (rawdata_source != scn->rawdata_base)
-+ free (rawdata_source);
-+ }
-+
-+ scn->data_list.data.d.d_buf = scn->data_base;
-+ scn->data_list.data.d.d_size = size;
-+ scn->data_list.data.d.d_type = type;
-+ scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
-+ scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
-+ scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
-+
-+ scn->data_list.data.s = scn;
-+
-+ /* In mips64 little-endian, r_info consists of four byte fields(contains
-+ three reloc types) and a 32-bit symbol index. In order to adapt
-+ GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol
-+ index and type. */
-+ /* references:
-+ https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
-+ Page40 && Page41 */
-+ GElf_Shdr shdr_mem;
-+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-+ if (shdr->sh_type == SHT_REL)
-+ {
-+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
-+ int nentries = shdr->sh_size / sh_entsize;
-+ for (int cnt = 0; cnt < nentries; ++cnt)
-+ {
-+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
-+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
-+ Elf64_Xword info = value->r_info;
-+ value->r_info = (((info & 0xffffffff) << 32)
-+ | ((info >> 56) & 0xff)
-+ | ((info >> 40) & 0xff00)
-+ | ((info >> 24) & 0xff0000)
-+ | ((info >> 8) & 0xff000000));
-+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
-+ }
-+ }
-+ else if (shdr->sh_type == SHT_RELA)
-+ {
-+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
-+ int nentries = shdr->sh_size / sh_entsize;
-+ for (int cnt = 0; cnt < nentries; cnt++)
-+ {
-+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
-+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
-+ Elf64_Xword info = value->r_info;
-+ value->r_info = (((info & 0xffffffff) << 32)
-+ | ((info >> 56) & 0xff)
-+ | ((info >> 40) & 0xff00)
-+ | ((info >> 24) & 0xff0000)
-+ | ((info >> 8) & 0xff000000));
-+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
-+ }
-+ }
-+}
-+
-+/* Convert the data in the current section. */
-+static void
- convert_data (Elf_Scn *scn, int eclass,
- int data, size_t size, Elf_Type type)
- {
-@@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn *
- return;
- }
-
-- /* Convert according to the version and the type. */
-- convert_data (scn, elf->class,
-+ GElf_Shdr shdr_mem;
-+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-+ GElf_Ehdr ehdr_mem;
-+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
-+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
-+ scn->elf->class == ELFCLASS64 && ehdr != NULL &&
-+ ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
-+ convert_data_for_mips64el (scn, elf->class,
-+ (elf->class == ELFCLASS32
-+ || (offsetof (struct Elf, state.elf32.ehdr)
-+ == offsetof (struct Elf, state.elf64.ehdr))
-+ ? elf->state.elf32.ehdr->e_ident[EI_DATA]
-+ : elf->state.elf64.ehdr->e_ident[EI_DATA]),
-+ scn->rawdata.d.d_size, scn->rawdata.d.d_type);
-+ else
-+ /* Convert according to the version and the type. */
-+ convert_data (scn, elf->class,
- (elf->class == ELFCLASS32
- || (offsetof (struct Elf, state.elf32.ehdr)
- == offsetof (struct Elf, state.elf64.ehdr))
---- a/libelf/elf_update.c
-+++ b/libelf/elf_update.c
-@@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd)
- size = -1;
- }
- else
-+ {
-+ /* Because we converted the relocation info in mips order when we call elf_getdata.c,
-+ so we need to convert the modified data in original order bits before writing the
-+ data to the file. */
-+ Elf_Scn *scn = NULL;
-+ while ((scn = elf_nextscn (elf, scn)) != NULL)
-+ {
-+ GElf_Shdr shdr_mem;
-+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-+ GElf_Ehdr ehdr_mem;
-+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
-+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
-+ scn->elf->class == ELFCLASS64 &&
-+ ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
-+ {
-+ Elf_Data *d = elf_getdata (scn, NULL);
-+ if (shdr->sh_type == SHT_REL)
-+ {
-+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
-+ int nentries = shdr->sh_size / sh_entsize;
-+ for (int cnt = 0; cnt < nentries; ++cnt)
-+ {
-+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
-+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
-+ Elf64_Xword info = value->r_info;
-+ value->r_info = (info >> 32
-+ | ((info << 56) & 0xff00000000000000)
-+ | ((info << 40) & 0xff000000000000)
-+ | ((info << 24) & 0xff0000000000)
-+ | ((info << 8) & 0xff00000000));
-+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
-+ }
-+ }
-+ else if (shdr->sh_type == SHT_RELA)
-+ {
-+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
-+ int nentries = shdr->sh_size / sh_entsize;
-+ for (int cnt = 0; cnt < nentries; cnt++)
-+ {
-+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
-+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
-+ Elf64_Xword info = value->r_info;
-+ value->r_info = (info >> 32
-+ | ((info << 56) & 0xff00000000000000)
-+ | ((info << 40) & 0xff000000000000)
-+ | ((info << 24) & 0xff0000000000)
-+ | ((info << 8) & 0xff00000000));
-+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
-+ }
-+ }
-+ }
-+ }
- size = write_file (elf, size, change_bo, shnum);
-+ }
- }
-
- out:
---- /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;
-+}
---- a/src/readelf.c
-+++ b/src/readelf.c
-@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *
- (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 *
- (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
- (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
- (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 *
- 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 *
- 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
- {
---- a/tests/Makefile.am
-+++ b/tests/Makefile.am
-@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s
- 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-arsymt
- 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
---- /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
---- a/src/elflint.c
-+++ b/src/elflint.c
-@@ -936,7 +936,9 @@ section [%2d] '%s': symbol %zu (%s): non
- }
-
- if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
-- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
-+ && GELF_ST_BIND (sym->st_info) != STB_LOCAL
-+ && ehdr->e_machine != EM_MIPS
-+ && strcmp (name, "_DYNAMIC_LINKING") != 0)
- ERROR (_("\
- section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
- idx, section_name (ebl, idx), cnt, name);
-@@ -3828,6 +3830,10 @@ cannot get section header for section [%
- && ebl_bss_plt_p (ebl))
- good_type = SHT_NOBITS;
-
-+ if (ehdr->e_machine == EM_MIPS
-+ && (strstr(special_sections[s].name, ".debug") != NULL))
-+ good_type = SHT_MIPS_DWARF;
-+
- /* In a debuginfo file, any normal section can be SHT_NOBITS.
- This is only invalid for DWARF sections and .shstrtab. */
- if (shdr->sh_type != good_type
-@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o
- ERROR (_("section [%2zu] '%s'"
- " contains invalid processor-specific flag(s)"
- " %#" PRIx64 "\n"),
-- cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
-+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
- sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
- }
- if (sh_flags & SHF_MASKOS)
-- if (gnuld)
-- sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
-+ {
-+ if (gnuld)
-+ sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
-+ if (!ebl_machine_section_flag_check (ebl,
-+ sh_flags & SHF_MASKOS))
-+ ERROR (_("section [%2zu] '%s'"
-+ " contains invalid os-specific flag(s)"
-+ " %#" PRIx64 "\n"),
-+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKOS);
-+ sh_flags &= ~(GElf_Xword) SHF_MASKOS;
-+ }
- if (sh_flags != 0)
- ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
- " %#" PRIx64 "\n"),
-@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but
- switch (shdr->sh_type)
- {
- case SHT_PROGBITS:
-+ case SHT_MIPS_DWARF:
- break;
-
- case SHT_NOBITS:
-@@ -4716,7 +4732,7 @@ program header offset in ELF header and
- if (shdr != NULL
- && ((is_debuginfo && shdr->sh_type == SHT_NOBITS)
- || (! is_debuginfo
-- && (shdr->sh_type == SHT_PROGBITS
-+ && (is_debug_section_type(shdr->sh_type)
- || shdr->sh_type == SHT_X86_64_UNWIND)))
- && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
- && ! strcmp (".eh_frame_hdr",
---- /dev/null
-+++ b/backends/mips64_corenote.c
-@@ -0,0 +1,2 @@
-+#define BITS 64
-+#include "mips_corenote.c"
---- a/libebl/eblcorenotetypename.c
-+++ b/libebl/eblcorenotetypename.c
-@@ -94,6 +94,8 @@ ebl_core_note_type_name (Ebl *ebl, uint3
- KNOWNSTYPE (ARM_SYSTEM_CALL);
- KNOWNSTYPE (SIGINFO);
- KNOWNSTYPE (FILE);
-+ KNOWNSTYPE (MIPS_FP_MODE);
-+ KNOWNSTYPE (MIPS_MSA);
- #undef KNOWNSTYPE
-
- default:
---- a/tests/run-allregs.sh
-+++ b/tests/run-allregs.sh
-@@ -2904,4 +2904,83 @@ FPU registers:
- 62: ft10 (ft10), float 64 bits
- 63: ft11 (ft11), float 64 bits
- EOF
-+
-+# See run-readelf-mixed-corenote.sh for instructions to regenerate
-+# this core file.
-+regs_test testfile-mips64-core <<\EOF
-+integer registers:
-+ 0: $0 (0), signed 32 bits
-+ 1: $1 (1), signed 32 bits
-+ 2: $2 (2), signed 32 bits
-+ 3: $3 (3), signed 32 bits
-+ 4: $4 (4), signed 32 bits
-+ 5: $5 (5), signed 32 bits
-+ 6: $6 (6), signed 32 bits
-+ 7: $7 (7), signed 32 bits
-+ 8: $8 (8), signed 32 bits
-+ 9: $9 (9), signed 32 bits
-+ 10: $10 (10), signed 32 bits
-+ 11: $11 (11), signed 32 bits
-+ 12: $12 (12), signed 32 bits
-+ 13: $13 (13), signed 32 bits
-+ 14: $14 (14), signed 32 bits
-+ 15: $15 (15), signed 32 bits
-+ 16: $16 (16), signed 32 bits
-+ 17: $17 (17), signed 32 bits
-+ 18: $18 (18), signed 32 bits
-+ 19: $19 (19), signed 32 bits
-+ 20: $20 (20), signed 32 bits
-+ 21: $21 (21), signed 32 bits
-+ 22: $22 (22), signed 32 bits
-+ 23: $23 (23), signed 32 bits
-+ 24: $24 (24), signed 32 bits
-+ 25: $25 (25), signed 32 bits
-+ 26: $26 (26), signed 32 bits
-+ 27: $27 (27), signed 32 bits
-+ 28: $28 (28), address 32 bits
-+ 29: $29 (29), address 32 bits
-+ 30: $30 (30), signed 32 bits
-+ 31: $31 (31), address 32 bits
-+ 32: $lo (lo), signed 32 bits
-+ 33: $hi (hi), signed 32 bits
-+ 34: $pc (pc), signed 32 bits
-+ 35: $bad (bad), address 32 bits
-+ 36: $sr (sr), signed 32 bits
-+ 37: $cause (cause), address 32 bits
-+FPU registers:
-+ 38: $f0 (f0), float 64 bits
-+ 39: $f1 (f1), float 64 bits
-+ 40: $f2 (f2), float 64 bits
-+ 41: $f3 (f3), float 64 bits
-+ 42: $f4 (f4), float 64 bits
-+ 43: $f5 (f5), float 64 bits
-+ 44: $f6 (f6), float 64 bits
-+ 45: $f7 (f7), float 64 bits
-+ 46: $f8 (f8), float 64 bits
-+ 47: $f9 (f9), float 64 bits
-+ 48: $f10 (f10), float 64 bits
-+ 49: $f11 (f11), float 64 bits
-+ 50: $f12 (f12), float 64 bits
-+ 51: $f13 (f13), float 64 bits
-+ 52: $f14 (f14), float 64 bits
-+ 53: $f15 (f15), float 64 bits
-+ 54: $f16 (f16), float 64 bits
-+ 55: $f17 (f17), float 64 bits
-+ 56: $f18 (f18), float 64 bits
-+ 57: $f19 (f19), float 64 bits
-+ 58: $f20 (f20), float 64 bits
-+ 59: $f21 (f21), float 64 bits
-+ 60: $f22 (f22), float 64 bits
-+ 61: $f23 (f23), float 64 bits
-+ 62: $f24 (f24), float 64 bits
-+ 63: $f25 (f25), float 64 bits
-+ 64: $f26 (f26), float 64 bits
-+ 65: $f27 (f27), float 64 bits
-+ 66: $f28 (f28), float 64 bits
-+ 67: $f29 (f29), float 64 bits
-+ 68: $f30 (f30), float 64 bits
-+ 69: $f31 (f31), float 64 bits
-+ 70: $fsr (fsr), float 64 bits
-+ 71: $fir (fir), float 64 bits
-+EOF
- exit 0
---- a/tests/run-readelf-mixed-corenote.sh
-+++ b/tests/run-readelf-mixed-corenote.sh
-@@ -716,4 +716,101 @@ Note segment of 1408 bytes at offset 0x3
- 2000155000-2000157000 00122000 8192 /lib64/libc-2.27.so
- EOF
-
-+# To reproduce this core dump, do this on a mips machine:
-+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
-+# $ ./a.out
-+testfiles testfile-mips64-core
-+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-mips64-core <<\EOF
-+
-+Note segment of 2572 bytes at offset 0x3c0:
-+ Owner Data size Type
-+ CORE 480 PRSTATUS
-+ info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
-+ sigpend: <>
-+ sighold: <>
-+ pid: 1660204, ppid: 1457483, pgrp: 1660204, sid: 1457483
-+ utime: 0.000000, stime: 0.012000, cutime: 0.000000, cstime: 0.000000
-+ pc: 0x000000aaacce0a64, fpvalid: 1
-+ bad: 0x12345678 sr: 0 cause: 0x0400ccf3
-+ f0: 0x1000000800000000 f1: 0x0000000000000000 f2: 0x0000000000000000
-+ f3: 0x0000000000000000 f4: 0x0000000000000000 f5: 0x0000000000000000
-+ f6: 0x0000000000000000
-+ 0: 0 1: 0 2: 1
-+ 3: 0 4: 305419896 5: 0
-+ 6: -73593800 7: 255 8: 1
-+ 9: 0 10: -73593464 11: 255
-+ 12: -73593448 13: 255 14: 0
-+ 15: 0 16: -244869184 17: 255
-+ 18: -244886336 19: 255 20: -73593472
-+ 21: 255 22: -1 23: -1
-+ 24: 3 25: 0 26: 3167716
-+ 27: 0 28: 0x00000024 29: 0x00000000
-+ 30: 49495 31: 0x00000000 lo: -73593464
-+ hi: 255 bad: 0x12345678 sr: 0
-+ cause: 0x0400ccf3 f0: 0x1000000800000000
-+ f1: 0x0000000000000000 f2: 0x0000000000000000
-+ f3: 0x0000000000000000 f4: 0x0000000000000000
-+ f5: 0x0000000000000000 f6: 0x0000000000000000
-+ CORE 136 PRPSINFO
-+ state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000402600
-+ uid: 1014, gid: 100, pid: 1660204, ppid: 1457483, pgrp: 1660204
-+ sid: 1457483
-+ fname: a.out, psargs: ./a.out
-+ CORE 128 SIGINFO
-+ si_signo: 11, si_errno: 1, si_code: 0
-+ sender PID: 305419896, sender UID: 0
-+ CORE 320 AUXV
-+ SYSINFO_EHDR: 0xffff14c000
-+ HWCAP: 0x7806
-+ PAGESZ: 16384
-+ CLKTCK: 100
-+ PHDR: 0xaaacce0040
-+ PHENT: 56
-+ PHNUM: 9
-+ BASE: 0xfff1694000
-+ FLAGS: 0
-+ ENTRY: 0xaaacce08d0
-+ UID: 1014
-+ EUID: 1014
-+ GID: 100
-+ EGID: 100
-+ SECURE: 0
-+ RANDOM: 0xfffb9d0f9c
-+ EXECFN: 0xfffb9d3ff0
-+ PLATFORM: 0xfffb9d0fb5
-+ BASE_PLATFORM: 0xfffb9d0fac
-+ NULL
-+ CORE 549 FILE
-+ 9 files:
-+ aaacce0000-aaacce4000 00000000 16384 /tmp/a.out
-+ aaaccf0000-aaaccf4000 00000000 16384 /tmp/a.out
-+ fff1470000-fff165c000 00000000 2015232 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
-+ fff165c000-fff1668000 001ec000 49152 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
-+ fff1668000-fff1670000 001e8000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
-+ fff1670000-fff1678000 001f0000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6
-+ fff1694000-fff16c4000 00000000 196608 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
-+ fff16d0000-fff16d4000 0002c000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
-+ fff16d4000-fff16d8000 00030000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1
-+ CORE 264 FPREGSET
-+ fcs: 0x000c0000, fir: 0x00f70501
-+ f0: 0xffffffffffffffff f1: 0xffffffffffffffff
-+ f2: 0xffffffffffffffff f3: 0xffffffffffffffff
-+ f4: 0xffffffffffffffff f5: 0xffffffffffffffff
-+ f6: 0xffffffffffffffff f7: 0xffffffffffffffff
-+ f8: 0xffffffffffffffff f9: 0xffffffffffffffff
-+ f10: 0xffffffffffffffff f11: 0xffffffffffffffff
-+ f12: 0xffffffffffffffff f13: 0xffffffffffffffff
-+ f14: 0xffffffffffffffff f15: 0xffffffffffffffff
-+ f16: 0xffffffffffffffff f17: 0xffffffffffffffff
-+ f18: 0xffffffffffffffff f19: 0xffffffffffffffff
-+ f20: 0xffffffffffffffff f21: 0xffffffffffffffff
-+ f22: 0xffffffffffffffff f23: 0xffffffffffffffff
-+ f24: 0xffffffffffffffff f25: 0xffffffffffffffff
-+ f26: 0xffffffffffffffff f27: 0xffffffffffffffff
-+ f28: 0xffffffffffffffff f29: 0xffffffffffffffff
-+ f30: 0xffffffffffffffff f31: 0xffffffffffffffff
-+ LINUX 4 MIPS_FP_MODE
-+ LINUX 528 MIPS_MSA
-+EOF
-+
- exit 0
diff --git a/tools/elfutils/patches/011-backport-mips-support-strip.patch b/tools/elfutils/patches/011-backport-mips-support-strip.patch
new file mode 100644
index 0000000000..7ea9bedc1a
--- /dev/null
+++ b/tools/elfutils/patches/011-backport-mips-support-strip.patch
@@ -0,0 +1,230 @@
+In mips64 little-endian, r_info consists of four byte fields(contains
+three reloc types) and a 32-bit symbol index. In order to adapt
+GELF_R_SYM and GELF_R_TYPE, need convert raw data to get correct symbol
+index and type.
+
+ libelf/elf_getdata.c: Some eu-utils use read-mmap method to map file,
+so we need to malloc and memcpy raw data to avoid segment fault. After
+modification, the correct value are saved in the malloced memory not in
+process address space.
+ libelf/elf_updata.c: Because we converted the relocation info in mips
+order when we call elf_getdata.c, so we need to convert the modified data
+in original order bits before writing the data to the file.
+
+Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+---
+ libelf/elf_getdata.c | 132 ++++++++++++++++++++++++++++++++++++++++++-
+ libelf/elf_update.c | 53 +++++++++++++++++
+ 2 files changed, 183 insertions(+), 2 deletions(-)
+
+--- a/libelf/elf_getdata.c
++++ b/libelf/elf_getdata.c
+@@ -135,6 +135,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int
+
+ /* Convert the data in the current section. */
+ static void
++convert_data_for_mips64el (Elf_Scn *scn, int eclass,
++ int data, size_t size, Elf_Type type)
++{
++ /* Do we need to convert the data and/or adjust for alignment? */
++ if (data == MY_ELFDATA || type == ELF_T_BYTE)
++ {
++ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
++ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
++ we need to malloc and memcpy raw data to avoid segment fault. After modification,
++ the correct value are saved in the malloced memory not in process address space. */
++ scn->data_base = malloc (size);
++ if (scn->data_base == NULL)
++ {
++ __libelf_seterrno (ELF_E_NOMEM);
++ return;
++ }
++
++ /* The copy will be appropriately aligned for direct access. */
++ memcpy (scn->data_base, scn->rawdata_base, size);
++ }
++ else
++ {
++ xfct_t fp;
++
++ scn->data_base = malloc (size);
++ if (scn->data_base == NULL)
++ {
++ __libelf_seterrno (ELF_E_NOMEM);
++ return;
++ }
++
++ /* Make sure the source is correctly aligned for the conversion
++ function to directly access the data elements. */
++ char *rawdata_source;
++ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert
++ relocation info(raw data). Some eu-utils use read-mmap method to map file, so
++ we need to malloc and memcpy raw data to avoid segment fault. After modification,
++ the correct value are saved in the malloced memory not in process address space. */
++ rawdata_source = malloc (size);
++ if (rawdata_source == NULL)
++ {
++ __libelf_seterrno (ELF_E_NOMEM);
++ return;
++ }
++
++ /* The copy will be appropriately aligned for direct access. */
++ memcpy (rawdata_source, scn->rawdata_base, size);
++
++ /* Get the conversion function. */
++ fp = __elf_xfctstom[eclass - 1][type];
++
++ fp (scn->data_base, rawdata_source, size, 0);
++
++ if (rawdata_source != scn->rawdata_base)
++ free (rawdata_source);
++ }
++
++ scn->data_list.data.d.d_buf = scn->data_base;
++ scn->data_list.data.d.d_size = size;
++ scn->data_list.data.d.d_type = type;
++ scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
++ scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
++ scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
++
++ scn->data_list.data.s = scn;
++
++ /* In mips64 little-endian, r_info consists of four byte fields(contains
++ three reloc types) and a 32-bit symbol index. In order to adapt
++ GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol
++ index and type. */
++ /* references:
++ https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
++ Page40 && Page41 */
++ GElf_Shdr shdr_mem;
++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
++ if (shdr->sh_type == SHT_REL)
++ {
++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
++ int nentries = shdr->sh_size / sh_entsize;
++ for (int cnt = 0; cnt < nentries; ++cnt)
++ {
++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
++ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
++ Elf64_Xword info = value->r_info;
++ value->r_info = (((info & 0xffffffff) << 32)
++ | ((info >> 56) & 0xff)
++ | ((info >> 40) & 0xff00)
++ | ((info >> 24) & 0xff0000)
++ | ((info >> 8) & 0xff000000));
++ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
++ }
++ }
++ else if (shdr->sh_type == SHT_RELA)
++ {
++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
++ int nentries = shdr->sh_size / sh_entsize;
++ for (int cnt = 0; cnt < nentries; cnt++)
++ {
++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d;
++ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
++ Elf64_Xword info = value->r_info;
++ value->r_info = (((info & 0xffffffff) << 32)
++ | ((info >> 56) & 0xff)
++ | ((info >> 40) & 0xff00)
++ | ((info >> 24) & 0xff0000)
++ | ((info >> 8) & 0xff000000));
++ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
++ }
++ }
++}
++
++/* Convert the data in the current section. */
++static void
+ convert_data (Elf_Scn *scn, int eclass,
+ int data, size_t size, Elf_Type type)
+ {
+@@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn *
+ return;
+ }
+
+- /* Convert according to the version and the type. */
+- convert_data (scn, elf->class,
++ GElf_Shdr shdr_mem;
++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
++ GElf_Ehdr ehdr_mem;
++ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
++ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
++ scn->elf->class == ELFCLASS64 && ehdr != NULL &&
++ ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
++ convert_data_for_mips64el (scn, elf->class,
++ (elf->class == ELFCLASS32
++ || (offsetof (struct Elf, state.elf32.ehdr)
++ == offsetof (struct Elf, state.elf64.ehdr))
++ ? elf->state.elf32.ehdr->e_ident[EI_DATA]
++ : elf->state.elf64.ehdr->e_ident[EI_DATA]),
++ scn->rawdata.d.d_size, scn->rawdata.d.d_type);
++ else
++ /* Convert according to the version and the type. */
++ convert_data (scn, elf->class,
+ (elf->class == ELFCLASS32
+ || (offsetof (struct Elf, state.elf32.ehdr)
+ == offsetof (struct Elf, state.elf64.ehdr))
+--- a/libelf/elf_update.c
++++ b/libelf/elf_update.c
+@@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd)
+ size = -1;
+ }
+ else
++ {
++ /* Because we converted the relocation info in mips order when we call elf_getdata.c,
++ so we need to convert the modified data in original order bits before writing the
++ data to the file. */
++ Elf_Scn *scn = NULL;
++ while ((scn = elf_nextscn (elf, scn)) != NULL)
++ {
++ GElf_Shdr shdr_mem;
++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
++ GElf_Ehdr ehdr_mem;
++ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem);
++ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) &&
++ scn->elf->class == ELFCLASS64 &&
++ ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
++ {
++ Elf_Data *d = elf_getdata (scn, NULL);
++ if (shdr->sh_type == SHT_REL)
++ {
++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT);
++ int nentries = shdr->sh_size / sh_entsize;
++ for (int cnt = 0; cnt < nentries; ++cnt)
++ {
++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
++ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt];
++ Elf64_Xword info = value->r_info;
++ value->r_info = (info >> 32
++ | ((info << 56) & 0xff00000000000000)
++ | ((info << 40) & 0xff000000000000)
++ | ((info << 24) & 0xff0000000000)
++ | ((info << 8) & 0xff00000000));
++ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value;
++ }
++ }
++ else if (shdr->sh_type == SHT_RELA)
++ {
++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT);
++ int nentries = shdr->sh_size / sh_entsize;
++ for (int cnt = 0; cnt < nentries; cnt++)
++ {
++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d;
++ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt];
++ Elf64_Xword info = value->r_info;
++ value->r_info = (info >> 32
++ | ((info << 56) & 0xff00000000000000)
++ | ((info << 40) & 0xff000000000000)
++ | ((info << 24) & 0xff0000000000)
++ | ((info << 8) & 0xff00000000));
++ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value;
++ }
++ }
++ }
++ }
+ size = write_file (elf, size, change_bo, shnum);
++ }
+ }
+
+ out:
diff --git a/tools/elfutils/patches/012-backport-mips-support-readelf.patch b/tools/elfutils/patches/012-backport-mips-support-readelf.patch
new file mode 100644
index 0000000000..cf2b7c827b
--- /dev/null
+++ b/tools/elfutils/patches/012-backport-mips-support-readelf.patch
@@ -0,0 +1,1079 @@
+-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 at 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
+
+--- a/backends/Makefile.am
++++ b/backends/Makefile.am
+@@ -102,7 +102,7 @@ loongarch_SRCS = loongarch_init.c loonga
+
+ 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) \
+--- /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;
++}
+--- a/backends/mips_init.c
++++ b/backends/mips_init.c
+@@ -48,5 +48,12 @@ mips_init (Elf *elf __attribute__ ((unus
+ /* 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;
+ }
+--- a/backends/mips_symbol.c
++++ b/backends/mips_symbol.c
+@@ -61,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int ty
+ 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;
++}
+--- a/libelf/libelfP.h
++++ b/libelf/libelfP.h
+@@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_
+ #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 */
+--- a/src/readelf.c
++++ b/src/readelf.c
+@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *
+ (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 *
+ (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
+ (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
+ (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 *
+ 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 *
+ 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
+ {
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s
+ 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-arsymt
+ 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
+--- /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
diff --git a/tools/elfutils/patches/013-backport-mips-support-elflint.patch b/tools/elfutils/patches/013-backport-mips-support-elflint.patch
new file mode 100644
index 0000000000..906a3bf0f2
--- /dev/null
+++ b/tools/elfutils/patches/013-backport-mips-support-elflint.patch
@@ -0,0 +1,156 @@
+The errors were:
+$ src/elflint --gnu src/nm
+section [ 2] '.MIPS.options' contains unknown flag(s) 0x8000000
+section [ 7] '.dynsym': symbol 165 (_DYNAMIC_LINKING): non-local section symbol
+section [24] '.got' contains invalid processor-specific flag(s) 0x10000000
+section [25] '.sdata' contains invalid processor-specific flag(s) 0x10000000
+section [29] '.debug_aranges' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [30] '.debug_info' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [31] '.debug_abbrev' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [32] '.debug_line' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [33] '.debug_frame' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [34] '.debug_str' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [35] '.debug_loc' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [36] '.debug_ranges' has wrong type: expected PROGBITS, is MIPS_DWARF
+section [38] '.symtab': symbol 785 (_gp): st_value out of bounds
+section [38] '.symtab': symbol 910 (_fbss): st_value out of bounds
+section [38] '.symtab': symbol 1051 (_DYNAMIC_LINKING): non-local section symbol
+
+After fixing:
+$ src/elflint --gnu src/nm
+No errors
+
+Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+---
+ backends/mips_init.c | 3 +++
+ backends/mips_symbol.c | 37 +++++++++++++++++++++++++++++++++++++
+ src/elflint.c | 26 +++++++++++++++++++++-----
+ 3 files changed, 61 insertions(+), 5 deletions(-)
+
+--- a/backends/mips_init.c
++++ b/backends/mips_init.c
+@@ -51,9 +51,12 @@ mips_init (Elf *elf __attribute__ ((unus
+ HOOK (eh, section_type_name);
+ HOOK (eh, machine_flag_check);
+ HOOK (eh, machine_flag_name);
++ HOOK (eh, machine_section_flag_check);
+ HOOK (eh, segment_type_name);
+ HOOK (eh, dynamic_tag_check);
+ HOOK (eh, dynamic_tag_name);
+ HOOK (eh, check_object_attribute);
++ HOOK (eh, check_special_symbol);
++ HOOK (eh, check_reloc_target_type);
+ return eh;
+ }
+--- a/backends/mips_symbol.c
++++ b/backends/mips_symbol.c
+@@ -158,6 +158,43 @@ mips_section_type_name (int type,
+ return NULL;
+ }
+
++bool
++mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
++{
++ return (sh_type == SHT_MIPS_DWARF);
++}
++
++/* Check whether given symbol's st_value and st_size are OK despite failing
++ normal checks. */
++bool
++mips_check_special_symbol (Elf *elf,
++ const GElf_Sym *sym __attribute__ ((unused)),
++ const char *name __attribute__ ((unused)),
++ const GElf_Shdr *destshdr)
++{
++ size_t shstrndx;
++ if (elf_getshdrstrndx (elf, &shstrndx) != 0)
++ return false;
++ const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
++ if (sname == NULL)
++ return false;
++ return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0);
++}
++
++/* Check whether SHF_MASKPROC flags are valid. */
++bool
++mips_machine_section_flag_check (GElf_Xword sh_flags)
++{
++ return ((sh_flags &~ (SHF_MIPS_GPREL |
++ SHF_MIPS_MERGE |
++ SHF_MIPS_ADDR |
++ SHF_MIPS_STRINGS |
++ SHF_MIPS_NOSTRIP |
++ SHF_MIPS_LOCAL |
++ SHF_MIPS_NAMES |
++ SHF_MIPS_NODUPE)) == 0);
++}
++
+ /* Check whether machine flags are valid. */
+ bool
+ mips_machine_flag_check (GElf_Word flags)
+--- a/src/elflint.c
++++ b/src/elflint.c
+@@ -936,7 +936,9 @@ section [%2d] '%s': symbol %zu (%s): non
+ }
+
+ if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
+- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
++ && GELF_ST_BIND (sym->st_info) != STB_LOCAL
++ && ehdr->e_machine != EM_MIPS
++ && strcmp (name, "_DYNAMIC_LINKING") != 0)
+ ERROR (_("\
+ section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
+ idx, section_name (ebl, idx), cnt, name);
+@@ -3828,6 +3830,10 @@ cannot get section header for section [%
+ && ebl_bss_plt_p (ebl))
+ good_type = SHT_NOBITS;
+
++ if (ehdr->e_machine == EM_MIPS
++ && (strstr(special_sections[s].name, ".debug") != NULL))
++ good_type = SHT_MIPS_DWARF;
++
+ /* In a debuginfo file, any normal section can be SHT_NOBITS.
+ This is only invalid for DWARF sections and .shstrtab. */
+ if (shdr->sh_type != good_type
+@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o
+ ERROR (_("section [%2zu] '%s'"
+ " contains invalid processor-specific flag(s)"
+ " %#" PRIx64 "\n"),
+- cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
++ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
+ sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
+ }
+ if (sh_flags & SHF_MASKOS)
+- if (gnuld)
+- sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
++ {
++ if (gnuld)
++ sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
++ if (!ebl_machine_section_flag_check (ebl,
++ sh_flags & SHF_MASKOS))
++ ERROR (_("section [%2zu] '%s'"
++ " contains invalid os-specific flag(s)"
++ " %#" PRIx64 "\n"),
++ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKOS);
++ sh_flags &= ~(GElf_Xword) SHF_MASKOS;
++ }
+ if (sh_flags != 0)
+ ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
+ " %#" PRIx64 "\n"),
+@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but
+ switch (shdr->sh_type)
+ {
+ case SHT_PROGBITS:
++ case SHT_MIPS_DWARF:
+ break;
+
+ case SHT_NOBITS:
+@@ -4716,7 +4732,7 @@ program header offset in ELF header and
+ if (shdr != NULL
+ && ((is_debuginfo && shdr->sh_type == SHT_NOBITS)
+ || (! is_debuginfo
+- && (shdr->sh_type == SHT_PROGBITS
++ && (is_debug_section_type(shdr->sh_type)
+ || shdr->sh_type == SHT_X86_64_UNWIND)))
+ && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
+ && ! strcmp (".eh_frame_hdr",
diff --git a/tools/elfutils/patches/014-backport-mips-support-stack.patch b/tools/elfutils/patches/014-backport-mips-support-stack.patch
new file mode 100644
index 0000000000..9907a30264
--- /dev/null
+++ b/tools/elfutils/patches/014-backport-mips-support-stack.patch
@@ -0,0 +1,273 @@
+From f2acb06970522a9563d82490f2f1b8fc0bb5b720 Mon Sep 17 00:00:00 2001
+From: Ying Huang <ying.huang at oss.cipunited.com>
+Date: Tue, 5 Mar 2024 17:51:21 +0800
+Subject: [PATCH] stack: Fix stack unwind failure on mips
+
+Add abi_cfi, set_initial_registers_tid, unwind on mips.
+
+ * backends/Makefile.am (mips_SRCS): Add mips_initreg.c,
+ mips_cfi.c and mips_unwind.c.
+ * backends/mips_init.c (mips_init): HOOK abi_cfi, unwind and
+ set_initial_registers_tid. Set frame_nregs to 71.
+ * backends/mips_cfi.c: New file.
+ * backends/mips_initreg.c: Likewise.
+ * backends/mips_unwind.c: Likewise.
+
+Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+---
+ backends/Makefile.am | 3 +-
+ backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++
+ backends/mips_init.c | 4 ++
+ backends/mips_initreg.c | 61 ++++++++++++++++++++++++++++++
+ backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 219 insertions(+), 1 deletion(-)
+ create mode 100644 backends/mips_cfi.c
+ create mode 100644 backends/mips_initreg.c
+ create mode 100644 backends/mips_unwind.c
+
+--- a/backends/Makefile.am
++++ b/backends/Makefile.am
+@@ -102,7 +102,8 @@ loongarch_SRCS = loongarch_init.c loonga
+
+ arc_SRCS = arc_init.c arc_symbol.c
+
+-mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
++mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
++ mips_cfi.c mips_unwind.c
+
+ libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
+ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
+--- /dev/null
++++ b/backends/mips_cfi.c
+@@ -0,0 +1,68 @@
++/* MIPS ABI-specified defaults for DWARF CFI.
++ Copyright (C) 2009 Red Hat, Inc.
++ 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 <dwarf.h>
++
++#define BACKEND mips_
++#include "libebl_CPU.h"
++
++int
++mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
++{
++ static const uint8_t abi_cfi[] =
++ {
++ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0),
++ /* Callee-saved regs. */
++ DW_CFA_same_value, ULEB128_7 (16), /* s0 */
++ DW_CFA_same_value, ULEB128_7 (17), /* s1 */
++ DW_CFA_same_value, ULEB128_7 (18), /* s2 */
++ DW_CFA_same_value, ULEB128_7 (19), /* s3 */
++ DW_CFA_same_value, ULEB128_7 (20), /* s4 */
++ DW_CFA_same_value, ULEB128_7 (21), /* s5 */
++ DW_CFA_same_value, ULEB128_7 (22), /* s6 */
++ DW_CFA_same_value, ULEB128_7 (23), /* s7 */
++ DW_CFA_same_value, ULEB128_7 (28), /* gp */
++ DW_CFA_same_value, ULEB128_7 (29), /* sp */
++ DW_CFA_same_value, ULEB128_7 (30), /* fp */
++
++ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0),
++ };
++
++ abi_info->initial_instructions = abi_cfi;
++ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
++ abi_info->data_alignment_factor = 8;
++
++ abi_info->return_address_register = 31; /* %ra */
++
++ return 0;
++}
+--- a/backends/mips_init.c
++++ b/backends/mips_init.c
+@@ -58,5 +58,9 @@ mips_init (Elf *elf __attribute__ ((unus
+ HOOK (eh, check_object_attribute);
+ HOOK (eh, check_special_symbol);
+ HOOK (eh, check_reloc_target_type);
++ HOOK (eh, set_initial_registers_tid);
++ HOOK (eh, abi_cfi);
++ HOOK (eh, unwind);
++ eh->frame_nregs = 71;
+ return eh;
+ }
+--- /dev/null
++++ b/backends/mips_initreg.c
+@@ -0,0 +1,61 @@
++/* Fetch live process registers from TID.
++ 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 <stdlib.h>
++#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
++# include <sys/user.h>
++# include <sys/ptrace.h>
++#include <asm/ptrace.h>
++#endif
++
++#define BACKEND mips_
++#include "libebl_CPU.h"
++
++
++bool
++mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
++ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
++ void *arg __attribute__ ((unused)))
++{
++#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__)
++ return false;
++#else /* __mips__ */
++/* For PTRACE_GETREGS */
++
++ struct pt_regs gregs;
++ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
++ return false;
++ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg))
++ return false;
++ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
++#endif /* __mips__ */
++}
+--- /dev/null
++++ b/backends/mips_unwind.c
+@@ -0,0 +1,84 @@
++/* Get previous frame state for an existing frame state.
++ Copyright (C) 2016 The Qt Company Ltd.
++ 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
++
++#define BACKEND mips_
++#define SP_REG 29
++#define FP_REG 30
++#define LR_REG 31
++#define FP_OFFSET 0
++#define LR_OFFSET 8
++#define SP_OFFSET 16
++
++#include "libebl_CPU.h"
++
++/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */
++
++bool
++EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
++ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
++ ebl_pid_memory_read_t *readfunc, void *arg,
++ bool *signal_framep __attribute__ ((unused)))
++{
++ Dwarf_Word fp, lr, sp;
++
++ if (!getfunc(LR_REG, 1, &lr, arg))
++ return false;
++
++ if (lr == 0 || !setfunc(-1, 1, &lr, arg))
++ return false;
++
++ if (!getfunc(FP_REG, 1, &fp, arg))
++ fp = 0;
++
++ if (!getfunc(SP_REG, 1, &sp, arg))
++ sp = 0;
++
++ Dwarf_Word newLr, newFp, newSp;
++
++ if (!readfunc(fp + LR_OFFSET, &newLr, arg))
++ newLr = 0;
++
++ if (!readfunc(fp + FP_OFFSET, &newFp, arg))
++ newFp = 0;
++
++ newSp = fp + SP_OFFSET;
++
++ // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
++ setfunc(LR_REG, 1, &newLr, arg);
++ setfunc(FP_REG, 1, &newFp, arg);
++ setfunc(SP_REG, 1, &newSp, arg);
++
++ // If the fp is invalid, we might still have a valid lr.
++ // But if the fp is valid, then the stack should be moving in the right direction.
++ return fp == 0 || newSp > sp;
++}
diff --git a/tools/elfutils/patches/015-backport-mips-support-regs.patch b/tools/elfutils/patches/015-backport-mips-support-regs.patch
new file mode 100644
index 0000000000..7547a12140
--- /dev/null
+++ b/tools/elfutils/patches/015-backport-mips-support-regs.patch
@@ -0,0 +1,475 @@
+From db33cb0cac3253c34881c0377ada51d9803eaae0 Mon Sep 17 00:00:00 2001
+From: Ying Huang <ying.huang at oss.cipunited.com>
+Date: Tue, 5 Mar 2024 17:51:22 +0800
+Subject: [PATCH] backends: Add register_info, return_value_location, core_note
+ on mips
+
+ * backends/Makefile.am (mips_SRCS): Add mips_regs.c,
+ mips_retval.c and mips_corenote.c.
+ * backends/mips_init.c (mips_init): HOOK register_info,
+ return_value_location and core_note.
+ * backends/mips_corenote.c: New file.
+ * backends/mips_regs.c: Likewise.
+ * backends/mips_retval.c: Likewise.
+
+Signed-off-by: Ying Huang <ying.huang at oss.cipunited.com>
+---
+ backends/Makefile.am | 3 +-
+ backends/mips_corenote.c | 85 +++++++++++++++++
+ backends/mips_init.c | 3 +
+ backends/mips_regs.c | 135 +++++++++++++++++++++++++++
+ backends/mips_retval.c | 196 +++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 421 insertions(+), 1 deletion(-)
+ create mode 100644 backends/mips_corenote.c
+ create mode 100644 backends/mips_regs.c
+ create mode 100644 backends/mips_retval.c
+
+--- a/backends/Makefile.am
++++ b/backends/Makefile.am
+@@ -103,7 +103,8 @@ loongarch_SRCS = loongarch_init.c loonga
+ arc_SRCS = arc_init.c arc_symbol.c
+
+ mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
+- mips_cfi.c mips_unwind.c
++ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \
++ mips_corenote.c
+
+ libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
+ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
+--- /dev/null
++++ b/backends/mips_corenote.c
+@@ -0,0 +1,85 @@
++/* MIPS specific core note handling.
++ 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 <elf.h>
++#include <inttypes.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <sys/time.h>
++
++#define BACKEND mips_
++#include "libebl_CPU.h"
++
++#define BITS 64
++#ifndef BITS
++# define BITS 32
++#else
++# define BITS 64
++#endif
++
++#define PRSTATUS_REGS_SIZE (45 * (BITS / 8))
++static const Ebl_Register_Location prstatus_regs[] =
++ {
++ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS },
++ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS },
++ };
++
++#define PRSTATUS_REGSET_ITEMS \
++ { \
++ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \
++ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \
++ .group = "register", \
++ .pc_register = true \
++ }
++
++#if BITS == 32
++# define ULONG uint32_t
++# define ALIGN_ULONG 4
++# define TYPE_ULONG ELF_T_WORD
++#define TYPE_LONG ELF_T_SWORD
++#else
++#define ULONG uint64_t
++#define ALIGN_ULONG 8
++#define TYPE_ULONG ELF_T_XWORD
++#define TYPE_LONG ELF_T_SXWORD
++#endif
++#define PID_T int32_t
++#define UID_T uint32_t
++#define GID_T uint32_t
++#define ALIGN_PID_T 4
++#define ALIGN_UID_T 4
++#define ALIGN_GID_T 4
++#define TYPE_PID_T ELF_T_SWORD
++#define TYPE_UID_T ELF_T_WORD
++#define TYPE_GID_T ELF_T_WORD
++
++#include "linux-core-note.c"
+--- a/backends/mips_init.c
++++ b/backends/mips_init.c
+@@ -61,6 +61,9 @@ mips_init (Elf *elf __attribute__ ((unus
+ HOOK (eh, set_initial_registers_tid);
+ HOOK (eh, abi_cfi);
+ HOOK (eh, unwind);
++ HOOK (eh, register_info);
++ HOOK (eh, return_value_location);
++ HOOK (eh, core_note);
+ eh->frame_nregs = 71;
+ return eh;
+ }
+--- /dev/null
++++ b/backends/mips_regs.c
+@@ -0,0 +1,135 @@
++/* Register names and numbers for mips DWARF.
++ Copyright (C) 2006 Red Hat, Inc.
++ 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 <assert.h>
++#include <dwarf.h>
++#include <string.h>
++
++#define BACKEND mips_
++#include "libebl_CPU.h"
++#include <system.h>
++ssize_t
++mips_register_info (Ebl *ebl __attribute__ ((unused)),
++ int regno, char *name, size_t namelen,
++ const char **prefix, const char **setname,
++ int *bits, int *type)
++{
++ if (name == NULL)
++ return 72;
++
++ if (regno < 0 || regno > 71 || namelen < 4)
++ return -1;
++
++ *prefix = "$";
++ if (regno < 38)
++ {
++ *setname = "integer";
++ *type = DW_ATE_signed;
++ *bits = 32;
++ }
++ else
++ {
++ *setname = "FPU";
++ *type = DW_ATE_float;
++ *bits = 64;
++ }
++
++ if (regno < 32)
++ {
++ if (regno < 10)
++ {
++ name[0] = regno + '0';
++ namelen = 1;
++ }
++ else
++ {
++ name[0] = (regno / 10) + '0';
++ name[1] = (regno % 10) + '0';
++ namelen = 2;
++ }
++ if (regno == 28 || regno == 29 || regno == 31)
++ *type = DW_ATE_address;
++ }
++ else if (regno == 32)
++ {
++ return stpcpy (name, "lo") + 1 - name;
++ }
++ else if (regno == 33)
++ {
++ return stpcpy (name, "hi") + 1 - name;
++ }
++ else if (regno == 34)
++ {
++ return stpcpy (name, "pc") + 1 - name;
++ }
++ else if (regno == 35)
++ {
++ *type = DW_ATE_address;
++ return stpcpy (name, "bad") + 1 - name;
++ }
++ else if (regno == 36)
++ {
++ return stpcpy (name, "sr") + 1 - name;
++ }
++ else if (regno == 37)
++ {
++ *type = DW_ATE_address;
++ return stpcpy (name, "cause") + 1 - name;
++ }
++ else if (regno < 70)
++ {
++ name[0] = 'f';
++ if (regno < 38 + 10)
++ {
++ name[1] = (regno - 38) + '0';
++ namelen = 2;
++ }
++ else
++ {
++ name[1] = (regno - 38) / 10 + '0';
++ name[2] = (regno - 38) % 10 + '0';
++ namelen = 3;
++ }
++ }
++ else if (regno == 70)
++ {
++ return stpcpy (name, "fsr") + 1 - name;
++ }
++ else if (regno == 71)
++ {
++ return stpcpy (name, "fir") + 1 - name;
++ }
++
++ name[namelen++] = '\0';
++ return namelen;
++}
+--- /dev/null
++++ b/backends/mips_retval.c
+@@ -0,0 +1,196 @@
++/* Function return value location for Linux/mips ABI.
++ Copyright (C) 2005 Red Hat, Inc.
++ 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 <assert.h>
++#include <dwarf.h>
++#include <string.h>
++#include <elf.h>
++#include <stdio.h>
++
++#define BACKEND mips_
++#include "libebl_CPU.h"
++#include "libdwP.h"
++#include <stdio.h>
++
++/* $v0 or pair $v0, $v1 */
++static const Dwarf_Op loc_intreg_o32[] =
++ {
++ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
++ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
++ };
++
++static const Dwarf_Op loc_intreg[] =
++ {
++ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 },
++ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 },
++ };
++#define nloc_intreg 1
++#define nloc_intregpair 4
++
++/* $f0 (float), or pair $f0, $f1 (double).
++ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */
++static const Dwarf_Op loc_fpreg_o32[] =
++ {
++ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
++ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
++ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 },
++ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 },
++ };
++
++/* $f0, or pair $f0, $f2. */
++static const Dwarf_Op loc_fpreg[] =
++ {
++ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 },
++ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
++ };
++#define nloc_fpreg 1
++#define nloc_fpregpair 4
++#define nloc_fpregquad 8
++
++/* The return value is a structure and is actually stored in stack space
++ passed in a hidden argument by the caller. But, the compiler
++ helpfully returns the address of that space in $v0. */
++static const Dwarf_Op loc_aggregate[] =
++ {
++ { .atom = DW_OP_breg2, .number = 0 }
++ };
++#define nloc_aggregate 1
++
++int
++mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
++{
++ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8;
++ if (!regsize)
++ return -2;
++
++ /* Start with the function's type, and get the DW_AT_type attribute,
++ which is the type of the return value. */
++
++ Dwarf_Attribute attr_mem;
++ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem);
++ if (attr == NULL)
++ /* The function has no return value, like a `void' function in C. */
++ return 0;
++
++ Dwarf_Die die_mem;
++ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem);
++ int tag = dwarf_tag (typedie);
++
++ /* Follow typedefs and qualifiers to get to the actual type. */
++ while (tag == DW_TAG_typedef
++ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
++ || tag == DW_TAG_restrict_type)
++ {
++ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
++ typedie = dwarf_formref_die (attr, &die_mem);
++ tag = dwarf_tag (typedie);
++ }
++
++ switch (tag)
++ {
++ case -1:
++ return -1;
++
++ case DW_TAG_subrange_type:
++ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
++ {
++ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
++ typedie = dwarf_formref_die (attr, &die_mem);
++ tag = dwarf_tag (typedie);
++ }
++ /* Fall through. */
++ FALLTHROUGH;
++
++ case DW_TAG_base_type:
++ case DW_TAG_enumeration_type:
++ CASE_POINTER:
++ {
++ Dwarf_Word size;
++ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
++ &attr_mem), &size) != 0)
++ {
++ if (dwarf_is_pointer (tag))
++ size = regsize;
++ else
++ return -1;
++ }
++ if (tag == DW_TAG_base_type)
++ {
++ Dwarf_Word encoding;
++ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
++ &attr_mem), &encoding) != 0)
++ return -1;
++
++#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc))
++
++ if (encoding == DW_ATE_float)
++ {
++ *locp = ARCH_LOC(loc_fpreg, regsize);
++ if (size <= regsize)
++ return nloc_fpreg;
++
++ if (size <= 2*regsize)
++ return nloc_fpregpair;
++
++ if (size <= 4*regsize)
++ return nloc_fpregquad;
++
++ goto aggregate;
++ }
++ }
++ *locp = ARCH_LOC(loc_intreg, regsize);
++ if (size <= regsize)
++ return nloc_intreg;
++ if (size <= 2*regsize)
++ return nloc_intregpair;
++
++ /* Else fall through. Shouldn't happen though (at least with gcc) */
++ }
++ FALLTHROUGH;
++
++ case DW_TAG_structure_type:
++ case DW_TAG_class_type:
++ case DW_TAG_union_type:
++ case DW_TAG_array_type:
++ aggregate:
++ *locp = loc_aggregate;
++ return nloc_aggregate;
++ case DW_TAG_unspecified_type:
++ return 0;
++ }
++
++ /* XXX We don't have a good way to return specific errors from ebl calls.
++ This value means we do not understand the type, but it is well-formed
++ DWARF and might be valid. */
++ return -2;
++}
More information about the lede-commits
mailing list